diff --git a/.github/workflows/bake.yaml b/.github/workflows/bake.yaml index a32ca278..51524f98 100644 --- a/.github/workflows/bake.yaml +++ b/.github/workflows/bake.yaml @@ -12,6 +12,10 @@ on: - production default: testing description: "Choose the environment to bake the images for" + target: + type: string + default: "" + description: "A comma separated list of targets to build. If empty, all targets will be built." jobs: # Start by building images for testing. We want to run security checks before pushing those to production. @@ -22,6 +26,8 @@ jobs: contents: read packages: write security-events: write + # Required by the cosign step + id-token: write outputs: metadata: ${{ steps.build.outputs.metadata }} images: ${{ steps.images.outputs.images }} @@ -55,6 +61,7 @@ jobs: revision: ${{ github.sha }} with: push: true + targets: ${{ github.event.inputs.target }} # Get a list of the images that were built and pushed. We only care about a single tag for each image. - name: Generated images @@ -62,6 +69,18 @@ jobs: run: | echo "images=$(echo '${{ steps.build.outputs.metadata }}' | jq -c '[ .[]."image.name" | sub(",.*";"") ]')" >> "$GITHUB_OUTPUT" + # Even if we're testing we sign the images, so we can push them to production later if that's required + - name: Install cosign + uses: sigstore/cosign-installer@v3 + # See https://github.blog/security/supply-chain-security/safeguard-container-signing-capability-actions/ + # and https://github.com/actions/starter-workflows/blob/main/ci/docker-publish.yml for more details on + # how to use cosign. + - name: Sign images + run: | + echo '${{ steps.build.outputs.metadata }}' | \ + jq '.[] | (."image.name" | sub(",.*";"" )) + "@" + ."containerimage.digest"' | \ + xargs cosign sign --yes + security: name: Security checks runs-on: ubuntu-latest @@ -144,3 +163,15 @@ jobs: revision: ${{ github.sha }} with: push: true + + - name: Install cosign + uses: sigstore/cosign-installer@v3 + # See https://github.blog/security/supply-chain-security/safeguard-container-signing-capability-actions/ + # and https://github.com/actions/starter-workflows/blob/main/ci/docker-publish.yml for more details on + # how to use cosign. + - name: Sign images + run: | + images=$(echo '${{ steps.build.outputs.metadata }}' | + jq '.[] | (."image.name" | sub(",.*";"" )) + "@" + ."containerimage.digest"' + ) + cosign sign --yes ${images} diff --git a/BUILD.md b/BUILD.md index 4e4f5343..722c82a0 100644 --- a/BUILD.md +++ b/BUILD.md @@ -122,6 +122,13 @@ docker run -d --rm -p 5000:5000 --name registry registry:2 This command runs a lightweight, temporary instance of the `registry:2` container on port `5000`. +## Image Signing Workflow + +Postgres operand images are securely signed with [cosign](https://github.com/sigstore/cosign) +based on their digest through a GitHub workflow, using the +[`cosign-installer` action](https://github.com/marketplace/actions/cosign-installer), which leverages +[short-lived tokens issued through OpenID Connect](https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/about-security-hardening-with-openid-connect). + ## Trademarks *[Postgres, PostgreSQL and the Slonik Logo](https://www.postgresql.org/about/policies/trademarks/) diff --git a/README.md b/README.md index 0c3ecf23..5e1fea6a 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,29 @@ docker buildx imagetools inspect --format "{{ json .SBOM.SPDX }}" This command outputs the SBOM in JSON format, providing a detailed view of the software components and build dependencies. +## Image Signatures + +CloudNativePG container images are securely signed using +[cosign](https://github.com/sigstore/cosign), a tool within the +[Sigstore](https://www.sigstore.dev/) ecosystem. +This signing process is automated via GitHub Actions and leverages +[short-lived tokens issued through OpenID Connect](https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/about-security-hardening-with-openid-connect). + +The token issuer is `https://token.actions.githubusercontent.com`, and the +signing identity corresponds to a GitHub workflow executed under the +`cloudnative-pg/postgres-containers` repository. This workflow uses the +[`cosign-installer` action](https://github.com/marketplace/actions/cosign-installer) +to facilitate the signing process. + +To verify the authenticity of an image using its digest, you can run the +following `cosign` command: + +```sh +cosign verify IMAGE \ + --certificate-identity-regexp="^https://github.com/cloudnative-pg/postgres-containers/" \ + --certificate-oidc-issuer="https://token.actions.githubusercontent.com" +``` + ## Building Images For detailed instructions on building PostgreSQL container images, refer to the