From c68a62ba00e0c11cc3548a4527a899c67ff531ce Mon Sep 17 00:00:00 2001 From: Theauditor <228822721+TheAuditorTool@users.noreply.github.com> Date: Mon, 13 Apr 2026 14:27:29 +0700 Subject: [PATCH] fix(docker): multi-arch image build (amd64+arm64) -- closes #223 The published Docker image was linux/arm64 only because it was built on an ARM64 host. This caused >60s startup via QEMU emulation on amd64, breaking downstream CI (ZAP scans). Changes: - VMs/buildDockerImage.sh: rewrite to use docker buildx with --platform linux/amd64,linux/arm64 for multi-arch manifest - VMs/Dockerfile: pin ubuntu:22.04, collapse RUN layers, add EXPOSE 8443 and CMD for usability - .github/workflows/docker-publish.yml: add CI workflow for automated multi-arch builds (workflow_dispatch only -- inactive until secrets and triggers are configured) - PR_multi-arch-docker.md: changelog, guide, and activation steps --- .github/workflows/docker-publish.yml | 66 ++++++++++++++++++++++++++++ VMs/Dockerfile | 53 +++++++++++----------- VMs/buildDockerImage.sh | 36 ++++++++++----- 3 files changed, 117 insertions(+), 38 deletions(-) create mode 100644 .github/workflows/docker-publish.yml diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml new file mode 100644 index 0000000000..2035c8c27b --- /dev/null +++ b/.github/workflows/docker-publish.yml @@ -0,0 +1,66 @@ +# ------------------------------------------------------------------ +# INACTIVE BY DEFAULT -- manual trigger only (workflow_dispatch). +# +# This workflow builds and publishes a multi-architecture Docker image +# (linux/amd64 + linux/arm64) to Docker Hub. +# +# TO ACTIVATE: +# 1. Add two repository secrets (Settings > Secrets and variables > Actions): +# DOCKERHUB_USERNAME - your Docker Hub username +# DOCKERHUB_TOKEN - a Docker Hub access token (not your password) +# 2. Optionally add automatic triggers by uncommenting the lines below: +# push: +# branches: [master] +# paths: ['VMs/Dockerfile'] +# release: +# types: [published] +# +# Until you do both steps, this workflow does nothing on its own. +# ------------------------------------------------------------------ + +name: Docker Publish + +on: + workflow_dispatch: + # Uncomment the triggers below when ready to automate: + # push: + # branches: [master] + # paths: ['VMs/Dockerfile'] + # release: + # types: [published] + +env: + IMAGE_NAME: owasp/benchmark + PLATFORMS: linux/amd64,linux/arm64 + +jobs: + build-and-push: + runs-on: ubuntu-latest + + permissions: + contents: read + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up QEMU (multi-arch emulation) + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push multi-arch image + uses: docker/build-push-action@v6 + with: + context: VMs + file: VMs/Dockerfile + platforms: ${{ env.PLATFORMS }} + push: true + tags: ${{ env.IMAGE_NAME }}:latest diff --git a/VMs/Dockerfile b/VMs/Dockerfile index aaa8d235a4..174cc218ba 100644 --- a/VMs/Dockerfile +++ b/VMs/Dockerfile @@ -1,44 +1,45 @@ # This dockerfile builds a container that pulls down and runs the latest version of BenchmarkJava -FROM ubuntu:latest +FROM ubuntu:22.04 LABEL org.opencontainers.image.authors="Dave Wichers dave.wichers@owasp.org" -RUN apt-get update -RUN DEBIAN_FRONTEND="noninteractive" apt-get -y install tzdata -RUN apt-get install -q -y \ - openjdk-17-jre-headless \ - openjdk-17-jdk \ - git \ - maven \ - wget \ - iputils-ping \ - && apt-get clean +RUN apt-get update \ + && DEBIAN_FRONTEND="noninteractive" apt-get -y install tzdata \ + && apt-get install -q -y \ + openjdk-17-jre-headless \ + openjdk-17-jdk \ + git \ + maven \ + wget \ + iputils-ping \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* RUN mkdir /owasp WORKDIR /owasp # Download, build, install Benchmark Utilities required by crawler and scorecard generation -RUN git clone https://github.com/OWASP-Benchmark/BenchmarkUtils.git -WORKDIR /owasp/BenchmarkUtils -RUN mvn install +RUN git clone https://github.com/OWASP-Benchmark/BenchmarkUtils.git \ + && cd BenchmarkUtils \ + && mvn install # Download, build BenchmarkJava -WORKDIR /owasp -RUN git clone https://github.com/OWASP-Benchmark/BenchmarkJava - -# Workaround for security fix for CVE-2022-24765 -RUN git config --global --add safe.directory /owasp/BenchmarkJava +RUN git clone https://github.com/OWASP-Benchmark/BenchmarkJava \ + && git config --global --add safe.directory /owasp/BenchmarkJava \ + && cd BenchmarkJava \ + && mvn clean package cargo:install -WORKDIR /owasp/BenchmarkJava -RUN mvn clean package cargo:install - -RUN useradd -d /home/bench -m -s /bin/bash bench -RUN echo bench:bench | chpasswd +RUN useradd -d /home/bench -m -s /bin/bash bench \ + && echo bench:bench | chpasswd RUN chown -R bench /owasp/ ENV PATH=/owasp/BenchmarkJava:$PATH -# start up Benchmark once, for 60 seconds, then kill it, so the additional dependencies required to run it are downloaded/cached in the image as well. -# exit 0 is required to return a 'success' code, otherwise the timeout returns a failure code, causing the Docker build to fail. +# Start up Benchmark once for 60 seconds then kill it, so additional runtime +# dependencies are downloaded and cached in the image. +# exit 0 prevents the timeout return code from failing the Docker build. WORKDIR /owasp/BenchmarkJava RUN timeout 60 ./runBenchmark.sh; exit 0 +EXPOSE 8443 +CMD ["./runBenchmark.sh"] + diff --git a/VMs/buildDockerImage.sh b/VMs/buildDockerImage.sh index b0dd310374..56a287b943 100755 --- a/VMs/buildDockerImage.sh +++ b/VMs/buildDockerImage.sh @@ -1,16 +1,28 @@ -# Pull in latest version of ubuntu. This builds an image using the OS native to this platform. -docker pull ubuntu:latest -# Remove any ubuntu: image if it was left behind by a new version of ubuntu:latest being pulled -i=$(docker images | grep "ubuntu" | grep "/dev/null 2>&1; then + echo "Creating buildx builder: $BUILDER_NAME" + docker buildx create --name "$BUILDER_NAME" --use +else + docker buildx use "$BUILDER_NAME" fi -# Since Docker doesn't auto delete anything, just like for the Ubuntu update, delete any existing benchmark:latest image before building a new one -docker image rm benchmark:latest -docker build -t benchmark . +# Build and push a multi-architecture image in one step. +# --push is required because multi-arch manifest lists cannot be loaded into +# the local daemon. The image is pushed directly to Docker Hub. +echo "Building ${IMAGE}:${TAG} for ${PLATFORMS} ..." +docker buildx build \ + --platform "$PLATFORMS" \ + --tag "${IMAGE}:${TAG}" \ + --push \ + . -# Once verified/tested, to publish an update to the OWASP Benchmark Docker image, run the following: -# docker push owasp/benchmark:latest +echo "Done. Published ${IMAGE}:${TAG} for ${PLATFORMS}."