From cd5e280db0892353e4bdeaf1fa60aa3fbe1a5fea Mon Sep 17 00:00:00 2001 From: Markus Rudy Date: Mon, 15 Jan 2024 16:58:31 +0100 Subject: [PATCH] ci: reproducible images based on upstream releases --- .github/workflows/build-images-releases.yaml | 184 ++++--------------- Makefile.defs | 4 +- images/cilium/Dockerfile | 24 +-- images/operator/Dockerfile | 17 +- 4 files changed, 48 insertions(+), 181 deletions(-) diff --git a/.github/workflows/build-images-releases.yaml b/.github/workflows/build-images-releases.yaml index 03535f638484e..14006381ebc3d 100644 --- a/.github/workflows/build-images-releases.yaml +++ b/.github/workflows/build-images-releases.yaml @@ -1,22 +1,30 @@ name: Image Release Build on: + workflow_dispatch: + inputs: + tag: + description: container image tag + required: false push: tags: +<<<<<<< HEAD - v1.15.[0-9]+ - v1.15.[0-9]+-rc.[0-9]+ +======= + - v[0-9]+.* +>>>>>>> c808d02dc1 (ci: reproducible images based on upstream releases) permissions: # To be able to access the repository with `actions/checkout` contents: read - # Required to generate OIDC tokens for `sigstore/cosign-installer` authentication - id-token: write + # Push to ghcr.io + packages: write jobs: build-and-push: timeout-minutes: 45 name: Build and Push Images - environment: release runs-on: ubuntu-22.04 strategy: matrix: @@ -39,120 +47,53 @@ jobs: - name: operator-generic dockerfile: ./images/operator/Dockerfile - - name: hubble-relay - dockerfile: ./images/hubble-relay/Dockerfile - - - name: clustermesh-apiserver - dockerfile: ./images/clustermesh-apiserver/Dockerfile - - - name: docker-plugin - dockerfile: ./images/cilium-docker-plugin/Dockerfile - steps: - - name: Checkout main branch to access local actions - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - with: - ref: ${{ github.event.repository.default_branch }} - persist-credentials: false - - - name: Set Environment Variables - uses: ./.github/actions/set-env-variables - - name: Set up Docker Buildx uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0 - - name: Login to DockerHub - uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 - if: ${{ env.PUSH_TO_DOCKER_HUB == 'true' }} - with: - username: ${{ secrets.DOCKER_HUB_RELEASE_USERNAME }} - password: ${{ secrets.DOCKER_HUB_RELEASE_PASSWORD }} - - - name: Login to quay.io - uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 - with: - registry: quay.io - username: ${{ secrets.QUAY_USERNAME_RELEASE_USERNAME }} - password: ${{ secrets.QUAY_PASSWORD_RELEASE_PASSWORD }} - - name: Getting image tag id: tag run: | - tag=${GITHUB_REF##*/} - echo tag=$tag >> $GITHUB_OUTPUT - if [ "${{ env.PUSH_TO_DOCKER_HUB }}" == "true" ]; then - echo image_tags=${{ github.repository_owner }}/${{ matrix.name }}:$tag,quay.io/${{ env.QUAY_ORGANIZATION }}/${{ matrix.name }}:$tag,${{ github.repository_owner }}/${{ matrix.name }}:stable,quay.io/${{ env.QUAY_ORGANIZATION }}/${{ matrix.name }}:stable >> $GITHUB_OUTPUT + if [ -z "${{ github.event.inputs.tag }}" ] + then + echo tag=${GITHUB_REF##*/} >> $GITHUB_OUTPUT else - echo image_tags=quay.io/${{ env.QUAY_ORGANIZATION }}/${{ matrix.name }}:$tag,quay.io/${{ env.QUAY_ORGANIZATION }}/${{ matrix.name }}:stable >> $GITHUB_OUTPUT + echo tag=${{ github.event.inputs.tag }}>> $GITHUB_OUTPUT fi + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Checkout Source Code uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: persist-credentials: false + - name: Determine SOURCE_DATE_EPOCH + id: epoch + run: echo epoch=$(git log -1 --pretty=%ct) >> $GITHUB_OUTPUT + - name: Release Build ${{ matrix.name }} uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0 id: docker_build_release + env: + SOURCE_DATE_EPOCH: ${{ steps.epoch.outputs.epoch }} with: provenance: false context: . file: ${{ matrix.dockerfile }} push: true platforms: linux/amd64,linux/arm64 - tags: ${{ steps.tag.outputs.image_tags }} + tags: | + ghcr.io/${{ github.repository }}/${{ matrix.name }}:${{ steps.tag.outputs.tag }} target: release build-args: | OPERATOR_VARIANT=${{ matrix.name }} - - - name: Install Cosign - uses: sigstore/cosign-installer@1fc5bd396d372bee37d608f955b336615edf79c8 # v3.2.0 - - - name: Sign Container Image - run: | - if [ "${{ env.PUSH_TO_DOCKER_HUB }}" == "true" ]; then - cosign sign -y docker.io/${{ github.repository_owner }}/${{ matrix.name }}@${{ steps.docker_build_release.outputs.digest }} - fi - cosign sign -y quay.io/${{ env.QUAY_ORGANIZATION }}/${{ matrix.name }}@${{ steps.docker_build_release.outputs.digest }} - - - name: Install Bom - shell: bash - env: - # renovate: datasource=github-releases depName=kubernetes-sigs/bom - BOM_VERSION: v0.5.1 - run: | - curl -L https://github.com/kubernetes-sigs/bom/releases/download/${{ env.BOM_VERSION }}/bom-amd64-linux -o bom - sudo mv ./bom /usr/local/bin/bom - sudo chmod +x /usr/local/bin/bom - - - name: Generate SBOM - shell: bash - # To-Do: generate SBOM from source after https://github.com/kubernetes-sigs/bom/issues/202 is fixed - # To-Do: format SBOM output to json after cosign v2.0 is released with https://github.com/sigstore/cosign/pull/2479 - run: | - bom generate -o sbom_${{ matrix.name }}_${{ steps.tag.outputs.tag }}.spdx \ - --image=quay.io/${{ env.QUAY_ORGANIZATION }}/${{ matrix.name }}:${{ steps.tag.outputs.tag }} - - - name: Attach SBOM to container images - run: | - if [ "${{ env.PUSH_TO_DOCKER_HUB }}" == "true" ]; then - cosign attach sbom --sbom sbom_${{ matrix.name }}_${{ steps.tag.outputs.tag }}.spdx docker.io/${{ github.repository_owner }}/${{ matrix.name }}@${{ steps.docker_build_release.outputs.digest }} - fi - cosign attach sbom --sbom sbom_${{ matrix.name }}_${{ steps.tag.outputs.tag }}.spdx quay.io/${{ env.QUAY_ORGANIZATION }}/${{ matrix.name }}@${{ steps.docker_build_release.outputs.digest }} - - - name: Sign SBOM Image - run: | - if [ "${{ env.PUSH_TO_DOCKER_HUB }}" == "true" ]; then - docker_build_release_digest="${{ steps.docker_build_release.outputs.digest }}" - image_name="docker.io/${{ github.repository_owner }}/${{ matrix.name }}:${docker_build_release_digest/:/-}.sbom" - docker_build_release_sbom_digest="sha256:$(docker buildx imagetools inspect --raw ${image_name} | sha256sum | head -c 64)" - cosign sign -y "docker.io/${{ github.repository_owner }}/${{ matrix.name }}@${docker_build_release_sbom_digest}" - fi - - docker_build_release_digest="${{ steps.docker_build_release.outputs.digest }}" - image_name="quay.io/${{ env.QUAY_ORGANIZATION }}/${{ matrix.name }}:${docker_build_release_digest/:/-}.sbom" - docker_build_release_sbom_digest="sha256:$(docker buildx imagetools inspect --raw ${image_name} | sha256sum | head -c 64)" - cosign sign -y "quay.io/${{ env.QUAY_ORGANIZATION }}/${{ matrix.name }}@${docker_build_release_sbom_digest}" + SOURCE_DATE_EPOCH=${{ steps.epoch.outputs.epoch }} - name: Image Release Digest shell: bash @@ -163,15 +104,8 @@ jobs: job_name_underscored=${job_name_capital//-/_} echo "${job_name_underscored}_DIGEST := \"${{ steps.docker_build_release.outputs.digest }}\"" > image-digest/makefile-digest.txt - echo "### ${{ matrix.name }}" > image-digest/${{ matrix.name }}.txt - echo "" >> image-digest/${{ matrix.name }}.txt - if [ "${{ env.PUSH_TO_DOCKERHUB }}" == "true" ]; then - echo "\`docker.io/${{ github.repository_owner }}/${{ matrix.name }}:${{ steps.tag.outputs.tag }}@${{ steps.docker_build_release.outputs.digest }}\`" >> image-digest/${{ matrix.name }}.txt - echo "\`docker.io/${{ github.repository_owner }}/${{ matrix.name }}:stable@${{ steps.docker_build_release.outputs.digest }}\`" >> image-digest/${{ matrix.name }}.txt - fi - echo "\`quay.io/${{ env.QUAY_ORGANIZATION }}/${{ matrix.name }}:${{ steps.tag.outputs.tag }}@${{ steps.docker_build_release.outputs.digest }}\`" >> image-digest/${{ matrix.name }}.txt - echo "\`quay.io/${{ env.QUAY_ORGANIZATION }}/${{ matrix.name }}:stable@${{ steps.docker_build_release.outputs.digest }}\`" >> image-digest/${{ matrix.name }}.txt - echo "" >> image-digest/${{ matrix.name }}.txt + printf "%s\n\n" "### ${{ matrix.name }}" >> $GITHUB_STEP_SUMMARY + echo "\`ghcr.io/${{ github.repository }}/${{ matrix.name }}:${{ steps.tag.outputs.tag }}@${{ steps.docker_build_release.outputs.digest }}\`" >> $GITHUB_STEP_SUMMARY # Upload artifact digests - name: Upload artifact digests @@ -181,55 +115,3 @@ jobs: path: image-digest retention-days: 10 - image-digests: - name: Display Digests - runs-on: ubuntu-22.04 - needs: build-and-push - steps: - - name: Getting image tag - id: tag - run: | - echo tag=${GITHUB_REF##*/} >> $GITHUB_OUTPUT - - name: Downloading Image Digests - shell: bash - run: | - mkdir -p image-digest/ - - - name: Download digests of all images built - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - path: image-digest/ - - - name: Image Digests Output - shell: bash - run: | - cd image-digest/ - echo "## Docker Manifests" > ../image-digest-output.txt - echo "" >> ../image-digest-output.txt - find -type f -not -name "makefile-digest.txt" | sort | xargs -d '\n' cat >> ../image-digest-output.txt - - - name: Image Makefile Digests - shell: bash - run: | - cd image-digest/ - echo "# File generated by .github/workflows/build-images-releases.yaml; DO NOT EDIT." > ../Makefile.digests - echo "# Copyright "$(date +'%Y')" Authors of Cilium" >> ../Makefile.digests - echo "# SPDX-License-Identifier: Apache-2.0" >> ../Makefile.digests - echo "" >> ../Makefile.digests - find -type f -name "makefile-digest.txt" | sort | xargs -d '\n' awk '{print "export " $0}' >> ../Makefile.digests - - # Upload artifact digests - - name: Upload artifact digests - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 - with: - name: image-digest-output.txt-${{ steps.tag.outputs.tag }} - path: image-digest-output.txt - retention-days: 10 - - # Upload artifact digests - - name: Upload artifact digests - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 - with: - name: Makefile.digests-${{ steps.tag.outputs.tag }} - path: Makefile.digests - retention-days: 10 diff --git a/Makefile.defs b/Makefile.defs index c5b6c5cf17241..3581459590bfd 100644 --- a/Makefile.defs +++ b/Makefile.defs @@ -119,7 +119,7 @@ ifeq ($(NOSTRIP),) # # -w: Omit the DWARF symbol table. # -s: Omit the symbol table and debug information. - GO_BUILD_LDFLAGS += -s -w + GO_BUILD_LDFLAGS += -s -w -buildid= endif ifneq ($(wildcard $(dir $(lastword $(MAKEFILE_LIST)))/images/cilium/Dockerfile),) @@ -143,7 +143,7 @@ BPF_SRCFILES := $(filter-out $(BPF_SRCFILES_IGNORE),$(subst ../,,$(subst $(ROOT_ CILIUM_DATAPATH_SHA256=$(shell cd $(ROOT_DIR); cat $(BPF_SRCFILES) | sha256sum | awk '{print $$1}') GO_BUILD_LDFLAGS += -X "github.com/cilium/cilium/pkg/datapath/loader.DatapathSHA256=$(CILIUM_DATAPATH_SHA256)" -GO_BUILD_FLAGS += -mod=vendor +GO_BUILD_FLAGS += -mod=vendor -trimpath GO_TEST_FLAGS += -mod=vendor -vet=all GO_CLEAN_FLAGS += -mod=vendor diff --git a/images/cilium/Dockerfile b/images/cilium/Dockerfile index b1f7858fb6aff..69d25bb3b88e2 100644 --- a/images/cilium/Dockerfile +++ b/images/cilium/Dockerfile @@ -39,6 +39,7 @@ ARG LOCKDEBUG ARG RACE ARG V ARG LIBNETWORK_PLUGIN +ARG SOURCE_DATE_EPOCH=0 # # Please do not add any dependency updates before the 'make install' here, @@ -46,14 +47,14 @@ ARG LIBNETWORK_PLUGIN # WORKDIR /go/src/github.com/cilium/cilium RUN --mount=type=bind,readwrite,target=/go/src/github.com/cilium/cilium --mount=target=/root/.cache,type=cache --mount=target=/go/pkg,type=cache \ - make GOARCH=${TARGETARCH} RACE=${RACE} NOSTRIP=${NOSTRIP} NOOPT=${NOOPT} LOCKDEBUG=${LOCKDEBUG} PKG_BUILD=1 V=${V} LIBNETWORK_PLUGIN=${LIBNETWORK_PLUGIN} \ + SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH} make GOARCH=${TARGETARCH} RACE=${RACE} NOSTRIP=${NOSTRIP} NOOPT=${NOOPT} LOCKDEBUG=${LOCKDEBUG} PKG_BUILD=1 V=${V} LIBNETWORK_PLUGIN=${LIBNETWORK_PLUGIN} \ DESTDIR=/tmp/install/${TARGETOS}/${TARGETARCH} build-container install-container-binary RUN --mount=type=bind,readwrite,target=/go/src/github.com/cilium/cilium --mount=target=/root/.cache,type=cache --mount=target=/go/pkg,type=cache \ # install-bash-completion will execute the bash_completion script. It is # fine to run this with same architecture as BUILDARCH since the output of # bash_completion is the same for both architectures. - make GOARCH=${BUILDARCH} RACE=${RACE} NOSTRIP=${NOSTRIP} NOOPT=${NOOPT} LOCKDEBUG=${LOCKDEBUG} PKG_BUILD=1 V=${V} LIBNETWORK_PLUGIN=${LIBNETWORK_PLUGIN} \ + SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH} make GOARCH=${BUILDARCH} RACE=${RACE} NOSTRIP=${NOSTRIP} NOOPT=${NOOPT} LOCKDEBUG=${LOCKDEBUG} PKG_BUILD=1 V=${V} LIBNETWORK_PLUGIN=${LIBNETWORK_PLUGIN} \ DESTDIR=/tmp/install/${TARGETOS}/${TARGETARCH} install-bash-completion licenses-all && \ mv LICENSE.all /tmp/install/${TARGETOS}/${TARGETARCH}/LICENSE.all @@ -62,6 +63,8 @@ COPY images/cilium/init-container.sh \ plugins/cilium-cni/cni-uninstall.sh \ /tmp/install/${TARGETOS}/${TARGETARCH} +RUN find /tmp/install/${TARGETOS}/${TARGETARCH} -depth -execdir touch --no-dereference -a -m -t $(date -u -d @${SOURCE_DATE_EPOCH} +%Y%m%d%H%M.%S) '{}' ';' + # # Cilium runtime install. # @@ -72,26 +75,13 @@ COPY images/cilium/init-container.sh \ # built while allowing the new versions to make changes that are not # backwards compatible. # -FROM ${CILIUM_RUNTIME_IMAGE} as release +FROM docker.io/cilium/cilium:v1.15.0-pre.3@sha256:c09d3fc906f26edbc93494cc46e6616668d7931a05470f02b9f9a266c2cfc279 as release # TARGETOS is an automatic platform ARG enabled by Docker BuildKit. ARG TARGETOS # TARGETARCH is an automatic platform ARG enabled by Docker BuildKit. ARG TARGETARCH -LABEL maintainer="maintainer@cilium.io" -RUN echo ". /etc/profile.d/bash_completion.sh" >> /etc/bash.bashrc -COPY --from=cilium-envoy /usr/lib/libcilium.so /usr/lib/libcilium.so -COPY --from=cilium-envoy /usr/bin/cilium-envoy /usr/bin/cilium-envoy-starter /usr/bin/ -# When used within the Cilium container, Hubble CLI should target the -# local unix domain socket instead of Hubble Relay. -ENV HUBBLE_SERVER=unix:///var/run/cilium/hubble.sock -COPY --from=hubble /out/${TARGETOS}/${TARGETARCH}/bin/hubble /usr/bin/hubble -COPY --from=hubble /out/linux/bash_completion /etc/bash_completion.d/hubble - -COPY --from=builder /tmp/install/${TARGETOS}/${TARGETARCH} / -WORKDIR /home/cilium -ENV INITSYSTEM="SYSTEMD" -CMD ["/usr/bin/cilium-dbg"] +COPY --link --from=builder /tmp/install/${TARGETOS}/${TARGETARCH} / # # Cilium debug image. diff --git a/images/operator/Dockerfile b/images/operator/Dockerfile index 9fbdbbbed154f..0eb535922b907 100644 --- a/images/operator/Dockerfile +++ b/images/operator/Dockerfile @@ -20,13 +20,14 @@ ARG NOOPT ARG LOCKDEBUG ARG RACE ARG OPERATOR_VARIANT +ARG SOURCE_DATE_EPOCH=0 WORKDIR /go/src/github.com/cilium/cilium RUN --mount=type=bind,readwrite,target=/go/src/github.com/cilium/cilium \ --mount=type=cache,target=/root/.cache \ --mount=type=cache,target=/go/pkg \ - make GOARCH=${TARGETARCH} RACE=${RACE} NOSTRIP=${NOSTRIP} NOOPT=${NOOPT} LOCKDEBUG=${LOCKDEBUG} \ + SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH} make GOARCH=${TARGETARCH} RACE=${RACE} NOSTRIP=${NOSTRIP} NOOPT=${NOOPT} LOCKDEBUG=${LOCKDEBUG} \ DESTDIR=/out/${TARGETOS}/${TARGETARCH} build-container-${OPERATOR_VARIANT} install-container-binary-${OPERATOR_VARIANT} # licenses-all is a "script" that executes "go run" so its ARCH should be set @@ -36,6 +37,8 @@ RUN --mount=type=bind,readwrite,target=/go/src/github.com/cilium/cilium \ --mount=type=cache,target=/go/pkg \ make GOARCH=${BUILDARCH} licenses-all && mv LICENSE.all /out/${TARGETOS}/${TARGETARCH} +RUN find /out/${TARGETOS}/${TARGETARCH} -depth -execdir touch --no-dereference -a -m -t $(date -u -d @${SOURCE_DATE_EPOCH} +%Y%m%d%H%M.%S) '{}' ';' + # BUILDPLATFORM is an automatic platform ARG enabled by Docker BuildKit. # Represents the plataform where the build is happening, do not mix with # TARGETARCH @@ -55,20 +58,12 @@ RUN --mount=type=bind,readwrite,target=/go/src/github.com/cilium/cilium \ --mount=type=cache,target=/go/pkg \ ./build-gops.sh -FROM ${BASE_IMAGE} as release +FROM docker.io/cilium/operator:v1.15.0-pre.3@sha256:1df2ea3840ca1c012d86f8e9dd785c3f24ce319915db3e6c99150627dfdc08cb as release # TARGETOS is an automatic platform ARG enabled by Docker BuildKit. ARG TARGETOS # TARGETARCH is an automatic platform ARG enabled by Docker BuildKit. ARG TARGETARCH -ARG OPERATOR_VARIANT -LABEL maintainer="maintainer@cilium.io" -COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt -COPY --from=gops /out/${TARGETOS}/${TARGETARCH}/bin/gops /bin/gops -COPY --from=builder /out/${TARGETOS}/${TARGETARCH}/usr/bin/cilium-${OPERATOR_VARIANT} /usr/bin/cilium-${OPERATOR_VARIANT} -COPY --from=builder /out/${TARGETOS}/${TARGETARCH}/LICENSE.all /LICENSE.all -WORKDIR / -ENV GOPS_CONFIG_DIR=/ -CMD ["/usr/bin/cilium-${OPERATOR_VARIANT}"] +COPY --link --from=builder /out/${TARGETOS}/${TARGETARCH} / FROM --platform=${BUILDPLATFORM} ${CILIUM_BUILDER_IMAGE} as debug-tools