diff --git a/.github/workflows/container-build.yml b/.github/workflows/container-build.yml index 6231d834..73043de3 100644 --- a/.github/workflows/container-build.yml +++ b/.github/workflows/container-build.yml @@ -1,4 +1,4 @@ -name: Build container image every change. +name: Build container image and SBOMs on: workflow_call: @@ -6,6 +6,7 @@ on: digest: description: "Container image digest" value: ${{jobs.build.outputs.digest}} + push: branches: - "main" @@ -13,36 +14,20 @@ on: jobs: build: - name: Build + name: Build container image uses: ./.github/workflows/container-image.yml permissions: packages: write + id-token: write with: push-image: true - sign: - runs-on: ubuntu-latest + sbom: + name: Generate SBOM and push them to OCI registry + needs: build + uses: ./.github/workflows/sbom.yml permissions: packages: write id-token: write - needs: build - steps: - - name: Login to GitHub Container Registry - uses: docker/login-action@v2 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - - uses: sigstore/cosign-installer@v3 - - - name: Sign the images - run: | - cosign sign --yes \ - ${{needs.build.outputs.repository}}@${{needs.build.outputs.digest}} - - - name: Sign the SBOM - run: | - tag=$(echo '${{needs.build.outputs.digest}}' | sed 's/:/-/g') - cosign sign --yes \ - "${{needs.build.outputs.repository}}:$tag.sbom" + with: + image-digest: ${{ needs.build.outputs.digest }} diff --git a/.github/workflows/container-image.yml b/.github/workflows/container-image.yml index 619915a5..61ee4da2 100644 --- a/.github/workflows/container-image.yml +++ b/.github/workflows/container-image.yml @@ -6,10 +6,6 @@ on: push-image: type: boolean required: true - generate-sbom: - type: boolean - required: false - default: true outputs: repository: description: "Repository used to build the container image" @@ -29,6 +25,7 @@ jobs: name: Build container image permissions: packages: write + id-token: write runs-on: ubuntu-latest outputs: repository: ${{ steps.setoutput.outputs.repository }} @@ -53,16 +50,8 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Install Golang - uses: actions/setup-go@v4 - with: - go-version: '1.19' - - - name: Install the bom command - uses: kubewarden/github-actions/kubernetes-bom-installer@v2 - - - name: Install Cosign - if: ${{ inputs.generate-sbom == true }} + name: Install cosign + if: ${{ inputs.push-image }} uses: sigstore/cosign-installer@v3 - name: Retrieve tag name (main branch) @@ -91,6 +80,12 @@ jobs: push: true tags: | ghcr.io/${{github.repository_owner}}/kubewarden-controller:${{ env.TAG_NAME }} + - + name: Sign container image + if: ${{ inputs.push-image }} + run: | + cosign sign --yes \ + ghcr.io/${{github.repository_owner}}/kubewarden-controller@${{ steps.build-image.outputs.digest }} - # Only build amd64 because buildx does not allow multiple platforms when # exporting the image to a tarball. As we use this only for end-to-end tests @@ -105,19 +100,6 @@ jobs: outputs: type=docker,dest=/tmp/kubewarden-controller-image-${{ env.TAG_NAME }}.tar tags: | ghcr.io/${{github.repository_owner}}/kubewarden-controller:${{ env.TAG_NAME }} - - - name: Create SBOM file - if: ${{ inputs.generate-sbom == true }} - shell: bash - run: | - bom generate -n https://kubewarden.io/kubewarden.spdx -o kubewarden-controller.spdx . - - - name: Attach SBOM file in the container image - if: ${{ inputs.generate-sbom == true }} - shell: bash - run: | - set -e - cosign attach sbom --sbom kubewarden-controller.spdx "ghcr.io/${{github.repository_owner}}/kubewarden-controller@${{ steps.build-image.outputs.digest }}" - name: Upload container image to use in other jobs if: ${{ inputs.push-image == false }} diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index 6ec8dff3..c0877841 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -16,7 +16,6 @@ jobs: packages: write with: push-image: false - generate-sbom: false run-e2e-tests: name: "Tests" needs: [build] diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ad9c5322..fe147130 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,33 +12,22 @@ jobs: uses: ./.github/workflows/ci.yml permissions: read-all - container-build: + build: + name: Build container image and SBOMs uses: ./.github/workflows/container-build.yml permissions: id-token: write packages: write - release: - permissions: - id-token: write - contents: write - name: Create release + + crds: + name: Build CRDs runs-on: ubuntu-latest - needs: - - ci - - container-build steps: - name: Install Golang uses: actions/setup-go@v4 with: go-version: '1.19' - - name: Install the bom command - shell: bash - run: go install sigs.k8s.io/bom/cmd/bom@v0.2.2 - - - name: Install cosign - uses: sigstore/cosign-installer@v3 - - name: Checkout code uses: actions/checkout@v3 @@ -46,27 +35,32 @@ jobs: run: | make generate-crds tar -czf CRDS.tar.gz -C generated-crds $(ls generated-crds) + - + name: Upload CRDs as artifacts + uses: actions/upload-artifact@v3 + with: + name: CRDS + path: CRDS.tar.gz + + release: + name: Create release + + needs: + - ci + - crds + - build + + permissions: + contents: write + runs-on: ubuntu-latest + + steps: - name: Retrieve tag name if: ${{ startsWith(github.ref, 'refs/tags/') }} run: | echo TAG_NAME=$(echo ${{ github.ref_name }}) >> $GITHUB_ENV - - name: Create SBOM file - shell: bash - run: | - bom generate -n https://kubewarden.io/kubewarden.spdx \ - --image "ghcr.io/${{github.repository_owner}}/kubewarden-controller@${{ needs.container-build.outputs.digest }}" \ - . > kubewarden-controller-sbom.spdx - - - name: Sign BOM file - run: | - cosign sign-blob --yes --output-certificate kubewarden-controller-sbom.spdx.cert \ - --output-signature kubewarden-controller-sbom.spdx.sig \ - kubewarden-controller-sbom.spdx - env: - COSIGN_EXPERIMENTAL: 1 - - name: Get latest release tag id: get_last_release_tag uses: actions/github-script@v6 @@ -100,13 +94,33 @@ jobs: } core.setFailed(`Draft release not found`) + - name: Download SBOM artifact + uses: actions/download-artifact@v3 + with: + name: sbom + + - name: Download CRDs artifact + uses: actions/download-artifact@v3 + with: + name: CRDS + + - name: Display structure of downloaded files + run: ls -R + - name: Upload release assets id: upload_release_assets uses: actions/github-script@v6 with: script: | let fs = require('fs'); - let files = ['kubewarden-controller-sbom.spdx', 'kubewarden-controller-sbom.spdx.cert', 'kubewarden-controller-sbom.spdx.sig', "CRDS.tar.gz"] + let files = [ + 'kubewarden-controller-sbom-amd64.spdx', + 'kubewarden-controller-sbom-amd64.spdx.cert', + 'kubewarden-controller-sbom-amd64.spdx.sig', + 'kubewarden-controller-sbom-arm64.spdx', + 'kubewarden-controller-sbom-arm64.spdx.cert', + 'kubewarden-controller-sbom-arm64.spdx.sig', + "CRDS.tar.gz"] const {RELEASE_ID} = process.env for (const file of files) { diff --git a/.github/workflows/sbom.yml b/.github/workflows/sbom.yml new file mode 100644 index 00000000..38543b8e --- /dev/null +++ b/.github/workflows/sbom.yml @@ -0,0 +1,84 @@ +name: Build container image + +on: + workflow_call: + inputs: + image-digest: + type: string + required: true + +jobs: + sbom: + name: Build SBOM, sign and attach them to OCI image + strategy: + matrix: + arch: [amd64, arm64] + + permissions: + packages: write + id-token: write + + runs-on: ubuntu-latest + steps: + - name: Install cosign + uses: sigstore/cosign-installer@v3 + + - name: Install the syft command + uses: kubewarden/github-actions/syft-installer@v3.1.5 + + - name: Install the crane command + uses: kubewarden/github-actions/crane-installer@v3.1.5 + + - name: Login to GitHub Container Registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Find platform digest + shell: bash + run: | + set -e + DIGEST=$(crane digest \ + --platform "linux/${{ matrix.arch }}" \ + ghcr.io/${{ github.repository_owner }}/kubewarden-controller@${{ inputs.image-digest }}) + echo "PLATFORM_DIGEST=${DIGEST}" >> "$GITHUB_ENV" + + - name: Create SBOM file + shell: bash + run: | + syft \ + -o spdx-json \ + --file kubewarden-controller-sbom-${{ matrix.arch }}.spdx \ + ghcr.io/${{ github.repository_owner }}/kubewarden-controller@${{ env.PLATFORM_DIGEST }} + + - name: Sign SBOM file + run: | + cosign sign-blob --yes \ + --output-certificate kubewarden-controller-sbom-${{ matrix.arch }}.spdx.cert \ + --output-signature kubewarden-controller-sbom-${{ matrix.arch }}.spdx.sig \ + kubewarden-controller-sbom-${{ matrix.arch }}.spdx + + - name: Attach SBOM file in the container image + shell: bash + run: | + cosign attach \ + sbom --sbom kubewarden-controller-sbom-${{ matrix.arch }}.spdx \ + ghcr.io/${{ github.repository_owner }}/kubewarden-controller@${{ env.PLATFORM_DIGEST }} + + - name: Sign SBOM file pushed to OCI registry + shell: bash + run: | + set -e + SBOM_TAG="$(echo ${{ env.PLATFORM_DIGEST }} | sed -e 's/:/-/g').sbom" + + cosign sign --yes \ + ghcr.io/${{github.repository_owner}}/kubewarden-controller:${SBOM_TAG} + + - + name: Upload SBOMs as artifacts + uses: actions/upload-artifact@v3 + with: + name: sbom + path: kubewarden-controller-sbom-* diff --git a/Dockerfile b/Dockerfile index 89a16612..8844e70b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,6 +23,10 @@ RUN CGO_ENABLED=0 GOOS=linux GO111MODULE=on go build -a -o manager . FROM gcr.io/distroless/static:nonroot WORKDIR / COPY --from=builder /workspace/manager . +# Copy the Go Modules manifests - these are used by BOM generators +# and by security scanner +COPY go.mod /go.mod +COPY go.sum /go.sum USER 65532:65532 ENTRYPOINT ["/manager"]