From 025d2f30818656b000934f92d0ee7a2b01505834 Mon Sep 17 00:00:00 2001 From: yiannistri <8741709+yiannistri@users.noreply.github.com> Date: Mon, 13 Jan 2025 10:10:38 +0000 Subject: [PATCH] ci: Make release SLSA compliant (cherry picked from commit e86cf8a5b84988915419bb080e11d36af1209426) --- .github/workflows/build.yaml | 6 +-- .github/workflows/release.yaml | 82 +++++++++++++++++++++------------- Makefile | 71 ++++++++++++++++------------- package/Dockerfile | 41 +++++++++++++---- pkg/version/version.go | 6 +++ 5 files changed, 130 insertions(+), 76 deletions(-) create mode 100644 pkg/version/version.go diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index b8d71f5a..12703ff0 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -12,9 +12,5 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 - - name: Install Go - uses: actions/setup-go@v5 - with: - go-version: 1.22.x - name: Build - run: make operator + run: make image-build diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 830a8653..656b72d1 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -16,47 +16,69 @@ on: # - PUBLIC_REGISTRY_PASSWORD jobs: - release: + publish-images: permissions: - contents: write # required for creating GH release - id-token: write # required for reading vault secrets + contents: read + id-token: write # required for reading vault secrets and for cosign's use in ecm-distro-tools/publish-image + strategy: + matrix: + include: + # Three images are created: + # - Multi-arch manifest for both amd64 and arm64 + - tag-suffix: "" + platforms: linux/amd64,linux/arm64 + # - arm64 manifest + - tag-suffix: "-arm64" + platforms: linux/arm64 + # - amd64 manifest + - tag-suffix: "-amd64" + platforms: linux/amd64 runs-on: ubuntu-latest steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ github.ref_name}} - name: Read secrets uses: rancher-eio/read-vault-secrets@main with: secrets: | secret/data/github/repo/${{ github.repository }}/dockerhub/${{ github.repository_owner }}/credentials username | PUBLIC_REGISTRY_USERNAME ; secret/data/github/repo/${{ github.repository }}/dockerhub/${{ github.repository_owner }}/credentials password | PUBLIC_REGISTRY_PASSWORD ; - - name: Login to DockerHub - uses: docker/login-action@v3 + 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: Publish images + uses: rancher/ecm-distro-tools/actions/publish-image@master with: - registry: ${{ vars.PUBLIC_REGISTRY }} - username: ${{ env.PUBLIC_REGISTRY_USERNAME }} - password: ${{ env.PUBLIC_REGISTRY_PASSWORD }} - - name: Setup QEMU - uses: docker/setup-qemu-action@v3 - - name: Setup Docker Buildx - uses: docker/setup-buildx-action@v3 + image: eks-operator + tag: ${{ github.ref_name }}${{ matrix.tag-suffix }} + platforms: ${{ matrix.platforms }} + public-registry: docker.io + public-repo: rancher + public-username: ${{ env.PUBLIC_REGISTRY_USERNAME }} + public-password: ${{ env.PUBLIC_REGISTRY_PASSWORD }} + prime-registry: ${{ env.PRIME_REGISTRY }} + prime-repo: rancher + prime-username: ${{ env.PRIME_REGISTRY_USERNAME }} + prime-password: ${{ env.PRIME_REGISTRY_PASSWORD }} + make-target: image-push + push-to-prime: true + - name: Cleanup checksum files # in order to avoid goreleaser dirty state error, remove once rancher/ecm-distro-tools/actions/publish-image@main gets updated + run: rm -f slsactl_*_checksums.txt* + + release: + permissions: + contents: write # required for creating GH release + runs-on: ubuntu-latest + needs: publish-images + steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 ref: ${{ github.ref_name}} - - name: Set up Go - uses: actions/setup-go@v5 - with: - go-version-file: 'go.mod' - check-latest: true - - name: Build and push all image variations - run: | - make operator - make image-push - TAG="${TAG}-amd64" TARGET_PLATFORMS=linux/amd64 make image-push - TAG="${TAG}-arm64" TARGET_PLATFORMS=linux/arm64 make image-push - env: - TAG: ${{ github.ref_name }} - REPO: ${{ vars.PUBLIC_REGISTRY }}/${{ vars.PUBLIC_REGISTRY_REPO }} - name: Create release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # required for creating GH release @@ -70,17 +92,17 @@ jobs: - name: Upload charts to release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # required for updating GH release - REPO: rancher/eks-operator # Docker repository to reference in `values.yaml` of the Helm chart release + REPO: rancher # First name component for Docker repository to reference in `values.yaml` of the Helm chart release, this is expected to be `rancher`, image name is appended to this value TAG: ${{ github.ref_name }} # image tag to be referenced in `values.yaml` of the Helm chart release run: | version=$(echo '${{ steps.goreleaser.outputs.metadata }}' | jq -r '.version') echo "Publishing helm charts (version: $version)" - + # Both version and appVersion are set to the same value in the Chart.yaml (excluding the 'v' prefix) CHART_VERSION=$version GIT_TAG=$version make charts - + for f in $(find bin/ -name '*.tgz'); do echo "Uploading $f to GitHub release $TAG" gh release upload $TAG $f done - echo "Charts successfully uploaded to GitHub release $TAG" + echo "Charts successfully uploaded to GitHub release $TAG" \ No newline at end of file diff --git a/Makefile b/Makefile index 2ae9a753..a4b06017 100644 --- a/Makefile +++ b/Makefile @@ -7,14 +7,21 @@ ifneq ($(GIT_BRANCH), main) GIT_TAG?=$(shell git describe --abbrev=0 --tags 2>/dev/null || echo "v0.0.0" ) endif TAG?=${GIT_TAG}-${GIT_COMMIT_SHORT} +REPO?=docker.io/rancher +IMAGE = $(REPO)/eks-operator:$(TAG) +MACHINE := rancher +# Define the target platforms that can be used across the ecosystem. +# Note that what would actually be used for a given project will be +# defined in TARGET_PLATFORMS, and must be a subset of the below: +DEFAULT_PLATFORMS := linux/amd64,linux/arm64,darwin/arm64,darwin/amd64 +TARGET_PLATFORMS := linux/amd64,linux/arm64 +BUILDX_ARGS ?= --sbom=true --attest type=provenance,mode=max + OPERATOR_CHART?=$(shell find $(ROOT_DIR) -type f -name "rancher-eks-operator-[0-9]*.tgz" -print) CRD_CHART?=$(shell find $(ROOT_DIR) -type f -name "rancher-eks-operator-crd*.tgz" -print) CHART_VERSION?=900 # Only used in e2e to avoid downgrades from rancher -REPO?=docker.io/rancher/eks-operator -IMAGE = $(REPO):$(TAG) -TARGET_PLATFORMS := linux/amd64,linux/arm64 -MACHINE := rancher CLUSTER_NAME?="eks-operator-e2e" + E2E_CONF_FILE ?= $(ROOT_DIR)/test/e2e/config/config.yaml ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) @@ -52,6 +59,10 @@ default: operator @./.dapper.tmp -v @mv .dapper.tmp .dapper +.PHONY: generate-go +generate-go: $(MOCKGEN) + go generate ./pkg/eks/... + .PHONY: generate-crd generate-crd: $(MOCKGEN) go generate main.go @@ -61,6 +72,10 @@ generate: $(MAKE) generate-go $(MAKE) generate-crd +.PHONY: clean +clean: + rm -rf build bin dist + .PHONY: $(TARGETS) $(TARGETS): .dapper ./.dapper $@ @@ -84,17 +99,27 @@ operator: -X github.com/rancher/eks-operator/pkg/version.Version=$(TAG)" \ -o bin/eks-operator . -.PHONY: generate-go -generate-go: $(MOCKGEN) - go generate ./pkg/eks/... - .PHONY: test test: $(SETUP_ENVTEST) $(GINKGO) KUBEBUILDER_ASSETS="$(KUBEBUILDER_ASSETS)" $(GINKGO) -v -r -p --trace ./pkg/... ./controller/... -.PHONY: clean -clean: - rm -rf build bin dist +buildx-machine: ## create rancher dockerbuildx machine targeting platform defined by DEFAULT_PLATFORMS + @docker buildx ls | grep $(MACHINE) || \ + docker buildx create --name=$(MACHINE) --platform=$(DEFAULT_PLATFORMS) + +.PHONY: image-build +image-build: buildx-machine ## build (and load) the container image targeting the current platform. + docker buildx build -f package/Dockerfile \ + --builder $(MACHINE) --build-arg COMMIT=$(GIT_COMMIT) --build-arg VERSION=$(TAG) \ + -t "$(IMAGE)" $(BUILD_ACTION) . + @echo "Built $(IMAGE)" + +.PHONY: image-push +image-push: buildx-machine ## build the container image targeting all platforms defined by TARGET_PLATFORMS and push to a registry. + docker buildx build -f package/Dockerfile \ + --builder $(MACHINE) $(IID_FILE_FLAG) $(BUILDX_ARGS) --build-arg COMMIT=$(GIT_COMMIT) --build-arg VERSION=$(TAG) \ + --platform=$(TARGET_PLATFORMS) -t "$(IMAGE)" --push . + @echo "Pushed $(IMAGE)" ALL_VERIFY_CHECKS = generate @@ -113,7 +138,7 @@ operator-chart: mkdir -p $(BIN_DIR) cp -rf $(ROOT_DIR)/charts/eks-operator $(BIN_DIR)/chart sed -i -e 's/tag:.*/tag: '${TAG}'/' $(BIN_DIR)/chart/values.yaml - sed -i -e 's|repository:.*|repository: '${REPO}'|' $(BIN_DIR)/chart/values.yaml + sed -i -e 's|repository:.*|repository: '${REPO}/eks-operator'|' $(BIN_DIR)/chart/values.yaml helm package --version ${CHART_VERSION} --app-version ${GIT_TAG} -d $(BIN_DIR)/ $(BIN_DIR)/chart rm -Rf $(BIN_DIR)/chart @@ -128,24 +153,6 @@ charts: $(MAKE) operator-chart $(MAKE) crd-chart -buildx-machine: - @docker buildx ls | grep $(MACHINE) || \ - docker buildx create --name=$(MACHINE) --platform=$(TARGET_PLATFORMS) - -.PHONY: image-build -image-build: buildx-machine ## build (and load) the container image targeting the current platform. - docker buildx build -f package/Dockerfile \ - --builder $(MACHINE) --build-arg VERSION=$(TAG) \ - -t "$(IMAGE)" $(BUILD_ACTION) . - @echo "Built $(IMAGE)" - -.PHONY: image-push -image-push: buildx-machine ## build the container image targeting all platforms defined by TARGET_PLATFORMS and push to a registry. - docker buildx build -f package/Dockerfile \ - --builder $(MACHINE) --build-arg VERSION=$(TAG) \ - --platform=$(TARGET_PLATFORMS) -t "$(IMAGE)" --push . - @echo "Pushed $(IMAGE)" - .PHONY: setup-kind setup-kind: CLUSTER_NAME=$(CLUSTER_NAME) $(ROOT_DIR)/scripts/setup-kind-cluster.sh @@ -161,7 +168,7 @@ e2e-tests: $(GINKGO) charts .PHONY: kind-e2e-tests kind-e2e-tests: docker-build-e2e setup-kind - kind load docker-image --name $(CLUSTER_NAME) ${REPO}:${TAG} + kind load docker-image --name $(CLUSTER_NAME) ${IMAGE} $(MAKE) e2e-tests kind-deploy-operator: @@ -174,7 +181,7 @@ docker-build-e2e: --build-arg "TAG=${GIT_TAG}" \ --build-arg "COMMIT=${GIT_COMMIT}" \ --build-arg "COMMITDATE=${COMMITDATE}" \ - -t ${REPO}:${TAG} . + -t ${IMAGE} . .PHOHY: delete-local-kind-cluster delete-local-kind-cluster: ## Delete the local kind cluster diff --git a/package/Dockerfile b/package/Dockerfile index a7837056..0d741862 100644 --- a/package/Dockerfile +++ b/package/Dockerfile @@ -1,22 +1,45 @@ -FROM registry.suse.com/bci/bci-base:15.6 AS builder +# Image that provides cross compilation tooling. +FROM --platform=$BUILDPLATFORM rancher/mirrored-tonistiigi-xx:1.5.0 AS xx + +FROM registry.suse.com/bci/bci-base:15.6 AS base RUN sed -i 's/^CREATE_MAIL_SPOOL=yes/CREATE_MAIL_SPOOL=no/' /etc/default/useradd RUN useradd --uid 1007 eks-operator +FROM --platform=$BUILDPLATFORM registry.suse.com/bci/golang:1.23 AS builder + +WORKDIR /app +COPY go.mod go.sum ./ +RUN go mod download && go mod verify + +COPY ./controller ./controller +COPY ./pkg ./pkg +COPY ./templates ./templates +COPY ./utils ./utils +COPY ./main.go ./main.go + +# Copy xx scripts to your build stage +COPY --from=xx / / + +ARG TARGETPLATFORM +ARG COMMIT +ARG VERSION +ENV CGO_ENABLED=0# +RUN xx-go build -ldflags \ + "-X github.com/rancher/eks-operator/pkg/version.GitCommit=${COMMIT} \ + -X github.com/rancher/eks-operator/pkg/version.Version=${VERSION}" \ + -o /eks-operator && \ + xx-verify /eks-operator + FROM registry.suse.com/bci/bci-micro:15.6 -COPY --from=builder /etc/passwd /etc/passwd -COPY --from=builder /etc/shadow /etc/shadow +COPY --from=base /etc/passwd /etc/passwd +COPY --from=base /etc/shadow /etc/shadow +COPY --from=builder /eks-operator /usr/bin/eks-operator RUN rm -rf /tmp/* /var/tmp/* /usr/share/doc/packages/* ENV KUBECONFIG="/home/eks-operator/.kube/config" ENV SSL_CERT_DIR="/etc/rancher/ssl" -# Once this image is migrated to be SLSA compliant and the Go build happens -# inside a build layer, we must pass the version and commit ID to the build, -# similar to what was done in https://github.com/rancher/aks-operator/pull/803 . -# This is just a reference for future changes, because it's needed for our VEX -# work. -COPY bin/eks-operator /usr/bin/ COPY package/entrypoint.sh /usr/bin RUN chmod +x /usr/bin/entrypoint.sh diff --git a/pkg/version/version.go b/pkg/version/version.go new file mode 100644 index 00000000..5a40ac92 --- /dev/null +++ b/pkg/version/version.go @@ -0,0 +1,6 @@ +package version + +var ( + GitCommit string + Version string +)