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

Question regarding verify_cert_identity when using the GitHub Actions credential #158

Closed
Lucas-C opened this issue Dec 16, 2024 · 14 comments
Labels
question Further information is requested

Comments

@Lucas-C
Copy link

Lucas-C commented Dec 16, 2024

Hi!

I'm trying to setup sigstore on https://github.com/py-pdf/fpdf2

I just switched to v3.0.0 and discovered the new upload-signing-artifacts setting, which I'm going to enable today, so that for the next release sigstore bundles can be downloaded as GitHub job artifacts.

PR: py-pdf/fpdf2#1331

I also wanted to enable verify, but I'm a bit hesitant regarding the value to provide for verify-cert-identity when using this GitHub Action and the OIDC token used for signing comes from GitHub?

If I'm not mistaken, a similar --cert-identity value will have to be provided to sigstore verify identity when end users will want to verify a fpdf2 package version against a sigstore bundle.

And again, I'm not sure which value to provide, and it does not seem displayed in the GitHub Action log.

Could you please provide some guidance regarding this? 🙂

@Lucas-C Lucas-C added the question Further information is requested label Dec 16, 2024
@woodruffw
Copy link
Member

Hi @Lucas-C, thanks for opening an issue!

FWIW: if you're publishing a Python project with pypa/gh-action-pypi-publish, you actually don't need this action at all: the action will generate a Sigstore bundle for you, and will send it to PyPI for users to download and verify.

In your case it looks like you're already doing so:

https://github.com/py-pdf/fpdf2/blob/bca0695cdb31850fa63e93d19f9a500cdede6af5/.github/workflows/continuous-integration-workflow.yml#L135

and the attestations are live on PyPI e.g. here:

https://pypi.org/project/fpdf2/#fpdf2-2.8.2.tar.gz

One current limitation of that is that it only uploads the attestations to PyPI, not to GitHub itself. That's being tracked here: pypa/gh-action-pypi-publish#288


However, to answer your actual question: verify-cert-identity should be the identity of the workflow that produced the Sigstore bundle. For GitHub Actions this is typically expressed in the form:

https://github.com/USER/REPO/.github/workflows/WORKFLOW@REF

where USER/REPO is your repo slug, WORKFLOW is the publishing workflow (continuous-integration-workflow.yml in your case), and REF is the git ref that triggered the run (probably refs/heads/master in your case).

In other words, this should be correct:

verify-cert-identity: https://github.com/py-pdf/fpdf2/.github/workflows/continuous-integration-workflow.yml@refs/heads/master

I'd also recommend experimenting with sigstore-python locally -- the error message for sigstore verify github or sigstore verify identity should tell you if the expected identity is slightly off 🙂

@Lucas-C
Copy link
Author

Lucas-C commented Dec 16, 2024

Thank you very much @woodruffw 🤩

I'm going to experiment with the sigstore verify github command to figure how to perform a verification based on the data published on Pypi.

One thing I did not figure out yet is: where to retrieve a .sigstore.json or .bundle file from Pypi?
One such file seems to be required by sigstore verify


EDIT: Example test I'm performing:

$ pip install sigstore
$ wget https://files.pythonhosted.org/packages/b0/54/0e86f986e81abad9e6b348f5176048a2aa046920d46292c42a581064d93e/fpdf2-2.8.2.tar.gz
$ sigstore verify github fpdf2-2.8.2.tar.gz --repository=py-pdf/fpdf2 --sha b9cfbb6d8ca1eb034e826fd358194e899a1daf28
usage: sigstore [-h] [-v] [-V] [--staging | --trust-config FILE] COMMAND ...
sigstore: error: Missing verification materials for fpdf2-2.8.2.tar.gz: fpdf2-2.8.2.tar.gz.sigstore.json

@Lucas-C
Copy link
Author

Lucas-C commented Dec 27, 2024

I tried to dig a little further...

I found a comment from 18 months ago on https://github.com/sigstore/sigstore-python that implies that .crt / .sig files are (were?) uploaded onto Pypi: sigstore/sigstore-python#126 (comment)

However I was not able to download them for the latest fpdf2 release:

$ wget https://github.com/actions/python-versions/releases/download/3.13.1-12154081405/python-3.13.1-linux-22.04-x64.tar.gz.crt
2024-12-27 08:58:47 ERROR 404: Not Found.

$ wget https://github.com/actions/python-versions/releases/download/3.13.1-12154081405/python-3.13.1-linux-22.04-x64.tar.gz.sig
2024-12-27 09:00:55 ERROR 404: Not Found.

I also found that the GitHub workflow generated .publish.attestation files, but I think that they have not been uploaded:
https://github.com/py-pdf/fpdf2/actions/runs/12350082009/job/34462193992

Showing hash values of files to be uploaded:
/github/workspace/dist/fpdf2-2.8.2-py2.py3-none-any.whl

SHA256: 951e26290d0fc6ab4582b0d0bbacb64716fecef0f2b9223f9178c90ec4321af7
MD5: 0b91dfbebd23a01f18b6dd1465776fa1
BLAKE2-256: eb467aae9cb2584dcac217e662ab6d4670ef4e447b73d624b6210f7155322411

/github/workspace/dist/fpdf2-2.8.2.tar.gz

SHA256: 3a2c6699c39b23b786fc6ad9fc3de5432e59f6b6383bb9ab4ce1f994a5f3e762
MD5: ff01a954528f583a6609dbc1f1c0283c
BLAKE2-256: b0540e86f986e81abad9e6b348f5176048a2aa046920d46292c42a581064d93e

/github/workspace/dist/fpdf2-2.8.2-py2.py3-none-any.whl.publish.attestation

SHA256: 3f46c364e7640fda48fb698c5323613bf9a2949eacde27361157ab3875e77a88
MD5: dd2b335efc038f425de507453b36ddd2
BLAKE2-256: c1e32d67606cf5d9dc0b4adb3a8322893453cae1abb2402741b825ac33e0685c

/github/workspace/dist/fpdf2-2.8.2.tar.gz.publish.attestation

SHA256: 9bb480ab775c2717b91aa8513b4721458d44bc87cdd8447218be98c369e838a9
MD5: 2bdcbeb856d16ba8507aeac80bccc1bf
BLAKE2-256: 6111918be987f8bab95e264cfb7925514148d90be83273da2abdaff133d3828b

Uploading distributions to https://upload.pypi.org/legacy/
Uploading fpdf2-2.8.2-py2.py3-none-any.whl
Uploading fpdf2-2.8.2.tar.gz
$ wget https://github.com/actions/python-versions/releases/download/3.13.1-12154081405/python-3.13.1-linux-22.04-x64.tar.gz.publish.attestation
2024-12-27 09:00:55 ERROR 404: Not Found.

Note: this workflow run used the Docker image pypa/gh-action-pypi-publish:release-v1 (sha256:65ba554)

I also tried to use the pypi-attestations project/tool, but it seems to also require a .publish.attestation file:

$ python -m pypi_attestations verify --identity https://github.com/py-pdf/fpdf2/.github/workflows/release.yml@refs/branch/master fpdf2-2.8.2.tar.gz
fpdf2-2.8.2.tar.gz.publish.attestation is not a file.

Hence my question: why no .publish.attestation files have been uploaded to Pypi from my pypa/gh-action-pypi-publish job, and is it normal?

@woodruffw
Copy link
Member

I also found that the GitHub workflow generated .publish.attestation files, but I think that they have not been uploaded:

They were uploaded, but they're not served at {url}.publish.attestation. The discovery scheme for provenance is documented here: https://docs.pypi.org/api/integrity/

TL;DR: They are uploaded to PyPI, but you need to access them via the simple HTML index (PEP 503) or JSON API (PEP 691) -- you can't just hit a URL and fetch them, since they get merged together 🙂

@Lucas-C
Copy link
Author

Lucas-C commented Jan 6, 2025

Alright, thank you very much for your answer 👍

Are there plans for the sigstore verify github / sigstore verify commands to perform signature retrieval from Pypi?

I'm thinking about a command like:

sigstore verify github fpdf2-2.8.2.tar.gz --repository=py-pdf/fpdf2 --provenance-from-pypi fpdf2

@woodruffw
Copy link
Member

Are there plans for the sigstore verify github / sigstore verify commands to perform signature retrieval from Pypi?

Nobody else has raised it, but I really like the idea of having this available from the sigstore CLI 🙂

I'll open up a separate tracking issue on sigstore-python for that -- the other maintainers will likely have opinions/thoughts on it.

@Lucas-C
Copy link
Author

Lucas-C commented Jan 6, 2025

Awesome @woodruffw, thank you!

I tested retrieving the signature/provenance file from Pypi, but it seems that it does not produce a valid .sigstore.json file:

$ curl https://pypi.org/integrity/fpdf2/2.8.2/fpdf2-2.8.2.tar.gz/provenance > fpdf2-2.8.2.tar.gz.sigstore.json

$ sigstore verify github fpdf2-2.8.2.tar.gz --repository=py-pdf/fpdf2 --sha b9cfbb6d8ca1eb034e826fd358194e899a1daf28
[21:11:19] ERROR    An issue occurred while parsing the Sigstore bundle.                                        errors.py:41

                    The provided bundle is malformed and may have been modified maliciously.

                    Additional context:

                    unsupported bundle format:

                    For detailed error information, run sigstore with the `--verbose` flag.

I also tested using pypi-attestations:

$ curl https://pypi.org/integrity/fpdf2/2.8.2/fpdf2-2.8.2.tar.gz/provenance > fpdf2-2.8.2.tar.gz.publish.attestation

$ python -m pypi_attestations verify --identity https://github.com/py-pdf/fpdf2/.github/workflows/release.yml@refs/branch/master fpdf2-2.8.2.tar.gz
Invalid attestation (fpdf2-2.8.2.tar.gz.publish.attestation): 2 validation errors for Attestation
verification_material
  Field required [type=missing, input_value={'attestation_bundles': [...w.yml'}}], 'version': 1}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.10/v/missing
envelope
  Field required [type=missing, input_value={'attestation_bundles': [...w.yml'}}], 'version': 1}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.10/v/missing

@woodruffw
Copy link
Member

Yeah, sorry for the confusion there -- that's because the /provenance is a JSON blob that contains one or more attestations (just one in your case).

The CLI interfaces here are pretty shoddy at the moment, but I'm working on improving those.

The Sphinx maintainers hit a similar set of rough edges; the resolution is here: trailofbits/pypi-attestations#55 (comment)

@Lucas-C
Copy link
Author

Lucas-C commented Jan 6, 2025

For the record, I got something working using those commands to select the 1st attestation:

$ curl -s https://pypi.org/integrity/fpdf2/2.8.2/fpdf2-2.8.2.tar.gz/provenance | jq -r .attestation_bundles[0].attestations[0] > fpdf2-2.8.2.tar.gz.publish.attestation

$ python -m pypi_attestations verify --identity https://github.com/py-pdf/fpdf2/.github/workflows/continuous-integration-workflow.yml@refs/heads/master fpdf2-2.8.2.tar.gz
OK: fpdf2-2.8.2.tar.gz.publish.attestation

It requires jq.

Regarding fpdf2, I'm going to wait for a new sigstore verify github --provenance-from-pypi parameter before adding signature verification in our documentation, because I'm not really sure on how to handle multiple attestation_bundles and/or attestations.

@woodruffw
Copy link
Member

Glad to hear you got it working! Sorry for the confusion there.

I'm going to wait for a new sigstore verify github --provenance-from-pypi parameter before adding signature verification in our documentation, because I'm not really what to do in case of multiple attestation_bundles and/or attestations.

Makes sense. FWIW in the case of multiple attestations you can do one-of-N, and that's what sigstore-python itself will likely do: multiple attestations aren't meant to contend with each other; they're solely a way for multiple different parties to attest to different things about the package.

@woodruffw
Copy link
Member

@Lucas-C we haven't cut a release for it yet, but the CLI changes here (trailofbits/pypi-attestations#82) should make it much easier to experiment with provenance JSON that's been pulled from PyPI.

@Lucas-C
Copy link
Author

Lucas-C commented Jan 13, 2025

@Lucas-C we haven't cut a release for it yet, but the CLI changes here (trailofbits/pypi-attestations#82) should make it much easier to experiment with provenance JSON that's been pulled from PyPI.

Thank you @woodruffw!

That is a very handy subcommand, thanks for introducing it 👍

I added a short paragraph to our documentation to give some pointers to our users on how to use pypy-attestations:
py-pdf/fpdf2#1331

Could you have a quick look and tell me if what I wrote in this paragraph is correct, please?

Moreover, I have a couple of feature requests:

  • instead of provided a full URL pointing to pythonhosted.org, could it be possible to specify pypi-attestations verify pypi fpdf2/#fpdf2-2.8.2.tar.gz, which would be resolved as https://pypi.org/project/fpdf2/#fpdf2-2.8.2.tar.gz, and then to the corresponding pythonhosted.org URL?
  • would it be possible to introduce extra parameters to the pypi-attestations verify pypi subcommand in order to verify more claims, like the fact the the fpdf2-2.8.2.tar.gz archive has been built based on the commit b9cfbb6 from our Github repo?

Could/should I open issues for those feature requests on https://github.com/trailofbits/pypi-attestations?

@woodruffw
Copy link
Member

Could you have a quick look and tell me if what I wrote in this paragraph is correct, please?

Those steps look correct to me!

  • instead of provided a full URL pointing to pythonhosted.org, could it be possible to specify pypi-attestations verify pypi fpdf2/#fpdf2-2.8.2.tar.gz, which would be resolved as pypi.org/project/fpdf2#fpdf2-2.8.2.tar.gz, and then to the corresponding pythonhosted.org URL?

Could/should I open issues for those feature requests on trailofbits/pypi-attestations?

Yes, please do!

A larger design pressure here is that we're trying to avoid inventing new syntax and we don't want pypi-attestations to be an official first-party CLI -- it's intended for experimentation while we work out a larger integration plan for packaging workflows. But filing those issues will help us better understand how best to do that integration 🙂

@Lucas-C
Copy link
Author

Lucas-C commented Jan 13, 2025

Could you have a quick look and tell me if what I wrote in this paragraph is correct, please?

Those steps look correct to me!

Thank you for taking a look 👍

I merged the PR, it's now part of fpdf2 documentation.

A larger design pressure here is that we're trying to avoid inventing new syntax and we don't want pypi-attestations to be an official first-party CLI -- it's intended for experimentation while we work out a larger integration plan for packaging workflows. But filing those issues will help us better understand how best to do that integration 🙂

Alright, I understand.

I opened those issues:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants