From 50c7f71f69c09e76a7ac6ed3190f626475cd5287 Mon Sep 17 00:00:00 2001 From: Diogo Teles Sant'Anna Date: Mon, 26 Sep 2022 12:07:30 -0300 Subject: [PATCH 01/13] feat: split release workflows into different jobs with different permissions Signed-off-by: Diogo Teles Sant'Anna --- .github/workflows/release.yml | 164 +++++++++++++++++++--------------- 1 file changed, 94 insertions(+), 70 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 38c7f0861..6408cc5e3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,78 +1,102 @@ +name: Release + on: release: types: - published -name: release - -permissions: - # Needed to access the workflow's OIDC identity. - id-token: write - - # Needed to upload release assets. - contents: write - jobs: - pypi: - name: Build, sign and publish release to PyPI + build: + name: Build and sign artifacts runs-on: ubuntu-latest + permissions: + id-token: write steps: - - uses: actions/checkout@d171c3b028d844f2bf14e9fdec0c58114451e4bf - - - uses: actions/setup-python@7f80679172b057fc5e90d70d197929d454754a5a - - - name: deps - run: python -m pip install -U build - - - name: build - run: python -m build - - - name: sign - run: | - mkdir -p smoketest-artifacts - - # we smoke-test sigstore by installing each of the distributions - # we've built in a fresh environment and using each to sign and - # verify for itself, using the ambient OIDC identity - for dist in dist/*; do - dist_base="$(basename "${dist}")" - - python -m venv smoketest-env - - ./smoketest-env/bin/python -m pip install "${dist}" - - # NOTE: signing artifacts currently go in a separate directory, - # to avoid confusing the package uploader (which otherwise tries - # to upload them to PyPI and fails). Future versions of twine - # and the gh-action-pypi-publish action should support these artifacts. - ./smoketest-env/bin/python -m \ - sigstore sign "${dist}" \ - --output-signature smoketest-artifacts/"${dist_base}.sig" \ - --output-certificate smoketest-artifacts/"${dist_base}.crt" - - ./smoketest-env/bin/python -m \ - sigstore verify "${dist}" \ - --cert "smoketest-artifacts/${dist_base}.crt" \ - --signature "smoketest-artifacts/${dist_base}.sig" \ - --cert-oidc-issuer https://token.actions.githubusercontent.com \ - - rm -rf smoketest-env - done - - - name: publish - uses: pypa/gh-action-pypi-publish@717ba43cfbb0387f6ce311b169a825772f54d295 - with: - user: __token__ - password: ${{ secrets.PYPI_TOKEN }} - - - name: upload artifacts to github - # Confusingly, this action also supports updating releases, not - # just creating them. This is what we want here, since we've manually - # created the release that triggered the action. - uses: softprops/action-gh-release@v1 - with: - # dist/ contains the built packages, which smoketest-artifacts/ - # contains the signatures and certificates. - files: | - dist/* - smoketest-artifacts/* + - uses: actions/checkout@d171c3b028d844f2bf14e9fdec0c58114451e4bf + + - uses: actions/setup-python@7f80679172b057fc5e90d70d197929d454754a5a + + - name: deps + run: python -m pip install -U build + + - name: build + run: python -m build + + - name: sign + run: | + mkdir -p smoketest-artifacts + # we smoke-test sigstore by installing each of the distributions + # we've built in a fresh environment and using each to sign and + # verify for itself, using the ambient OIDC identity + for dist in dist/*; do + dist_base="$(basename "${dist}")" + python -m venv smoketest-env + ./smoketest-env/bin/python -m pip install "${dist}" + # NOTE: signing artifacts currently go in a separate directory, + # to avoid confusing the package uploader (which otherwise tries + # to upload them to PyPI and fails). Future versions of twine + # and the gh-action-pypi-publish action should support these artifacts. + ./smoketest-env/bin/python -m \ + sigstore sign "${dist}" \ + --output-signature smoketest-artifacts/"${dist_base}.sig" \ + --output-certificate smoketest-artifacts/"${dist_base}.crt" + ./smoketest-env/bin/python -m \ + sigstore verify "${dist}" \ + --cert "smoketest-artifacts/${dist_base}.crt" \ + --signature "smoketest-artifacts/${dist_base}.sig" \ + --cert-oidc-issuer https://token.actions.githubusercontent.com \ + rm -rf smoketest-env + done + + - name: Upload built packages + uses: actions/upload-artifact@v3 + with: + name: built-packages + path: ./dist/ + if-no-files-found: warn + + - name: Upload smoketest-artifacts + uses: actions/upload-artifact@v3 + with: + name: smoketest-artifacts + path: smoketest-artifacts/ + if-no-files-found: warn + + release-pypi: + needs: [build] + runs-on: ubuntu-latest + permissions: + id-token: write + steps: + - name: Download artifacts diretories # goes to current working directory + uses: actions/download-artifact@v3 + with: + name: built-packages + + - name: publish + uses: pypa/gh-action-pypi-publish@717ba43cfbb0387f6ce311b169a825772f54d295 + with: + user: __token__ + password: ${{ secrets.PYPI_TOKEN }} + packages_dir: built-packages/ + + release-github: + needs: [build] + runs-on: ubuntu-latest + permissions: + # Needed to upload release assets. + contents: write + steps: + - name: Download artifacts diretories # goes to current working directory + uses: actions/download-artifact@v3 + + - name: Upload artifacts to github + # Confusingly, this action also supports updating releases, not + # just creating them. This is what we want here, since we've manually + # created the release that triggered the action. + uses: softprops/action-gh-release@v1 + with: + # smoketest-artifacts/ contains the signatures and certificates. + files: | + built-packages/* + smoketest-artifacts/* From 88583f09027aa579ed17a21ba0b127465db9efee Mon Sep 17 00:00:00 2001 From: Diogo Teles Sant'Anna Date: Mon, 26 Sep 2022 13:48:34 -0300 Subject: [PATCH 02/13] feat: add workflow_dispatch trigger for release action Signed-off-by: Diogo Teles Sant'Anna --- .github/workflows/release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6408cc5e3..eb96e9abf 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,6 +1,7 @@ name: Release on: + workflow_dispatch: release: types: - published From 9926aa6c6c04d8e0dc91e8bd78a60d749e33740c Mon Sep 17 00:00:00 2001 From: Diogo Teles Sant'Anna Date: Mon, 26 Sep 2022 13:53:40 -0300 Subject: [PATCH 03/13] feat: add provenance generation to release workflow Signed-off-by: Diogo Teles Sant'Anna --- .github/workflows/release.yml | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index eb96e9abf..887a3e24a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,6 +12,8 @@ jobs: runs-on: ubuntu-latest permissions: id-token: write + outputs: + hashes: ${{ steps.hash.outputs.hashes }} steps: - uses: actions/checkout@d171c3b028d844f2bf14e9fdec0c58114451e4bf @@ -49,6 +51,15 @@ jobs: rm -rf smoketest-env done + - name: Generate hashes for provenance + shell: bash + id: hash + run: | + # sha256sum generates sha256 hash for all artifacts. + # base64 -w0 encodes to base64 and outputs on a single line. + # sha256sum artifact1 artifact2 ... | base64 -w0 + echo "::set-output name=hashes::$(sha256sum ./dist/* | base64 -w0)" + - name: Upload built packages uses: actions/upload-artifact@v3 with: @@ -63,8 +74,21 @@ jobs: path: smoketest-artifacts/ if-no-files-found: warn - release-pypi: + generate-provenance: needs: [build] + name: Generate build provenance + permissions: + actions: read # To read the workflow path. + id-token: write # To sign the provenance. + contents: write # To add assets to a release. + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.2.0 + with: + attestation-name: sigstore-python-provenance.intoto.jsonl + base64-subjects: "${{ needs.build.outputs.hashes }}" + upload-assets: true + + release-pypi: + needs: [build, generate-provenance] runs-on: ubuntu-latest permissions: id-token: write @@ -82,7 +106,7 @@ jobs: packages_dir: built-packages/ release-github: - needs: [build] + needs: [build, generate-provenance] runs-on: ubuntu-latest permissions: # Needed to upload release assets. From ba053800ab21f2e4983b15ebc9c5913d092e6801 Mon Sep 17 00:00:00 2001 From: Diogo Teles Sant'Anna Date: Mon, 26 Sep 2022 14:01:08 -0300 Subject: [PATCH 04/13] fix: wrong line breaking on sign step of release Signed-off-by: Diogo Teles Sant'Anna --- .github/workflows/release.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 887a3e24a..052ab12c9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,13 +28,17 @@ jobs: - name: sign run: | mkdir -p smoketest-artifacts + # we smoke-test sigstore by installing each of the distributions # we've built in a fresh environment and using each to sign and # verify for itself, using the ambient OIDC identity for dist in dist/*; do dist_base="$(basename "${dist}")" + python -m venv smoketest-env + ./smoketest-env/bin/python -m pip install "${dist}" + # NOTE: signing artifacts currently go in a separate directory, # to avoid confusing the package uploader (which otherwise tries # to upload them to PyPI and fails). Future versions of twine @@ -43,11 +47,13 @@ jobs: sigstore sign "${dist}" \ --output-signature smoketest-artifacts/"${dist_base}.sig" \ --output-certificate smoketest-artifacts/"${dist_base}.crt" + ./smoketest-env/bin/python -m \ sigstore verify "${dist}" \ --cert "smoketest-artifacts/${dist_base}.crt" \ --signature "smoketest-artifacts/${dist_base}.sig" \ - --cert-oidc-issuer https://token.actions.githubusercontent.com \ + --cert-oidc-issuer https://token.actions.githubusercontent.com + rm -rf smoketest-env done From ef17cc599cd80e23cbe2e42ec9a95a00bfb7be30 Mon Sep 17 00:00:00 2001 From: Diogo Teles Sant'Anna Date: Mon, 26 Sep 2022 14:11:07 -0300 Subject: [PATCH 05/13] docs: update README to add SLSA 3 badge and instructions to verify build provenance Signed-off-by: Diogo Teles Sant'Anna --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index a236598a5..945de30c4 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ sigstore-python ![CI](https://github.com/sigstore/sigstore-python/workflows/CI/badge.svg) [![PyPI version](https://badge.fury.io/py/sigstore.svg)](https://pypi.org/project/sigstore) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/sigstore/sigstore-python/badge)](https://api.securityscorecards.dev/projects/github.com/sigstore/sigstore-python) +[![SLSA](https://slsa.dev/images/gh-badge-level3.svg)](https://slsa.dev/) ⚠️ This project is not ready for general-purpose use! ⚠️ @@ -305,6 +306,12 @@ Everyone interacting with this project is expected to follow the Should you discover any security issues, please refer to sigstore's [security process](https://github.com/sigstore/.github/blob/main/SECURITY.md). +### SLSA Provenance +This project emits a SLSA provenance on it's release! This enables you to verify the integrity +of the downloaded artifacts and ensured that the binary's code really comes from this source code. +To do so, please follow the instructions [here](https://github.com/urllib3/urllib3/blob/main/.github/workflows/publish.yml). + + ## Info `sigstore-python` is developed as part of the [`sigstore`](https://sigstore.dev) project. From 055231a7e81965842bed7d34b5bfa50cba1d2c64 Mon Sep 17 00:00:00 2001 From: Diogo Teles Sant'Anna Date: Mon, 26 Sep 2022 14:22:08 -0300 Subject: [PATCH 06/13] fix: issue downloading artifacts for release on pypi Signed-off-by: Diogo Teles Sant'Anna --- .github/workflows/release.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 052ab12c9..8b5dbbd6a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -56,7 +56,7 @@ jobs: rm -rf smoketest-env done - + - name: Generate hashes for provenance shell: bash id: hash @@ -65,7 +65,7 @@ jobs: # base64 -w0 encodes to base64 and outputs on a single line. # sha256sum artifact1 artifact2 ... | base64 -w0 echo "::set-output name=hashes::$(sha256sum ./dist/* | base64 -w0)" - + - name: Upload built packages uses: actions/upload-artifact@v3 with: @@ -101,8 +101,6 @@ jobs: steps: - name: Download artifacts diretories # goes to current working directory uses: actions/download-artifact@v3 - with: - name: built-packages - name: publish uses: pypa/gh-action-pypi-publish@717ba43cfbb0387f6ce311b169a825772f54d295 From a271a40722c607b4b656441004118c68a95a4fb2 Mon Sep 17 00:00:00 2001 From: Diogo Teles Sant'Anna Date: Mon, 26 Sep 2022 14:43:00 -0300 Subject: [PATCH 07/13] Revert "feat: add workflow_dispatch trigger for release action" This reverts commit 88583f09027aa579ed17a21ba0b127465db9efee. --- .github/workflows/release.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8b5dbbd6a..69038e104 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,7 +1,6 @@ name: Release on: - workflow_dispatch: release: types: - published From beee99d0c8018ccda6f02bb3249ebb8c7302273f Mon Sep 17 00:00:00 2001 From: Diogo Teles Sant'Anna Date: Mon, 26 Sep 2022 17:09:04 -0300 Subject: [PATCH 08/13] fix: wrong URL being reffered on README On the instructions on how to verify the provenance, we were reffering to the instructions on how to do so, but linking to the wrong URL. Signed-off-by: Diogo Teles Sant'Anna --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 945de30c4..ed5d8a381 100644 --- a/README.md +++ b/README.md @@ -309,7 +309,7 @@ process](https://github.com/sigstore/.github/blob/main/SECURITY.md). ### SLSA Provenance This project emits a SLSA provenance on it's release! This enables you to verify the integrity of the downloaded artifacts and ensured that the binary's code really comes from this source code. -To do so, please follow the instructions [here](https://github.com/urllib3/urllib3/blob/main/.github/workflows/publish.yml). +To do so, please follow the instructions [here](https://github.com/slsa-framework/slsa-github-generator#verification-of-provenance). ## Info From 009ac66c91fd9d4f45166d6c43c1cd0349730d4a Mon Sep 17 00:00:00 2001 From: Diogo Teles Sant'Anna Date: Mon, 26 Sep 2022 17:19:48 -0300 Subject: [PATCH 09/13] feat: change provenance name to have the version number Signed-off-by: Diogo Teles Sant'Anna --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 69038e104..6ace7a01d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -88,7 +88,7 @@ jobs: contents: write # To add assets to a release. uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.2.0 with: - attestation-name: sigstore-python-provenance.intoto.jsonl + attestation-name: provenance-sigstore-${{ github.event.release.tag_name }}.intoto.jsonl base64-subjects: "${{ needs.build.outputs.hashes }}" upload-assets: true From 3c59263f556aeade99e8e08255e7cf1900e221d1 Mon Sep 17 00:00:00 2001 From: Diogo Teles Sant'Anna Date: Tue, 27 Sep 2022 13:57:45 -0300 Subject: [PATCH 10/13] feat: remove unnecessary permission on job workflow On release-pypi job on release workflow, the token-id permission was set to "write", but it's not necessary and was removed. Signed-off-by: Diogo Teles Sant'Anna --- .github/workflows/release.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6ace7a01d..b7149a7a0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -95,8 +95,7 @@ jobs: release-pypi: needs: [build, generate-provenance] runs-on: ubuntu-latest - permissions: - id-token: write + permissions: {} steps: - name: Download artifacts diretories # goes to current working directory uses: actions/download-artifact@v3 From 74f678be4ba95bb4c106f20cbdd5637a89d481c7 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Tue, 27 Sep 2022 15:33:54 -0400 Subject: [PATCH 11/13] Update README.md Signed-off-by: William Woodruff --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ed5d8a381..cd56385f3 100644 --- a/README.md +++ b/README.md @@ -307,7 +307,7 @@ Should you discover any security issues, please refer to sigstore's [security process](https://github.com/sigstore/.github/blob/main/SECURITY.md). ### SLSA Provenance -This project emits a SLSA provenance on it's release! This enables you to verify the integrity +This project emits a SLSA provenance on its release! This enables you to verify the integrity of the downloaded artifacts and ensured that the binary's code really comes from this source code. To do so, please follow the instructions [here](https://github.com/slsa-framework/slsa-github-generator#verification-of-provenance). From 8fbd1d758e6e617bd949993469bec327f50aae4f Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Tue, 27 Sep 2022 15:34:02 -0400 Subject: [PATCH 12/13] Update README.md Signed-off-by: William Woodruff --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index cd56385f3..56abf4a4f 100644 --- a/README.md +++ b/README.md @@ -309,6 +309,7 @@ process](https://github.com/sigstore/.github/blob/main/SECURITY.md). ### SLSA Provenance This project emits a SLSA provenance on its release! This enables you to verify the integrity of the downloaded artifacts and ensured that the binary's code really comes from this source code. + To do so, please follow the instructions [here](https://github.com/slsa-framework/slsa-github-generator#verification-of-provenance). From 574756259206c104bec644ce730a7095e1eb2d50 Mon Sep 17 00:00:00 2001 From: Diogo Teles Sant'Anna Date: Wed, 28 Sep 2022 13:24:24 -0300 Subject: [PATCH 13/13] docs: explain why not using hash pinning in a GHA Because of a demand of SLSA Generator, their action cannot be used through pinned hashing. As using tags goes agains the best practices, I'm letting explicit the reason why we are using them. Signed-off-by: Diogo Teles Sant'Anna --- .github/workflows/release.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b7149a7a0..62e090d35 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -86,6 +86,8 @@ jobs: actions: read # To read the workflow path. id-token: write # To sign the provenance. contents: write # To add assets to a release. + # Currently this action needs to be referred by tag. More details at: + # https://github.com/slsa-framework/slsa-github-generator#verification-of-provenance uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.2.0 with: attestation-name: provenance-sigstore-${{ github.event.release.tag_name }}.intoto.jsonl