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

Python Enhancement Proposals

PEP 381 – Spiegelinfrastruktur für PyPI

Autor:
Tarek Ziadé <tarek at ziade.org>, Martin von Löwis <martin at v.loewis.de>
Status:
Zurückgezogen
Typ:
Standards Track
Thema:
Packaging
Erstellt:
21.03.2009
Post-History:


Inhaltsverzeichnis

Zusammenfassung

Dieses PEP beschreibt eine Spiegelinfrastruktur für PyPI.

Rücknahme eines PEP

Der Haupt-Webdienst von PyPI wurde im Mai 2013 hinter das Fastly Caching CDN verlegt: https://mail.python.org/pipermail/distutils-sig/2013-May/020848.html

Anschließend wurde diese Vereinbarung als Sachleistungssponsoring mit der PSF formalisiert, und die PSF hat auch die Aufgabe des Risikomanagements übernommen, falls diese Sponsoringvereinbarung jemals beendet werden sollte.

Die Download-Statistiken, die zuvor direkt auf PyPI bereitgestellt wurden, werden nun indirekt über Google Big Query veröffentlicht: https://packaging.python.org/guides/analyzing-pypi-package-downloads/

Daher ist der in diesem PEP beschriebene Spiegelvorschlag nicht mehr erforderlich und wurde als zurückgezogen markiert.

Begründung

PyPI hostet über 6000 Projekte und wird täglich von Leuten zum Erstellen von Anwendungen genutzt. Insbesondere Systeme wie easy_install und zc.buildout nutzen PyPI intensiv.

Für Leute, die PyPI intensiv nutzen, kann es zu einem Single Point of Failure werden. Leute haben begonnen, einige Spiegel einzurichten, sowohl private als auch öffentliche. Diese Spiegel sind aktive Spiegel, was bedeutet, dass sie PyPI durchsuchen, um synchronisiert zu werden.

Um das System zuverlässiger zu machen, beschreibt dieses PEP

  • die Spiegelauflistung und Registrierung bei PyPI
  • die Seiten, die ein öffentlicher Spiegel pflegen sollte. Diese Seiten werden von PyPI verwendet, um Trefferzahlen und das Datum der letzten Änderung zu erhalten.
  • wie ein Spiegel mit PyPI synchronisieren sollte
  • wie ein Client einen Fail-over-Mechanismus implementieren kann

Spiegelauflistung und Registrierung

Personen, die PyPI spiegeln möchten, machen einen Vorschlag bei catalog-SIG. Wenn ein Spiegel in der Mailingliste vorgeschlagen wird, wird er manuell in eine Spiegel-Liste in der PyPI-Anwendung aufgenommen, nachdem er auf Konformität mit den Spiegelregeln geprüft wurde.

Die Spiegel-Liste wird als Liste von Hostnamen des Formats bereitgestellt

X.pypi.python.org

Die Werte von X sind die Sequenz a,b,c,…,aa,ab,… a.pypi.python.org ist der Master-Server; die Spiegel beginnen mit b. Ein CNAME-Eintrag last.pypi.python.org verweist auf den letzten Hostnamen. Spiegelbetreiber sollten eine statische Adresse verwenden und geplante Änderungen an dieser Adresse im Voraus an distutils-sig melden.

Der neue Spiegel erscheint auch unter http://pypi.python.org/mirrors, einer menschenlesbaren Seite, die die Liste der Spiegel anzeigt. Diese Seite erklärt auch, wie ein neuer Spiegel registriert wird.

Statistikseite

PyPI bietet Statistiken über Downloads unter /stats. Diese Seite wird täglich von PyPI berechnet, indem die lokalen Statistiken aller Spiegel gelesen und summiert werden.

Die Statistiken werden in täglichen oder monatlichen Dateien unter /stats/days und /stats/months präsentiert. Jede Datei ist eine bzip2-Datei mit diesen Formaten

  • YYYY-MM-DD.bz2 für tägliche Dateien
  • YYYY-MM.bz2 für monatliche Dateien

Beispiele

  • /stats/days/2008-11-06.bz2
  • /stats/days/2008-11-07.bz2
  • /stats/days/2008-11-08.bz2
  • /stats/months/2008-11.bz2
  • /stats/months/2008-10.bz2

Spiegelauthentizität

Bei einem verteilten Spiegelungssystem möchten Clients möglicherweise überprüfen, ob die gespiegelten Kopien authentisch sind. Es gibt mehrere Bedrohungen zu berücksichtigen

  1. der zentrale Index kann kompromittiert werden
  2. der zentrale Index wird als vertrauenswürdig angenommen, aber die Spiegel könnten manipuliert werden.
  3. ein Man-in-the-Middle zwischen dem zentralen Index und dem Endbenutzer oder zwischen einem Spiegel und dem Endbenutzer könnte Datagramme manipulieren.

Diese Spezifikation befasst sich nur mit der zweiten Bedrohung. Es werden einige Vorkehrungen getroffen, um Man-in-the-Middle-Angriffe zu erkennen. Um den ersten Angriff zu erkennen, müssen Paketautoren ihre Pakete mit PGP-Schlüsseln signieren, damit Benutzer überprüfen, ob das Paket von dem vertrauenswürdigen Autor stammt.

Der zentrale Index stellt einen DSA-Schlüssel unter der URL /serverkey im PEM-Format bereit, wie er von "openssl dsa -pubout" generiert wird (d.h. RFC 3280 SubjectPublicKeyInfo, mit dem Algorithmus 1.3.14.3.2.12). Diese URL darf *nicht* gespiegelt werden, und Clients müssen den offiziellen Serverkey direkt von PyPI abrufen oder die im PyPI-Client-Software enthaltene Kopie verwenden. Spiegel sollten den Schlüssel dennoch herunterladen, um einen Schlüsselwechsel zu erkennen.

Für jedes Paket wird eine gespiegelte Signatur unter /serversig/<package> bereitgestellt. Dies ist die DSA-Signatur der parallelen URL /simple/<package> im DER-Format, unter Verwendung von SHA-1 mit DSA (d.h. als RFC 3279 Dsa-Sig-Value, erstellt vom Algorithmus 1.2.840.10040.4.3)

Clients, die einen Spiegel verwenden, müssen die folgenden Schritte ausführen, um ein Paket zu verifizieren

  1. die /simple-Seite herunterladen und ihren SHA-1-Hash berechnen
  2. die DSA-Signatur dieses Hashs berechnen
  3. das entsprechende /serversig herunterladen und es (Byte für Byte) mit dem in Schritt 2 berechneten Wert vergleichen.
  4. die MD-5-Hashes aller von ihnen vom Spiegel heruntergeladenen Dateien berechnen und verifizieren (anhand der /simple-Seite).

Eine Implementierung des Verifizierungsalgorithmus ist verfügbar unter https://svn.python.org/packages/trunk/pypi/tools/verify.py

Die Verifizierung ist beim Herunterladen vom zentralen Index nicht erforderlich und sollte vermieden werden, um den Rechenaufwand zu reduzieren.

Ungefähr einmal im Jahr wird der Schlüssel durch einen neuen ersetzt. Spiegel müssen alle /serversig-Seiten neu abrufen. Clients, die Spiegel verwenden, müssen eine vertrauenswürdige Kopie des neuen Serverschlüssels finden. Eine Möglichkeit, ihn zu erhalten, ist der Download von https://pypi.python.org/serverkey. Um Man-in-the-Middle-Angriffe zu erkennen, müssen Clients das SSL-Serverzertifikat verifizieren, das von der CACert-Autorität signiert wird.

Spezielle Seiten, die ein Spiegel bereitstellen muss

Ein Spiegel ist eine Teilkopie von PyPI, daher bietet er dieselbe Struktur, indem er sie kopiert.

  • simple: REST-Version des Paketindex
  • packages: Pakete, gespeichert nach Python-Version und Buchstaben
  • serversig: Signaturen für die einfachen Seiten

Er muss auch zwei spezielle Elemente bereitstellen

  • last-modified
  • local-stats

Datum der letzten Änderung

CPAN verwendet ein Aktualisierungsdatumsystem, bei dem das letzte Synchronisationsdatum des Spiegels verfügbar gemacht wird.

Für PyPI muss jeder Spiegel eine URL mit einfachem Textinhalt pflegen, der das letzte Synchronisationsdatum darstellt, das der Spiegel pflegt.

Das Datum wird in GMT-Zeit im ISO 8601-Format angegeben [2]. Jeder Spiegel ist für die Pflege seines letzten Änderungsdatums verantwortlich.

Diese Seite muss sich unter befinden: /last-modified und muss eine text/plain-Seite sein.

Lokale Statistiken

Jeder Spiegel ist dafür verantwortlich, alle Downloads zu zählen, die über ihn erfolgt sind. Dies wird von PyPI verwendet, um alle Downloads zu summieren und die Gesamtsumme anzuzeigen.

Diese Statistiken sind in CSV-ähnlicher Form, mit einer Kopfzeile in der ersten Zeile. Sie müssen PEP 305 gehorchen. Grundsätzlich sollte sie vom Python-eigenen csv-Modul lesbar sein.

Die Felder in dieser Datei sind

  • package: die Distutils-ID des Pakets.
  • filename: der Dateiname, der heruntergeladen wurde.
  • useragent: der User-Agent des Clients, der das Paket heruntergeladen hat.
  • count: die Anzahl der Downloads.

Der Inhalt wird so aussehen

# package,filename,useragent,count
zc.buildout,zc.buildout-1.6.0.tgz,MyAgent,142
...

Die Zählung beginnt am Tag, an dem der Spiegel gestartet wird, und es gibt eine Datei pro Tag, komprimiert im bzip2-Format. Jede Datei ist wie der Tag benannt. Zum Beispiel ist 2008-11-06.bz2 die Datei für den 6. November 2008.

Sie werden dann in einem Ordner namens days bereitgestellt. Zum Beispiel

  • /local-stats/days/2008-11-06.bz2
  • /local-stats/days/2008-11-07.bz2
  • /local-stats/days/2008-11-08.bz2

Diese Seite muss sich unter befinden /local-stats.

Wie ein Spiegel mit PyPI synchronisieren sollte

Ein Spiegelprotokoll namens Simple Index wurde von Martin v. Loewis und Jim Fulton beschrieben und implementiert, basierend darauf, wie easy_install funktioniert. Dieser Abschnitt fasst es zusammen und gibt ein paar relevante Links, plus einen kleinen Teil über User-Agent.

Das Spiegelprotokoll

Spiegel müssen die Menge der zwischen dem zentralen Server und dem Spiegel übertragenen Daten reduzieren. Um dies zu erreichen, MÜSSEN sie den changelog() PyPI XML-RPC-Aufruf verwenden und nur die Pakete neu abrufen, die seit dem letzten Mal geändert wurden. Für jedes Paket P MÜSSEN sie die Dokumente /simple/P/ und /serversig/P kopieren. Wenn ein Paket auf dem zentralen Server gelöscht wird, MÜSSEN sie das Paket und alle zugehörigen Dateien löschen. Um Änderungen an Paketdateien zu erkennen, KÖNNEN sie die ETag der Datei zwischenspeichern und sie mit dem If-none-match-Header überspringen.

Jedes Spiegelwerkzeug MUSS sich mit einem beschreibenden User-Agent-Header identifizieren.

Das Paket pep381client [1] bietet eine Anwendung, die dieses Protokoll beim Browsen von PyPI einhält.

User-Agent-Request-Header

Um Aktionen von Clients über PyPI unterscheiden zu können, sollte ein spezifischer User-Agent-Name von aller Spiegelsoftware bereitgestellt werden.

Dies gilt auch für alle Clients wie

XXX Registrierungsmechanismus für User-Agents bei PyPI?

Wie ein Client PyPI und seine Spiegel nutzen kann

Clients, die PyPI durchsuchen, sollten alternative Spiegel nutzen können, indem sie die Liste der Spiegel über last.pypi.python.org abrufen.

Codebeispiel

>>> import socket
>>> socket.gethostbyname_ex('last.pypi.python.org')[0]
'h.pypi.python.org'

Die bisherigen Clients, die diesen Mechanismus nutzen konnten

  • setuptools
  • zc.buildout (über setuptools)
  • pip

Fail-over-Mechanismus

Clients, die PyPI durchsuchen, sollten in der Lage sein, alternative Spiegel zu verwenden, wenn PyPI oder der verwendete Spiegel nicht reagiert.

Es liegt am Client zu entscheiden, welcher Spiegel verwendet werden soll, möglicherweise basierend auf seiner geografischen Lage und seiner Reaktionsfähigkeit.

Dieses PEP beschreibt nicht, wie dieser Fail-over-Mechanismus funktionieren soll, aber es wird dringend empfohlen, dass die Clients versuchen, den nächstgelegenen Spiegel zu verwenden.

Die bisherigen Clients, die diesen Mechanismus nutzen konnten

  • setuptools
  • zc.buildout (über setuptools)
  • pip

Zusätzliche Paketindizes

Es ist offensichtlich, dass einige Pakete nicht auf PyPI hochgeladen werden, sei es, weil sie privat sind oder weil der Projektmanager seinen eigenen Server betreibt, von dem aus Benutzer das Projektpaket erhalten können. Es wird jedoch dringend empfohlen, dass ein öffentlicher Paketindex PyPI- und Distutils-Protokolle befolgt.

Mit anderen Worten, die Befehle register und upload sollten mit jedem Paketindex-Server kompatibel sein.

Software, die bisher mit PyPI und Distutils kompatibel ist

  • PloneSoftwareCenter [6], das zum Ausführen des Produktbereichs von plone.org verwendet wird.
  • EggBasket [7].

Ein zusätzlicher Paketindex ist kein Spiegel von PyPI, kann aber eigene Spiegel haben.

Zusammenführung mehrerer Indizes

Wenn ein Client Pakete aus mehreren verschiedenen Indizes abrufen muss, sollte er in der Lage sein, jeden davon als potenziellen Paketlieferanten zu nutzen. Verschiedene Indizes sollten als sortierte Liste definiert werden, damit der Client nach einem Paket suchen kann.

Jeder unabhängige Index kann natürlich eine Liste seiner Spiegel bereitstellen.

XXX definieren, wie der Hostname für die Spiegel eines beliebigen Index bezogen wird.

Das ermöglicht alle Kombinationen auf Client-Ebene für ein zuverlässiges Paketiersystem mit allen Datenschutzniveaus.

Es liegt am Client, die Zusammenführung zu handhaben.

Referenzen

Danksagungen

Georg Brandl.


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

Zuletzt geändert: 2025-02-01 08:55:40 GMT