diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..cf027760 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,68 @@ +*.class +*.log +apis.yaml +docker-compose.yml + +# sbt specific +.cache +.history +.lib/ +target/ +lib_managed/ +src_managed/ +project/boot/ +project/plugins/project/ + +# Scala-IDE specific +.scala_dependencies +.worksheet +*.sc + +#IntelliJ specific +.idea + +# eclipse specific +*.pydevproject +.project +.metadata +bin/** +tmp/** +tmp/**/* +*.tmp +*.bak +*.swp +*~.nib +local.properties +.classpath +.settings/ +.loadpath + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# Downloaded dependencies + +*.DS_Store +.DS_Store + +.sass-cache +.sass-cache/* + +.vscode/ +admin/webapp/.bsp/ +admin/webapp/websrc/.bsp/ +token.json + +.metals +admin/test/REST_API/output +admin/webapp/root +admin/webapp/.angular +/.bsp/* +/admin/.angular/ +/admin/webapp/websrc/assets/mockdata +/admin/webapp/package-lock.json +admin/webapp/websrc/assets/i18n/en.json +admin/webapp/websrc/assets/i18n/zh_cn.json diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..bf532933 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,68 @@ +name: Release + +on: + push: + tags: + - 'v*' + +jobs: + + publish: + runs-on: ubuntu-latest + permissions: + contents: read + # write is needed for: + # - OIDC for cosign's use in ecm-distro-tools/publish-image. + # - Read vault secrets in rancher-eio/read-vault-secrets. + id-token: write + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Load Secrets from Vault + uses: rancher-eio/read-vault-secrets@main + with: + secrets: | + secret/data/github/repo/${{ github.repository }}/dockerhub/rancher/credentials username | RANCHER_DOCKER_USERNAME ; + secret/data/github/repo/${{ github.repository }}/dockerhub/rancher/credentials password | RANCHER_DOCKER_PASSWORD ; + secret/data/github/repo/${{ github.repository }}/dockerhub/neuvector/credentials username | DOCKER_USERNAME ; + secret/data/github/repo/${{ github.repository }}/dockerhub/neuvector/credentials password | DOCKER_PASSWORD ; + secret/data/github/repo/${{ github.repository }}/rancher-prime-registry/credentials registry | PRIME_REGISTRY ; + secret/data/github/repo/${{ github.repository }}/rancher-prime-registry/credentials username | PRIME_REGISTRY_USERNAME ; + secret/data/github/repo/${{ github.repository }}/rancher-prime-registry/credentials password | PRIME_REGISTRY_PASSWORD + - name: Parse target tag + run: | + TARGET=${{ github.ref_name }} + echo "TAG=${TARGET#v}" >> $GITHUB_ENV + - name: Publish neuvector manifest + uses: rancher/ecm-distro-tools/actions/publish-image@master + with: + push-to-public: true + push-to-prime: false + image: manager + tag: ${{ env.TAG }} + platforms: linux/amd64,linux/arm64 + + public-registry: docker.io + public-repo: neuvector + public-username: ${{ env.DOCKER_USERNAME }} + public-password: ${{ env.DOCKER_PASSWORD }} + - name: Publish rancher manifest + uses: rancher/ecm-distro-tools/actions/publish-image@master + env: + IMAGE_PREFIX: neuvector- + with: + image: neuvector-manager + tag: ${{ env.TAG }} + platforms: linux/amd64,linux/arm64 + + public-registry: docker.io + public-repo: rancher + public-username: ${{ env.RANCHER_DOCKER_USERNAME }} + public-password: ${{ env.RANCHER_DOCKER_PASSWORD }} + + prime-registry: ${{ env.PRIME_REGISTRY }} + prime-repo: rancher + prime-username: ${{ env.PRIME_REGISTRY_USERNAME }} + prime-password: ${{ env.PRIME_REGISTRY_PASSWORD }} diff --git a/Makefile b/Makefile index 683af2cb..1fa952f6 100644 --- a/Makefile +++ b/Makefile @@ -31,4 +31,69 @@ jar: @echo "Pulling images ..." docker pull neuvector/build_manager:${BUILD_IMAGE_TAG} @echo "Making $@ ..." - docker run --rm -ia STDOUT --name build -v prebuild_manager:/prebuild/manager -v $(CURDIR):/manager -w /manager --entrypoint ./make_jar.sh neuvector/build_manager:${BUILD_IMAGE_TAG} \ No newline at end of file + docker run --rm -ia STDOUT --name build -v prebuild_manager:/prebuild/manager -v $(CURDIR):/manager -w /manager --entrypoint ./make_jar.sh neuvector/build_manager:${BUILD_IMAGE_TAG} + +RUNNER := docker +IMAGE_BUILDER := $(RUNNER) buildx +MACHINE := neuvector +BUILDX_ARGS ?= --sbom=true --attest type=provenance,mode=max +DEFAULT_PLATFORMS := linux/amd64,linux/arm64,linux/x390s,linux/riscv64 + +COMMIT = $(shell git rev-parse --short HEAD) +ifeq ($(VERSION),) + # Define VERSION, which is used for image tags or to bake it into the + # compiled binary to enable the printing of the application version, + # via the --version flag. + CHANGES = $(shell git status --porcelain --untracked-files=no) + ifneq ($(CHANGES),) + DIRTY = -dirty + endif + + + COMMIT = $(shell git rev-parse --short HEAD) + VERSION = $(COMMIT)$(DIRTY) + + # Override VERSION with the Git tag if the current HEAD has a tag pointing to + # it AND the worktree isn't dirty. + GIT_TAG = $(shell git tag -l --contains HEAD | head -n 1) + ifneq ($(GIT_TAG),) + ifeq ($(DIRTY),) + VERSION = $(GIT_TAG) + endif + endif +endif + +ifeq ($(TAG),) + TAG = $(VERSION) + ifneq ($(DIRTY),) + TAG = dev + endif +endif + +TARGET_PLATFORMS ?= linux/amd64,linux/arm64 +STAGE_DIR=stage +REPO ?= neuvector +IMAGE = $(REPO)/manager:$(TAG) +BUILD_ACTION = --load + +buildx-machine: + docker buildx ls + @docker buildx ls | grep $(MACHINE) || \ + docker buildx create --name=$(MACHINE) --platform=$(DEFAULT_PLATFORMS) + +test-image: + # Instead of loading image, target all platforms, effectivelly testing + # the build for the target architectures. + $(MAKE) build-image BUILD_ACTION="--platform=$(TARGET_PLATFORMS)" + +build-image: buildx-machine ## build (and load) the container image targeting the current platform. + $(IMAGE_BUILDER) build -f package/Dockerfile \ + --builder $(MACHINE) $(IMAGE_ARGS) \ + --build-arg VERSION=$(VERSION) --build-arg COMMIT=$(COMMIT) -t "$(IMAGE)" $(BUILD_ACTION) . + @echo "Built $(IMAGE)" + +push-image: buildx-machine + $(IMAGE_BUILDER) build -f package/Dockerfile \ + --builder $(MACHINE) $(IMAGE_ARGS) $(IID_FILE_FLAG) $(BUILDX_ARGS) \ + --build-arg VERSION=$(VERSION) --build-arg COMMIT=$(COMMIT) --platform=$(TARGET_PLATFORMS) -t "$(REPO)/$(IMAGE_PREFIX)manager:$(TAG)" --push . + @echo "Pushed $(REPO)/$(IMAGE_PREFIX)manager:$(TAG)" diff --git a/package/Dockerfile b/package/Dockerfile new file mode 100644 index 00000000..6da4675d --- /dev/null +++ b/package/Dockerfile @@ -0,0 +1,122 @@ +# Builder image +FROM registry.suse.com/bci/openjdk:17 AS builder + +ARG TARGETOS +ARG TARGETARCH + +COPY admin /src/admin +COPY cli /src/cli +COPY common /src/common +COPY images /src/images +COPY licenses /src/licenses +COPY java.security /src/java.security +COPY package /src/package +COPY project /src/project +COPY scripts /src/scripts +COPY build.sbt .scalafix.conf .scalafmt.conf /src/ + +WORKDIR /src + +RUN zypper refresh && \ + zypper install -y ca-certificates wget curl zip git awk nodejs20 npm20 + +ARG VERSION + +ARG CS_VERSION=v2.1.18 +RUN if [ "$TARGETARCH" = "amd64" ]; then \ + curl -fL https://github.com/coursier/coursier/releases/download/${CS_VERSION}/cs-x86_64-pc-${TARGETOS}.gz | gzip -d > cs; \ + elif [ "$TARGETARCH" = "arm64" ]; then \ + curl -fL https://github.com/VirtusLab/coursier-m1/releases/download/${CS_VERSION}/cs-aarch64-pc-${TARGETOS}.gz | gzip -d > cs; \ + else \ + echo "Unsupported architecture: $ARCH"; \ + exit 1; \ + fi && \ + chmod +x cs && \ + export PATH="$PATH:/root/.local/share/coursier/bin" && \ + ./cs install scala:3.3.4 sbt:1.10.2 --install-dir /usr/local/bin + +RUN npm install -g @angular/cli@14 && \ + npm install -g npm-force-resolutions + +RUN sed -i -e 's/interim.*xxxx/'"$VERSION"'/g' ./common/src/main/resources/application.conf +RUN bash package/build_manager.sh + +# Manager unitest +RUN if [ "$ARCH" = "amd64" ]; then \ + zypper addrepo https://download.opensuse.org/repositories/M17N:fonts/15.6/M17N:fonts.repo && \ + rpm --import https://download.opensuse.org/repositories/M17N/15.6/repodata/repomd.xml.key && \ + zypper --non-interactive refresh && \ + zypper install -y liberation-fonts && \ + wget https://dl.google.com/${OS}/direct/google-chrome-stable_current_${ARCH}.rpm && \ + wget https://dl.google.com/${OS}/${OS}_signing_key.pub && \ + rpm --import linux_signing_key.pub && \ + zypper install -y google-chrome-stable_current_x86_64.rpm; \ +fi + +# Base image +FROM registry.suse.com/bci/bci-micro:15.6 AS micro +FROM registry.suse.com/bci/bci-base:15.6 AS base + +COPY --from=builder /src/package/requirements.txt /chroot/requirements.txt +COPY --from=micro / /chroot/ + +RUN zypper refresh && zypper --installroot /chroot -n in --no-recommends \ + python312 python312-pip iproute2 lsof procps grep awk && \ + cp /etc/resolv.conf /chroot/etc/resolv.conf && \ + chroot /chroot /usr/bin/python3.12 -m pip install --upgrade pip setuptools && \ + rm /chroot/usr/lib/python3.12/site-packages/distutils-precedence.pth && \ + zypper --installroot /chroot clean -a && \ + rm -rf /chroot/var/log/ + +# Create proper symbolic links for Python and pip +RUN ln -sf /usr/bin/python3.12 /chroot/usr/bin/python3 && \ + ln -sf /usr/bin/python3.12 /chroot/usr/bin/python && \ + ln -sf /usr/bin/pip3.12 /chroot/usr/bin/pip3 && \ + ln -sf /usr/bin/pip3.12 /chroot/usr/bin/pip + +# Install requirements and clean up +RUN chroot /chroot /bin/sh -c "pip install --no-cache-dir -r /requirements.txt && \ + rm -rf /root/.cache /requirements.txt" + +# Remove unnecessary binaries to reduce image size +RUN cd /chroot/usr/bin/ && \ + rm -rf basename chcon chgrp chmod chown chroot cksum dd df dircolors \ + dirname du install install-info join locale localedef mkdir mkfifo \ + mknod mktemp paste pathchk readlink realpath sync smidiff smidump \ + smilink smiquery smistrip smixlate tee tiemout tload top truncate \ + unlink watch + +FROM micro +ARG VERSION +ARG COMMIT +WORKDIR / +COPY --from=base /chroot/ / +COPY --from=base /usr/sbin/useradd /usr/sbin +COPY --from=builder /usr/lib64/ /usr/lib64/ +COPY --from=builder /src/stage / + +ENV JAVA_HOME=/usr/lib64/jvm/java-17-openjdk-17 \ + PATH=/usr/lib64/jvm/java-17-openjdk-17/bin:$PATH \ + LD_LIBRARY_PATH=/usr/lib64 \ + LANG=C.UTF-8 \ + PYTHONUNBUFFERED=1 + +LABEL "name"="manager" \ + "vendor"="SUSE Security" \ + "neuvector.image"="neuvector/manager" \ + "neuvector.role"="manager" \ + "neuvector.rev"="${COMMIT}" \ + "io.artifacthub.package.logo-url"=https://avatars2.githubusercontent.com/u/19367275 \ + "io.artifacthub.package.readme-url"="https://raw.githubusercontent.com/neuvector/manager/${VERSION}/README.md" \ + "org.opencontainers.image.description"="SUSE Security Manager" \ + "org.opencontainers.image.title"="SUSE Security Manager" \ + "org.opencontainers.image.source"="https://github.com/neuvector/manager/" \ + "org.opencontainers.image.version"="${VERSION}" \ + "org.opensuse.reference"="neuvector/manager:${VERSION}" + +ARG user=manager +RUN echo "$user:x:1000:1000::/nonexistent:/bin/bash" >> /etc/passwd && \ + echo "$user:x:1000:" >> /etc/group +USER $user + +ENTRYPOINT ["java", "-Xms256m", "-Xmx2048m", "-Djdk.tls.rejectClientInitiatedRenegotiation=true", "-Dpekko.http.parsing.max-header-value-length=32k", "-jar", "/usr/local/bin/admin-assembly-1.0.jar"] diff --git a/package/build_manager.sh b/package/build_manager.sh new file mode 100644 index 00000000..29cfd8f8 --- /dev/null +++ b/package/build_manager.sh @@ -0,0 +1,60 @@ +#!/bin/bash +set -e + +STAGE_DIR=stage + +export CHROME_BIN=/usr/bin/google-chrome + +rm -rf admin/target +pushd admin/webapp +if [[ $# > 0 ]]; then + case $1 in + -d) + mkdir -p /root/.ivy2 + ln -s /prebuild/manager/cache /root/.ivy2/cache + # ln -s /prebuild/manager/node_modules node_modules + ;; + *) + ;; + esac +fi +npm install --legacy-peer-deps 2>&1 +if [ $? -eq 0 ]; then + echo npm package installation SUCCEED +else + npm cache clean --force 2>&1 + sleep 10 + npm install 2>&1 + if [ $? -eq 0 ]; then + echo npm package installation SUCCEED + else + echo ================================ + echo npm package installation FAILED + echo ================================ + exit 1 + fi +fi +npm run build 2>&1 +if [ $? -eq 0 ]; then + echo UI build SUCCEED +else + echo ================================ + echo UI build FAILED + echo ================================ + exit 1 +fi +# npm run unittest +popd +env JAVA_OPTS="-Xms2g -Xmx3g" sbt admin/assembly +zip -d admin/target/scala-3.3.4/admin-assembly-1.0.jar rest-management-private-classpath\* +rm -rf admin/webapp/root/.sass-cache + +mkdir -p ${STAGE_DIR}/licenses/ ${STAGE_DIR}/usr/local/bin/ ${STAGE_DIR}/usr/lib/jvm/java-17-openjdk/lib/security ${STAGE_DIR}/usr/lib64/jvm/java-17-openjdk-17/conf/security/ +cp licenses/* ${STAGE_DIR}/licenses/ +cp cli/cli ${STAGE_DIR}/usr/local/bin/ +cp cli/cli.py ${STAGE_DIR}/usr/local/bin/ +cp -r cli/prog ${STAGE_DIR}/usr/local/bin/ +cp scripts/* ${STAGE_DIR}/usr/local/bin/ +cp java.security ${STAGE_DIR}/usr/lib/jvm/java-17-openjdk/lib/security/ +cp java.security ${STAGE_DIR}/usr/lib64/jvm/java-17-openjdk-17/conf/security/ +cp admin/target/scala-3.3.4/admin-assembly-1.0.jar ${STAGE_DIR}/usr/local/bin/ diff --git a/package/requirements.txt b/package/requirements.txt new file mode 100644 index 00000000..084818cc --- /dev/null +++ b/package/requirements.txt @@ -0,0 +1,8 @@ +click==8.1.2 +cmd2==2.3.3 +prettytable==2.5.0 +requests==2.32.0 +six==1.11.0 +supervisor==4.2.5 +urllib3==1.26.19 +