Skip to content
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
27 changes: 22 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,14 @@ print(bundle.to_json())
## Usage as a command line tool

> [!IMPORTANT]
> The `python -m pypi_attestations` CLI is intended primarily for
> The `pypi-attestations` CLI is intended primarily for
> experimentation, and is not considered a stable interface for
> generating or verifying attestations. Users are encouraged to
> generate attestations using [the official PyPA publishing action]
> or via this package's [public Python APIs].

````bash
python -m pypi_attestations --help
pypi-attestations --help
usage: pypi-attestation [-h] [-v] [-V] COMMAND ...

Sign, inspect or verify PEP 740 attestations
Expand Down Expand Up @@ -119,7 +119,7 @@ options:
```bash
# Generate a whl file
make package
python -m pypi_attestations sign dist/pypi_attestations-*.whl
pypi-attestations sign dist/pypi_attestations-*.whl
```

### Inspecting a PEP 740 Attestation
Expand All @@ -129,7 +129,7 @@ python -m pypi_attestations sign dist/pypi_attestations-*.whl
> the attestation.

```bash
python -m pypi_attestations inspect dist/pypi_attestations-*.whl.publish.attestation
pypi-attestations inspect dist/pypi_attestations-*.whl.publish.attestation
```

### Verifying a PEP 740 Attestation
Expand All @@ -140,14 +140,31 @@ python -m pypi_attestations inspect dist/pypi_attestations-*.whl.publish.attesta
> workflow that generated the attestation. The format of that identity

```bash
python -m pypi_attestations verify --staging \
pypi-attestations verify attestation --staging \
--identity william@yossarian.net \
test/assets/rfc8785-0.1.2-py3-none-any.whl
```

The attestation present in the test has been generated using the staging
environment of Sigstore and signed by the identity `william@yossarian.net`.

### Verifying a PyPI package
> [!NOTE]
> The URL must be a direct link to the distribution artifact hosted by PyPI.
> These can be found in the "Download files" section of the project's page,
> e.g: https://pypi.org/project/sigstore/#files

```bash
pypi-attestations verify pypi --repository https://github.com/sigstore/sigstore-python \
https://files.pythonhosted.org/packages/70/f5/324edb6a802438e97e289992a41f81bb7a58a1cda2e49439e7e48896649e/sigstore-3.6.1-py3-none-any.whl
```

This command downloads the artifact from the given URL and gets its provenance
from PyPI. The artifact is then verified against the provenance, while also
checking that the provenance's signing identity matches the repository specified
by the user.


[PEP 740]: https://peps.python.org/pep-0740/

[here]: https://trailofbits.github.io/pypi-attestations
Expand Down
12 changes: 7 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ dependencies = [
"packaging",
"pyasn1 ~= 0.6",
"pydantic >= 2.10.0",
"requests",
"rfc3986",
"sigstore >= 3.5.3, < 3.7",
"sigstore-protobuf-specs",
]
Expand All @@ -28,7 +30,7 @@ test = ["pytest", "pytest-cov", "pretend", "coverage[toml]"]
lint = [
# NOTE: ruff is under active development, so we pin conservatively here
# and let Dependabot periodically perform this update.
"ruff ~= 0.2",
"ruff ~= 0.9",
"mypy >= 1.0",
"types-html5lib",
"types-requests",
Expand All @@ -39,6 +41,8 @@ lint = [
]
dev = ["pypi-attestations[doc,test,lint]", "build"]

[project.scripts]
pypi-attestations = "pypi_attestations._cli:main"

[project.urls]
Homepage = "https://pypi.org/project/pypi-attestations"
Expand All @@ -51,7 +55,7 @@ name = "pypi_attestations"

[tool.coverage.run]
# don't attempt code coverage for the CLI entrypoints
omit = ["src/pypi_attestations/_cli.py", "src/pypi_attestations/__main__.py"]
omit = ["src/pypi_attestations/__main__.py"]

[tool.mypy]
mypy_path = "src"
Expand Down Expand Up @@ -80,11 +84,10 @@ target-version = "py39"

[tool.ruff.lint]
select = ["E", "F", "I", "W", "UP", "ANN", "D", "COM", "ISC", "TCH", "SLF"]
# ANN101 and ANN102 are deprecated
# D203 and D213 are incompatible with D211 and D212 respectively.
# COM812 and ISC001 can cause conflicts when using ruff as a formatter.
# See https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules.
ignore = ["ANN101", "ANN102", "D203", "D213", "COM812", "ISC001"]
ignore = ["D203", "D213", "COM812", "ISC001"]
# Needed since Pydantic relies on runtime type annotations, and we target Python versions
# < 3.10. See https://docs.astral.sh/ruff/rules/non-pep604-annotation/#why-is-this-bad
pyupgrade.keep-runtime-typing = true
Expand All @@ -104,7 +107,6 @@ pyupgrade.keep-runtime-typing = true
exclude = [
"env",
"test",
"src/pypi_attestations/_cli.py",
"src/pypi_attestations/__main__.py",
]
ignore-semiprivate = true
Expand Down
Loading
Loading