Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python Enhancement Proposals

PEP 807 – Index-Unterstützung für Trusted Publishing

Autor:
William Woodruff <william at yossarian.net>
Sponsor:
Donald Stufft <donald at stufft.io>
PEP-Delegate:
Donald Stufft <donald at stufft.io>
Discussions-To:
Discourse thread
Status:
Entwurf
Typ:
Standards Track
Thema:
Packaging
Erstellt:
19-Sep-2025
Post-History:
08-Aug-2025, 29-Sep-2025

Inhaltsverzeichnis

Zusammenfassung

Diese PEP schlägt einen standardisierten Mechanismus vor, über den beliebige Python-Paketindizes „Trusted Publishing“ unterstützen können, ein missbrauchssicheres Credential-Austauschschema, das bereits vom Python Package Index (PyPI) implementiert wird.

Der in dieser PEP vorgeschlagene Mechanismus soll die bestehende Implementierung von Trusted Publishing auf PyPI kapseln und es anderen Indizes ermöglichen, dasselbe Schema so zu implementieren, dass es von bestehenden Python-Paket-Upload-Clients entdeckt werden kann und mit ihnen interoperabel ist.

Motivation

„Trusted Publishing“ ist ein Fachbegriff auf PyPI für die Verwendung des OpenID Connect (OIDC)-Standards zum Austausch eines kurzlebigen Identitäts-Credentials von einem vertrauenswürdigen Drittanbieterdienst (wie einem CI/CD- oder Cloud-Anbieter) gegen ein kurzlebiges, minimal zugewiesenes Upload-Credential, das zum Veröffentlichen im Index verwendet werden kann.

Trusted Publishing wurde ursprünglich 2023 als nicht standardisierte (PyPI-spezifische) Funktion entworfen und auf PyPI aktiviert, ähnlich wie die bestehende Upload-API. Es hat in dieser Funktion eine breite Akzeptanz gefunden: Über eine Million Dateien wurden bis September 2025 mit einem Trusted Publisher auf PyPI veröffentlicht, was etwa jeder achten Datei entspricht, die seit der Verfügbarkeit auf PyPI hochgeladen wurde. Darüber hinaus hat das Design von PyPI ähnliche Designs in den Ökosystemen Rust (crates.io), Ruby (RubyGems) und JavaScript (npm) inspiriert.

Das Fehlen eines Standards für Trusted Publishing stellt ein langfristiges Hindernis für die Akzeptanz dar: Drittanbieter-Indizes (d. h. andere als PyPI und TestPyPI) können Trusted Publishing nicht einfach implementieren, ohne auf das nicht standardisierte Design von PyPI zurückzugreifen. Dies wiederum birgt ein langfristiges Reifrisiko, ähnlich dem der nicht standardisierten Upload-API: Paket-Upload-Clients (wie Twine und uv) müssen entweder Verhaltensunterschiede zwischen Indizes akzeptieren (was zu einer Ansammlung von Hacks führt) oder weiterhin Nicht-PyPI-Implementierungen von Trusted Publishing ablehnen.

Begründung

Das Fehlen eines bestehenden Standards für Trusted Publishing ist die primäre Begründung für diese PEP.

Das in dieser PEP vorgeschlagene Design folgt eng der bestehenden Implementierung von PyPI, mit einer zusätzlichen Schicht der Entdeckung, die es Upload-Clients ermöglicht, festzustellen, ob ein beliebiger Index Trusted Publishing unterstützt, ohne PyPI-spezifische Annahmen zu treffen.

Die Begründung für dieses Design lautet wie folgt

  1. Die bestehende (nicht standardisierte) Implementierung von Trusted Publishing auf PyPI hat eine nachgewiesene Erfolgsbilanz und ist bereits weit verbreitet in Upload-Tools. Eine signifikante Abweichung vom bestehenden Design würde unnötige Kompatibilitätsrisiken mit sich bringen.
  2. Der in dieser PEP vorgeschlagene Entdeckungsmechanismus ist so konzipiert, dass er mit bestehenden Standards für Machine-to-Machine-Protokolle, insbesondere RFC 8615 (Well-Known URIs), übereinstimmt. Darüber hinaus ermöglicht dieser Entdeckungsmechanismus, dass mehrere Indizes unter einer einzigen Domäne gehostet werden können, was eine gängige Topologie für Hosts von Drittanbieterindizes ist.

Zusammenfassend lässt sich sagen, dass die Begründung für diese PEP darin besteht, die bestehenden Schnittstellen von PyPI zu standardisieren und sie auffindbar zu machen, während gleichzeitig Index-Hosts, die nicht PyPIs Topologie entsprechen, die Implementierung von Trusted Publishing ermöglicht wird.

Spezifikation

Die Spezifikation dieser PEP besteht aus zwei Teilen

  • Ein Entdeckungsmechanismus, den Paket-Upload-Clients verwenden können, um festzustellen, ob ein beliebiger Python-Paketindex-Host Trusted Publishing unterstützt.
  • Ein Token-Austauschmechanismus, den Paket-Upload-Clients verwenden können, um ein Identitäts-Credential gegen ein Upload-Credential auszutauschen.

Beschränkungen

Sofern nicht ausdrücklich anders angegeben, gelten für alle Teile der Spezifikation dieser PEP die folgenden Beschränkungen

  • Alle URLs MÜSSEN potenziell vertrauenswürdige Ursprünge haben. In der Praxis bedeutet dies, dass alle URLs MÜSSEN das Schema https verwenden, eine Variante der lokalen Schleife (localhost, 127.0.0.1 usw.) sein oder andernfalls im Kontext der Interaktion als a priori vertrauenswürdig gelten (z. B. ein internes Netzwerk).

    Upload-Clients MÜSSEN alle URLs ablehnen, die diese Beschränkung nicht erfüllen.

  • Alle vom Server gelieferten URLs (d. h. die in Entdeckungsantworten) MÜSSEN die gleiche Host-Unterkomponente wie die vom Benutzer bereitgestellte Upload-URL haben. Upload-Clients MÜSSEN alle URLs ablehnen, die diese Beschränkung nicht erfüllen.

    In der Praxis bedeutet dies, dass eine Entdeckungsanfrage an https://upload.example.com/.well-known/pytp/{key} nur URLs mit dem Host upload.example.com zurückgeben kann.

  • Alle Client-Anfragen SOLLTEN einen Header Accept: application/vnd.pypi.pytp.v1+json haben. Bei Fehlen eines Accept-Headers MUSS der empfangende Server so verhalten, als wäre dieser Header vorhanden.

    Empfangende Server SOLLTEN mit einem Statuscode 406 Not Acceptable antworten, wenn ein anderer Accept-Header vorhanden ist.

Trusted Publishing Discovery

Das gesamte Python-Paket-Hochladen ist derzeit „endpunktgesteuert“, in dem Sinne, dass Upload-Clients (wie twine und uv) eine Upload-URL (und nicht nur einen Domainnamen) erhalten.

Um beispielsweise auf PyPI hochzuladen, sollen Upload-Clients eine Verbindung zu https://upload.pypi.org/legacy/ herstellen.

Der nachfolgend vorgeschlagene Entdeckungsmechanismus nutzt diese Tatsache aus, um es einzelnen Domänen zu ermöglichen, Unterstützung für mehrere Indizes (und ihre entsprechenden Upload-Endpunkte) anzukündigen.

Der Entdeckungsmechanismus ist wie folgt

  1. Der Upload-Client erhält eine Upload-URL, z. B. https://upload.example.com/legacy/.
  2. Der Upload-Client extrahiert die Pfadkomponente der URL, wie in RFC 3986 definiert. Wenn die Pfadkomponente leer ist, sollte der leere String verwendet werden.

    Für das obige Beispiel ist die Pfadkomponente /legacy/.

  3. Der Upload-Client nimmt den SHA2-256-Hash der Pfadkomponente und erzeugt den discovery key.

    Für das obige Beispiel ist der discovery key 0cace9579789849db6e16d48df183951c8f17582200d84bc93c7678d6c8f78a7. [1]

  4. Der Upload-Client konstruiert eine discovery URL, indem er die Schema- und Komponenten desAuthority (wie in RFC 3986 definiert) der Upload-URL nimmt und /.well-known/pytp/ und den discovery key anhängt.

    Für das obige Beispiel ist die discovery URL https://upload.example.com/.well-known/pytp/af030c06750716b1b35852298fe852b90def13dcbd012a5fe5148470f1206bfc.

  5. Der Upload-Client führt eine HTTP GET-Anfrage an die discovery URL aus.
  6. Der Server antwortet mit einem Statuscode 200 OK und einem Body, der ein JSON-Objekt enthält, wenn der Index Trusted Publishing für die gegebene Upload-URL unterstützt. Das JSON-Objekt MUSS die folgenden Felder enthalten
    • audience-endpoint: ein String, der die URL des OIDC-Audience-Endpunkts enthält, der während des Token-Austauschs verwendet werden soll.
    • token-mint-endpoint: ein String, der die URL des Token-Minting-Endpunkts enthält, der während des Token-Austauschs verwendet werden soll.

    Für das obige Beispiel wäre ein gültiger Antwortbody

    {
       "audience-endpoint": "https://upload.example.com/_/oidc/audience",
       "token-mint-endpoint": "https://upload.example.com/_/oidc/mint-token"
    }
    

Wenn der Server Trusted Publishing für die gegebene Upload-URL nicht unterstützt, MUSS er mit einem Statuscode 404 Not Found antworten. Bei der Antwort mit einem 404 Not Found SOLLTE der Server KEINEN Antwortbody enthalten. Wenn ein Antwortbody enthalten ist, MUSS er vom Client ignoriert werden.

Server KÖNNEN zusätzlich mit jedem anderen Standard-HTTP-Fehlercode im Bereich 400 oder 500 antworten, um einen Fehlerzustand anzuzeigen.

Antworten, die NICHT 200 OK und NICHT 404 Not Found sind, KÖNNEN einen Body enthalten, der, falls vorhanden, ein JSON-Objekt mit einer Error Response sein MUSS.

Trusted Publishing Token Exchange

Sobald ein Upload-Client einen erfolgreichen Entdeckungsablauf durchgeführt hat, kann er mit dem eigentlichen Trusted Publishing Token-Austausch fortfahren.

Der Token-Austausch erfolgt in drei Schritten

  1. Der Upload-Client verwendet den während der Entdeckung erhaltenen Audience-Endpunkt, um den Index nach seinem erwarteten OIDC-Audience zu fragen.
  2. Der Upload-Client verwendet den erwarteten Audience, um ein entsprechend gebundenes Identity-Credential vom verwendeten Trusted Publishing Provider zu erhalten (d. h. vom CI/CD- oder Cloud-Provider, von dem aus der Upload durchgeführt wird). Die Details dieses Schritts sind anbieterspezifisch und liegen außerhalb des Geltungsbereichs dieser PEP. [2]
  3. Der Upload-Client verwendet den während der Entdeckung erhaltenen Token-Minting-Endpunkt, um das erhaltene Identity-Credential gegen ein kurzlebiges Upload-Credential auszutauschen, das zum Hochladen in den Index verwendet werden kann.

Audience Retrieval

Um den erwarteten OIDC-Audience abzurufen, führt der Upload-Client eine HTTP GET-Anfrage an den Audience-Endpunkt aus, der während der Entdeckung erhalten wurde.

Bei Erfolg antwortet der Server mit einem Statuscode 200 OK und einem Body, der ein JSON-Objekt mit dem folgenden Feld enthält

  • audience: ein String, der den erwarteten OIDC-Audience enthält.

Bei einem Fehler MUSS der Server mit jedem Standard-HTTP-Fehlercode im Bereich 400 oder 500 antworten, um einen Fehlerzustand anzuzeigen. Fehlerantworten KÖNNEN einen Body enthalten, der, falls vorhanden, ein JSON-Objekt mit einer Error Response sein MUSS.

Token Minting

Nachdem der Upload-Client Audience-Abruf durchgeführt und ein Identity-Credential vom Trusted Publishing Provider erhalten hat, kann er mit dem Prägen eines Upload-Credentials fortfahren.

Um ein Upload-Credential zu prägen, führt der Upload-Client eine HTTP POST-Anfrage an den während der Entdeckung erhaltenen Token-Minting-Endpunkt aus. Der Body der POST-Anfrage MUSS ein JSON-Objekt sein, das Folgendes enthält

  • token: ein String, der das vom Trusted Publishing Provider erhaltene Identity-Credential enthält.

Bei Erfolg antwortet der Server mit einem Statuscode 200 OK und einem Body, der ein JSON-Objekt mit den folgenden Feldern enthält

  • token: ein String, der das Upload-Credential enthält. Das Format des Upload-Credentials ist implementierungsdefiniert und indexspezifisch.
  • expires: eine optionale Ganzzahl, die einen Unix-Zeitstempel enthält, der angibt, wann das Upload-Credential abläuft. Wenn dieses Feld nicht vorhanden ist, KANN der Upload-Client einen Ablaufpunkt von nicht mehr als 15 Minuten (900 Sekunden) nach dem Zeitpunkt seiner Anfrage annehmen.

    Der Server DURFTE keine temporären Upload-Credentials ausstellen, die weniger als 15 Minuten (900 Sekunden) oder mehr als 6 Stunden (21.600 Sekunden) ab dem Zeitpunkt der Anfrage ablaufen.

    Die maximale Ablaufzeit von 6 Stunden wird gewählt, um mit gängigen Laufzeitbeschränkungen bei beliebten CI/CD-Anbietern wie GitHub Actions übereinzustimmen.

    Der Upload-Client KANN diese Zeit (oder die oben angegebene Mindestdauer) verwenden, um zu bestimmen, wann das Upload-Credential bei Bedarf aktualisiert werden soll.

Bei einem Fehler MUSS der Server mit jedem Standard-HTTP-Fehlercode im Bereich 400 oder 500 antworten, um einen Fehlerzustand anzuzeigen. Fehlerantworten MÜSSEN einen Body enthalten, der, falls vorhanden, ein JSON-Objekt mit einer Error Response sein MUSS.

Fehlerantworten

Wenn ein Fehlerantwortbody enthalten ist, MUSS es sich um ein JSON-Objekt handeln, das die folgenden Felder enthält

  • message: ein String, der eine kurze, oberflächliche
    menschenlesbare Zusammenfassung des Fehlers enthält.
  • errors: ein Array aus einem oder mehreren Objekten, die jeweils
    die folgenden Felder enthalten
    • code: ein String, der einen maschinenlesbaren Fehlercode enthält.
    • description: ein String, der eine menschenlesbare Beschreibung des Fehlers enthält.

Diese PEP legt keine bestimmten Fehlercodes fest. Clients SOLLTEN NICHT davon ausgehen, dass Fehlercodes über verschiedene Indizes hinweg konsistent sind, und MÜSSEN stattdessen Fehlercodes als undurchsichtige Strings behandeln.

Sicherheitsimplikationen

Diese PEP zielt darauf ab, die Sicherheit und Transparenz des Python-Packaging-Ökosystems zu verbessern, indem der von PyPI bereits verwendete Trusted Publishing Flow formal standardisiert wird.

Diese PEP identifiziert keine positiven oder negativen Sicherheitsauswirkungen im Zusammenhang mit den Trusted Publishing Discovery- oder Exchange-Flows selbst.

Unabhängig von den Flows hat Trusted Publishing selbst ein Sicherheitsmodell auf PyPI und gilt als sicherere Alternative zu langlebigen API-Tokens oder Passwörtern. Die primären positiven Sicherheitsauswirkungen von Trusted Publishing sind

  • Alle ausgestellten Upload-Credentials sind kurzlebig und können minimal zugewiesen werden, was die „Blast-Radius“ eines kompromittierten Credentials begrenzt. Insbesondere bedeutet die automatische Ablaufzeit, dass Angreifer keine „Harvest now, use later“-Kampagnen gegen Pakete starten können, die Trusted Publishing verwenden.
  • Trusted Publishing verknüpft konzeptionell ein hochgeladenes Paket mit der Identität des CI/CD- oder Cloud-Providers, der zum Hochladen autorisiert ist. Diese Verknüpfung ist aus Sicht der nachgelagerten Konsumenten implizit, kann aber durch PEP 740 Atteste oder (weniger formell) URL-Verifizierung explizit gemacht werden.

Abwärtskompatibilität

Diese PEP ändert kein bestehendes Verhalten und ist vollständig abwärtskompatibel mit bestehenden Upload-Clients und Indizes.

Bestehende Clients, die den nicht standardmäßigen Trusted Publishing Upload-Flow von PyPI verwenden, funktionieren weiterhin wie bisher, ebenso wie bestehende Uploads zu allen Indizes, die Trusted Publishing nicht implementieren.

Wie man das lehrt

Diese PEP ist eine Formalisierung von Trusted Publishing, das bereits breite Akzeptanz im Python-Packaging-Ökosystem gefunden hat. Diese Akzeptanz wurde von einer Vielzahl von Schulungsressourcen zur Einführung von Trusted Publishing als Endbenutzer begleitet, darunter

Abgelehnte Ideen

„Laterale“ Entdeckung

Der Entdeckungsmechanismus dieser PEP verwendet das .well-known Location Scheme, das in RFC 8615 definiert ist. Dieses Scheme wird von Machine-to-Machine-Protokollen weitgehend übernommen, einschließlich OpenID Connect selbst (für OpenID Connect Discovery).

Eine alternative Idee war die Verwendung eines „lateralen“ Entdeckungsmechanismus, bei dem der Upload-Client die Entdeckung versucht, indem er einen benachbarten Pfad relativ zur Upload-URL konstruiert. Zum Beispiel würde bei https://upload.example.com/legacy/ der Upload-Client versuchen, die Unterstützung für Trusted Publishing unter https://upload.example.com/legacy/pytp (oder einer entsprechenden URL) zu entdecken.

Der Vorteil dieses Ansatzes besteht darin, dass Indexbetreiber keine Kontrolle über ihre (Sub-)Domäne haben müssen, was das .well-known Scheme erfordert (da Well-Known-URIs vom Stamm einer Domäne aus bedient werden können).

Dieser Ansatz hat jedoch auch Nachteile

  • Er geht davon aus, dass beliebige Indizes einen benachbarten Pfad bereitstellen können, ohne bestehende Funktionalität zu beeinträchtigen, was nicht unbedingt der Fall ist. Zum Beispiel kann eine bestimmte Drittanbieter-Implementierung bereits alle Routen unter /legacy/{*} für andere Zwecke verwenden.
  • Er ist weniger konsistent mit bestehenden Konventionen für Machine-to-Machine-Protokolle, die überwiegend das .well-known Scheme verwenden. Die Entwicklung eines benutzerdefinierten Location Schemes hier würde zusätzliche Informationsmaterialien für Serveradministratoren und Betreiber erfordern, die an das .well-known Scheme gewöhnt sind.

„Implizite“ Entdeckung

Eine weitere alternative Idee war die Durchführung einer „impliziten“ Entdeckung, ähnlich dem, was PyPI derzeit für Trusted Publishing tut: Anstatt eines expliziten Entdeckungsschritts könnte der Upload-Client direkt mit dem Versuch der Audience- und Token-Minting-Schritte fortfahren und alle auftretenden Fehler behandeln.

Der Vorteil dieses Ansatzes ist die Einfachheit: Er eliminiert den Netzwerk-Roundtrip für den Entdeckungsschritt und eliminiert die indirekte Abfrage der Audience- und Token-Minting-Endpunkte aus der Entdeckungsantwort.

Auch dieser Ansatz hat Nachteile

  • Er beschränkt implizit eine gegebene Domäne auf eine einzige Index/Upload-Implementierung, da der implizite „Entdeckungsschritt“ auf PyPI darin besteht, die Audience- und Token-Minting-Endpunkte gegen die Basisdomäne der Upload-URL zu konstruieren. Diese Beschränkung ist im Kontext eines einzelnen Index-Hosts wie PyPI akzeptabel, lässt sich aber nicht auf andere Index-Topologien übertragen (wie Index-Hosts, die isolierte private Indizes bereitstellen).
  • Er stützt sich auf vollständig statische Endpunktkonstruktionsregeln für die Audience- und Token-Minting-Endpunkte, was erhebliche Störungen für bestehende Clients bedeutet, wenn diese Endpunkte jemals geändert werden müssen.

Fußnoten


Quelle: https://github.com/python/peps/blob/main/peps/pep-0807.rst

Zuletzt geändert: 2025-09-30 20:28:20 GMT