PEP 381 – PyPI 미러링 인프라
- Author:
- Tarek Ziadé <tarek at ziade.org>, Martin von Löwis <martin at v.loewis.de>
- Status:
- Withdrawn
- Type:
- Standards Track
- Topic:
- Packaging
- Created:
- 21-Mar-2009
- Post-History:
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
이 PEP는 PyPI를 위한 미러링 인프라를 설명합니다.
PEP 철회
2013년 5월에 PyPI의 기본 웹 서비스가 Fastly 캐싱 CDN 뒤로 이전되었습니다: https://mail.python.org/pipermail/distutils-sig/2013-May/020848.html
이후 이 방식은 PSF와의 현물 후원으로 공식화되었으며, PSF는 해당 후원 방식이 중단되는 경우의 위험 관리 업무도 맡았습니다.
이전에 PyPI에서 직접 제공되던 다운로드 통계는 이제 Google Big Query를 통해 간접적으로 게시됩니다: https://packaging.python.org/guides/analyzing-pypi-package-downloads/
따라서 이 PEP에서 설명하는 미러링 제안은 더 이상 필요하지 않으며, 철회됨으로 표시되었습니다.
근거
PyPI는 6000개가 넘는 프로젝트를 호스팅하며, 사람들은 애플리케이션을 구축하기 위해 매일 PyPI를 사용합니다. 특히 easy_install 및 zc.buildout과 같은 시스템은 PyPI를 집중적으로 사용합니다.
PyPI를 집중적으로 사용하는 사람들에게 PyPI는 단일 장애 지점으로 작용할 수 있습니다. 사람들은 비공개 및 공개 미러를 일부 구축하기 시작했습니다. 이러한 미러는 활성 미러입니다. 즉, 동기화하기 위해 PyPI를 탐색합니다.
시스템의 신뢰성을 높이기 위해 이 PEP는 다음 사항을 설명합니다:
- PyPI에서 미러를 나열하고 등록하는 방법
- 공개 미러가 유지해야 하는 페이지 PyPI는 적중 횟수와 최종 수정 날짜를 확인하기 위해 이러한 페이지를 사용합니다.
- 미러가 PyPI와 동기화하는 방법
- 클라이언트가 장애 조치 메커니즘을 구현하는 방법
미러 나열 및 등록
PyPI를 미러링하려는 사람은 catalog-SIG에 제안합니다. 메일링 리스트에서 미러가 제안되면, 미러링 규칙을 준수하는지 확인한 후 PyPI 애플리케이션의 미러 목록에 수동으로 추가합니다.
미러 목록은 다음 형식의 호스트 이름 목록으로 제공됩니다.
X.pypi.python.org
X의 값은 a,b,c,…,aa,ab,…의 순서입니다. a.pypi.python.org는 마스터 서버이며, 미러는 b부터 시작합니다. CNAME 레코드 last.pypi.python.org는 마지막 호스트 이름을 가리킵니다. 미러 운영자는 고정 주소를 사용해야 하며, 해당 주소에 대한 예정된 변경 사항을 distutils-sig에 미리 알려야 합니다.
새 미러는 미러 목록을 제공하는 사람이 읽을 수 있는 페이지인 http://pypi.python.org/mirrors에도 나타납니다. 이 페이지에서는 새 미러를 등록하는 방법도 설명합니다.
통계 페이지
PyPI는 /stats에서 다운로드 통계를 제공합니다. 이 페이지는 모든 미러의 로컬 통계를 읽고 합산하여 PyPI가 매일 계산합니다.
통계는 /stats/days 및 /stats/months 아래의 일별 또는 월별 파일로 제공됩니다. 각 파일은 다음 형식의 bzip2 파일입니다:
- 일별 파일의 경우 YYYY-MM-DD.bz2
- 월별 파일의 경우 YYYY-MM.bz2
예:
- /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
미러의 진위성
분산 미러링 시스템을 사용할 때 클라이언트는 미러링된 사본이 진본인지 확인하려 할 수 있습니다. 고려해야 할 위협은 여러 가지입니다.
- 중앙 색인이 손상될 수 있습니다.
- 중앙 색인은 신뢰할 수 있다고 가정되지만, 미러가 변조될 수 있습니다.
- 중앙 색인과 최종 사용자 사이 또는 미러와 최종 사용자 사이의 중간자가 데이터그램을 변조할 수 있습니다.
이 명세는 두 번째 위협만 다룹니다. 중간자 공격을 탐지하기 위한 일부 조항이 마련되어 있습니다. 첫 번째 공격을 탐지하려면 패키지 작성자가 PGP 키를 사용하여 패키지에 서명해야 하며, 이를 통해 사용자는 해당 패키지가 자신이 신뢰하는 작성자로부터 온 것인지 확인할 수 있습니다.
중앙 색인은 “openssl dsa -pubout”으로 생성되는 PEM 형식(즉, 알고리즘 1.3.14.3.2.12를 사용하는 RFC 3280 SubjectPublicKeyInfo)의 DSA 키를 URL /serverkey에서 제공합니다. 이 URL은 미러링되어서는 안 되며, 클라이언트는 PyPI에서 직접 공식 serverkey를 가져오거나 PyPI 클라이언트 소프트웨어와 함께 제공된 사본을 사용해야 합니다. 미러는 키 롤오버를 탐지할 수 있도록 여전히 키를 다운로드해야 합니다.
각 패키지에 대해 /serversig/<package>에서 미러링된 서명이 제공됩니다. 이는 SHA-1과 DSA를 사용한 DER 형식의 대응 URL /simple/<package>에 대한 DSA 서명입니다(즉, 알고리즘 1.2.840.10040.4.3으로 생성된 RFC 3279 Dsa-Sig-Value입니다).
미러를 사용하는 클라이언트는 패키지를 검증하기 위해 다음 단계를 수행해야 합니다.
- /simple 페이지를 다운로드하고 SHA-1 해시를 계산합니다.
- 해당 해시의 DSA 서명을 계산합니다.
- 해당 /serversig를 다운로드하고, 이를 2단계에서 계산한 값과 바이트 단위로 비교합니다.
- 미러에서 다운로드하는 모든 파일의 MD-5 해시를 계산하고 /simple 페이지와 대조하여 검증합니다.
검증 알고리즘의 구현은 https://svn.python.org/packages/trunk/pypi/tools/verify.py 에서 구할 수 있습니다.
중앙 색인에서 다운로드할 때는 검증이 필요하지 않으며, 계산 오버헤드를 줄이기 위해 검증을 피해야 합니다.
약 1년에 한 번 키가 새 키로 교체됩니다. 미러는 모든 /serversig 페이지를 다시 가져와야 합니다. 미러를 사용하는 클라이언트는 새 서버 키의 신뢰할 수 있는 사본을 찾아야 합니다. 이를 얻는 한 가지 방법은 https://pypi.python.org/serverkey 에서 다운로드하는 것입니다. 중간자 공격을 탐지하려면 클라이언트는 CACert 기관이 서명할 SSL 서버 인증서를 검증해야 합니다.
미러가 제공해야 하는 특수 페이지
미러는 PyPI의 부분 복사본이므로, 이를 복사하여 동일한 구조를 제공합니다.
- simple: 패키지 색인의 REST 버전
- packages: Python 버전 및 문자별로 저장된 패키지
- serversig: simple 페이지의 서명
또한 다음 두 가지 특정 요소를 제공해야 합니다.
- last-modified
- local-stats
최종 수정 날짜
CPAN은 미러의 마지막 동기화 날짜를 제공하는 최신성 날짜 시스템을 사용합니다.
PyPI의 경우 각 미러는 미러가 유지하는 마지막 동기화 날짜를 나타내는 단순한 텍스트 콘텐츠가 포함된 URL을 유지해야 합니다.
날짜는 ISO 8601 형식 [2]을 사용하여 GMT 시간으로 제공됩니다. 각 미러는 최종 수정 날짜를 유지할 책임이 있습니다.
이 페이지는 /last-modified에 위치해야 하며 text/plain 페이지여야 합니다.
로컬 통계
각 미러는 해당 미러를 통해 수행된 모든 다운로드를 집계할 책임이 있습니다. PyPI는 전체 합계를 표시할 수 있도록 모든 다운로드를 합산하는 데 이 통계를 사용합니다.
이러한 통계는 CSV와 유사한 형식이며, 첫 번째 줄에 헤더가 있습니다. 이는 PEP 305를 준수해야 합니다. 기본적으로 Python의 csv 모듈로 읽을 수 있어야 합니다.
이 파일의 필드는 다음과 같습니다.
- package: 패키지의 distutils ID입니다.
- filename: 다운로드된 파일 이름입니다.
- useragent: 패키지를 다운로드한 클라이언트의 User-Agent입니다.
- count: 다운로드 횟수입니다.
콘텐츠는 다음과 같은 형태입니다.:
# package,filename,useragent,count
zc.buildout,zc.buildout-1.6.0.tgz,MyAgent,142
...
카운팅은 미러가 시작된 날부터 시작하며, 하루에 하나의 파일이 있고 bzip2 형식으로 압축됩니다. 각 파일의 이름은 날짜와 같습니다. 예를 들어, 2008-11-06.bz2는 2008년 11월 6일의 파일입니다.
그런 다음 days라는 폴더에 제공됩니다. 예를 들면 다음과 같습니다.
- /local-stats/days/2008-11-06.bz2
- /local-stats/days/2008-11-07.bz2
- /local-stats/days/2008-11-08.bz2
이 페이지는 /local-stats에 있어야 합니다.
미러가 PyPI와 동기화하는 방법
Simple Index라는 미러링 프로토콜은 Martin v. Loewis와 Jim Fulton이 easy_install의 작동 방식을 바탕으로 설명하고 구현했습니다. 이 절에서는 이를 종합하고 몇 가지 관련 링크와 User-Agent에 관한 간단한 내용을 제공합니다.
미러링 프로토콜
미러는 중앙 서버와 미러 사이에서 전송되는 데이터의 양을 줄여야 합니다. 이를 위해 미러는 changelog() PyPI XML-RPC 호출을 반드시 사용하고, 마지막 이후 변경된 패키지만 다시 가져와야 합니다. 각 패키지 P에 대해 미러는 /simple/P/ 및 /serversig/P 문서를 반드시 복사해야 합니다. 중앙 서버에서 패키지가 삭제되면 미러는 해당 패키지와 관련된 모든 파일을 반드시 삭제해야 합니다. 패키지 파일의 수정을 감지하기 위해 미러는 파일의 ETag를 캐시할 수 있으며, If-none-match 헤더를 사용하여 해당 파일을 건너뛰도록 요청할 수도 있습니다.
각 미러링 도구는 descripte User-agent 헤더를 사용하여 자신을 반드시 식별해야 합니다.
pep381client 패키지 [1]는 이 프로토콜을 준수하여 PyPI를 탐색하는 애플리케이션을 제공합니다.
User-agent 요청 헤더
PyPI에서 클라이언트가 수행한 작업을 구별할 수 있도록 모든 미러링 소프트웨어는 특정 사용자 에이전트 이름을 제공해야 합니다.
다음과 같은 모든 클라이언트에도 해당합니다.
PyPI의 XXX 사용자 에이전트 등록 메커니즘?
클라이언트가 PyPI와 해당 미러를 사용하는 방법
PyPI를 탐색하는 클라이언트는 last.pypi.python.org를 사용하여 미러 목록을 가져옴으로써 대체 미러를 사용할 수 있어야 합니다.
코드 예제:
>>> import socket
>>> socket.gethostbyname_ex('last.pypi.python.org')[0]
'h.pypi.python.org'
지금까지 이 메커니즘을 사용할 수 있는 클라이언트는 다음과 같습니다.
- setuptools
- zc.buildout (setuptools를 통해)
- pip
페일오버 메커니즘
PyPI를 탐색하는 클라이언트는 PyPI나 사용 중인 미러가 응답하지 않을 때 페일오버 메커니즘을 사용할 수 있어야 합니다.
어떤 미러를 사용할지는 클라이언트가 결정할 몫이며, 지리적 위치와 응답성 등을 참고할 수 있습니다.
이 PEP는 이 페일오버 메커니즘이 어떻게 동작해야 하는지는 기술하지 않지만, 클라이언트가 가장 가까운 미러를 사용하도록 시도할 것을 강력히 권장합니다.
지금까지 이 메커니즘을 사용할 수 있는 클라이언트는 다음과 같습니다:
- setuptools
- zc.buildout (setuptools를 통해)
- pip
추가 패키지 색인
프로젝트 관리자가 사람들이 프로젝트 패키지를 받을 수 있는 자체 서버를 운영하든, 비공개이든 간에 일부 패키지가 PyPI에 업로드되지 않으리라는 것은 명백합니다. 그러나 공개 패키지 색인은 PyPI 및 Distutils 프로토콜을 따를 것을 강력히 권장합니다.
다시 말해, register와 upload 명령어는 어떤 패키지 색인 서버와도 호환되어야 합니다.
지금까지 PyPI 및 Distutils와 호환되는 소프트�어:
추가 패키지 색인은 PyPI의 미러가 아니지만, 그 자체로 일부 미러를 가질 수 있습니다.
여러 색인 병합
클라이언트가 여러 개의 개별 색인에서 일부 패키지를 가져와야 할 때, 각 색인을 패키지의 잠재적 공급원으로 사용할 수 있어야 합니다. 서로 다른 색인들은 클라이언트가 패키지를 찾을 수 있도록 정렬된 목록으로 정의되어야 합니다.
각 독립적인 색인은 물론 자신의 미러 목록을 제공할 수 있습니다.
XXX 임의의 색인의 미러에 대한 호스트명을 얻는 방법을 정의합니다.
이는 모든 수준의 프라이버시를 갖춘 신뢰할 수 있는 패키징 시스템을 위해, 클라이언트 수준에서 모든 조합을 허용합니다.
병합을 처리하는 것은 클라이언트에게 달려 있습니다.
참고 문헌
감사의 말
Georg Brandl.
Copyright
This document has been placed in the public domain.