diff --git a/.github/workflows/publish-container-images.yml b/.github/workflows/publish-container-images.yml index ac6d205..0f30849 100644 --- a/.github/workflows/publish-container-images.yml +++ b/.github/workflows/publish-container-images.yml @@ -21,9 +21,17 @@ permissions: packages: write jobs: - publish: - name: Build and publish container images - runs-on: ubuntu-latest + build: + name: Build ${{ matrix.arch }} images + runs-on: ${{ matrix.runner }} + strategy: + fail-fast: false + matrix: + include: + - arch: amd64 + runner: ubuntu-26.04 + - arch: arm64 + runner: ubuntu-26.04-arm steps: - name: Checkout repository @@ -36,10 +44,33 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: echo "${GITHUB_TOKEN}" | docker login ghcr.io --username "${GITHUB_ACTOR}" --password-stdin - - name: Build local container images - run: ./scripts/build_container_images.sh all + - name: Build and push single-architecture images + env: + ARCH: ${{ matrix.arch }} + run: | + set -euo pipefail + + arch_tag="sha-${GITHUB_SHA::12}-${ARCH}" + + export PUSH=1 + export IMAGE_TAGS="${arch_tag}" + # derived images must build on the base pushed by this same job + export BASE_IMAGE="ghcr.io/githubsecuritylab/seclab-shell-base:${arch_tag}" + + ./scripts/build_container_images.sh all + + publish: + name: Publish multi-architecture images + needs: build + runs-on: ubuntu-26.04 + + steps: + - name: Log in to GHCR + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: echo "${GITHUB_TOKEN}" | docker login ghcr.io --username "${GITHUB_ACTOR}" --password-stdin - - name: Tag and push images + - name: Combine per-architecture images into manifest lists env: CUSTOM_TAG: ${{ github.event.inputs.tag }} run: | @@ -69,8 +100,11 @@ jobs: ) for image in "${images[@]}"; do + args=() for tag in "${tags[@]}"; do - docker tag "${image}:latest" "${image}:${tag}" - docker push "${image}:${tag}" + args+=(--tag "${image}:${tag}") done + docker buildx imagetools create "${args[@]}" \ + "${image}:sha-${short_sha}-amd64" \ + "${image}:sha-${short_sha}-arm64" done diff --git a/scripts/build_container_images.sh b/scripts/build_container_images.sh index 031434c..498f143 100755 --- a/scripts/build_container_images.sh +++ b/scripts/build_container_images.sh @@ -8,6 +8,12 @@ # # Usage: ./scripts/build_container_images.sh [base|malware|network|source-access|sast|all] # default: all +# +# Environment: +# PUSH set to 1 to also push the images to the registry +# IMAGE_TAGS space-separated tags to apply (default: latest) +# BASE_IMAGE base image the derived images build on +# (default: ${IMAGE_PREFIX}/seclab-shell-base:latest) set -euo pipefail @@ -16,29 +22,47 @@ __root="$(cd "${__dir}/.." && pwd)" CONTAINERS_DIR="${__root}/src/seclab_taskflows/containers" IMAGE_PREFIX="ghcr.io/githubsecuritylab" +PUSH="${PUSH:-0}" +IMAGE_TAGS="${IMAGE_TAGS:-latest}" +BASE_IMAGE="${BASE_IMAGE:-${IMAGE_PREFIX}/seclab-shell-base:latest}" + +read -ra IMAGE_TAG_LIST <<< "${IMAGE_TAGS}" + +# build_image [extra docker buildx build args...] +build_image() { + local name="$1" context="$2" + shift 2 + local image="${IMAGE_PREFIX}/${name}" + local args=() + local tag + for tag in "${IMAGE_TAG_LIST[@]}"; do + args+=(--tag "${image}:${tag}") + done + if [[ "${PUSH}" == "1" ]]; then + args+=(--push) + fi + echo "Building ${image}..." + docker buildx build "${args[@]}" "$@" "${CONTAINERS_DIR}/${context}/" +} + build_base() { - echo "Building ${IMAGE_PREFIX}/seclab-shell-base..." - docker build -t "${IMAGE_PREFIX}/seclab-shell-base:latest" "${CONTAINERS_DIR}/base/" + build_image seclab-shell-base base } build_malware() { - echo "Building ${IMAGE_PREFIX}/seclab-shell-malware-analysis..." - docker build -t "${IMAGE_PREFIX}/seclab-shell-malware-analysis:latest" "${CONTAINERS_DIR}/malware_analysis/" + build_image seclab-shell-malware-analysis malware_analysis --build-arg "BASE_IMAGE=${BASE_IMAGE}" } build_network() { - echo "Building ${IMAGE_PREFIX}/seclab-shell-network-analysis..." - docker build -t "${IMAGE_PREFIX}/seclab-shell-network-analysis:latest" "${CONTAINERS_DIR}/network_analysis/" + build_image seclab-shell-network-analysis network_analysis --build-arg "BASE_IMAGE=${BASE_IMAGE}" } build_source_access() { - echo "Building ${IMAGE_PREFIX}/seclab-shell-source-access..." - docker build -t "${IMAGE_PREFIX}/seclab-shell-source-access:latest" "${CONTAINERS_DIR}/source_access/" + build_image seclab-shell-source-access source_access } build_sast() { - echo "Building ${IMAGE_PREFIX}/seclab-shell-sast..." - docker build -t "${IMAGE_PREFIX}/seclab-shell-sast:latest" "${CONTAINERS_DIR}/sast/" + build_image seclab-shell-sast sast --build-arg "BASE_IMAGE=${BASE_IMAGE}" } target="${1:-all}" diff --git a/src/seclab_taskflows/containers/malware_analysis/Dockerfile b/src/seclab_taskflows/containers/malware_analysis/Dockerfile index b659046..a5ce0ca 100644 --- a/src/seclab_taskflows/containers/malware_analysis/Dockerfile +++ b/src/seclab_taskflows/containers/malware_analysis/Dockerfile @@ -1,7 +1,8 @@ # SPDX-FileCopyrightText: GitHub, Inc. # SPDX-License-Identifier: MIT -FROM ghcr.io/githubsecuritylab/seclab-shell-base:latest +ARG BASE_IMAGE=ghcr.io/githubsecuritylab/seclab-shell-base:latest +FROM ${BASE_IMAGE} RUN apt-get update && apt-get install -y --no-install-recommends \ binwalk yara libimage-exiftool-perl checksec \ && rm -rf /var/lib/apt/lists/* diff --git a/src/seclab_taskflows/containers/network_analysis/Dockerfile b/src/seclab_taskflows/containers/network_analysis/Dockerfile index 5fb58ea..a99fafb 100644 --- a/src/seclab_taskflows/containers/network_analysis/Dockerfile +++ b/src/seclab_taskflows/containers/network_analysis/Dockerfile @@ -1,7 +1,8 @@ # SPDX-FileCopyrightText: GitHub, Inc. # SPDX-License-Identifier: MIT -FROM ghcr.io/githubsecuritylab/seclab-shell-base:latest +ARG BASE_IMAGE=ghcr.io/githubsecuritylab/seclab-shell-base:latest +FROM ${BASE_IMAGE} RUN apt-get update && apt-get install -y --no-install-recommends \ nmap tcpdump tshark netcat-openbsd dnsutils curl jq httpie \ && rm -rf /var/lib/apt/lists/* diff --git a/src/seclab_taskflows/containers/sast/Dockerfile b/src/seclab_taskflows/containers/sast/Dockerfile index e358dd2..340ed22 100644 --- a/src/seclab_taskflows/containers/sast/Dockerfile +++ b/src/seclab_taskflows/containers/sast/Dockerfile @@ -1,7 +1,8 @@ # SPDX-FileCopyrightText: GitHub, Inc. # SPDX-License-Identifier: MIT -FROM ghcr.io/githubsecuritylab/seclab-shell-base:latest +ARG BASE_IMAGE=ghcr.io/githubsecuritylab/seclab-shell-base:latest +FROM ${BASE_IMAGE} RUN apt-get update && apt-get install -y --no-install-recommends \ universal-ctags global cscope ripgrep fd-find graphviz tree \ && ln -s /usr/bin/fdfind /usr/local/bin/fd \