diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3ebd0ec42..da15035db 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -111,6 +111,8 @@ jobs: - test-linux-arm64 - test-windows runs-on: ubuntu-latest + permissions: + id-token: write steps: - uses: actions/checkout@v4 with: @@ -192,20 +194,6 @@ jobs: - name: Set env run: | cat tag.txt >> $GITHUB_ENV - - name: Rename cosign public key - run: | - cp cosign.pub lifecycle-v${{ env.LIFECYCLE_VERSION }}-cosign.pub - - uses: actions/upload-artifact@v3 - with: - name: lifecycle-cosign-public-key - path: lifecycle-v${{ env.LIFECYCLE_VERSION }}-cosign.pub - - name: Calculate cosign sha - run: | - shasum -a 256 lifecycle-v${{ env.LIFECYCLE_VERSION }}-cosign.pub > lifecycle-v${{ env.LIFECYCLE_VERSION }}-cosign.pub.sha256 - - uses: actions/upload-artifact@v3 - with: - name: lifecycle-cosign-public-key-sha256 - path: lifecycle-v${{ env.LIFECYCLE_VERSION }}-cosign.pub.sha256 - name: Publish images if: github.event_name == 'push' run: | @@ -229,11 +217,14 @@ jobs: MANIFEST_SHA=$(docker manifest push buildpacksio/lifecycle:${LIFECYCLE_IMAGE_TAG}) echo "MANIFEST_SHA: $MANIFEST_SHA" - COSIGN_PASSWORD=${{ secrets.COSIGN_PASSWORD }} cosign sign -r --tlog-upload=false \ - --key <(echo -n "${{ secrets.COSIGN_PRIVATE_KEY }}" | base64 --decode) \ + cosign sign -r -y \ -a tag=${LIFECYCLE_IMAGE_TAG} \ buildpacksio/lifecycle:${LIFECYCLE_IMAGE_TAG}@${MANIFEST_SHA} - cosign verify --insecure-ignore-tlog=true --key cosign.pub -a tag=${LIFECYCLE_IMAGE_TAG} buildpacksio/lifecycle:${LIFECYCLE_IMAGE_TAG} + cosign verify \ + --certificate-identity-regexp "https://github.com/${{ github.repository_owner }}/lifecycle/.github/workflows/build.yml" \ + --certificate-oidc-issuer https://token.actions.githubusercontent.com \ + -a tag=${LIFECYCLE_IMAGE_TAG} \ + buildpacksio/lifecycle:${LIFECYCLE_IMAGE_TAG} - name: Scan image if: github.event_name == 'push' uses: anchore/scan-action@v3 diff --git a/.github/workflows/draft-release.yml b/.github/workflows/draft-release.yml index 6863989d1..7406533c7 100644 --- a/.github/workflows/draft-release.yml +++ b/.github/workflows/draft-release.yml @@ -6,6 +6,8 @@ on: jobs: draft-release: runs-on: ubuntu-latest + permissions: + contents: write steps: - uses: actions/checkout@v4 - name: Install jq @@ -80,8 +82,8 @@ jobs: if (urlList.length === 0) { throw "no artifacts found" } - if (urlList.length != 10) { - throw "there should be exactly ten artifacts" + if (urlList.length != 8) { + throw "there should be exactly 8 artifacts" } return urlList.join(",") }) diff --git a/.github/workflows/post-release.yml b/.github/workflows/post-release.yml index 941202e05..442f06a19 100644 --- a/.github/workflows/post-release.yml +++ b/.github/workflows/post-release.yml @@ -8,6 +8,8 @@ on: jobs: retag-lifecycle-images: runs-on: ubuntu-latest + permissions: + id-token: write steps: - uses: actions/checkout@v4 - name: Setup go @@ -30,15 +32,15 @@ jobs: echo "LIFECYCLE_IMAGE_TAG=$(git describe --always --abbrev=7)" >> $GITHUB_ENV - name: Verify lifecycle images run: | - LINUX_AMD64_SHA=$(cosign verify -key cosign.pub buildpacksio/lifecycle:${{ env.LIFECYCLE_IMAGE_TAG }}-linux-x86-64 | jq -r .[0].critical.image.\"docker-manifest-digest\") + LINUX_AMD64_SHA=$(cosign verify --certificate-identity-regexp "https://github.com/${{ github.repository_owner }}/lifecycle/.github/workflows/build.yml" --certificate-oidc-issuer https://token.actions.githubusercontent.com buildpacksio/lifecycle:${{ env.LIFECYCLE_IMAGE_TAG }}-linux-x86-64 | jq -r .[0].critical.image.\"docker-manifest-digest\") echo "LINUX_AMD64_SHA: $LINUX_AMD64_SHA" echo "LINUX_AMD64_SHA=$LINUX_AMD64_SHA" >> $GITHUB_ENV - LINUX_ARM64_SHA=$(cosign verify -key cosign.pub buildpacksio/lifecycle:${{ env.LIFECYCLE_IMAGE_TAG }}-linux-arm64 | jq -r .[0].critical.image.\"docker-manifest-digest\") + LINUX_ARM64_SHA=$(cosign verify --certificate-identity-regexp "https://github.com/${{ github.repository_owner }}/lifecycle/.github/workflows/build.yml" --certificate-oidc-issuer https://token.actions.githubusercontent.com buildpacksio/lifecycle:${{ env.LIFECYCLE_IMAGE_TAG }}-linux-arm64 | jq -r .[0].critical.image.\"docker-manifest-digest\") echo "LINUX_ARM64_SHA: $LINUX_ARM64_SHA" echo "LINUX_ARM64_SHA=$LINUX_ARM64_SHA" >> $GITHUB_ENV - WINDOWS_AMD64_SHA=$(cosign verify -key cosign.pub buildpacksio/lifecycle:${{ env.LIFECYCLE_IMAGE_TAG }}-windows | jq -r .[0].critical.image.\"docker-manifest-digest\") + WINDOWS_AMD64_SHA=$(cosign verify --certificate-identity-regexp "https://github.com/${{ github.repository_owner }}/lifecycle/.github/workflows/build.yml" --certificate-oidc-issuer https://token.actions.githubusercontent.com buildpacksio/lifecycle:${{ env.LIFECYCLE_IMAGE_TAG }}-windows | jq -r .[0].critical.image.\"docker-manifest-digest\") echo "WINDOWS_AMD64_SHA: $WINDOWS_AMD64_SHA" echo "WINDOWS_AMD64_SHA=$WINDOWS_AMD64_SHA" >> $GITHUB_ENV - name: Download SBOM @@ -62,18 +64,24 @@ jobs: MANIFEST_SHA=$(docker manifest push buildpacksio/lifecycle:${{ env.LIFECYCLE_VERSION }}) echo "MANIFEST_SHA: $MANIFEST_SHA" - COSIGN_PASSWORD=${{ secrets.COSIGN_PASSWORD }} cosign sign -r \ - -key <(echo -n "${{ secrets.COSIGN_PRIVATE_KEY }}" | base64 --decode) \ + cosign sign -r -y \ -a tag=${{ env.LIFECYCLE_VERSION }} \ buildpacksio/lifecycle:${{ env.LIFECYCLE_VERSION }}@${MANIFEST_SHA} - cosign verify -key cosign.pub -a tag=${{ env.LIFECYCLE_VERSION }} buildpacksio/lifecycle:${{ env.LIFECYCLE_VERSION }} + cosign verify \ + --certificate-identity-regexp "https://github.com/${{ github.repository_owner }}/lifecycle/.github/workflows/post-release.yml" \ + --certificate-oidc-issuer https://token.actions.githubusercontent.com \ + -a tag=${{ env.LIFECYCLE_VERSION }} \ + buildpacksio/lifecycle:${{ env.LIFECYCLE_VERSION }} - cosign attach sbom -sbom ./*-bom.cdx.json -type cyclonedx buildpacksio/lifecycle:${{ env.LIFECYCLE_VERSION }} - COSIGN_PASSWORD=${{ secrets.COSIGN_PASSWORD }} cosign sign -r \ - -key <(echo -n "${{ secrets.COSIGN_PRIVATE_KEY }}" | base64 --decode) \ - -a tag=${{ env.LIFECYCLE_VERSION }} -attachment sbom \ + cosign attach sbom --sbom ./*-bom.cdx.json --type cyclonedx buildpacksio/lifecycle:${{ env.LIFECYCLE_VERSION }} + cosign sign -r -y \ + -a tag=${{ env.LIFECYCLE_VERSION }} --attachment sbom \ buildpacksio/lifecycle:${{ env.LIFECYCLE_VERSION }}@${MANIFEST_SHA} - cosign verify -key cosign.pub -a tag=${{ env.LIFECYCLE_VERSION }} -attachment sbom buildpacksio/lifecycle:${{ env.LIFECYCLE_VERSION }}@${MANIFEST_SHA} + cosign verify \ + --certificate-identity-regexp "https://github.com/${{ github.repository_owner }}/lifecycle/.github/workflows/post-release.yml" \ + --certificate-oidc-issuer https://token.actions.githubusercontent.com \ + -a tag=${{ env.LIFECYCLE_VERSION }} --attachment sbom \ + buildpacksio/lifecycle:${{ env.LIFECYCLE_VERSION }} - name: Retag lifecycle images & create manifest list - latest if: "!contains(env.LIFECYCLE_VERSION, 'rc') && !contains(env.LIFECYCLE_VERSION, 'pre')" run: | @@ -91,15 +99,21 @@ jobs: MANIFEST_SHA=$(docker manifest push buildpacksio/lifecycle:latest) echo "MANIFEST_SHA: $MANIFEST_SHA" - COSIGN_PASSWORD=${{ secrets.COSIGN_PASSWORD }} cosign sign -r \ - -key <(echo -n "${{ secrets.COSIGN_PRIVATE_KEY }}" | base64 --decode) \ + cosign sign -r -y \ -a tag=latest \ buildpacksio/lifecycle:latest@${MANIFEST_SHA} - cosign verify -key cosign.pub -a tag=latest buildpacksio/lifecycle:latest + cosign verify \ + --certificate-identity-regexp "https://github.com/${{ github.repository_owner }}/lifecycle/.github/workflows/post-release.yml" \ + --certificate-oidc-issuer https://token.actions.githubusercontent.com \ + -a tag=latest \ + buildpacksio/lifecycle:latest - cosign attach sbom -sbom ./*-bom.cdx.json -type cyclonedx buildpacksio/lifecycle:latest - COSIGN_PASSWORD=${{ secrets.COSIGN_PASSWORD }} cosign sign -r \ - -key <(echo -n "${{ secrets.COSIGN_PRIVATE_KEY }}" | base64 --decode) \ - -a tag=${{ env.LIFECYCLE_VERSION }} -attachment sbom \ + cosign attach sbom --sbom ./*-bom.cdx.json --type cyclonedx buildpacksio/lifecycle:latest + cosign sign -r -y \ + -a tag=${{ env.LIFECYCLE_VERSION }} --attachment sbom \ buildpacksio/lifecycle:latest@${MANIFEST_SHA} - cosign verify -key cosign.pub -a tag=${{ env.LIFECYCLE_VERSION }} -attachment sbom buildpacksio/lifecycle:latest@${MANIFEST_SHA} + cosign verify \ + --certificate-identity-regexp "https://github.com/${{ github.repository_owner }}/lifecycle/.github/workflows/post-release.yml" \ + --certificate-oidc-issuer https://token.actions.githubusercontent.com \ + -a tag=${{ env.LIFECYCLE_VERSION }} --attachment sbom \ + buildpacksio/lifecycle:latest diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index d35027db9..3dffd06ea 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -47,20 +47,18 @@ The lifecycle release process involves chaining a series of GitHub actions together such that: * The "build" workflow creates the artifacts - * .tgz files containing the lifecycle binaries, shasums for the .tgz files, a cosign public key, an SBOM, etc. + * .tgz files containing the lifecycle binaries, shasums for the .tgz files, an SBOM, etc. * OCI images containing the lifecycle binaries, tagged with their commit sha (for more information, see RELEASE.md) * The "draft-release" workflow finds the artifacts and downloads them, creating the draft release * The "post-release" workflow re-tags the OCI images that were created during the "build" workflow with the release version It can be rather cumbersome to test changes to these workflows, as they are heavily intertwined. Thus we recommend forking the buildpacks/lifecycle repository in GitHub and running through the entire release process end-to-end. For the fork, it is necessary to add the following secrets: -* COSIGN_PASSWORD (see [cosign](https://github.com/sigstore/cosign#generate-a-keypair)) -* COSIGN_PRIVATE_KEY * DOCKER_PASSWORD (if not using ghcr.io) * DOCKER_USERNAME (if not using ghcr.io) The tools/test-fork.sh script can be used to update the source code to reflect the state of the fork. -It can be invoked like so: `./tools/test-fork.sh ` +It can be invoked like so: `./tools/test-fork.sh ` ## Tasks diff --git a/IMAGE.md b/IMAGE.md index d3ab324c2..83a810fdd 100644 --- a/IMAGE.md +++ b/IMAGE.md @@ -12,18 +12,24 @@ Supported tags are semver-versioned manifest lists - e.g., `0.12.0` or `0.12.0-r # About this image Images are built in [GitHub actions](https://github.com/buildpacks/lifecycle/actions) and signed with [`cosign`](https://github.com/sigstore/cosign). To verify: -* Locate the public key `lifecycle-v-cosign.pub` on the [releases page](https://github.com/buildpacks/lifecycle/releases) * Run: ``` -cosign verify -key lifecycle-v-cosign.pub buildpacksio/lifecycle: +cosign version # must be at least 2.0.0 +cosign verify \ + --certificate-identity-regexp "https://github.com/buildpacks/lifecycle/.github/workflows/post-release.yml" \ + --certificate-oidc-issuer https://token.actions.githubusercontent.com \ + buildpacksio/lifecycle: ``` A CycloneDX SBOM is "attached" to the image and signed with [`cosign`](https://github.com/sigstore/cosign). To verify: -* Locate the public key `lifecycle-v-cosign.pub` on the [releases page](https://github.com/buildpacks/lifecycle/releases) * Run: ``` -cosign version # must be at least 1.2.0 -cosign verify -key cosign.pub -a tag= -attachment sbom buildpacksio/lifecycle: +cosign version # must be at least 2.0.0 +cosign verify \ + --certificate-identity-regexp "https://github.com/buildpacks/lifecycle/.github/workflows/post-release.yml" \ + --certificate-oidc-issuer https://token.actions.githubusercontent.com \ + -a tag= -attachment sbom \ + buildpacksio/lifecycle: cosign download sbom buildpacksio/lifecycle: ``` diff --git a/cosign.pub b/cosign.pub deleted file mode 100644 index 32522007e..000000000 --- a/cosign.pub +++ /dev/null @@ -1,5 +0,0 @@ ------BEGIN PUBLIC KEY----- -MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEVHkU6XfpwHxNLpqvPOWrGBvwQuN5 -YftzwwYnvdxnu5aoCnkfOpLks+3r+tQQRbcjHsgZr/HjSFFiia5WAwNq4Q== ------END PUBLIC KEY----- - diff --git a/tools/test-fork.sh b/tools/test-fork.sh index f7deb1e3e..a4273e295 100755 --- a/tools/test-fork.sh +++ b/tools/test-fork.sh @@ -1,8 +1,7 @@ #!/bin/bash # $1 - registry repo name -# $2 - path to cosign public key -# $3 - enable tests +# $2 - enable tests echo "Parse registry: $1" firstPart=$(echo $1 | cut -d/ -f1) @@ -42,14 +41,11 @@ if [[ $registry == *"ghcr.io"* ]]; then sed -i '' "s/secrets.DOCKER_PASSWORD/secrets.GITHUB_TOKEN/g" .github/workflows/*.yml fi -echo "Using public key from fork (assumes base-64 encoded COSIGN_PRIVATE_KEY and COSIGN_PASSWORD have been added to GitHub secrets)" -cp $2 cosign.pub - echo "Removing arm tests (these require a self-hosted runner)" sed -i '' "/test-linux-arm64:/,+14d" .github/workflows/build.yml sed -i '' "/test-linux-arm64/d" .github/workflows/build.yml -if [[ -z $3 ]]; then +if [[ -z $2 ]]; then echo "Removing all tests to make things faster" sed -i '' "s/make test/echo test/g" .github/workflows/*.yml sed -i '' "s/make acceptance/echo acceptance/g" .github/workflows/*.yml