PEP 759 – 외부 휠 호스팅
- Author:
- Barry Warsaw <barry at python.org>, Emma Harper Smith <emma at python.org>
- PEP-Delegate:
- Donald Stufft <donald at python.org>
- Discussions-To:
- Discourse thread
- Status:
- Withdrawn
- Type:
- Standards Track
- Topic:
- Packaging
- Created:
- 01-Oct-2024
- Post-History:
- 10-Oct-2024, 31-Jan-2025
- Resolution:
- 31-Jan-2025
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain or CC0-1.0, whichever is more permissive 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
이 PEP는 pypi.org에 호스팅되는 프로젝트가 PyPI가 아닌 외부 사이트에 휠 아티팩트를 안전하게 호스팅할 수 있도록 하는 메커니즘을 제안합니다. 이 PEP는 프로젝트, 패키지 또는 그 메타데이터의 외부 호스팅을 명시적으로 제안하지 않습니다. 그러한 기능은 독립적인 패키지 색인을 외부에 호스팅하는 방식으로 이미 사용할 수 있습니다. 이 PEP는 프로젝트가 특정 릴리스의 wheel 아티팩트에 대해 다운로드 URL을 사용자 지정할 수 있는 메커니즘만 제공하므로, pip나 uv 같은 일반적인 설치 프로그램 도구에 이미 구현된 의존성 해석 방식은 바꿀 필요가 없습니다.
이 PEP는 이 맥락에서 “안전하다”는 것이 무엇을 의미하는지 정의하며, .rim 파일이라는 새로운 패키지 업로드 파일 형식도 정의합니다. 또한 .rim 파일이 패키지의 단순 저장소 API에서 HTML과 JSON 두 형식으로 반환되는 메타데이터에 어떤 영향을 미치는지, 그리고 기존 휠을 어떻게 손쉽게 .rim 파일로 바꿀 수 있는지 정의합니다.
PEP 철회
이 PEP는 2025-01-31에 저자들에 의해 철회되었습니다. 논의 스레드의 분위기를 저희가 읽기로는, 이 PEP가 해결하려는 문제들은 타당하지만 대부분의 사람들은 다른 접근 방식을 선호합니다. 구체적으로, 저희가 파악하기로는 대부분의 사용자가 여러 색인을 지정하는 기능, 그 색인들이 상호 운용되는 방식, 그리고 그 색인들의 우선순위와 신뢰 표명을 더 세밀하게 제어하기를 원합니다. 예를 들어 PEP 766 같은 해결책이 더 나은 방향을 제시할 수 있습니다. 그동안은 기존의 임시방편(예: PyPI 제한 상향 요청 및 “wheel-stub” 방식)으로도 이상적이지는 않더라도 충분합니다. 저자들은 건설적인 논의에 기여해 주신 모든 분께, 특히 공개적으로나 비공개적으로 이 PEP에 대한 지지를 보여 주신 분들께 감사드립니다.
근거
Python 패키지 색인(https://pypi.org)은 업로드 아티팩트 파일 크기(100 MiB)와 전체 프로젝트 크기(10 GiB)에 기본 제한을 둡니다. 대부분의 프로젝트는 수년에 걸쳐 업로드를 하더라도 프로젝트 수명 동안 이 제한 안에 넉넉히 들어갑니다. 일부 프로젝트는 이 제한에 부딪혀 파일 크기와 프로젝트 크기 모두에 대해 예외를 허가받았으며, 덕분에 소비자가 여전히 사용하고 있을 수 있는 파일(예: 버전 고정을 통해)을 삭제하는 것과 같은 더 과감한 조치를 취하지 않고도 새 릴리스를 계속 업로드할 수 있었습니다.
관련된 우회 방법으로 “wheel stub” 방식이 있는데, 이 방식은 PyPI와 이러한 제한을 피할 수 있는 외부 서드파티 패키지 색인 사이에 간접적인 연결을 제공합니다. 휠 스텁은 PEP 517 빌드 백엔드를 사용하는 소스 배포 (일명 “sdist”)로, 이 빌드 백엔드는 소스 코드를 바이너리 휠로 만드는 대신 외부에 호스팅된 기존 휠을 다운로드하여 설치할 URL을 계산하는 로직을 수행합니다. 이 방식은 동작하지만, 이 정보를 pip 또는 그 밖의 도구에 제시할 방법이 없기 때문에 PyPI, sdist, 외부에 호스팅된 휠 사이의 연결이 불분명해집니다.
역사적 배경
2013년에 PEP 438은 PyPI의 릴리스 파일 호스팅과 관련된 여러 측면을 수정하기 위해 “하위 호환성을 유지하는 2단계 전환 절차”를 제안했습니다. 이 PEP에 설명된 바와 같이, PyPI는 원래 아티팩트 파일 호스팅은 허용하지 않고 프로젝트와 릴리스의 등록만 지원했습니다. 그래서 대부분의 프로젝트는 릴리스 파일 아티팩트를 다른 곳에 호스팅했습니다. 이후 아티팩트 호스팅이 추가되었지만, 외부에 호스팅된 파일과 PyPI에 호스팅된 파일이 뒤섞이면서 사용성 문제와 잠재적인 보안 관련 문제가 폭넓게 발생했습니다. PEP 438은 PyPI 우선 호스팅을 장려하면서도 외부 호스팅을 허용하기 위한 여러 기능을 제공하려는 시도였습니다.
PEP 438은 세 가지 서로 다른 “호스팅 모드”, 호스팅 위치를 나타내기 위해 단순 HTML 색인 페이지에 넣는 rel 메타데이터, 그리고 PyPI와 설치 프로그램 도구에 영향을 주는 2단계 전환 계획을 포함하여 복잡했습니다. PEP 438은 결국 2015년에 PEP 470에 의해 철회되었으며, PEP 470은 PEP 438이 다음과 같은 점에서 성공했음을 인정합니다…
더 많은 사람이 PyPI의 저장소 기능을 활용하도록 이끌었다는 점으로, 이는 PyPI를 뒷받침하는 전 세계 CDN이 많은 사람에게 속도 향상을 제공한다는 점을 고려하면 전적으로 좋은 일입니다[…]
PEP 470은 외부 호스팅 대신 명시적으로 여러 저장소를 사용하도록 권장했습니다. 각 저장소는 완전한 패키지 색인과 아티팩트 호스팅을 제공하며, pip install --extra-index-url처럼 설치 프로그램 도구가 이를 지원합니다. 이 옵션을 사용하면 pip는 패키지 설치를 해석할 때 여러 저장소를 사실상 하나의 전역 저장소로 취급합니다. 이 방식이 오랫동안 공인된 표준이었기 때문에, 모든 Python 패키지 설치 도구는 의존성 해석을 위해 여러 색인을 조회하는 기능을 지원합니다.
다중 색인의 문제점
그렇다면 이 PEP는 왜 더 제한된 형태의 외부 호스팅을 허용하자고 제안하며, 이 제안은 PEP 470에 기술된 문제들을 어떻게 피합니까?
여러 색인을 통합할 때 발생하는 잘 알려진 문제 중 하나는 의존성 혼동 공격입니다. pip install이 패키지 의존성과 선호 버전을 해석하는 데 사용하는 알고리즘 때문에 Python은 이 공격에 특히 취약할 수 있습니다. uv 도구는 추가적인 색인 전략 옵션을 지원하여 이 문제를 해결합니다. 사용자는 이 옵션으로 예를 들어 pip 호환 전략과, 이러한 의존성 혼동 공격을 방지하는 더 제한적인 전략 중에서 선택할 수 있습니다.
PEP 708은 의존성 혼동 공격에 관한 추가 배경 정보를 제공하며, 이를 방지하기 위해 다른 접근 방식을 취합니다. PEP 708의 핵심은 저장소 소유자가 프로젝트가 서로 다른 저장소에 걸쳐 추적된다는 것을 표시할 수 있게 하는 것입니다. 그러면 설치 프로그램은 여러 저장소를 합칠 때 전역 패키지 네임스페이스를 어떻게 다룰지 결정할 수 있습니다. PEP 708은 PEP 708에 명시된 몇 가지 필수 조건을 전제로 잠정 승인되었으며, 그중 일부는 향후 전망이 불확실할 수 있습니다. PEP 708 스스로 밝히듯이 이것만으로 의존성 혼동 공격이 해결되지는 않습니다. 다만 설치 프로그램에 충분한 정보를 제공하여 이러한 공격을 최소화하는 데 도움이 되는 한 가지 방법입니다.
완전히 독립적인 패키지 색인을 구축하는 타당한 사용 사례가 여전히 있을 수 있지만(예를 들어 완전한 형태의 변형 제안이 승인되기 전까지 GPU에 대해 더 풍부한 플랫폼 지원을 제공하는 경우), 이 PEP는 다르고 더 단순한 접근 방식을 취하며 기존의, 제안된, 또는 승인된 패키지 색인 협력 명세 중 어느 것도 대체하지 않습니다.
또한 이 PEP는 PyPI의 핵심 목적을 보존하며, PyPI가 모든 Python 패키지의 전통적이고 정식인 중앙 색인으로 남을 수 있게 합니다.
PyPI 제한 해결
이 제안은 PyPI가 부과하는 크기 제한 문제도 해결합니다. PyPI에는 100 MiB의 기본 아티팩트 크기 제한과 10 GiB의 기본 전체 프로젝트 크기 제한이 있습니다. 대부분의 패키지와 아티팩트는 다양한 플랫폼용 바이너리 확장 모듈을 포함하는 패키지라 하더라도 이 제한 안에 쉽게 들어갑니다. 소수이지만 중요한 부류의 패키지는 일상적으로 이 제한을 초과하므로, PyPI 예외 요청 지원 티켓(exception request support tickets)을 제출해야 합니다. 이러한 예외를 해결받는 것이 반드시 어려운 것은 아니지만, 해결에 시간이 걸릴 수 있는 특별한 절차이며, 예외를 허가하는 기준도 잘 문서화되어 있지 않습니다.
운영 복잡성 감소
패키지 색인 전체를 구축하고 유지 관리하는 것은 시간과 자원이 많이 드는 복잡한 운영 방식일 수 있습니다. 그러한 색인의 주된 목적이 단지 파일 크기 제한을 피하는 것이라면 특히 그렇습니다. 외부 색인 방식은 또한 외부 색인에 있는 프로젝트의 사용자에게 까다로운 UX를 강요하여, --external-index-url 같은 CLI 옵션이 어떻게 동작하는지와 그러한 플래그의 보안상 영향까지 이해하도록 요구합니다. 대용량 휠 패키지의 제작자와 사용자 모두에게는 HTTP GET보다 복잡하지 않은 API로 개별 파일을 제공할 수 있는 단순한 웹 서버를 구축하고 유지 관리하는 편이 훨씬 쉬울 것입니다. 이러한 인터페이스는 캐시하기도 쉽고 CDN 뒤에 두기도 쉽습니다. 단순한 HTTP 서버는 보안 감사도 훨씬 쉽고 프록시하기도 쉬우며, 일반적으로 운영, 지원, 유지 관리에 드는 자원도 훨씬 적습니다. 심지어 Amazon S3 같은 것도 외부 휠을 호스팅하는 데 사용할 수 있습니다.
이 PEP는 이러한 운영상의 단순성을 중시하는 접근 방식을 제안합니다.
명세
업로드할 수 있는 새로운 유형의 파일인 “RIM”(즉, .rim), 또는 “원격 설치 가능 메타데이터(Remote Installable Metadata)” 파일을 정의합니다. 이 이름은 타이어를 벗겨 낸 휠(wheel)을 떠올리게 하며, .rim 파일을 .whl 파일에서 쉽게 만들 수 있다는 점을 강조합니다. .whl을 .rim으로 바꾸는 과정은 아래에서 개략적으로 설명합니다. 파일 이름 형식은 휠 파일 이름 형식 명세와 정확히 같습니다. 다만 RIM 파일은 .rim 접미사를 사용합니다. 따라서 .whl 파일을 구별하는 데 쓰이는 모든 태그로 서로 다른 .rim 파일도 구별할 수 있으며, 현재 .whl 파일에서와 똑같이 의존성 해결 단계에서 이 태그를 사용할 수 있습니다. 이런 점에서 .whl 파일과 .rim 파일은 서로 바꿔 쓸 수 있습니다.
.rim 파일의 내용은 .whl 파일과 거의 같습니다. 그러나 .rim 파일에는 휠의 .dist-info 디렉터리만 반드시 들어 있어야 합니다. .rim zip 파일에는 그 밖의 최상위 파일이나 디렉터리를 둘 수 없습니다. .dist-info 디렉터리에는 .whl 파일의 .dist-info 디렉터리에 허용되는(allowed) 파일 외에 추가 파일 하나가 반드시 들어 있어야 합니다. 그 파일의 이름은 EXTERNAL-HOSTING.json입니다.
이 파일은 다음 키를 담은 JSON 파일입니다.
version- 파일 형식 버전입니다. 이 PEP에서는 반드시
1.0이어야 합니다. owner- 외부에 호스팅된 이 파일을 소유한 PyPI 조직의 이름을 반드시 지정해야 합니다. 그 이유는 아래에서 자세히 설명합니다.
uri- 외부 사이트에 호스팅된 실제
.whl파일의 위치를 가리키는 단일 URL입니다. 이 URL은 반드시https스킴을 사용해야 합니다. size- 원격 호스트에 있는 실제
.whl파일의 크기를 바이트 단위로 나타내는 정수 값입니다. hashes- PEP 694에 설명된 형식의 딕셔너리입니다. 실제
.whl파일의 PEP 694을 담는 데 쓰이며, 그 PEP에서 제안한 것과 같은 제약 조건을 따릅니다. 이 해시는 PyPI에 한 번 업로드되면 바꿀 수 없으므로, 외부에 호스팅된 휠이 손상되거나 변조되지 않았음을 확인하는 중요한 검증 수단이 됩니다.
RIM 파일의 효과
.rim 파일의 유일한 효과는 simple repository API의 HTML 인터페이스와 JSON 인터페이스 모두에서 휠 아티팩트의 다운로드 URL을 바꾸는 것입니다. 패키지 릴리스의 HTML 페이지에서 href 속성은 반드시 uri 키의 값이어야 하며, #<hashname>=<hashvalue> 프래그먼트를 포함해야 합니다. 이 해시 프래그먼트는 반드시 PEP 376에서 비롯된 signed wheel file format이 .dist-info/RECORD 파일에 대해 설명하는 형식과 정확히 같아야 합니다. 해시 알고리즘 선택과 인코딩에도 이와 똑같은 규칙을 적용합니다.
마찬가지로 JSON response에서는 다운로드 파일을 가리키는 url 키가 uri 키의 값이어야 합니다. 또한 hashes 딕셔너리를 반드시 포함해야 하며, 그 값은 위에서 제공한 hashes 딕셔너리의 값으로 채웁니다.
그 밖의 모든 면에서 명세를 준수하는 패키지 색인은 .rim 파일을 .whl 파일과 똑같이 다루어야 합니다. 다만 아래에 설명하는 몇 가지 작은 예외가 있습니다. 예를 들어 .rim 파일도 여느 .whl 파일처럼 삭제하거나 철회(yank, PEP 592)할 수 있으며, 그 의미도 정확히 같습니다(즉, 삭제는 영구적입니다). .rim이 삭제되면 색인은 이에 대응하는 .whl 파일이나 .rim 파일의 (재)업로드를 허용해서는 안 됩니다.
사용 가능 순서
외부에 호스팅된 휠은 이에 대응하는 .rim 파일이 PyPI에 업로드되기 전에 반드시 사용 가능한 상태여야 합니다. 그렇지 않으면 게시 과정에서 경쟁 조건이 생깁니다. 다만 PEP 694 스테이징 릴리스에 업로드되는 .rim 파일에는 이 요구 사항을 완화할 수도 있습니다.
휠에 의한 RIM 재정의
파일 이름 태그가 정확히 같은 일치하는 .whl 파일이 이미 존재하는 경우, 색인은 .rim 파일을 반드시 거부해야 합니다. 그러나 일치하는 .rim 파일이 존재하더라도 그 .rim 파일이 삭제되거나 철회(yank)되지 않았다면, 색인은 .whl 파일을 허용할 수 있습니다. 이를 통해 업로드하는 사람은 외부에서 호스팅되는 wheel 파일을 색인에서 호스팅되는 wheel 파일로 교체할 수 있습니다. 그러나 그 반대는 금지됩니다. 기본적으로 wheel은 패키지 메타데이터가 있는 같은 패키지 색인에서 호스팅되므로, 이미 업로드된 기존 wheel 파일을 “다운그레이드”하는 것은 허용되지 않습니다. .whl이 .rim을 대체하는 경우, 색인은 자체 파일 호스팅 서비스를 사용하여 해당 패키지의 다운로드 URL을 반드시 제공해야 합니다. 재정의하는 .whl 파일을 업로드할 때 패키지 색인은 기존 .rim 파일의 해시를 반드시 검증해야 하며, 두 해시는 일치해야 합니다. 일치하지 않으면 재정의 업로드를 반드시 거부해야 합니다.
PyPI API 버전 상향 불필요
이 변경 사항은 하위 호환성이 충분하므로 PyPI repository version을 올릴 필요는 없을 가능성이 높습니다. .rim 파일은 본질적으로 업로드 API만 변경하므로, 패키지 리졸버와 패키지 설치 프로그램은 늘 지원해 온 API 함수를 그대로 사용하여 계속 동작할 수 있습니다.
외부 호스팅의 복원력
PEP 470에서 PEP 438이 철회되는 데 이른 주요 우려 중 하나는 외부 색인이 사라졌을 때 사용자가 겪을 수 있는 혼란이었습니다. PEP 470에서 인용합니다:
이 혼란은 결국 프로젝트의 최종 사용자가 해당 프로젝트가 PyPI에서 호스팅되는지, 아니면 외부 서비스에 의존하는지 모른다는 데서 비롯됩니다. 이는 흔히 PyPI는 정상인데 외부 서비스가 중단되었을 때 드러납니다. 사람들은 PyPI도 동작하고 다른 프로젝트도 동작하는데 유독 이 특정 프로젝트만 동작하지 않는다는 것을 보게 됩니다. 이들은 문제를 해결하려면 누구에게 연락해야 하는지, 또는 어떤 조치를 취해야 하는지 모르는 경우가 많습니다.
외부 휠 호스팅 서비스가 중단되는 문제를 이 PEP가 직접 해결하지는 않지만, PyPI 관리자의 잠재적 부담을 크게 줄이기 위한 여러 안전장치가 마련되어 있습니다.
따라서 이 PEP는 다음을 제안합니다:
- 외부 휠 호스팅은 조직 계정이 소유한 패키지에만 허용됩니다. 외부 호스팅은 조직 전체에 적용되는 설정입니다.
- 조직 계정이 외부 휠 호스팅 기능을 자동으로 얻지는 않습니다. 이 기능은 PyPI 관리자가 재량에 따라 반드시 명시적으로 활성화해야 합니다. 이는 흔한 요청이 아닐 것이므로, 그 부담이 PEP 541 처리, 계정 복구 요청, 심지어 파일/프로젝트 크기 증가 요청만큼 크지는 않을 것으로 예상합니다. 외부 호스팅 요청은 이러한 요청과 같은 방식으로, 즉 PyPI GitHub 지원 트래커를 통해 처리됩니다.
- 외부 휠 호스팅을 요청하는 조직 계정은 자체 지원 연락처 URI를 반드시 등록해야 합니다. 이 URI는 연락용 이메일 주소를 가리키는
mailtoURI일 수도 있고, 조직의 지원 트래커 URL일 수도 있습니다. 외부 wheel 파일 호스팅을 이용하지 않는 조직은 이러한 연락처 URI를 등록하지 않아도 됩니다.
이 URI를 EXTERNAL-HOSTING.json 파일의 owner 키와 함께 사용하면, 설치 프로그램 도구는 모든 다운로드 오류를 PyPI 지원 관리자가 아니라 해당 조직의 지원 관리자에게 명확하게 전달할 수 있습니다.
이 조직 지원 URL을 저장하고 조회하는 구체적인 방식은 별도로 정의하겠지만, 예를 들어 패키지 foo가 `https://foo.example.com <https://foo.example.com>`__에서 wheel 파일을 외부 호스팅하는데 그 호스트에 연결할 수 없게 되었다고 가정해 봅시다. 설치 프로그램 도구가 패키지 foo의 wheel을 다운로드하여 설치하려고 하면 다운로드 단계에서 실패합니다. 이때 설치 프로그램은 PyPI에 질의하여 최종 사용자에게 유용한 오류 메시지를 제공할 수 있습니다:
- 설치 프로그램은
.rim파일을 다운로드하고,.rimzip 파일 안의EXTERNAL-HOSTING.json파일에서owner키를 읽습니다. - 설치 프로그램은 외부에서 호스팅되는 wheel의 소유자인 조직의 지원 URI를 PyPI에 질의합니다.
- 그러면 다음과 같이 유용한 정보를 담은 오류 메시지가 표시됩니다:외부에서 호스팅되는 wheel 파일
foo-....whl을 다운로드할 수 없습니다. 도움이 필요하면 support@foo.example.com으로 문의하십시오. 이 문제를 PyPI 관리자에게 보고하지 마십시오.
휠 분리하기
일반적으로 기존 .whl 파일에서 .rim 파일을 만드는 것은 매우 쉽습니다. 이 작업은 추가 명령줄 옵션을 갖춘 PEP 518 빌드 백엔드로 효율적으로 수행할 수도 있고, .whl 파일을 입력으로 받아 그에 대응하는 .rim 파일을 만드는 별도의 도구로 수행할 수도 있습니다. 비유를 완성하자면, .whl을 .rim으로 바꾸는 행위를 “분리(dismounting)”라고 부릅니다. 이러한 도구가 수행할 단계는 다음과 같습니다:
- 원본
.whl파일, 패키지의 조직 소유자,.whl이 호스팅될 URL, 그리고 다운로드 문제를 보고할 지원 URI를 입력으로 받습니다. 사실 이 정보들은pyproject.toml파일에 기록할 수도 있지만, 그 명세는 이 PEP의 범위를 벗어납니다. .whl의 압축을 풀고.rimzip 아카이브를 만듭니다..whl안의 경로 중.dist-info디렉터리를 루트로 하지 않는 경로는 모두.rim파일에서 제외합니다.- 원본
.whl파일의 해시를 계산합니다. - 위에서 설명한 JSON 키와 값을 담은
EXTERNAL-HOSTING.json파일을.rim아카이브에 추가합니다.
도구의 변경 사항
이론적으로는 설치 프로그램 도구를 전혀 바꿀 필요가 없습니다. 다운로드하여 설치할 wheel을 정하고 나면 PyPI의 Simple API가 반환한 다운로드 URL을 참조하기만 하면 되기 때문입니다. 그러나 실제로는 pip나 uv 같은 도구가 PyPI 자체의 pythonhosted.org 도메인처럼 다운로드를 허용할 호스트 목록을 제한해 두었을 수 있습니다.
이 경우 해당 도구들은 그러한 제약을 완화해야 합니다. 다만 이에 대한 구체적인 정책은 설치 프로그램 도구가 직접 정합니다. .rim 파일을 다운로드하여 EXTERNAL-HOSTING.json 메타데이터를 검증하거나, 체크섬이 일치하는 휠이라면 외부 다운로드를 그냥 신뢰하는 등 다양한 방식을 구현할 수 있습니다. 또한 다운로드를 신뢰하기 전에 PyPI에 프로젝트의 조직 소유자와 지원 URI를 조회할 수도 있습니다. 외부에서 호스팅되는 wheel 파일을 만나면 사용자에게 경고하거나, 추가 다운로드 호스트를 허용하려면 명령줄 옵션을 사용하도록 요구하거나, 두 가지를 모두 할 수 있습니다. 이러한 검증 정책 중 무엇을 사용할지는 설정 파일에서 선택할 수 있습니다.
설치 프로그램 도구는 호스트에 연결할 수 없는 경우처럼 외부에서 호스팅되는 wheel을 다운로드할 수 없을 때 더 나은 오류 메시지도 제공하는 것이 좋습니다. 위에서 설명했듯이, 그러한 도구는 PyPI에서 충분한 메타데이터를 조회하여 사용자에게 패키지의 외부 호스팅 지원 이메일이나 이슈 트래커를 안내하는 명확하고 구별되는 오류 메시지를 제공할 수 있습니다.
외부 호스팅 서비스에 대한 제약
다음 제약을 따르면 신뢰할 수 있고 호환되는 외부 휠 호스팅 서비스를 만들 수 있습니다:
- 외부 휠은 Mozilla의 루트 인증서 저장소가 서명한 인증서를 사용하여 HTTPS로 반드시 제공되어야 합니다. 이렇게 하면 pip 및 uv와의 호환성이 보장됩니다. 이 글을 쓰는 시점에 Python 3.10 이상에서 실행되는
pip24.2는 서드파티 certifi Python 패키지가 제공하는 Mozilla 저장소와 함께 시스템 인증서 저장소도 사용합니다.uv는 webpki-roots 크레이트가 제공하는 Mozilla 저장소를 사용하며,--native-tls플래그를 지정하지 않으면 시스템 저장소는 사용하지 않습니다 [1]. PyPI 관리자는 향후 이 요구 사항을 수정할 수 있지만, 널리 쓰이는 설치 프로그램과의 호환성은 손상되지 않을 것입니다. - 외부 휠 호스트는 PyPI와 마찬가지로 콘텐츠 전송 네트워크(CDN)를 사용해야 합니다.
- 외부 휠 호스트는 자신이 호스팅하는 모든 휠에 대해 안정적인 URL을 유지하도록 반드시 커밋해야 합니다.
- 외부에서 호스팅되는 휠은 대응하는
.rim파일이 PyPI에서 먼저 삭제되지 않는 한 외부 휠 호스트에서 제거해서는 안 되며(MUST NOT), yank된 릴리스의 외부 휠을 제거해서도 안 됩니다(MUST NOT). - 외부 휠 호스트는 HTTP range requests를 반드시 지원해야 합니다(MUST).
- 외부 휠 호스트는 HTTP/2 프로토콜을 지원하는 것이 좋습니다(SHOULD).
보안
이 제안에서 설명한 다음과 같은 여러 요소가 외부에서 호스팅되는 휠과 관련된 보안 우려를 완화할 것입니다.
- wheel 파일 체크섬은
.rim파일에 반드시(MUST) 포함되어야 하며, 한 번 업로드하면 변경할 수 없습니다. PyPI에 저장된 체크섬은 필수이며 변경할 수 없으므로, 소유 조직이 호스팅 도메인의 제어권을 잃더라도 외부 wheel 파일을 위조할 수 없습니다. - 외부에서 호스팅되는 휠은 반드시 HTTPS를 통해 제공되어야 합니다(MUST).
- 외부에서 호스팅되는 휠을 제공하려면 조직은 반드시 PyPI 관리자의 승인을 받아야 합니다(MUST).
사용자가 PyPI에서 호스팅되는 프로젝트에서 악성 코드나 취약점을 발견하면, 이제 PyPI의 악성 코드 신고 기능을 사용하여 이를 신고할 수 있으며, 이는 이 blog post에서도 설명되어 있습니다. 외부에서 호스팅되는 휠의 보안 문제를 신고할 때에도 동일한 절차를 사용할 수 있으며, 동일한 해결 절차를 사용해야 합니다. 또한 외부 호스팅이 활성화된 조직은 반드시 지원 연락처 URI를 제공해야 하므로, 경우에 따라 해당 URI를 사용하여 호스팅 조직에 보안 문제를 신고할 수 있습니다. 이러한 조직 대상 신고는 악성 코드의 경우에는 의미가 없겠지만, 외부에서 호스팅되는 휠의 보안 취약점을 신고하는 데에는 실제로 매우 유용한 방법이 될 수 있습니다.
기각된 아이디어
여러 아이디어가 검토되었으나 거부되었습니다.
- 외부에서 호스팅되는 wheel 파일에 해시와 함께, 또는 해시 대신 디지털 서명을 요구하는 방안. 체크섬 요구 사항만으로도 PyPI에 있는 휠의 메타데이터가 다운로드된 휠과 정확히 일치하는지 검증하기에 충분하므로, 이는 불필요하다고 판단합니다. 키 관리로 인해 추가되는 복잡성이 그러한 디지털 서명이 가져다줄 수 있는 어떠한 추가 이점보다도 큽니다.
.rim파일 업로드 시 해시를 검증하는 방안입니다. PyPI는 업로드를 수락하기 전에 업로드된.rim파일의 해시가 외부에서 호스팅되는 휠과 일치하는지 검증할 수도 있지만, 이를 위해서는 외부 휠을 다운로드하고 체크섬을 계산해야 하며, 이는 곧 외부.whl파일이 다운로드되어 검증될 때까지.rim파일의 업로드를 수락할 수 없다는 것을 의미하기도 합니다. 이로 인해 PyPI의 대역폭 사용량이 증가하고 업로드 요청이 느려지지만, PEP 694 초안 업로드가 이러한 우려를 완화할 가능성은 있습니다. 그렇다 하더라도 그 이점이 추가되는 복잡성을 감수할 만큼의 가치가 있을 가능성은 낮습니다.- 색인이 다운로드 URL을 주기적으로 검증하는 방안입니다. PyPI는 예를 들어 HTTP HEAD 요청을 통해 외부 휠 호스트나 외부
.whl파일 자체가 여전히 사용 가능한지 주기적으로 확인하려고 시도할 수 있습니다. 이는 과도한 조치일 가능성이 높으며, 응답에 파일의 체크섬도 함께 제공하지 않는다면 [2] 큰 추가 이점을 제공하지 못할 수도 있습니다. - 이 PEP는 조직이 대체 다운로드 호스트를 제공하도록 허용하여, 기본 호스트가 중단되었을 때 보조 호스트를 사용할 수 있게 할 수도 있습니다. 저희는 DNS 기반 복제가 훨씬 더 좋고 잘 알려진 기법이며, 어쨌든 아마도 훨씬 더 복원력이 높을 것이라고 생각합니다.
.rim파일 교체입니다. a).rim파일이 삭제되거나 yank되지 않았고, b) 체크섬이 일치하는 한,.whl파일이 기존.rim파일을 대체하는 것은 허용되지만,.whl파일을.rim파일로 대체하는 것은 허용하지 않으며,.rim파일이 기존.rim파일을 덮어쓰는 것도 허용하지 않습니다. 후자는 외부에서 호스팅되는.whl의 호스팅 URL을 변경하는 기법이 될 수 있지만, 저희는 이것이 좋은 생각이라고 보지 않습니다. 위에서 설명한 것처럼 외부 호스트 URL을 “수정”하는 다른 방법이 있으며, 저희는 기존.rim파일의 대량 재업로드를 장려하고 싶지 않습니다.
각주
Copyright
This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive.