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

Python 개선 제안 한국어 번역

PEP 458 – 서명된 저장소 메타데이터를 사용한 안전한 PyPI 다운로드

Author:
Trishank Karthik Kuppusamy <karthik at trishank.com>, Vladimir Diaz <vladimir.diaz at nyu.edu>, Marina Moore <mm9693 at nyu.edu>, Lukas Puehringer <lukas.puehringer at nyu.edu>, Joshua Lock <jlock at vmware.com>, Lois Anne DeLong <lad278 at nyu.edu>, Justin Cappos <jcappos at nyu.edu>
Sponsor:
Alyssa Coghlan <ncoghlan at gmail.com>
BDFL-Delegate:
Donald Stufft <donald at stufft.io>
Discussions-To:
Discourse thread
Status:
Accepted
Type:
Standards Track
Topic:
Packaging
Created:
27-Sep-2013
Post-History:
06-Jan-2019, 13-Nov-2019
Resolution:
Discourse message

Table of Contents

번역·라이선스 안내

이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판

초록

이 PEP는 사용자가 PyPI에서 유효한 패키지를 받을 수 있도록 보장하는 데 필요한 PyPI 인프라의 변경 사항을 설명합니다. 이러한 변경 사항은 생태계의 다른 부분에 미치는 영향을 최소화해야 합니다. 이 PEP는 PyPI와 사용자 간의 통신에 중점을 두므로 패키지 개발자의 작업을 요구하지 않습니다. 개발자는 현재 프로세스를 사용하여 패키지를 업로드하고, PyPI는 이러한 패키지에 대한 서명된 저장소 메타데이터를 자동으로 생성합니다.

보안 메커니즘이 효과적으로 작동하려면 PyPI 소비자(예: pip)가 PyPI에서 제공하는 서명과 메타데이터를 확인하기 위한 추가 작업을 수행해야 합니다. 이 검증은 실패하는 경우를 제외하면 사용자에게 투명하게 이루어질 수 있으며, 자동 보안 메커니즘을 제공합니다. TUF 저장소에는 TUF 메타데이터를 사용하는 방법에 관한 문서가 있습니다. 그러나 PyPI 소비자의 변경은 PyPI에서 메타데이터를 게시하기 위한 선행 조건이 아니며, 각 프로젝트의 일정과 우선순위에 따라 수행할 수 있습니다.

제안된 TUF 통합

이 PEP는 The Update Framework [2] (TUF)를 Python 패키지 색인(PyPI [1])에 통합하는 방안을 제안합니다. TUF는 소프트웨어 업데이터 또는 패키지 관리자를 위한 유연한 보안 추가 기능으로 설계되었습니다. 프레임워크를 완전히 구현하면 역할 책임 분리, 패키지 서명을 위한 다수인 규칙 채택, 서명 키의 오프라인 보관, 만료되었거나 손상된 서명 키의 폐기와 같은 최선의 보안 관행이 통합됩니다. 그 결과 공격자가 저장소에서 사용 가능한 파일을 지정하는 역할을 손상시키려면 독립적으로 저장된 여러 서명 키를 훔쳐야 합니다. 또는 저장소의 최신 스냅샷을 나타내는 역할도 손상시켜야 할 수 있습니다.

이 PEP에서 제안하는 초기 통합을 통해 pip [3]와 같은 현대적인 패키지 관리자는 PyPI 미러와 PyPI 자체 콘텐츠 배포 네트워크에 대한 공격에 더욱 안전해지고, 이러한 공격으로부터 사용자를 더 효과적으로 보호할 수 있습니다. 구체적으로 이 PEP는 TUF 메타데이터(즉, 최소 보안 모델)를 생성하고 통합하도록 PyPI 프로세스를 조정하는 방법을 설명합니다. 이 최소 보안 모델은 PyPI에 저장된 키로 서명된 PyPI 배포 패키지의 검증을 지원합니다. 개발자가 업로드한 배포 패키지는 PyPI가 서명하므로 개발자는 배포 패키지를 업로드하는 것 외에 아무 작업도 할 필요가 없으며, 즉시 다운로드할 수 있습니다. 또한 최소 보안 모델은 서명 프로세스의 상당 부분을 자동화하여 PyPI의 관리 책임을 최소화합니다.

PEP에서는 개발자가 서명한 프로젝트 배포 패키지(최대 보안 모델) 지원을 논의하지 않습니다. 이 가능한 향후 확장은 PEP 480에서 자세히 다룹니다. 최대 보안 모델은 PyPI의 관리 작업을 더 많이 요구하며(클라이언트의 추가 작업은 필요하지 않음), 개발자/게시자를 위한 사용하기 쉬운 키 관리 솔루션, PyPI 인프라의 향후 빌드 팜과 인터페이스하는 방법에 대한 아이디어, 종단 간 서명의 실현 가능성도 제안합니다.

이 PEP는 구현 권장 사항을 제공하지만, pip와 같은 패키지 관리자가 TUF 메타데이터를 사용하여 PyPI에서 프로젝트를 설치하거나 업데이트하도록 조정되는 정확한 방식을 규정하지는 않습니다. 클라이언트 측에서 TUF 도입에 관심이 있는 패키지 관리자는 이 목적을 위해 작성된 해당 library documentation를 참고할 수 있습니다.

목표가 아닌 사항

이 PEP는 PyPI의 기존 기능을 제거하지 않습니다. 특히 기존 OpenPGP 서명 지원을 대체하지 않습니다. 개발자는 배포물과 함께 분리형 OpenPGP 서명을 계속 업로드할 수 있습니다. 향후 PEP 480을 통해 개발자가 자신의 OpenPGP 키를 사용하여 TUF 메타데이터에 직접 서명할 수 있게 될 수도 있습니다.

PEP 상태

이 PEP를 구현하는 데 필요한 작업량으로 인해, 적절한 자금을 확보하여 PEP를 구현할 수 있을 때까지 2019년 초에 연기되었습니다. Python Software Foundation은 이 자금을 확보했고 [22] 새로운 PEP 공동 작성자들이 PEP 논의를 재개했습니다.

동기

매우 우수한 보안 관행을 갖춘 조직에서도 소프트웨어 저장소에 대한 공격은 흔합니다. 그 결과 발생한 저장소 침해로 공격자는 저장소에 저장된 모든 파일을 편집하고 저장소에 보관된 모든 키(온라인 키)를 사용하여 해당 파일에 서명할 수 있습니다. TLS와 같은 많은 서명 방식에서는 이러한 접근 권한으로 공격자가 저장소의 파일을 교체하고 해당 파일이 PyPI에서 제공되는 것처럼 보이게 만들 수 있습니다. 신뢰하는 개인 키를 폐기하고 교체할 방법이 없다면 저장소 침해에서 복구하기가 매우 어렵습니다. 저장소 침해의 위험뿐만 아니라 소프트웨어 저장소는 네트워크상의 공격자(MITM)가 파일을 가로채고 변경하는 공격에도 취약합니다. 이러한 공격과 소프트웨어 저장소에 대한 기타 공격은 여기에 자세히 설명되어 있습니다.

이 PEP는 PEP 480의 후속 제안과 함께 PyPI 패키지의 무결성, 일관성 및 최신성 속성이 침해되지 않도록 PyPI 사용자를 보호하고, 키 위험을 완화하며 PyPI 또는 해당 서명 키가 침해된 경우 복구할 수 있는 메커니즘을 제공하여 침해 복원력을 향상하는 것을 목표로 합니다.

2013년 1월 5일, Python Software Foundation(PSF)은 Python 및 Jython의 python.org 위키에서 보안 침해가 발생했다고 발표했습니다 [4]. 그 결과 위키 데이터 전체가 파괴되었습니다. 다행히 PyPI 인프라는 이 침해의 영향을 받지 않았습니다. 그러나 이 사건은 침해가 발생할 경우 사용자를 최대한 보호하기 위해 PyPI가 방어 조치를 취해야 한다는 점을 상기시켜 줍니다. 소프트웨어 저장소에 대한 공격은 항상 발생합니다 [5]. PSF는 보안 침해 가능성을 받아들이고 그에 맞게 PyPI를 대비해야 합니다. PyPI는 수천 명, 많게는 수백만 명이 사용하는 귀중한 자원이기 때문입니다.

위키 공격이 발생하기 전에 PyPI는 pip와 같은 패키지 관리자에게 배포 파일이 전송 중 손상되었는지 여부를 알리기 위해 MD5 해시를 사용했습니다. 그러나 SSL이 없었기 때문에 패키지 관리자가 PyPI로의 전송 무결성을 확인하기가 어려웠습니다. 따라서 pip와 PyPI 사이에서 중간자 공격을 수행하여 배포물의 콘텐츠를 임의로 변경하기가 쉬웠습니다. 그 결과 사용자가 악성 배포물을 설치하도록 속을 수 있었습니다. 위키 공격 이후에는 이전보다 훨씬 높은 수준의 보안을 제공하기 위한 여러 조치가 제안되었습니다(그중 일부는 구현되었습니다). 이러한 조치에는 PyPI와 통신할 때 SSL을 사용하도록 요구하는 것 [6], 프로젝트 이름을 제한하는 것 [7], MD5 해시에서 SHA-2 해시로 이전하는 것이 [8] 포함되었습니다.

이러한 단계는 필요하지만, 다른 경로를 통한 공격이 여전히 가능하므로 배포판을 보호하기에는 불충분합니다. 예를 들어 공개 미러는 PyPI를 정직하게 미러링한다고 신뢰받지만, 일부 미러는 실수로든 악의적인 개입으로든 비정상적으로 동작할 수 있습니다. pip와 같은 패키지 관리자는 공개 미러에서 다운로드한 배포 파일을 검증하기 위해 PyPI의 서명을 사용해야 하지만, 실제로 그렇게 하는 것으로 알려진 관리자는 없습니다 [10]. 따라서 공개 미러나 콘텐츠 전송 네트워크 [11] (CDN)에서 발생하는 공격을 탐지하기 위한 보안 조치를 추가하는 것이 현명합니다.

공식 미러가 PyPI에서 사용 중단되었지만, 패키지 관리자에 대한 다양한 다른 공격 벡터가 여전히 존재합니다 [13]. 이러한 공격은 클라이언트 시스템을 중단시키거나, 오래된 배포판을 설치하게 하거나, 심지어 공격자가 임의의 코드를 실행하도록 허용할 수 있습니다. 2013년 9월에 Distutils 메일링 리스트에 게시된 글에서는 당시 최신 버전의 pip가 이러한 공격에 취약하다는 사실과 TUF가 이러한 공격으로부터 사용자를 보호할 수 있는 방법을 보여 주었습니다 [14]. 구체적으로는 TUF를 사용하거나 사용하지 않을 때 pip가 이러한 공격에 어떻게 대응하는지 확인하기 위한 테스트가 수행되었습니다. 테스트한 공격에는 재생 및 동결, 임의 설치, 느린 검색, 무한 데이터가 포함되었습니다. 또한 이 글에는 PyPI가 침해되었을 때 pip가 어떻게 대응하는지에 대한 시연도 포함되어 있었습니다.

PyPI에 대한 침해 복원력 있는 보호를 제공하기 위해 이 PEP는 The Update Framework [2] (TUF)의 사용을 제안합니다. TUF는 소프트웨어 업데이트 시스템에 대한 다양한 공격을 방어하는 동시에, 저장소가 침해된 경우 복구할 수 있는 메커니즘도 제공합니다. TUF는 여러 조직에서 실제 운영 환경에 사용되어 왔으며, Docker Registry에서 컨테이너 이미지 서명을 위한 인프라를 제공하는 Cloud Native Computing Foundation의 Notary 서비스에도 사용되었습니다. TUF 사양은 세 차례의 독립적인 보안 감사 대상이 되었습니다.

PEP의 범위는 PyPI 미러와 PyPI 자체의 TLS 종료 및 콘텐츠 배포 인프라가 침해되는 상황으로부터 사용자를 보호하는 것입니다. PyPI 자체의 침해에 대한 보호는 PEP 480에서 논의합니다.

위협 모델

위협 모델은 다음을 가정합니다.

  • 오프라인 키는 안전하며 안전하게 저장됩니다.
  • 공격자는 온라인에 저장된 PyPI의 신뢰할 수 있는 키를 침해할 수 없습니다.
  • 공격자는 클라이언트 요청에 응답할 수 있습니다.

공격자가 클라이언트로 하여금 소프트웨어 배포 파일의 최신 버전이 아닌 것을 설치하게 하거나 설치된 상태로 유지하게 만들 수 있다면, 해당 공격은 성공한 것으로 간주합니다. 공격자가 업데이트 설치를 방해하는 경우, 공격자는 클라이언트가 문제가 있다는 사실을 알아차리지 못하게 하려고 합니다.

이 위협 모델은 최소 보안 모델을 설명합니다. 관련 PEP 480에 설명된 최대 보안 모델은 공격자가 PyPI의 온라인 키를 탈취할 수 있다고 가정합니다.

정의

이 문서에서 “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, “OPTIONAL” 키워드는 RFC 2119에 설명된 의미로 해석해야 합니다.

이 PEP는 TUF를 PyPI에 통합하는 데만 중점을 둡니다. 그러나 독자는 TUF 설계 원칙 [2]을 검토하는 것이 권장되며, TUF 사양 [16]을 잘 알고 있어야 합니다.

이 PEP에서 사용되는 다음 용어는 Python 패키징 용어집 [17]: 프로젝트, 릴리스, 배포판에 정의되어 있습니다.

이 PEP에서 사용되는 추가 용어는 다음과 같이 정의합니다:

  • 역할: TUF는 하나의 root 역할과, 해당 root 역할이 직접 또는 간접적으로 책임을 위임하는 여러 다른 역할을 지정합니다. top-level 역할이라는 용어는 root 역할과 root 역할이 직접 지정하는 모든 역할, 즉 timestamp, snapshottargets 역할을 가리킵니다. 각 역할에는 해당 역할이 제공한다고 신뢰되는 단일 메타데이터 파일이 있습니다.
  • 배포 파일: 릴리스를 배포하는 데 사용되는 Python 패키지, 모듈 및 기타 리소스 파일을 포함하는 버전이 지정된 아카이브 파일입니다. 이 PEP에서는 배포 파일, 배포 패키지 [17], 또는 단순히 배포패키지라는 용어를 서로 바꾸어 사용할 수 있습니다.
  • 단순 색인: 배포 파일로 연결되는 내부 링크를 포함하는 HTML 페이지입니다.
  • 대상 파일: 일반적으로 대상 파일은 TUF를 사용하여 무결성을 보장해야 하는 PyPI의 모든 파일입니다. 일반적으로 여기에는 배포 파일과 단순 색인 같은 PyPI 메타데이터가 포함됩니다.
  • 메타데이터: 메타데이터는 역할, 기타 메타데이터 및 대상 파일을 설명하는 서명된 파일입니다. 달리 명시되지 않은 경우, 메타데이터는 TUF 전용 메타데이터를 의미합니다.
  • 저장소: 저장소는 이름이 지정된 메타데이터와 대상 파일의 원천입니다. 클라이언트는 저장소에 저장된 메타데이터와 대상 파일을 요청합니다.
  • 일관된 스냅샷: 특정 시점에 존재했던 PyPI의 모든 프로젝트 전체 상태를 포착하는 TUF 메타데이터 및 대상 파일 집합입니다.
  • 개발자: 프로젝트의 TUF 메타데이터와 해당 프로젝트의 대상 파일을 업데이트할 수 있는 프로젝트 소유자 또는 유지 관리자입니다.
  • 온라인 키: PyPI 서버 인프라에 저장해야 하는 개인 암호 키입니다. 이는 일반적으로 해당 키를 사용한 자동 서명을 허용하기 위한 것입니다. 그러나 PyPI 인프라를 침해한 공격자는 이러한 키를 읽을 수 있습니다.
  • 오프라인 키: PyPI 서버 인프라와 독립적으로 저장해야 하는 개인 암호 키입니다. 이를 통해 해당 키를 사용한 자동 서명을 방지합니다. PyPI 인프라를 침해한 공격자는 이러한 키를 즉시 읽을 수 없습니다.
  • 임계값 서명 방식: 역할은 메타데이터에 서명하려면 n개의 키 중 최소 t개가 필요하다고 지정하여 키 침해에 대한 복원력을 높일 수 있습니다. t-1개의 키가 침해되는 것만으로는 역할 자체를 침해하기에 충분하지 않습니다. 역할에 (t, n)개의 키가 필요하다고 표현하는 것은 임계값 서명 속성을 나타냅니다.

TUF 개요

TUF는 최상위 수준에서 애플리케이션이 파일의 새 버전을 파악하고 가져올 수 있는 안전한 방법을 제공합니다. 겉으로 보기에는 이 모든 것이 간단해 보입니다. 애플리케이션을 업데이트하는 기본 단계는 다음과 같습니다:

  • 업데이트가 존재한다는 사실을 파악합니다.
  • 업데이트된 파일의 최신 버전을 올바르게 복사하여 다운로드합니다.

문제는 악의적인 활동이 개입되지 않은 경우에만 애플리케이션 업데이트가 간단하다는 점입니다. 공격자가 겉보기에는 간단한 이러한 단계들을 방해하려 한다면, 공격자가 할 수 있는 일은 매우 많습니다.

소프트웨어 업데이트 프로그램이 대부분의 시스템(적어도 보안을 유지하려고 시도하는 시스템)이 취하는 방식을 따른다고 가정합니다. 소프트웨어 업데이트 프로그램은 원하는 파일과 해당 파일의 암호화 서명을 모두 다운로드합니다. 소프트웨어 업데이트 프로그램은 서명을 생성하는 데 신뢰할 키가 무엇인지 이미 알고 있습니다. 소프트웨어 업데이트 프로그램은 서명이 올바르고 이 신뢰할 수 있는 키로 생성되었는지 확인합니다. 안타깝게도 소프트웨어 업데이트 프로그램은 여전히 여러 방식으로 위험에 노출되며, 다음과 같은 상황이 포함됩니다.

  • 공격자가 소프트웨어 업데이트 프로그램에 계속 같은 업데이트 파일을 제공하므로, 소프트웨어 업데이트 프로그램은 업데이트가 있다는 사실을 전혀 알아차리지 못합니다.
  • 공격자가 소프트웨어 업데이트 프로그램에 이미 보유한 파일의 더 오래되고 안전하지 않은 버전을 제공하므로, 소프트웨어 업데이트 프로그램은 해당 파일을 다운로드하고 더 최신 버전이라고 생각하여 무비판적으로 사용합니다.
  • 공격자가 소프트웨어 업데이트 프로그램에 파일의 더 최신 버전을 제공하지만, 최신 버전은 아닙니다. 해당 파일은 소프트웨어 업데이트 프로그램 기준으로는 더 최신 버전이지만, 안전하지 않을 수 있으며 공격자가 이를 악용할 수 있습니다.
  • 공격자가 이러한 파일에 서명하는 데 사용되는 키를 손상시키면, 소프트웨어 업데이트 프로그램은 올바르게 서명된 악성 파일을 다운로드하게 됩니다.

TUF는 서명된 메타데이터(저장소의 파일을 설명하는 텍스트 파일)를 저장소에 추가하고 업데이트 절차 중 메타데이터 파일을 참조함으로써 이러한 공격과 그 밖의 공격을 해결하도록 설계되었습니다. 저장소 파일은 소프트웨어 업데이트 시스템에 전달되기 전에 메타데이터에 포함된 정보와 대조하여 검증됩니다. 이 프레임워크는 다중 서명 신뢰, 암호화 키의 명시적 및 암시적 폐기, 메타데이터 책임 분리, 키 위험 최소화도 제공합니다. TUF가 해결하는 저장소 공격과 소프트웨어 업데이트 프로그램의 약점에 대한 전체 목록과 개요는 부록 A를 참조하십시오.

PyPI와 TUF 통합

소프트웨어 업데이트 시스템이 TUF를 통합하려면 두 가지 주요 작업을 완료해야 합니다. 첫째, 서버 측 저장소를 수정하여 서명된 TUF 메타데이터를 제공해야 합니다. 이 PEP에서는 통합의 첫 번째 부분과 TUF를 사용한 소프트웨어 업데이트를 지원하기 위해 PyPI에 필요한 변경 사항을 다룹니다.

둘째, 업데이트 시스템의 클라이언트 측에 해당 프레임워크를 추가해야 합니다. 예를 들어 TUF를 pip 패키지 관리자에 통합할 수 있습니다. 따라서 이후에 출시되는 pip의 새 버전은 설치하기 전에 기본적으로 TUF를 사용하여 PyPI에서 배포 패키지를 다운로드하고 검증해야 합니다. 그러나 TUF를 통해 배포 패키지( pip 자체 포함)를 설치하거나 업데이트하지 못하게 하는 예기치 않은 문제가 발생할 수 있습니다. 따라서 이러한 문제가 해결될 때까지 우회할 수 있도록 pip는 예를 들어 --unsafely-disable-package-verification 옵션을 제공해야 합니다. 제안된 옵션 이름은 의도적으로 긴 이름입니다. 사용자가 해당 작업이 안전하지 않으며 일반적으로 권장되지 않는다는 점을 이해하도록 도와야 하기 때문입니다.

pip는 PyPI에서만 다운로드한 배포 패키지를 검증하는 데 TUF를 사용한다고 가정합니다. pip는 elsewhere에서 다운로드한 배포 패키지도 TUF를 사용하여 검증할 수 있도록 TAP 4를 지원할 수 있습니다.

PyPI에 필요한 추가 저장소 파일은 무엇입니까?

pip와 같은 패키지 관리자가 TUF를 사용하여 배포 패키지를 다운로드하고 검증할 수 있도록 PyPI에 몇 가지 추가 파일을 추가해야 합니다. 이러한 추가 저장소 파일을 TUF 메타데이터라고 하며, 신뢰할 수 있는 키, 파일의 cryptographic hashes, 서명, 메타데이터 버전 번호, 그리고 메타데이터가 만료된 것으로 간주되어야 하는 날짜와 같은 정보를 포함합니다.

패키지 관리자가 업데이트를 확인하려는 경우, TUF에 작업을 수행하도록 요청합니다. 즉, 패키지 관리자는 이 추가 메타데이터를 직접 처리하거나 내부에서 무슨 일이 일어나는지 이해할 필요가 전혀 없습니다. TUF가 사용 가능한 업데이트가 있다고 알려 주면, 패키지 관리자는 TUF에 PyPI에서 이 파일을 다운로드하도록 요청할 수 있습니다. TUF는 파일을 다운로드하고, 저장소에서 함께 다운로드한 TUF 메타데이터와 대조하여 확인합니다. 다운로드한 대상 파일을 신뢰할 수 있는 경우, TUF는 해당 파일을 패키지 관리자에게 전달합니다.

TUF 사양의 문서 형식 섹션에서는 필요한 각 메타데이터 유형과 예상 콘텐츠에 관한 정보를 제공합니다. 다음 섹션에서는 PyPI에 권장되는 다양한 메타데이터 종류를 다룹니다.

또한 모든 대상 파일은 디스크에서 최소 두 개의 사본으로 제공되어야 합니다. 하나는 하위 호환성을 위해 원래 파일 이름으로 저장하고, 다른 하나는 파일 이름에 SHA-512 해시를 포함하여 저장합니다. 이는 Consistent Snapshots 생성에 필요합니다.

사용하는 파일 시스템에 따라 대상 파일을 하드 카피하여 저장할 때 저장 공간이 증가하는 것을 방지하기 위해 다양한 데이터 중복 제거 메커니즘을 사용할 수 있습니다.

PyPI 및 TUF 메타데이터

TUF 메타데이터는 클라이언트가 업데이트 여부를 결정하는 데 사용할 수 있는 정보를 제공합니다. 예를 들어, targets 메타데이터는 PyPI에서 사용 가능한 대상 파일을 나열하고 각 파일에 필요한 서명, 암호화 해시 및 파일 크기를 포함합니다. 서로 다른 메타데이터 파일은 서로 다른 정보를 제공하며, 각각 별도의 역할이 서명합니다. root 역할은 각 역할에 어떤 메타데이터가 속하는지 나타냅니다. 역할 개념을 사용하면 TUF가 여러 역할에 책임을 위임할 수 있으므로, 어느 한 역할이 침해되더라도 그 영향을 최소화할 수 있습니다.

TUF에는 네 개의 최상위 역할이 필요합니다. 이는 root, timestamp, snapshottargets입니다. root 역할은 최상위 역할의 공개 암호화 키를 지정합니다(자신의 키 포함). timestamp 역할은 최신 snapshot을 참조하며 저장소의 새 스냅샷을 사용할 수 있게 되었는지를 나타낼 수 있습니다. snapshot 역할은 timestamp 이외의 모든 TUF 메타데이터 파일의 최신 버전을 나타냅니다. targets 역할은 사용 가능한 대상 파일의 파일 경로를 해당 암호화 해시와 함께 나열합니다. 파일 경로는 기본 URL을 기준으로 지정해야 합니다. 따라서 클라이언트가 기본 URL에 액세스할 수 있기만 하면 실제 대상 파일을 어디에서든 제공할 수 있습니다. 각 최상위 역할은 예외 없이 자신의 책임을 수행합니다. 표 1에서는 TUF에서 사용되는 역할의 개요를 제공합니다.

Roles and Responsibilities
root The root role is the locus of trust for the entire repository. The root role signs the root.json metadata file. This file indicates which keys are authorized for each of the top-level roles, including for the root role itself. The roles “root”, “snapshot”, “timestamp” and “targets” must be specified and each has a list of public keys.
targets The targets role is responsible for indicating which target files are available from the repository. More precisely, it shares the responsibility of providing information about the content of updates. The targets role signs targets.json metadata, and can delegate trust for repository files to other roles (delegated roles).
delegated roles If the top-level targets role performs delegation, the resulting delegated roles can then provide their own metadata files. The format of the metadata files provided by delegated targets roles is the same as that of targets.json. As with targets.json, the latest version of metadata files belonging to delegated roles are described in the snapshot role’s metadata.
snapshot The snapshot role is responsible for ensuring that clients see a consistent repository state. It provides repository state information by indicating the latest versions of the top-level targets and delegated targets metadata files on the repository in snapshot.json. root and timestamp are not listed in snapshot.json, because timestamp signs for its freshness, after snapshot.json has been created, and root, which has all top-level keys, is required ahead of time to trust any of the top-level roles.
timestamp The timestamp role is responsible for providing information about the timeliness of available updates. Timeliness information is made available by frequently signing a new timestamp.json file that has a short expiration time. This file indicates the latest version of snapshot.json.

표 1: TUF 역할 개요.

달리 지정되지 않는 한, 이 PEP에서는 모든 메타데이터 또는 대상 파일을 SHA-2 계열의 SHA2-512 함수로 해시할 것을 권고합니다. SHA-2는 Python 2 및 3을 기본적으로 지원하며 충분히 테스트되었으므로, Python 외의 추가 종속성 없이 이러한 해시를 검증할 수 있습니다. 더 강력한 보안 보장이 필요한 경우에는 SHA2-256과 SHA2-512를 함께 사용하거나 SHA2-256과 SHA3-256을 함께 사용하는 대신 사용할 수 있습니다. SHA2-256과 SHA3-256은 서로 매우 다른 설계를 기반으로 하므로 충돌 공격에 대한 추가적인 보호를 제공합니다. 그러나 SHA-3을 사용하려면 Python 2에 추가적인 Python 외 종속성을 설치해야 합니다.

메타데이터 서명 및 저장소 관리

최상위 root 역할은 최상위 timestamp, snapshot, targetsroot 역할의 키에 서명합니다. timestamp 역할은 저장소 메타데이터의 새 스냅샷마다 서명합니다. snapshot 역할은 root, targets 및 위임된 모든 targets 역할에 서명합니다. 위임된 targets 역할인 bins는 다시 bin-n 역할에 위임하며, 이 역할들은 등록된 PyPI 프로젝트에 속한 모든 배포 파일에 서명합니다.

그림 1은 PyPI에서 사용할 수 있는 역할의 개요를 제공하며, 여기에는 최상위 역할과 targets가 위임한 역할이 포함됩니다. 또한 이 그림은 각 역할에 서명하는 데 사용되는 키의 유형과 PyPI에서 제공되는 파일에 서명하도록 신뢰받는 역할을 보여 줍니다. 다음 두 절에서는 저장소 파일 서명의 세부 사항과 각 역할에 사용되는 키 유형을 다룹니다.

../_images/pep-0458-1.png

그림 1: PyPI에서 사용할 수 있는 역할 메타데이터의 개요입니다.

가장 자주 변경되는 역할은 timestamp, snapshotbins가 위임한 역할(즉, bin-n)입니다. root, targets 또는 위임된 메타데이터가 업데이트될 때마다 timestampsnapshot 메타데이터를 반드시 업데이트해야 합니다. 다만 roottargets 메타데이터는 위임된 메타데이터만큼 자주 업데이트될 가능성이 훨씬 낮다는 점에 유의하십시오. 마찬가지로 bins 역할은 bin-n 역할이 추가, 업데이트 또는 제거될 때만 업데이트됩니다. 따라서 프로젝트의 지속적 제공을 지원하기 위해 위임된 메타데이터가 자주 업데이트되므로 timestamp, snapshotbin-n 메타데이터도 매우 자주(분마다일 가능성도 있음) 업데이트될 것입니다. 지속적 제공은 PyPI가 다른 스냅샷과 독립적으로 안전하게 공존하고 삭제될 수 있는 스냅샷을 생성하는 데 사용하는 일련의 프로세스입니다 [18].

매년 PyPI 관리자는 roottargets 역할 키에 서명해야 합니다. 자동화 시스템은 모든 프로젝트의 타임스탬프가 지정된 스냅샷에 지속적으로 서명합니다. 저장소 메타데이터 API를 사용할 수 있으며, 이를 사용하여 TUF 저장소 관리를 수행할 수 있습니다.

일반적인 작업에서는 새 배포 패키지가 PyPI에 업로드될 때 bin-n 메타데이터가 업데이트되고 서명됩니다. 그러나 PyPI가 다시 초기화될 때마다 PyPI 저장소에 포함된 기존의 모든 배포 패키지에 대한 bin-n 메타데이터를 생성하고 서명할 일회성 온라인 초기화 메커니즘도 필요합니다.

PyPI 루트 키에 대한 초기 신뢰 설정 방법

pip와 같은 패키지 관리자는 사용자가 처음 다운로드하는 설치 파일과 함께 root 메타데이터 파일을 반드시 제공해야 합니다. 여기에는 모든 최상위 역할에 대해 신뢰되는 키에 관한 정보가 포함됩니다(루트 키 자체도 포함합니다). 패키지 관리자는 TUF 클라이언트 라이브러리도 함께 제공해야 합니다. TUF 클라이언트 라이브러리가 다운로드할 수 있는 모든 새 버전의 root 메타데이터는 패키지 관리자와 함께 처음 제공된 루트 키를 사용하여 검증됩니다. 루트 키가 손상되었지만 일정 임계값의 키가 여전히 안전하게 보호되고 있다면, PyPI 관리자는 손상된 키에 대한 신뢰를 철회하는 새 root 메타데이터를 반드시 배포해야 합니다. 루트 키의 임계값이 손상되면 root 메타데이터를 대역 외 방식으로 반드시 업데이트해야 합니다. (그러나 이 사건이 극히 드물게 발생하도록 루트 키의 임계값을 선택해야 합니다.) 패키지 관리자의 새 릴리스 사이에 루트 키가 철회되거나 추가되더라도 패키지 관리자를 즉시 업데이트해야 하는 것은 아닙니다. 사용되는 TUF 사양에 하위 호환성이 없는 경우가 아니라면, TUF 업데이트 프로세스가 이전 root 키의 임계값이 새 root 키에 서명하는 상황을 자동으로 처리하기 때문입니다. 따라서 예를 들어, 패키지 관리자가 처음에 root 메타데이터 버전 1과 함께 배포되었고, 버전 1의 root 키가 임계 수만큼 root 메타데이터 버전 2에 서명했으며, 버전 2의 root 키가 임계 수만큼 root 메타데이터, 버전 3에 서명했다면, 패키지 관리자는 TUF 클라이언트 라이브러리를 사용하여 자체 *root 메타데이터 사본을 버전 1에서 버전 3으로 투명하게 업데이트할 수 있어야 합니다.

따라서 다시 말하면, CPython과 함께 제공되는 pip의 모든 새 버전에는 최신의 정상 root 메타데이터 사본과 TUF 클라이언트 라이브러리가 반드시 포함되어야 합니다(ensurepip를 통해). 그러면 패키지 관리자 내부의 TUF 클라이언트 라이브러리가 root 메타데이터를 로드하고 나머지 역할을 다운로드하며, 변경된 경우에는 root 메타데이터도 업데이트합니다. outline of the update process를 사용할 수 있습니다.

최소 보안 모델

TUF를 PyPI에 통합할 때 고려해야 할 보안 모델은 두 가지입니다. 이 PEP에서 제안하는 모델은 최소 보안 모델이며, PyPI에 저장된 개인 암호화 키로 서명된 PyPI 배포판을 검증할 수 있도록 지원합니다. 개발자가 업로드한 배포판은 PyPI가 서명하며, 즉시 다운로드할 수 있습니다. 관련 PEP 480에서 논의된 이 PEP의 가능한 향후 확장안은 최대 보안 모델을 제안하며 개발자가 자신의 프로젝트에 서명할 수 있도록 합니다. 개발자 키는 온라인에 저장되지 않으므로 프로젝트는 PyPI 침해로부터 안전합니다.

최소 보안 모델은 개발자의 조치가 필요하지 않으며, 악성 CDN [19] 및 공개 미러로부터 보호합니다. 업로드된 배포판의 지속적 제공을 지원하기 위해 PyPI는 온라인 키로 프로젝트를 대신해 서명합니다. 이 보안 수준은 미러나 CDN이 프로젝트에 서명하는 데 필요한 키를 전혀 보유하지 않으므로, 프로젝트가 미러나 CDN에 의해 실수로 또는 의도적으로 변조되는 것을 방지합니다. 그러나 PyPI를 침해한 공격자로부터 프로젝트를 보호하지는 못합니다. 공격자는 온라인에 저장된 키를 사용하여 TUF 메타데이터를 조작할 수 있기 때문입니다.

이 PEP에서는 bin-n 역할이 온라인 키로 모든 PyPI 프로젝트에 서명하도록 제안합니다. 이러한 bin-n 역할은 모두 오프라인 키로 서명되는 상위 수준의 bins 역할에 의해 위임되어야 하며, 이 역할은 다시 오프라인 키로 서명되는 최상위 targets 역할에 의해 위임되어야 합니다. 즉, pip와 같은 패키지 관리자가 TUF를 사용하여 PyPI의 프로젝트에서 배포 파일을 다운로드할 때 해당 배포 파일의 TUF 메타데이터에 관해 targets 역할을 참조합니다. 최종적으로 targetsbins를 통해 위임한 bin-n 역할 중 어느 것도 해당 배포 파일을 지정하지 않으면, 해당 파일은 PyPI에 존재하지 않는 것으로 간주됩니다.

targetsbin-n에 직접 위임하지 않고 중간에 bins 역할을 사용하는 이유는 bins-to-bin-n 매핑에 영향을 주지 않으면서 다른 위임을 쉽게 추가하거나 제거할 수 있도록 하기 위해서입니다. 이는 PEP 480의 구현에 매우 중요합니다.

메타데이터 만료 시간

root, targets, bins 역할의 메타데이터는 각각 1년 후 만료되어야 합니다. 이러한 메타데이터 파일은 변경되는 일이 매우 드물 것으로 예상되기 때문입니다.

timestamp, snapshot, bin-n 메타데이터는 각각 1일 후 만료되어야 합니다. CDN 또는 미러가 매일 PyPI와 동기화되어야 하기 때문입니다. 또한 이처럼 넉넉한 기간은 클라이언트 시계가 크게 틀어져 있거나 시간이 어긋난 경우도 고려합니다.

메타데이터 확장성

저장소의 프로젝트와 배포판 수가 증가함에 따라 TUF 메타데이터도 그에 상응하여 증가해야 합니다. 예를 들어, bins 역할을 고려하십시오. 2013년 8월, bins 역할 자체가 약 220K개의 PyPI 대상(단순 인덱스와 배포판)에 서명하는 경우 bins 메타데이터의 크기가 약 42MB인 것으로 확인되었습니다. 이 PEP에서는 세부 사항을 다루지 않지만, TUF에는 대규모 targets 메타데이터 파일을 여러 개의 작은 파일로 분할하는 이른바 “hashed bin delegation” 방식이 있습니다. 이를 통해 TUF 클라이언트 업데이트 프로그램은 bins 역할이 서명한 프로젝트를 업데이트하는 데 필요한 소수의 TUF 메타데이터 파일만 지능적으로 다운로드할 수 있습니다. 예를 들어, 이전 저장소에 이 방식을 적용한 결과, TUF를 통해 PyPI 프로젝트를 설치하거나 업그레이드할 때 pip이 1.3KB에서 111KB 사이를 다운로드했습니다.

구현을 위해 이 문서를 업데이트한 시점(2019년 11월 7일)의 조사 결과를 바탕으로 하며, 표 2~3에 요약된 바와 같이 PyPI는 bins 역할의 모든 대상을 16,384개의 bin-n 역할에 위임하여 분할해야 합니다(표 2의 C10 참조). 각 bin-n 역할은 SHA2-512 해시가 해당 빈에 속하는 PyPI 대상에 서명합니다(그림 1 및 Consistent Snapshots에 나오는 내용 참조). 이 빈 수는 기존 사용자의 경우 5~9%의 메타데이터 오버헤드(다운로드한 배포 파일의 평균 크기 대비)를 초래하고, pip을 처음 설치하는 신규 사용자의 경우 69%의 오버헤드를 초래하는 것으로 확인되었습니다(표 3의 V13 및 V15, V17 참조).

다음은 이러한 메타데이터 오버헤드 백분율을 계산하는 데 사용한 몇 가지 가정입니다:

  1. root, timestamp 및 top-level targets 메타데이터는 무시합니다.
  2. pip에는 항상 모든 역할에 대한 최신의 정상적인 메타데이터 사본이 함께 포함됩니다.
이름 설명
C1 SHA2-512 16진수 다이제스트의 바이트 수 128
C2 SHA2-512 공개 키 ID의 바이트 수 64
C3 Ed25519 서명의 바이트 수 128
C4 Ed25519 공개 키의 바이트 수 64
C5 대상 상대 파일 경로의 바이트 수 256
C6 대상 파일 크기를 인코딩하는 데 필요한 바이트 수 7
C7 버전 번호를 인코딩하는 데 필요한 바이트 수 6
C8 대상 수(단순 색인 및 배포판) 2,273,539
C9 다운로드된 배포판의 평균 바이트 수 2,184,393
C10 빈의 수 16,384

C8은 릴리스 파일 수를 조회하여 계산되었습니다. C9는 지난 31일 동안 다운로드된 릴리스 파일의 평균 크기에 대한 대략적인 추정치(1,628,321바이트)와 디스크에 저장된 릴리스 파일의 평균 크기(2,740,465바이트)의 평균을 구하여 도출되었습니다. Ee Durbin은 2019년 11월 7일에 이 수치를 제공하는 데 도움을 주었습니다.

표 2: 메타데이터 오버헤드를 계산하는 데 사용되는 상수 목록

이름 설명 수식
V1 경로 해시 접두사의 길이 math.ceil(math.log(C10, 16)) 4
V2 경로 해시 접두사의 총수 16**V1 65,536
V3 빈당 평균 대상 수 math.ceil(C8/C10) 139
V4 빈당 SHA-512 해시의 평균 크기 V3*C1 17,792
V5 빈당 대상 경로의 평균 크기 V3*C5 35,584
V6 빈당 길이의 평균 크기 V3*C6 973
V7 bin-n 메타데이터의 평균 크기(바이트) V4+V5+V6 54,349
V8 빈의 공개 키 ID 총 크기 C10*C2 1,048,576
V9 빈의 경로 해시 접두사의 총 크기 V1*V2 262,144
V10 빈 메타데이터의 추정 크기(바이트) V8+V9 1,310,720
V11 스냅샷 메타데이터의 추정 크기(바이트) C10*C7 98,304
V12 동일 스냅샷에서 재방문 사용자별 배포 패키지당 메타데이터 오버헤드의 추정 크기입니다 2*V7 108,698
V13 동일 스냅샷에서 재방문 사용자별 배포 패키지당 메타데이터 오버헤드의 추정치입니다 round((V12/C9)*100) 5%
V14 다른 스냅샷에서 재방문 사용자별 배포 패키지당 메타데이터 오버헤드의 추정 크기입니다 V12+V11 207,002
V15 다른 스냅샷에서 재방문 사용자별 배포 패키지당 메타데이터 오버헤드의 추정치입니다 round((V14/C9)*100) 9%
V16 신규 사용자별 배포 패키지당 메타데이터 오버헤드의 추정 크기입니다 V14+V10 1,517,722
V17 신규 사용자별 배포 패키지당 메타데이터 오버헤드의 추정치입니다 round((V16/C9)*100) 69%

표 3: 신규 사용자 및 재방문 사용자의 메타데이터 오버헤드 추정치입니다.

관심 있는 독자는 메타데이터 오버헤드 계산기의 대화형 버전을 여기에서 찾을 수 있습니다:

이 bin의 수는 기존 사용자에 대한 메타데이터 오버헤드가 50%를 초과할 때 증가해야 합니다. 현재 이는 대상 수가 2M 초과에서 22M 초과로 최소 10배 증가할 때 발생해야 하며, 이 시점에서 bin의 수가 고정되어 있다고 가정하면 기존 사용자와 신규 사용자에 대한 메타데이터 오버헤드는 각각 약 50~54%와 114%가 됩니다. bin의 수가 증가하면 모든 사용자의 비용은 사실상 신규 사용자의 비용이 됩니다. 이는 사용자의 비용이 bins 메타데이터에 포함된 많은 위임을 다운로드하는 (가끔 발생하는) 비용에 의해 지배되기 때문입니다. 신규 사용자의 비용이 주로 bins 메타데이터 다운로드 오버헤드로 인해 지나치게 큰 것으로 판명되면, 그렇게 되기 전에 이 문제를 재검토해야 합니다.

서버에서 bin의 수를 변경해도 클라이언트에는 투명하다는 점에 유의하십시오. 패키지 관리자는 신규 사용자인 것처럼 새로운 메타데이터 세트를 다운로드해야 하지만, 이 작업을 수행하기 위해 명시적인 코드 로직이나 사용자 상호 작용이 필요하지는 않습니다.

TUF 메타데이터를 JSON 텍스트 형식이 아닌 바이너리 형식으로 표현하여 더 작게 만들 수 있습니다. 그럼에도 불구하고 충분히 많은 프로젝트와 배포 패키지는 언젠가 확장성 문제를 일으킬 것이므로, 문제를 해결하려면 Figure 1에 설명된 것처럼 bins 역할에 여전히 위임이 필요합니다. JSON 형식은 데이터 교환을 위한 개방적이고 잘 알려진 표준이며 이미 TUF 참조 구현에서 지원되므로, 이 PEP가 권장하는 데이터 형식입니다. 그러나 많은 위임으로 인해 기존 Warehouse의 HTTP 압축 메커니즘을 통해 모든 메타데이터의 압축 버전도 클라이언트에 제공되어야 합니다. 또한 JSON 메타데이터를 클라이언트에 전송하기 전에 압축할 수도 있습니다. TUF 참조 구현은 현재 압축된 JSON 메타데이터 다운로드를 지원하지 않지만, 메타데이터 크기를 줄이기 위해 이 기능을 추가할 수 있습니다.

PyPI 및 키 요구 사항

이 절에서는 PyPI에서 TUF 역할에 서명하는 데 필요한 키의 종류를 살펴봅니다. TUF는 디지털 서명 알고리즘의 선택에 관해 특정 입장을 취하지 않습니다. 그러나 이 PEP는 모든 디지털 서명을 Ed25519 알고리즘 [15]으로 생성할 것을 권장합니다. Ed25519는 기본적으로 제공되고 충분히 검증된 Python 지원을 갖추고 있으며(추가적인 비Python 종속성 없이 서명을 검증할 수 있음), 작은 키를 사용하고, 최신 HSM 및 인증 토큰 하드웨어에서 지원됩니다.

권장되는 키의 수와 유형

root 역할 키는 보안에 매우 중요하므로 극히 드물게 사용해야 합니다. 이 키는 주로 키 폐기에 사용되며, 모든 PyPI에 대한 신뢰의 근원입니다. root 역할은 각 최상위 역할(자체 역할 포함)에 권한이 부여된 키에 서명합니다. root 역할에 속하는 키는 매우 철저히 보호하고 모든 키 중 가장 낮은 빈도로 사용하도록 되어 있습니다. PSF 이사회가 현재 신뢰할 수 있는 루트 키 보유자 집합을 결정하고, 각 보유자가 (강력한) 루트 키를 소유하도록 할 것을 권장합니다. 그런 다음 이들 중 과반수가 모든 최상위 키에 대한 신뢰를 철회하거나 부여하기 위한 정족수를 구성할 수 있습니다. 또는 PyPI의 시스템 관리자가 root 역할에 서명할 책임을 맡을 수도 있습니다. 따라서 root 역할에는 (t, n) 키가 필요해야 하며, 여기서 n은 PSF 이사회가 결정한 키 보유자의 수이고 t > 1입니다(최소 두 명의 구성원이 root 역할에 서명해야 함).

targets 역할은 모든 대상을 bins 역할에 정적으로 위임하는 데 서명하는 용도로만 사용됩니다. 이러한 대상 위임은 침해가 발생할 경우 공격으로부터 보호되어야 하므로, targets 역할의 키는 오프라인 상태이며 다른 키와 독립적이어야 합니다. 보안을 희생하지 않으면서 키 관리를 단순화하기 위해, targets 역할의 키는 생성되어 해당 역할에 서명하는 데 사용되는 즉시 영구적으로 폐기할 것을 권장합니다. 따라서 targets 역할에는 (2, 2) 키가 필요해야 합니다. 이는 키가 영구적으로 폐기될 예정이기 때문이며, 암호화 알고리즘의 다양성이 유지되지 않는 한 오프라인 키를 더 많이 사용해도 키 복구 공격 [20]에 대한 저항력이 향상되지 않습니다.

유사한 이유로 bins 역할의 키는 targets 역할의 키와 유사하게 설정해야 합니다.

지속적 배포를 지원하려면, timestamp, snapshot및 모든 bin-n역할의 키가 온라인 상태여야 합니다. 공격자가 PyPI를 침해하면 이 모든 역할을 침해할 수 있을 것으로 추정되므로, 모든 역할에 서로 다른 온라인 키를 사용하도록 요구하는 것은 실익이 거의 없습니다. 따라서 이 모든 역할에 하나의 온라인 키를 사용하는 것이 합리적입니다.

온라인 키 관리

timestamp, snapshot및 모든 bin-n역할이 공유하는 온라인 키는 암호화 여부와 관계없이 Python 인프라에 저장할 수 있습니다. 예를 들어, 키를 자체 호스팅 키 관리 서비스(예: Hashicorp Vault)에 보관하거나, 타사 서비스(예: AWS KMS, Google Cloud KMS 또는 Azure Key Vault)에 보관할 수 있습니다.

이러한 키 관리 서비스 중 일부에서는 키를 하드웨어 보안 모듈(HSM)(예: Hashicorp Vault, AWS CloudHSM, Google Cloud HSM 또는 Azure Key Vault)에 저장할 수 있습니다. 이렇게 하면 공격자가 온라인 개인 키를 탈취하는 것을 막을 수 있습니다(다만 키를 사용하는 것까지 막지는 못하며, 이제 공격자의 행위는 암호학적으로 감사할 수 있습니다). 그러나 이를 위해서는 HSM을 지원하도록 참조 TUF 구현을 수정해야 합니다(WIP).

이 온라인 키를 어디에 어떻게 보관하든 관계없이, 키 사용 내역을 주의 깊게 기록하고, 모니터링하며, 감사해야 하며, 이상적으로는 PyPI를 침해한 공격자가 이 기록, 모니터링 및 감사를 즉시 중단할 수 없도록 해야 합니다.

오프라인 키 관리

이전 절에서 설명한 것처럼, 최대한의 보안을 위해 root, targetsbins역할 키는 오프라인 상태여야 합니다. 이러한 키가 오프라인이라는 것은 개인 키를 PyPI에 저장해서는 안 된다는 의미이며, 일부 키는 프로젝트의 사설 인프라에서 온라인 상태일 수 있습니다.

필요할 때(예: 최상위 TUF 역할의 키를 교체할 때) Python 관리자를 제외한 누구도 개인 키를 읽을 수 없도록 이러한 키를 생성하고, 백업하며, 저장하는 오프라인 키 의식을 마련해야 합니다. 따라서 키는 가급적 사이드 채널 공격을 우려하지 않아도 되는 물리적 장소에서 다음을 사용하여 생성해야 합니다.

  1. 신뢰할 수 있는 에어갭 컴퓨터, 진정한 난수 생성기 및 의식이 끝난 후 데이터가 남지 않는 환경
  2. 신뢰할 수 있는 운영 체제
  3. 신뢰할 수 있는 타사 패키지 집합(예: 신뢰할 수 있는 운영 체제에서 제공하는 버전이 충분히 최신이 아닌 경우 최신 버전의 암호화 라이브러리 또는 TUF 참조 구현)

의식이 끝난 후 백업 미디어 이외의 곳에 민감한 데이터(예: 개인 키)가 남는 것을 방지하려면, 오프라인 키를 강력한 암호를 사용하여 암호화된 상태로 생성해야 하며, 다음 중 하나를 사용해야 합니다(신뢰도가 낮아지는 순서): 사설 HSM(예: YubiHSM), 클라우드 기반 HSM(예: 위에 나열된 것), 휘발성 메모리(예: RAM) 또는 비휘발성 메모리(예: SSD 또는 microSD)입니다. 키를 비휘발성 메모리에서 생성해야 하는 경우, 키를 안전하게 백업한 후 해당 메모리를 복구할 수 없도록 파기해야 합니다.

키를 암호화하는 데 사용되는 암호는 Python 관리자만 접근할 수 있는 내구성 있고 신뢰할 수 있는 곳에 저장해야 합니다.

의식 중 OPSEC오류를 최소화하려면, 신뢰할 수 있는 키 생성 컴퓨터에서 실행하여 다음과 같은 의식의 번거로운 단계를 자동화하는 스크립트를 작성해야 합니다.

  • 새 키를 생성하고 기존 키를 교체하는 데 필요한 모든 코드와 데이터(이전 TUF 메타데이터 및 root키)를 sneakernet으로 내보내기
  • 방화벽을 강화하고, 보안 취약점을 수정하도록 전체 운영 체제를 업데이트하며, 컴퓨터를 에어갭 상태로 만들기
  • 새로운 TUF 메타데이터와 키를 모두 암호화된 백업 미디어로 내보내기 이 백업은 PyPI TUF 저장소를 복원하는 데 필요한 데이터의 완전한 사본을 제공합니다.
  • 새로운 TUF 메타데이터와 온라인 키 암호화된 백업 미디어로 내보내기 이 백업은 PyPI 인프라로 가져올 모든 온라인 데이터를 제공하며, 온라인 데이터를 이전에 보관된 상태에서 복원해야 할 때 유용합니다.
  • 새 TUF 메타데이터의 암호화 해시를 출력하고 저장합니다. 이 인쇄본은 추가적인 오프라인 종이 백업을 제공하며, 침해가 발생한 경우 비교 자료로 사용할 수 있습니다.

targetsbins 역할의 일회용 키는 오프라인 키 의식 중에 안전하게 생성하고 사용한 후 삭제할 수 있다는 점에 유의하십시오. 또한, 오프라인 키 의식 자체에서는 root 키를 생성하지 않을 수 있습니다. 대신 위에서 설명한 n명의 Python 관리자로 구성된 임계값 t의 관리자는 다른 모든 키를 생성하는 데 사용된 오프라인 키 의식 after root 메타데이터에 독립적으로 서명할 수 있습니다.

메타데이터는 어떻게 생성해야 합니까?

프로젝트 개발자는 PyPI에 업로드하는 배포 패키지를 즉시 다운로드할 수 있기를 기대합니다. 안타깝게도 많은 리더와 라이터가 동일한 메타데이터 및 대상 파일에 동시에 액세스하면 문제가 발생합니다. 즉, 여러 개발자가 이러한 파일을 동시에 변경할 때 메타데이터와 대상 파일의 일관성을 보장할 방법이 필요합니다. TUF가 없는 PyPI에도 일관성 문제가 있지만, PyPI에서 실시간으로 사용할 수 있는 파일을 반드시 추적해야 하는 서명된 메타데이터에서는 문제가 더 심각합니다.

PyPI가 timestamp를 제외한 모든 메타데이터의 최신 버전을 버전 1로 나타내는 snapshot을 생성하고 클라이언트가 PyPI에 이 snapshot을 요청한다고 가정하십시오. 클라이언트가 이 snapshot을 다운로드하는 동안 PyPI가 새 스냅샷에 버전 2라는 타임스탬프를 기록한다고 가정하십시오. 메타데이터의 일관성을 보장하지 않으면 클라이언트는 PyPI에서 제공되는 내용과 일치하지 않는 snapshot사본을 갖게 됩니다. 그 결과는 공격자가 주입한 임의의 메타데이터와 구별할 수 없게 됩니다. PyPI와 동기화하려는 미러에서도 같은 문제가 발생합니다.

일관된 스냅샷

PyPI의 TUF 메타데이터를 변동성이 매우 큰 대상 파일과 일관되게 유지하려면 일관된 스냅샷을 사용해야 합니다. 각 일관된 스냅샷은 특정 시점에 알려진 모든 프로젝트의 상태를 포착하며, 다른 스냅샷에 영향을 주지 않고 다른 스냅샷과 안전하게 공존하거나 독립적으로 삭제할 수 있습니다.

일관된 스냅샷을 유지하려면 모든 TUF 메타데이터를 디스크에 기록할 때 파일 이름에 버전 번호를 포함해야 합니다.

VERSION_NUMBER.ROLENAME.json,
여기서 VERSION_NUMBER는 증가하는 정수이고, ROLENAME은 최상위 메타데이터 역할인 root, snapshot 또는 targets 중 하나이거나 위임된 targets 역할인 bins 또는 bin-n 중 하나입니다.

유일한 예외는 timestamp 메타데이터 파일이며, 클라이언트가 업데이트를 수행할 때 그 버전을 미리 알 수 없습니다. timestamp 메타데이터에는 snapshot 메타데이터의 버전이 나열되며, 이는 다시 주어진 일관된 스냅샷의 일부로 targets 및 위임된 targets 메타데이터의 버전들을 나열합니다.

일반적인 사용에서는 버전 번호 오버플로가 발생할 가능성이 낮습니다. 예를 들어 8바이트 정수는 밀리초마다 한 번씩 증가시켜도 거의 3억 년 동안 사용할 수 있습니다. 공격자가 버전 번호를 임의로 증가시키면 TUF 사양 에 설명된 대로 침해된 키를 폐기하고 버전 번호를 재설정하여 저장소를 복구할 수 있습니다.

targets 또는 위임된 targets 메타데이터는 위에서 지정한 암호화 해시를 포함하여 실제 대상 파일을 참조합니다. 따라서 대상 파일을 일관된 스냅샷의 일부로 표시하려면 디스크에 기록할 때 파일 이름에 해당 해시를 포함해야 합니다.

HASH.FILENAME
여기서 HASH는 파일 내용 해시의 hex digest이고 FILENAME은 원래 파일 이름입니다.

이는 위에서 지정한 각 암호화 해시 함수마다 하나씩, 모든 대상 파일의 사본이 여러 개 존재할 수 있음을 의미합니다.

무한한 디스크 공간, 엄격하게 증가하는 버전 번호, 그리고 hash collisions이 없다고 가정하면, PyPI가 다른 스냅샷을 생성하는 동안 클라이언트는 한 스냅샷에서 안전하게 읽을 수 있습니다.

pip와 같이 TUF 프로토콜을 사용하는 클라이언트는 timestamp 메타데이터를 제외한 모든 메타데이터와 대상 파일을 다운로드하도록 수정해야 합니다. 이는 파일 요청 시 메타데이터의 경우 파일 버전을, 대상 파일의 경우 파일의 암호화 해시를 파일 이름에 포함하여 수행합니다.

이처럼 간단하면서도 효과적인 방식으로 PyPI는 특정 시점의 모든 프로젝트와 관련 메타데이터에 대한 일관된 스냅샷을 생성할 수 있습니다. 다음 하위 절에서는 이 아이디어의 구현 세부 사항을 설명합니다.

참고: 이 PEP는 일관된 스냅샷을 생성하기 위해 고급 파일 시스템이나 도구를 사용하는 것을 금지하지 않습니다. 이 PEP에서 간단한 해결책을 제안하는 데에는 두 가지 중요한 이유가 있습니다. 첫째, 이 해결책은 PyPI가 특정 파일 시스템이나 도구를 사용하도록 요구하지 않습니다. 둘째, 일반적인 파일 시스템 기반 접근 방식에서는 미러가 rsync와 같은 기존 파일 전송 도구를 사용하여 PyPI에서 일관된 스냅샷을 효율적으로 전송할 수 있습니다.

일관된 스냅샷 생성

새 배포 파일이 PyPI에 업로드되면 PyPI는 해당 파일을 담당하는 bin-n 메타데이터를 업데이트해야 합니다. 모든 대상 파일은 파일 이름 해시에 따라 빈으로 정렬된다는 점을 기억하십시오. PyPI는 업데이트된 bin-n 메타데이터를 반영하도록 snapshot을 업데이트하고, 업데이트된 snapshot 메타데이터를 반영하도록 timestamp도 업데이트해야 합니다. 이러한 업데이트는 자동화된 snapshot process에서 처리해야 합니다.

파일 업로드는 병렬로 처리할 수 있지만, 일관된 스냅샷은 엄격하게 순차적인 방식으로 생성해야 합니다. 또한 배포 파일이 자체 완결형인 한, 업로드된 각 파일에 대해 일관된 스냅샷을 생성할 수 있습니다. 이를 위해 업로드 프로세스는 새 배포 파일을 동시성 안전 FIFO 큐에 배치하고, 스냅샷 프로세스는 해당 큐에서 한 번에 한 파일씩 읽어 다음 작업을 수행합니다.

먼저 새 파일 경로를 관련 bin-n 메타데이터에 추가하고, 버전 번호를 증가시키며, bin-n 역할 키로 서명한 다음 VERSION_NUMBER.bin-N.json에 기록합니다.

그런 다음 최신 snapshot 메타데이터를 가져와 bin-n 메타데이터의 버전 번호를 업데이트하고, 자체 버전 번호를 증가시키며, snapshot 역할 키로 서명한 다음 VERSION_NUMBER.snapshot.json에 기록합니다.

마지막으로 스냅샷 프로세스는 최신 timestamp 메타데이터를 가져와 snapshot 메타데이터의 해시와 버전 번호를 업데이트하고, 자체 버전 번호를 증가시키며, 새 만료 시간을 설정하고, timestamp 역할 키로 서명한 다음 timestamp.json에 기록합니다.

일관된 스냅샷을 위해 bin-n 메타데이터를 업데이트할 때 스냅샷 프로세스는 관련 bin-n 메타데이터에 단순 색인 페이지의 새 해시 또는 업데이트된 해시도 포함해야 합니다. 단순 색인 페이지는 API 호출 시 동적으로 생성될 수 있으므로, 일관된 스냅샷의 유효 기간 전체에 걸쳐 해당 출력이 안정적으로 유지되는 것이 중요합니다.

스냅샷 프로세스는 일관된 스냅샷을 엄격하게 순차적인 방식으로 생성해야 하므로 병목이 됩니다. 다행히 서명 작업은 초당 천 번 이상 수행할 수 있을 만큼 빠릅니다.

또한 PyPI는 해당 일관된 스냅샷 메타데이터가 생성되기 전에 클라이언트에 배포 파일을 제공할 수 있습니다. 이 경우 클라이언트 소프트웨어는 완전한 TUF 보호를 아직 사용할 수 없지만 곧 제공될 것임을 사용자에게 알려야 합니다.

PyPI는 감사를 위해 업로드 프로세스와 스냅샷 큐를 기록하고, 서버 장애 후 오류를 복구하기 위해 transaction log를 사용해야 합니다.

오래된 메타데이터 정리

새로운 일관된 스냅샷이 지속적으로 생성되어 디스크 공간이 부족해지는 것을 방지하기 위해, PyPI는 오래된 일관된 스냅샷, 즉 1시간과 같이 합리적인 시간이 지난 후 폐기된 메타데이터와 대상 파일을 정기적으로 삭제해야 합니다.

최신 일관된 스냅샷을 보존하기 위해 PyPI는 “mark-and-sweep” 알고리즘을 사용할 수 있습니다. 즉, 최신 일관된 스냅샷의 루트, 즉 timestamp에서 snapshot을 거쳐 targets 및 위임된 targets까지 대상 파일에 이를 때까지 탐색하면서 방문한 모든 파일을 표시하고, 표시되지 않은 모든 파일을 삭제합니다. 최근 몇 개의 일관된 스냅샷도 유사한 방식으로 보존할 수 있습니다.

일관된 스냅샷을 삭제하면 클라이언트는 해당 일관된 스냅샷 내 파일에 대한 모든 요청에 대해 HTTP 404 응답만 보게 됩니다. 그러면 클라이언트는 최신 일관된 스냅샷을 사용하여 이전과 같이 요청을 다시 시도해야 합니다.

버전이 지정되어 있더라도 root 메타데이터는 어떤 일관된 스냅샷에도 포함되지 않는다는 점에 유의하십시오. PyPI는 이전 버전의 root 메타데이터를 삭제해서는 안 됩니다. 이를 통해 클라이언트의 로컬 root 메타데이터가 아무리 오래되었더라도 최신 root 역할 키로 업데이트할 수 있습니다.

프로젝트 및 배포판에 대한 신뢰 철회

때때로 프로젝트 또는 배포판에 대한 신뢰를 철회해야 합니다. 프로젝트 또는 배포판에 대한 신뢰를 철회하려면 관련 bin-n 역할에서 해당 targets를 간단히 제거하고 bin-n 메타데이터에 다시 서명할 수 있습니다. 이 작업에는 온라인 bin-n 키를 사용한 작업만 필요합니다.

키 손상 분석

이 PEP에서는 최소 보안 모델, 배포판의 지속적 제공을 지원하기 위해 추가해야 하는 TUF 역할, 그리고 각 역할의 메타데이터를 생성하고 서명하는 방법을 다루었습니다. 나머지 절에서는 PyPI가 저장소 메타데이터를 감사해야 하는 방법과 PyPI가 손상을 탐지하고 복구하는 데 사용할 수 있는 방법을 논의합니다.

표 4에서는 PyPI 역할 중 어느 역할에 속하든 일정 수 이상의 개인 암호화 키가 손상되었을 때 가능한 공격 몇 가지를 요약합니다. 가장 왼쪽 열에는 손상된 역할 또는 역할 조합이 나열되어 있으며, 그 오른쪽 열에는 손상된 역할로 인해 클라이언트가 악성 업데이트, 동결 공격 또는 메타데이터 불일치 공격에 취약해지는지가 표시됩니다. timestamp, snapshot 및 bin-n 역할이 동일한 온라인 위치에 저장되어 있다면 하나가 손상될 경우 모두 손상된다는 점에 유의하십시오. 따라서 표에서는 이러한 역할을 함께 다룹니다. 이러한 역할을 개별적으로 고려한 이 표의 버전은 PEP 480에 포함되어 있습니다.

Role Compromise Malicious Updates Freeze Attack Metadata Inconsistency Attacks
targets OR bins NO timestamp and snapshot need to cooperate
timestamp AND snapshot AND bin-n YES limited by earliest root, targets, or bins metadata expiry time
root YES

표 4: 특정 역할 키 조합을 손상시켜 발생할 수 있는 공격입니다. September 2013에 당시 최신 버전의 pip가 이러한 공격에 취약했으며 TUF가 이에 대해 사용자를 보호할 수 있는 방법이 제시되었습니다 [14].

targets 또는 bins를 손상시키는 것만으로는 공격자가 즉시 악성 업데이트를 제공할 수 없다는 점에 유의하십시오. 공격자는 timestampsnapshot 역할도 손상시켜야 하며, 이 둘은 모두 온라인 상태이므로 손상될 가능성이 더 높습니다. 이는 공격을 수행하려면 중간자 역할을 할 수 있을 뿐 아니라 timestamp 키도 손상시켜야 한다는 의미입니다(또는 root 키를 손상시키고 새로운 timestamp 키에 서명해야 합니다). 동결 공격 이외의 공격을 수행하려면 snapshot 키도 손상시켜야 합니다. 실제로 이 PEP에서는 snapshot, timestampbin-n 키를 함께 저장하거나, 심지어 이러한 모든 역할에 동일한 키를 사용할 것을 권장합니다. 따라서 공격자는 위에 나열된 공격을 수행하기 위해 이 단일 서버만 손상시키면 됩니다. CDN이나 미러와 같은 비서명 인프라가 손상되더라도 클라이언트는 여전히 보호된다는 점에 유의하십시오. 또한 오프라인 root 키를 사용하면 온라인 키를 철회하여 저장소가 공격에서 복구할 수 있습니다.

최대 보안 모델은 최종 서명을 위한 추가 역할을 도입하여 TUF가 온라인 키 손상을 완화하는 방법을 보여 줍니다. 개발자 키를 생성하고 업로드 배포판에 서명하는 방법에 대한 자세한 내용은 PEP 480에 제공되어 있습니다.

키가 손상된 경우

키 손상이란 PyPI의 메타데이터 역할에 속한 일정 임계 개수의 키와 PyPI 인프라가 손상되어 PyPI에서 새 메타데이터에 서명하는 데 사용된 상태를 의미합니다.

timestamp, snapshot, targets, bins 또는 bin-n 키가 일정 임계 개수만큼 손상된 경우 PyPI는 다음 단계를 반드시 수행해야 합니다:

  1. root 역할에서 timestamp, snapshottargets 역할 키를 폐기하십시오. 손상된 timestamp, snapshottargets 키를 새로 발급된 키로 교체하여 이를 수행합니다.
  2. targets 역할에서 bins 키를 새로 발급된 키로 교체하여 폐기하십시오. 새 targets 역할 메타데이터에 서명한 후 새 키를 폐기하십시오(앞서 설명했듯이 이렇게 하면 targets 메타데이터의 보안이 향상되기 때문입니다).
  3. bin-n 역할의 모든 targets를 timestamp, snapshot, bins 또는 bin-n 키가 손상된 것으로 알려지지 않았던 마지막으로 알려진 정상 일관 스냅샷과 비교해야 합니다. 손상된 일관 스냅샷에서 추가, 업데이트 또는 삭제된 targets가 마지막으로 알려진 정상 일관 스냅샷과 일치하지 않는 경우 이전 버전으로 복원할 수 있습니다. 모든 bin-n targets의 무결성을 확인한 후 해당 키를 bins 메타데이터에서 갱신해야 합니다.
  4. binsbin-n 메타데이터의 버전 번호를 증가시키고, 만료 시간을 적절히 연장하며, 서명을 갱신해야 합니다.
  5. 타임스탬프가 지정된 새 일관 스냅샷을 반드시 발행해야 합니다.

이러한 단계를 따르면 이들 역할 중 하나만 손상되었더라도 모든 역할을 선제적으로 보호할 수 있습니다.

root 키가 일정 임계 개수만큼 손상된 경우 PyPI는 위 단계를 반드시 수행하고 root 역할의 모든 root 키도 교체해야 합니다.

또한 PyPI가 보안 게시판을 통해 손상 사실을 충분히 문서화할 것을 권장합니다. 이러한 보안 게시판은 pip-with-TUF 사용자가 timestamp, snapshot 또는 root 역할의 키가 더 이상 유효하지 않아 프로젝트를 설치하거나 업데이트할 수 없을 때 가장 유용합니다. 그러면 사용자는 PyPI 웹 사이트를 방문하여 더 이상 설치하거나 업데이트할 수 없는 이유를 설명하는 데 도움이 되는 보안 게시판을 확인한 다음 그에 따라 조치를 취할 수 있습니다. 손상으로 인해 root 키가 일정 임계 개수만큼 폐기되지 않은 경우, 기존 root 키 중 일정 임계 개수가 새 root 메타데이터의 무결성에 서명하는 데 사용되므로 새 root 메타데이터를 안전하게 업데이트할 수 있습니다. TUF 클라이언트는 이전에 알려진 root 키 중 일정 임계 개수를 사용하여 새 root 메타데이터의 무결성을 검증할 수 있습니다. 이것이 일반적인 경우입니다. 그렇지 않고 최악의 경우, 즉 손상으로 인해 root 키가 일정 임계 개수만큼 폐기된 경우 최종 사용자는 out-of-band 메커니즘을 사용하여 새 root 메타데이터를 업데이트할 수 있습니다.

스냅샷 감사

악의적인 주체가 PyPI를 손상시키면 온라인 키 중 어느 것이든 사용하여 임의의 파일에 서명할 수 있습니다. 오프라인 키를 사용하는 역할(즉, root, targetsbins)은 여전히 보호됩니다. 저장소 손상에서 안전하게 복구하려면 파일이 신뢰할 수 있는 버전으로만 복원되도록 스냅샷을 감사해야 합니다.

저장소 손상이 탐지되면 세 가지 유형의 정보 무결성을 검증해야 합니다:

  1. 저장소의 온라인 키가 손상된 경우 targets 역할이 새 키에 위임하는 새 메타데이터에 서명하도록 하여 해당 키를 폐기할 수 있습니다.
  2. 저장소의 역할 메타데이터가 변경된 경우, 온라인 키로 서명된 메타데이터에 영향을 미칩니다. 마지막 기간 이후 생성된 모든 역할 정보는 폐기해야 합니다. 그 결과, 새 프로젝트의 개발자는 프로젝트를 다시 등록해야 합니다.
  3. 대상 파일 자체가 변조되었을 가능성이 있는 경우, 마지막 기간 당시 존재했던 대상 파일에 대해 저장된 해시 정보를 사용하여 이를 검증할 수 있습니다.

보안 침해가 발생했을 때 스냅샷을 안전하게 복원하기 위해, PyPI는 일정에 따라 PyPI 스냅샷을 복사하는 소수의 자체 미러를 유지해야 합니다. 이 목적에는 미러링 프로토콜을 즉시 사용할 수 있습니다. 미러는 PyPI 미러링만을 담당하도록 보안이 유지되고 격리되어야 합니다. 우발적 또는 악의적인 장애를 감지하기 위해 미러를 서로 대조하여 검사할 수 있습니다.

또 다른 방법은 snapshot의 암호학적 해시를 주기적으로 생성하여 트윗하는 것입니다. 어쩌면 한 사용자가 실제 메타데이터를 제시하고 저장소 유지 관리자가 메타데이터 파일의 암호화 해시를 검증할 수도 있습니다. 또는 PyPI는 외부에서 제공되는 메타데이터에 의존하는 대신 snapshot의 자체 버전을 주기적으로 보관할 수 있습니다. 이 경우 PyPI는 저장소의 모든 대상 파일에 대한 암호화 해시를 계산하여 오프라인 장치에 이 데이터를 저장해야 합니다. 대상 파일 해시가 변경되었다면 이는 공격이 발생했음을 나타냅니다.

서로 다른 버전의 메타데이터를 제공하거나 배포 패키지의 특정 버전을 고정하는 공격은 암시적 키 폐기 및 메타데이터 불일치 감지 [2]와 같은 기법을 사용하여 TUF로 처리할 수 있습니다.

업데이트 프로세스의 향후 변경 사항 관리

업데이트 프로세스에 호환성을 깨뜨리는 변경 사항이 적용되는 경우, PyPI는 기존 클라이언트를 중단하지 않고 이러한 변경 사항을 구현해야 합니다. 이를 수행하는 방법에 대한 일반적인 지침은 TAP 저장소에서 진행 중인 논의를 참조하십시오.

이 PEP에 따른 PyPI의 변경 사항은 하위 호환성을 유지한다는 점에 유의하십시오. 이 PEP에서는 대상 파일과 단순 색인의 위치를 변경하지 않으므로 기존 PyPI 클라이언트는 계속해서 이러한 파일을 사용하여 업데이트를 수행할 수 있습니다. 이 PEP는 클라이언트가 TUF 메타데이터를 사용하여 업데이트 프로세스의 보안을 향상할 수 있는 기능을 추가합니다.

해시 알고리즘 전환 계획

대상 파일과 메타데이터 파일을 해시하는 데 사용되는 알고리즘이 취약해지는 경우, 더 강력한 해시 알고리즘으로 교체해야 합니다.

TUF 메타데이터 형식에서는 알고리즘 식별자와 함께 서로 다른 해시 알고리즘의 다이제스트를 나란히 나열할 수 있으므로, 클라이언트는 알고리즘 간에 원활하게 전환할 수 있습니다.

그러나 이전 알고리즘에 대한 지원이 중단되면 새 알고리즘을 지원하지 않는 클라이언트는 TUF 검증을 비활성화해야만 클라이언트 자체를 포함한 패키지를 설치하거나 업데이트할 수 있습니다. 클라이언트가 TUF 보장 수준을 일시적으로 잃지 않고 전환할 수 있도록 다음 절차를 권장합니다.

  1. Warehouse에 새 알고리즘을 구현하십시오.
  2. 기존의 만료되지 않은 TUF 메타데이터를 다시 생성하여 이전 알고리즘과 새 알고리즘을 모두 사용한 해시를 포함하십시오. 이후 생성되는 모든 새 메타데이터에는 두 해시 알고리즘을 모두 나열해야 합니다. 참고로, 대상 파일 또는 기타 메타데이터의 해시 다이제스트를 나열하는 TUF 메타데이터만 갱신하면 됩니다. 즉, bin-n, snapshottimestamp입니다. 따라서 갱신된 메타데이터에 서명하는 데 온라인 키만 필요합니다.
  3. Python Discourse의 패키징PyPI 변경 사항 메일링 리스트와 같이 가시성이 높은 채널에 전환을 공지하십시오.
  4. pip 및 bandersnatch와 같은 널리 사용되는 클라이언트가 새로운 해시 알고리즘을 채택할 기회를 제공하십시오.
  5. 최종 사용자가 클라이언트를 업데이트할 기회를 제공하십시오.
  6. PyPI 유지 관리자들이 이전 해시 알고리즘을 제거하는 데 대략적인 합의를 이루도록 하십시오.
  7. 이전 알고리즘에 대한 Warehouse 지원을 제거하고 새로운 알고리즘만 지원하십시오.

부록 A: TUF로 방지되는 저장소 공격

  • 임의의 소프트웨어 설치: 공격자가 클라이언트 시스템에 원하는 것은 무엇이든 설치합니다. 즉, 공격자는 다운로드 요청에 대한 응답으로 임의의 파일을 제공할 수 있으며, 해당 파일은 부적법한 것으로 탐지되지 않습니다.
  • 롤백 공격: 공격자가 클라이언트가 이미 확인한 파일보다 오래된 파일을 소프트웨어 업데이트 시스템에 제시합니다. 이로 인해 클라이언트는 오래된 파일을 사용하게 됩니다.
  • 무기한 동결 공격: 공격자가 클라이언트가 이미 확인한 동일한 파일을 소프트웨어 업데이트 시스템에 계속 제시합니다. 그 결과 클라이언트는 새로운 파일을 사용할 수 있다는 사실을 알지 못합니다.
  • 무한 데이터 공격: 공격자가 파일 다운로드 요청에 무한한 데이터 스트림으로 응답하여 클라이언트에 피해를 줍니다(예: 디스크 파티션이 가득 차거나 메모리가 고갈되는 경우).
  • 느린 검색 공격: 공격자가 클라이언트에 매우 느린 데이터 스트림으로 응답하여, 결과적으로 클라이언트가 업데이트 프로세스를 결코 계속하지 못하게 합니다.
  • 불필요한 종속성 공격: 공격자가 클라이언트에 원하는 소프트웨어를 설치하려면 관련 없는 소프트웨어도 설치해야 한다고 알립니다. 이 관련 없는 소프트웨어는 신뢰할 수 있는 출처에서 제공될 수 있지만, 공격자가 악용할 수 있는 알려진 취약점을 포함할 수 있습니다.
  • 혼합 및 일치 공격: 공격자가 저장소에 동일한 시점에 함께 존재한 적이 없는 파일들이 포함된 저장소의 모습을 클라이언트에 제시합니다. 이로 인해 예를 들어 종속성의 오래된 버전이 설치될 수 있습니다.
  • 잘못된 소프트웨어 설치: 공격자가 클라이언트가 원한 것이 아닌 신뢰할 수 있는 파일을 클라이언트에 제공합니다.
  • 업데이트를 방해하는 악성 미러: 하나의 저장소 미러를 제어하는 공격자가 사용자가 다른 정상적인 미러에서 업데이트를 받지 못하도록 할 수 있습니다.
  • 키 손상에 대한 취약성: 하나의 키 또는 지정된 키 수 임계값 미만의 키를 손상할 수 있는 공격자가 클라이언트를 손상시킬 수 있습니다. 여기에는 SSL로만 보호되는 단일 온라인 키 또는 대부분의 소프트웨어 업데이트 시스템이 파일 서명에 사용하는 단일 오프라인 키에 의존하는 경우가 포함됩니다.

참고 자료

감사의 말

이 자료는 국립과학재단(National Science Foundation)의 보조금 번호 CNS-1345049 및 CNS-0959138의 지원을 받은 연구를 기반으로 합니다. 이 자료에 표현된 모든 의견, 발견 및 결론이나 권고 사항은 저자(들)의 것이며, 반드시 국립과학재단의 견해를 반영하는 것은 아닙니다.

Alyssa Coghlan, Daniel Holth, Donald Stufft, 그리고 distutils-sig 커뮤니티 전반에 감사드립니다. 이들은 TUF를 PyPI와 사용성 있고 효율적으로 통합하는 방법을 고민하는 데 도움을 주었습니다.

Roger Dingledine, Sebastian Hahn, Nick Mathewson, Martin Peck, Justin Samuel은 Tor 프로젝트의 Thandy를 전신으로 하여 TUF를 설계하는 데 도움을 주었습니다.

TUF 개발에 힘써준 Konstantin Andrianov, Geremy Condra, Zane Fisher, Justin Samuel, Tian Tian, Santiago Torres, John Ward, Yuyu Zheng의 노고에 감사드립니다.

Vladimir Diaz, Monzur Muhammad, Sai Teja Peddinti, Sumana Harihareswara, Ee Durbin, Dustin Ingram은 이 PEP를 검토하는 데 도움을 주었습니다.

Zane Fisher는 이 PEP를 검토하고 옮겨 적는 데 도움을 주었습니다.