Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SLSA provenance generator to release; closes #222 #223

Merged
merged 14 commits into from
Sep 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
193 changes: 123 additions & 70 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,78 +1,131 @@
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
outputs:
hashes: ${{ steps.hash.outputs.hashes }}
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: 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:
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

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.
# 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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nonblocking: for consistency with the other actions in this workflow, we should probably use a hash rev instead of a symbolic (tag) rev.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, let's update this.

Copy link
Contributor

@laurentsimon laurentsimon Sep 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hash is not supported for the builder, due to a lack of GH support to map a hash to a branch. This is an intentional design decision we have made. We aim to change that once the relevant GitHub support is there. See the reasoning at slsa-framework/slsa-verifier#12

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that it would maintain the consistency and also follow the best practice rules, but currently SLSA generator does not support hash pinning, although there already is an issue about that. More details here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However I think it would be a good idea to add a comment on code explaining this decision, because it's indeed contradictory and more people can question that. Will work on it

Copy link
Contributor

@laurentsimon laurentsimon Sep 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1, with a link to the documentation. We can add a link to the tracking issue in the documentation of our repo.

with:
attestation-name: provenance-sigstore-${{ github.event.release.tag_name }}.intoto.jsonl
base64-subjects: "${{ needs.build.outputs.hashes }}"
upload-assets: true

release-pypi:
needs: [build, generate-provenance]
runs-on: ubuntu-latest
permissions: {}
steps:
- name: Download artifacts diretories # goes to current working directory
uses: actions/download-artifact@v3

- name: publish
uses: pypa/gh-action-pypi-publish@717ba43cfbb0387f6ce311b169a825772f54d295
with:
user: __token__
password: ${{ secrets.PYPI_TOKEN }}
packages_dir: built-packages/

release-github:
needs: [build, generate-provenance]
runs-on: ubuntu-latest
permissions:
# Needed to upload release assets.
contents: 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/*
- 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/*
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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/)
<!--- @end-badges@ --->

⚠️ This project is not ready for general-purpose use! ⚠️
Expand Down Expand Up @@ -305,6 +306,13 @@ 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 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).
woodruffw marked this conversation as resolved.
Show resolved Hide resolved


## Info

`sigstore-python` is developed as part of the [`sigstore`](https://sigstore.dev) project.
Expand Down