Skip to content

Commit

Permalink
Initial PEP 740 documentation (#16398)
Browse files Browse the repository at this point in the history
* initial attestations user docs

Signed-off-by: William Woodruff <william@trailofbits.com>

* more background, use preview

Signed-off-by: William Woodruff <william@trailofbits.com>

* docs: more improvements

Signed-off-by: William Woodruff <william@trailofbits.com>

* docs: attestation internals

Signed-off-by: William Woodruff <william@trailofbits.com>

* Update docs/user/attestations/internals.md

Co-authored-by: Facundo Tuesca <facundo.tuesca@trailofbits.com>

* publish/v1: clarify the signing target

Signed-off-by: William Woodruff <william@trailofbits.com>

* Apply suggestions from code review

Co-authored-by: Facundo Tuesca <facundo.tuesca@trailofbits.com>

* v1: be explicit about payload

Signed-off-by: William Woodruff <william@trailofbits.com>

* attestations: avoid "index attestations"

Signed-off-by: William Woodruff <william@trailofbits.com>

* attestations/internals: remove another confusing phrase

Signed-off-by: William Woodruff <william@trailofbits.com>

* Apply suggestions from code review

Co-authored-by: Dustin Ingram <di@users.noreply.github.com>

* docs: move internals doc to dev-docs

Signed-off-by: William Woodruff <william@trailofbits.com>

* dev: fix backticks

Signed-off-by: William Woodruff <william@trailofbits.com>

* lintage, add note about trust

Signed-off-by: William Woodruff <william@trailofbits.com>

* docs/dev: add callout for user docs

Signed-off-by: William Woodruff <william@trailofbits.com>

* Update attestation-internals.rst

Co-authored-by: Dustin Ingram <di@users.noreply.github.com>

* Update attestation-internals.rst

Co-authored-by: Dustin Ingram <di@users.noreply.github.com>

* tweak index attestations warning

Signed-off-by: William Woodruff <william@trailofbits.com>

* docs: more PEP 740 docs, begin migrating user API docs

Signed-off-by: William Woodruff <william@trailofbits.com>

* docs: integrity API, details

Signed-off-by: William Woodruff <william@trailofbits.com>

* api/integrity: fill in example

Signed-off-by: William Woodruff <william@trailofbits.com>

* document status code

Signed-off-by: William Woodruff <william@trailofbits.com>

* docs/dev: add note about api docs migration

Signed-off-by: William Woodruff <william@trailofbits.com>

* Apply suggestions from code review

Co-authored-by: Dustin Ingram <di@users.noreply.github.com>

* api/integrity: avoid weird formatting

Signed-off-by: William Woodruff <william@trailofbits.com>

* Apply suggestions from code review

Co-authored-by: Dustin Ingram <di@users.noreply.github.com>

* docs: link to #17001

Signed-off-by: William Woodruff <william@trailofbits.com>

* docs/dev: use sampleproject for attestation docs

Signed-off-by: William Woodruff <william@trailofbits.com>

* dev-docs: more attestation internals to security/

Signed-off-by: William Woodruff <william@trailofbits.com>

* dev-docs: remove old index ref

Signed-off-by: William Woodruff <william@trailofbits.com>

* dev-docs: fix two more broken refs

Signed-off-by: William Woodruff <william@trailofbits.com>

* user-docs: use a real provenance example

Signed-off-by: William Woodruff <william@trailofbits.com>

* remove incorrect header

Signed-off-by: William Woodruff <william@trailofbits.com>

* make toctree placement less confusing

Signed-off-by: William Woodruff <william@trailofbits.com>

---------

Signed-off-by: William Woodruff <william@trailofbits.com>
Co-authored-by: Facundo Tuesca <facundo.tuesca@trailofbits.com>
Co-authored-by: Dustin Ingram <di@users.noreply.github.com>
  • Loading branch information
3 people authored Nov 7, 2024
1 parent c2d911f commit ac0dee9
Show file tree
Hide file tree
Showing 14 changed files with 831 additions and 7 deletions.
8 changes: 8 additions & 0 deletions docs/dev/api-reference/index.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
API reference
=============

.. note::

API documentation is being moved to PyPI's
`user documentation site <https://docs.pypi.org/api/>`_.

Please see `issue #16541 <https://github.com/pypi/warehouse/issues/16541>`_
for more information and status updates.

Warehouse has several API endpoints. See :doc:`../application` for the
parts of Warehouse that generate them.

Expand Down
5 changes: 4 additions & 1 deletion docs/dev/api-reference/legacy.rst
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ legacy PyPI upload API. This is the endpoint that tools such as `twine
<https://twine.readthedocs.io/>`_ use to `upload distributions to PyPI
<https://packaging.python.org/guides/distributing-packages-using-setuptools/#uploading-your-project-to-pypi>`_.

The upload api can be used to upload artifacts by sending a multipart/form-data
The upload API can be used to upload artifacts by sending a ``multipart/form-data``
POST request with the following fields:

- ``:action`` set to ``file_upload``
Expand All @@ -314,6 +314,9 @@ POST request with the following fields:
``source``
- ``metadata_version``, ``name`` and ``version`` set according to the
`Core metadata specifications`_
- ``attestations`` can be set to a JSON array of :pep:`740` attestation
objects. PyPI will reject the upload if it can't verify each of the
supplied.
- You can set any other field from the `Core metadata specifications`_.
All fields need to be renamed to lowercase and hyphens need to replaced
by underscores. So instead of "Description-Content-Type" the field must be
Expand Down
2 changes: 1 addition & 1 deletion docs/dev/development/submitting-patches.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ As you work on your patch, keep this in mind:
2.0.

If you believe you've identified a security issue in Warehouse, follow the
directions on the :doc:`security page </security>`.
directions on the :doc:`security page </security/index>`.

Code
----
Expand Down
2 changes: 1 addition & 1 deletion docs/dev/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Contents:
architecture
api-reference/index
ui-principles
security
security/index
translations
roadmap

Expand Down
348 changes: 348 additions & 0 deletions docs/dev/security/attestation-internals.rst

Large diffs are not rendered by default.

10 changes: 9 additions & 1 deletion docs/dev/security.rst → docs/dev/security/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
Security
========

Contents:

.. toctree::
:maxdepth: 2

attestation-internals

Security policy
---------------
To read the most up to date version of our security policy, including
Expand All @@ -11,5 +18,6 @@ directions for submitting security vulnerabilities, please visit

Project and release activity details
------------------------------------
See :doc:`api-reference/feeds` for how to track new and updated releases on
See :doc:`/api-reference/feeds` for how to track new and updated releases on
PyPI.

11 changes: 10 additions & 1 deletion docs/mkdocs-user-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ markdown_extensions:
- pymdownx.superfences
- pymdownx.tabbed:
alternate_style: true
slugify: !!python/object/apply:pymdownx.slugs.slugify {kwds: {case: lower}}
slugify:
!!python/object/apply:pymdownx.slugs.slugify { kwds: { case: lower } }
- tables
- pymdownx.emoji:
emoji_index: !!python/name:material.extensions.emoji.twemoji
Expand Down Expand Up @@ -71,4 +72,12 @@ nav:
- "trusted-publishers/security-model.md"
- "trusted-publishers/troubleshooting.md"
- "trusted-publishers/internals.md"
- "Digital Attestations":
- "attestations/index.md"
- "attestations/producing-attestations.md"
- "attestations/consuming-attestations.md"
- "attestations/publish/v1.md"
- "project_metadata.md"
- "API Reference":
- "api/index.md"
- "api/integrity.md"
52 changes: 52 additions & 0 deletions docs/user/api/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Introduction

<!--[[ preview('user-api-docs') ]]-->

PyPI has several API endpoints, each of which is referenced in the table
of contents for this hierarchy.

## API policies

Please be aware of these PyPI API policies:

### Caching

All API requests are cached. Requests to the JSON, RSS or Legacy APIs are
cached by our CDN provider. You can determine if you've hit the cache based on
the ``X-Cache`` and ``X-Cache-Hits`` headers in the response.

Requests to the JSON, RSS and Legacy APIs also provide an ``ETag`` header. If
you're making a lot of repeated requests, ensure your API consumer will respect
this header to determine whether to actually repeat a request or not.

The XML-RPC API does not have the ability to indicate cached responses.

### Rate limiting

Due to the heavy caching and CDN use, there is currently no rate limiting of
PyPI APIs at the edge. The XML-RPC API may be rate limited if usage is causing
degradation of service.

In addition, PyPI reserves the right to temporarily or permanently prohibit a
consumer based on irresponsible activity.

If you plan to make a lot of requests to a PyPI API, adhere to these
suggestions:

* Set your consumer's ``User-Agent`` header to uniquely identify your requests.
Adding your contact information to this value would be helpful as well.
* Try not to make a lot of requests (thousands) in a short amount of time
(minutes). Generally PyPI can handle it, but it's preferred to make requests
in serial over a longer amount of time if possible.
* If your consumer is actually an organization or service that will be
downloading a lot of packages from PyPI, consider `using your own index
mirror or cache
<https://packaging.python.org/guides/index-mirrors-and-caches/>`_.

### API Preference

For periodically checking for new packages or updates to existing packages,
use our RSS feeds.

No new integrations should use the XML-RPC APIs as they are planned for
deprecation. Existing consumers should migrate to JSON/RSS/Legacy APIs.
122 changes: 122 additions & 0 deletions docs/user/api/integrity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# Integrity API

<!--[[ preview('user-api-docs') ]]-->

The Integrity API provides access to PyPI's implementation of [PEP 740].

## Concepts

The concepts and objects in the Integrity API closely mirror [PEP 740]:

* **Attestation objects** encapsulate a single "attestation" for a single file,
such as a [publish attestation] or [SLSA Provenance].

* **Provenance objects** encapsulate *one or more* attestations for a given
file, bundling them with the *identity* that produced them.

The Integrity API deals in provenance objects; users should extract and verify
individual attestations from a file's provenance, as appropriate.

## Routes

### Get provenance for file

Route: `GET /integrity/<project>/<version>/<filename>/provenance`

Get the provenance object for the given `<filename>`.

This endpoint is currently only available as JSON.

Example JSON request (default if no `Accept` header is passed):

```http
GET /integrity/sampleproject/4.0.0/sampleproject-4.0.0.tar.gz/provenance HTTP/1.1
Host: pypi.org
Accept: application/vnd.pypi.integrity.v1+json
```

??? note "Example JSON response"

This is an example response, demonstrating a provenance object containing
one attestation and its Trusted Publishing identity.

```json
{
"attestation_bundles": [
{
"attestations": [
{
"envelope": {
"signature": "MEUCIQD1JCA8lWR9na44+zY2tr13sEuMCIu+FLS6eDkwESP5KgIgQDNG+eA5PiLSvVd+0AJn3Nk1V3CpRjRoz59L/MMTxyM=",
"statement": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjEiLCJzdWJqZWN0IjpbeyJuYW1lIjoic2FtcGxlcHJvamVjdC00LjAuMC50YXIuZ3oiLCJkaWdlc3QiOnsic2hhMjU2IjoiMGFjZTc5ODBmODJjNTgxNWVkZTRjZDdiZjlmNjY5MzY4NGNlYzJhZTQ3YjliN2FkZTlhZGQ1MzNiODYyN2M2YiJ9fV0sInByZWRpY2F0ZVR5cGUiOiJodHRwczovL2RvY3MucHlwaS5vcmcvYXR0ZXN0YXRpb25zL3B1Ymxpc2gvdjEiLCJwcmVkaWNhdGUiOm51bGx9"
},
"verification_material": {
"certificate": "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",
"transparency_entries": [
{
"canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiZHNzZSIsInNwZWMiOnsiZW52ZWxvcGVIYXNoIjp7ImFsZ29yaXRobSI6InNoYTI1NiIsInZhbHVlIjoiOTNlMWYzNjRjODYwZWQ3MzI1MWYzYjI2YTU0YTM5NzFiZmZmZWYwNGU5MGNhNDgyNGU2YjhlMDJhMWIxMTVjMiJ9LCJwYXlsb2FkSGFzaCI6eyJhbGdvcml0aG0iOiJzaGEyNTYiLCJ2YWx1ZSI6Ijk1YTdkMGM3ZmVhZWQ1NDA5NDJlZGZlNzBhZjlkM2JiNjNiNjNlODgwZDJkN2ExYzYzZmQ4NDI0YTU2YjQ1YmMifSwic2lnbmF0dXJlcyI6W3sic2lnbmF0dXJlIjoiTUVVQ0lRRDFKQ0E4bFdSOW5hNDQrelkydHIxM3NFdU1DSXUrRkxTNmVEa3dFU1A1S2dJZ1FETkcrZUE1UGlMU3ZWZCswQUpuM05rMVYzQ3BSalJvejU5TC9NTVR4eU09IiwidmVyaWZpZXIiOiJMUzB0TFMxQ1JVZEpUaUJEUlZKVVNVWkpRMEZVUlMwdExTMHRDazFKU1VkdlZFTkRRbWxwWjBGM1NVSkJaMGxVUm1GcEsxQkVTMkZyTVhoQk1VaE1jVEJ0YzJ0eGFFUldOWHBCUzBKblozRm9hMnBQVUZGUlJFRjZRVE1LVFZKVmQwVjNXVVJXVVZGTFJYZDRlbUZYWkhwa1J6bDVXbE0xYTFwWVdYaElha0ZqUW1kT1ZrSkJUVlJHV0U1d1dqTk9NR0l6U214TVYyeDFaRWRXZVFwaVYxWnJZVmRHTUZwVVFXVkdkekI1VGtSRmVFMUVXWGxOYWswelRVUmtZVVozTUhsT1JFVjRUVVJaZVUxcVVUTk5SR1JoVFVGQmQxZFVRVlJDWjJOeENtaHJhazlRVVVsQ1FtZG5jV2hyYWs5UVVVMUNRbmRPUTBGQlVtSjRNVVp6WlRKTWJqQXdUMjQxWVVaaFRDdHNTRTVIUmxsTVlYRmxTMFJrZFhCc1drUUtVRXBUSzNjeVVHcFpaazVRVERCbkwyNDBjMFJYUlZGR1dtWjVTVVY0UlZkTGRXeGFNa2RMVG5wQll6QXJVMjFWYnpSSlJsTkVRME5DVlZGM1JHZFpSQXBXVWpCUVFWRklMMEpCVVVSQloyVkJUVUpOUjBFeFZXUktVVkZOVFVGdlIwTkRjMGRCVVZWR1FuZE5SRTFDTUVkQk1WVmtSR2RSVjBKQ1ZDOTFVMFZKQ2xodFVYcDFVbXR3Y0ZkWWNsUkxWbXRtV2taS1lucEJaa0puVGxaSVUwMUZSMFJCVjJkQ1ZHWXdLMjVRVm1sUlVteDJiVzh5VDJ0dlZtRk1SMHhvYUdzS1VIcENhRUpuVGxaSVVrVkNRV1k0UlZaNlFsWm9iRTV2WkVoU2QyTjZiM1pNTW1Sd1pFZG9NVmxwTldwaU1qQjJZMGhzZDFsVE9YcFpWekYzWWtkV2R3cGpiVGx4V2xkT01FeDVOVzVoV0ZKdlpGZEpkbVF5T1hsaE1scHpZak5rZWt3elNteGlSMVpvWXpKVmRXVlhNWE5SU0Vwc1dtNU5kbUZIVm1oYVNFMTJDbUpYUm5CaWFrRTFRbWR2Y2tKblJVVkJXVTh2VFVGRlFrSkRkRzlrU0ZKM1kzcHZka3d6VW5aaE1sWjFURzFHYW1SSGJIWmliazExV2pKc01HRklWbWtLWkZoT2JHTnRUblppYmxKc1ltNVJkVmt5T1hSTlFrbEhRMmx6UjBGUlVVSm5OemgzUVZGSlJVSklRakZqTW1kM1RtZFpTMHQzV1VKQ1FVZEVkbnBCUWdwQmQxRnZUbXBKZUZwVVVUVk9lbEpxV1ZSSk1Wa3lWVEZOZWtVelRucE9hMXBYV1RGUFJGcHBXVlJPYkZwRWFHeE9lazB5V1dwT2JWbDZRVlpDWjI5eUNrSm5SVVZCV1U4dlRVRkZSVUpCWkZOYVYzaHNXVmhPYkUxRFFVZERhWE5IUVZGUlFtYzNPSGRCVVZWRlJXNUNOV05IUlhaak1rWjBZMGQ0YkdOSVNuWUtZVzFXYW1SRVFXUkNaMjl5UW1kRlJVRlpUeTlOUVVWSFFrRTVlVnBYV25wTU1taHNXVmRTZWt3eU1XaGhWelIzVDNkWlMwdDNXVUpDUVVkRWRucEJRZ3BEUVZGMFJFTjBiMlJJVW5kamVtOTJURE5TZG1FeVZuVk1iVVpxWkVkc2RtSnVUWFZhTW13d1lVaFdhV1JZVG14amJVNTJZbTVTYkdKdVVYVlpNamwwQ2sxSFRVZERhWE5IUVZGUlFtYzNPSGRCVVd0RlZsRjRWR0ZJVWpCalNFMDJUSGs1Ym1GWVVtOWtWMGwxV1RJNWRFd3pRalZqUjBWMll6SkdkR05IZUd3S1kwaEtkbUZ0Vm1wa1F6aDFXakpzTUdGSVZtbE1NMlIyWTIxMGJXSkhPVE5qZVRsNVdsZDRiRmxZVG14TWJteDBZa1ZDZVZwWFducE1NbWhzV1ZkU2VncE1NakZvWVZjMGQwOUJXVXRMZDFsQ1FrRkhSSFo2UVVKRFoxRnhSRU5uTWsxcVJteE9SR3N6VGtkT2FFMXFWbXBhVkZWNlRWUmpNMDB5VW14YWFsVTBDazV0U21oTk1sWnJUMGRWTTAxNldtbE5NbHBxVFVJd1IwTnBjMGRCVVZGQ1p6YzRkMEZSYzBWRWQzZE9XakpzTUdGSVZtbE1WMmgyWXpOU2JGcEVRVEVLUW1kdmNrSm5SVVZCV1U4dlRVRkZUVUpEWTAxS1YyZ3daRWhDZWs5cE9IWmFNbXd3WVVoV2FVeHRUblppVXpsM1pWaENhRXd6VG1oaVdFSnpXbGhDZVFwaU1uQnNXVE5SZDA5QldVdExkMWxDUWtGSFJIWjZRVUpFVVZGeFJFTm5NazFxUm14T1JHc3pUa2RPYUUxcVZtcGFWRlY2VFZSak0wMHlVbXhhYWxVMENrNXRTbWhOTWxaclQwZFZNMDE2V21sTk1scHFUVUk0UjBOcGMwZEJVVkZDWnpjNGQwRlJORVZGVVhkUVkyMVdiV041T1c5YVYwWnJZM2s1ZEZsWGJIVUtUVUpuUjBOcGMwZEJVVkZDWnpjNGQwRlJPRVZEWjNkSlRWUlJORTlVYXpGUFZGbDNTbmRaUzB0M1dVSkNRVWRFZG5wQlFrVkJVVnBFUW1SdlpFaFNkd3BqZW05MlRESmtjR1JIYURGWmFUVnFZakl3ZG1OSWJIZFpWRUZYUW1kdmNrSm5SVVZCV1U4dlRVRkZVa0pCWjAxQ2Fsa3dUbnBCZVU1VVFtcENaMjl5Q2tKblJVVkJXVTh2VFVGRlUwSkdWVTFWTW1nd1pFaENlazlwT0haYU1td3dZVWhXYVV4dFRuWmlVemwzWlZoQ2FFd3pUbWhpV0VKeldsaENlV0l5Y0d3S1dUTlJka3h0WkhCa1IyZ3hXV2s1TTJJelNuSmFiWGgyWkROTmRtTnRWbk5hVjBaNldsTTFOV0pYZUVGamJWWnRZM2s1YjFwWFJtdGplVGwwV1Zkc2RRcE5SR2RIUTJselIwRlJVVUpuTnpoM1FWSk5SVXRuZDI5T2FrbDRXbFJSTlU1NlVtcFpWRWt4V1RKVk1VMTZSVE5PZWs1cldsZFpNVTlFV21sWlZFNXNDbHBFYUd4T2VrMHlXV3BPYlZsNlFWVkNaMjl5UW1kRlJVRlpUeTlOUVVWVlFrRlpUVUpJUWpGak1tZDNWMUZaUzB0M1dVSkNRVWRFZG5wQlFrWlJVa3dLUkVWc2IyUklVbmRqZW05MlRESmtjR1JIYURGWmFUVnFZakl3ZG1OSWJIZFpVemw2V1ZjeGQySkhWbmRqYlRseFdsZE9NRXd5Um1wa1IyeDJZbTVOZGdwamJsWjFZM2s0ZUUxVVkzaE5la0Y2VDBSck5FMVRPV2hrU0ZKc1lsaENNR041T0hoTlFsbEhRMmx6UjBGUlVVSm5OemgzUVZKWlJVTkJkMGRqU0ZacENtSkhiR3BOU1VkTFFtZHZja0puUlVWQlpGbzFRV2RSUTBKSWQwVmxaMEkwUVVoWlFUTlVNSGRoYzJKSVJWUktha2RTTkdOdFYyTXpRWEZLUzFoeWFtVUtVRXN6TDJnMGNIbG5Remh3TjI4MFFVRkJSMVJCTlM5WU5VRkJRVUpCVFVGU2VrSkdRV2xCTm01WlN6QkhlSEZXZWtwMWRISnFjbGxCTVdKQlNVdElWUXBxUjNKelNFMU1jazlLVkZSRlZXbEZVa0ZKYUVGS1dtOTBRVlJ1VTNkc1MzUTNRek5hZDJoNE0yWmpVM0pvUjJaUFlXdFViRTB5ZHlzNGNXMXNkR05xQ2sxQmIwZERRM0ZIVTAwME9VSkJUVVJCTW1OQlRVZFJRMDFDSzJsc2MxQm5lVFI1YmxWSE9VZDBjVVJGUW5GWE9DdGFjV3BZTmt4d2RYaFJjV3BEY2pjS2N6UjVkSGwwTW5Cd1JtUm5hbkpIY2tjeFJGazBibE5hZEZGSmQySnNjbWR4T1hRNWFYcEJUVlJyU21WeGFGRkNjekpQVldsNVNVcGFhWEJqWlVRMWRncEJRVVV2VG1ablpDODVkVXN3VFZwQlNFWnpUR2RoYkhGUFFtdzRDaTB0TFMwdFJVNUVJRU5GVWxSSlJrbERRVlJGTFMwdExTMEsifV19fQ==",
"inclusionPromise": {
"signedEntryTimestamp": "MEQCIGzFZon9/joNsiQOL1uoIP/gtz7/A6eAB+50oX3M0CBaAiAZmLVxcgknlWls6R1FswJWCHY0vkwQ/jE5dSkcY43jWA=="
},
"inclusionProof": {
"checkpoint": {
"envelope": "rekor.sigstore.dev - 1193050959916656506\n25232879\nQrnMowJnGj9hZkL1UOvkg7w+KuG27PEDcsdaEqCtoDM=\n\n— rekor.sigstore.dev wNI9ajBFAiEAshgj30XTIU+L6UyYL0yzLXJbLFmxPEc8ZRmS1R3N1sQCIFCjFEqe9J+Et9sWzJp6SE3p7Eh/+97zON7mwX6unCem\n"
},
"hashes": [
"Bc4heeKQhKCr6/ZtuEHmAyp8AzvP4N1ROusEacAmfFQ=",
"ZTeyp2wk6H1Bgz3SZOqQWoQvCmkiltfFstDiy1WaR9Y=",
"vnHPC5XIhbYQib86Hi6M4OaEOFGFMlOip8+5mxZd8cs=",
"BEONTVFois+c47/YA7vzwZG7fbNLBkVLz1hUM/WMb1k=",
"PWqRmPYAwa1fq6R1qSrYlOxCtiKnFZq9hnNt7XwCIA8=",
"KHxYP0XNSf1yKjp+xY/5Kkckw0Yweyjx9Z6qn2+pnZM=",
"8/b9kmTAbALhl4EaKIH4uMXhES9ILB0XQkuH44FltJY=",
"mXfX9NDkaWje6HpniWis2CBELUGjv8LiW2jeMOclCs0=",
"jRPOva2IEma7ZE7mPN3xHtEnXtMF/HNvrmbC5TKTy14=",
"s8vUdxeRlxXWTCMdSLhiSzRiYM3eGsVvrm+5HWkTNBc=",
"4lUF0YOu9XkIDXKXA0wMSzd6VeDY3TZAgmoOeWmS2+Y=",
"gf+9m552B3PnkWnO0o4KdVvjcT3WVHLrCbf1DoVYKFw="
],
"logIndex": "25232877",
"rootHash": "QrnMowJnGj9hZkL1UOvkg7w+KuG27PEDcsdaEqCtoDM=",
"treeSize": "25232879"
},
"integratedTime": "1730932627",
"kindVersion": {
"kind": "dsse",
"version": "0.0.1"
},
"logId": {
"keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="
},
"logIndex": "147137139"
}
]
},
"version": 1
}
],
"publisher": {
"claims": null,
"environment": "",
"kind": "GitHub",
"repository": "pypa/sampleproject",
"workflow": "release.yml"
}
}
],
"version": 1
}
```

#### Status codes

* `200 OK` - no error, provenance is available
* `403 Forbidden` - access is temporarily disabled by the PyPI administrators
* `404 Not Found` - file has no provenance
* `406 Not Acceptable` - `Accept:` header not recognized

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

[publish attestation]: /attestations/publish/v1

[SLSA Provenance]: https://slsa.dev/spec/v1.0/provenance
10 changes: 10 additions & 0 deletions docs/user/attestations/consuming-attestations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Consuming attestations

<!--[[ preview('index-attestations') ]]-->

PyPI makes a file's attestations available via the simple index (HTML)
and simple JSON APIs.

For a full API reference, see the [Integrity API documentation].

[Integrity API documentation]: /api/integrity/
47 changes: 47 additions & 0 deletions docs/user/attestations/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
title: Introduction
---

<!--[[ preview('index-attestations') ]]-->

These pages document PyPI's implementation of digital attestations ([PEP 740]),
including in-toto attestation predicates specific to PyPI itself.

## Quick background

*Digital attestations* enable package maintainers as well as third parties (such
as the index itself, external auditors, etc.) to *cryptographically sign*
for uploaded packages.

These signatures bind each release distribution (such as an individual sdist or
wheel) to a strong cryptographic digest of its contents, allowing both PyPI
and downstream users to verify that a particular package was attested to by
a particular identity (such as a GitHub Actions workflow).

These attestations can take multiple forms, including [publish attestations]
for publicly verifiable proof that a package was published via a specific
[Trusted Publisher], or more general [SLSA Provenance] attesting to a package's
original source location.

## Supported attestations

PyPI uses the [in-toto Attestation Framework] for the attestations it accepts.

Currently, PyPI allows the following attestation predicates:

* [SLSA Provenance]
* [PyPI Publish]

[in-toto Attestation Framework]: https://github.com/in-toto/attestation/blob/main/spec/README.md

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

[PyPI Publish]: /attestations/publish/v1/

[publish attestations]: /attestations/publish/v1/

[Trusted Publisher]: /trusted-publishers/

[SLSA Provenance]: https://slsa.dev/spec/v1.0/provenance


Loading

0 comments on commit ac0dee9

Please sign in to comment.