Skip to content

Commit 058fdb2

Browse files
committed
Update docs and changelog
1 parent 5327537 commit 058fdb2

3 files changed

Lines changed: 48 additions & 7 deletions

File tree

‎CHANGES/1340.feature‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Added support for verifying SLSA attestations with a configured public key.
1+
Added custom (non-PEP 740) support for verifying attestations signed with a server-configured public key via `ATTESTATION_VERIFICATION_KEY`, with optional embedded key in `verification_material`.

‎docs/user/guides/attestation.md‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,44 @@ http $PULP_API/pypi/foo/simple/twine/ "Accept:application/vnd.pypi.simple.v1+jso
8989

9090
http $PULP_API/pypi/foo/integrity/twine/6.2.0/twine-6.2.0.tar.gz/provenance/
9191
```
92+
93+
## Custom Key Verification (non-PEP 740)
94+
95+
!!! note
96+
This is a custom extension outside the PEP 740 spec. Standard PEP 740 users using Sigstore
97+
keyless signing do not need this feature.
98+
99+
Pulp Python supports verifying attestations signed with a custom public key instead of a Sigstore
100+
certificate. This is useful for environments that sign packages with their own key (e.g. internal
101+
build systems) rather than using Sigstore's keyless signing.
102+
103+
To enable this, configure the `ATTESTATION_VERIFICATION_KEY` setting with the path to a PEM public
104+
key file:
105+
106+
```
107+
PULP_ATTESTATION_VERIFICATION_KEY=/path/to/public-key.pem
108+
```
109+
110+
When this setting is configured, Pulp uses two verification paths that coexist on the same server:
111+
112+
- **Attestations with a Sigstore certificate** are verified through the standard PEP 740 path,
113+
regardless of whether `ATTESTATION_VERIFICATION_KEY` is set.
114+
- **Attestations without a Sigstore certificate** are verified against the server-configured key using RSA
115+
PKCS1v15 signatures.
116+
117+
This means a single Pulp instance can host packages with Sigstore certificates and
118+
internally-signed packages with key-based attestations. Each attestation is independently
119+
routed to the appropriate verification path based on whether it contains a certificate.
120+
121+
### Embedded public key
122+
123+
Uploaders may optionally include the public key in the attestation's `verification_material` field.
124+
This makes the attestation self-contained for consumers who want to verify offline without fetching
125+
the key separately. The embedded key must match the server-configured key. Also, the `certificate`
126+
and `public_key` fields are mutually exclusive — an attestation's `verification_material` cannot contain both.
127+
128+
### Limitations
129+
130+
- A single key is used across all repositories and domains.
131+
- The key-based path only supports RSA PKCS1v15 with SHA-256 signatures.
132+
- Publisher enrichment is supported for SLSA v0.2 provenance statements only.

‎pulp_python/app/provenance.py‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -232,11 +232,11 @@ def _verify_embedded_key(attestation, server_key):
232232
def verify_provenance(filename, sha256, provenance, offline=True):
233233
"""Verify the provenance object is valid for the package.
234234
235-
Attestations with valid Sigstore certificates are verified through the
236-
standard Sigstore path. Attestations without certificates are verified
237-
against a custom public key configured via ATTESTATION_VERIFICATION_KEY.
238-
Currently, it supports RSA PKCS1v15 signatures and SLSA v0.2 provenance
239-
publisher enrichment.
235+
Each attestation is routed to one of two coexisting verification paths:
236+
1. Attestations with a valid Sigstore certificate follow the standard PEP 740 path.
237+
2. Attestations without a certificate are verified against the server-configured
238+
ATTESTATION_VERIFICATION_KEY using RSA PKCS1v15 signatures, with support for SLSA
239+
v0.2 publisher enrichment and optional embedded public key in verification_material.
240240
"""
241241
dist = Distribution(name=filename, digest=sha256)
242242
verification_key = _load_verification_key()
@@ -257,7 +257,7 @@ def verify_provenance(filename, sha256, provenance, offline=True):
257257
_verify_embedded_key(attestation, verification_key)
258258
else:
259259
raise VerificationError(
260-
"Attestation has no Sigstore certificate or no custom "
260+
"Attestation has no Sigstore certificate and no custom "
261261
"verification key configured via ATTESTATION_VERIFICATION_KEY "
262262
"(embedded key in verification_material is optional)"
263263
)

0 commit comments

Comments
 (0)