[Final] PEP 466 - Network Security Enhancements for Python 2.7.x

원문 링크: PEP 466 - Network Security Enhancements for Python 2.7.x

상태: Final 유형: Standards Track 작성일: 23-Mar-2014

PEP 466 – Python 2.7.x의 네트워크 보안 강화

  • 작성자: Alyssa Coghlan
  • 상태: Final
  • 유형: Standards Track
  • 생성일: 2014년 3월 23일
  • Python 버전: 2.7.9
  • 해결: Python-Dev 메시지

요약 (Abstract)

대부분의 CPython 트래커 이슈는 동작 오류나 제안된 개선 사항으로 분류됩니다. 동작 오류를 수정하는 대부분의 패치는 모든 활성 유지보수 브랜치에 적용됩니다. 반면, 개선 사항 패치는 다음 Python 버전이 될 기본 브랜치에만 제한됩니다.

이러한 방식은 Python의 일반적인 18-24개월 기능 릴리스 주기 동안 합리적으로 잘 작동하지만, Python 2의 표준 라이브러리는 현재 네트워크 보안 프로토콜의 최신 기술에 비해 상당히 뒤떨어져 있습니다. 이로 인해 단기간 내에 Python 3으로 업그레이드가 어려운 사용 사례에서 실제적인 문제를 야기하고 있습니다.

Python 2.7의 4년 이상 유지보수 주기 동안 발생한 추가적인 실제적 고려 사항을 인정하여, 이 PEP는 Python 3.4의 중요한 네트워크 보안 관련 기능 세트를 향후 Python 2.7.x 유지보수 릴리스로 백포트(backport)할 수 있도록 허용합니다.

이 PEP는 더 이상 활성 유지보수 상태가 아닌 보안 수정 전용 브랜치에 대한 핵심 개발 팀의 처리 방식에 어떤 변경도 가하지 않지만, Python 표준 라이브러리에 대한 확장 지원 기간을 제공하는 상업적 재배포자(redistributors)에게는 이러한 기능을 지원되는 버전으로 백포트하거나, 구 버전이 공용 인터넷에 직접 연결하는 역할로 사용될 경우 지원하지 않음을 명시적으로 표명할 것을 권고합니다.

Python 2.7 유지보수 릴리스의 새로운 보안 관련 기능

이 제안에 따라 다음 기능들이 Python 3.4에서 향후 Python 2.7.x 유지보수 릴리스로 백포트될 예정입니다.

  • os 모듈에서:
    • os.urandom()을 위한 영구 파일 디스크립터.
  • hmac 모듈에서:
    • 상수 시간 비교 함수 (hmac.compare_digest()).
  • hashlib 모듈에서:
    • 비밀번호 해싱 함수 (hashlib.pbkdf2_hmac()).
    • 해시 알고리즘 가용성에 대한 세부 정보 (hashlib.algorithms_guaranteedhashlib.algorithms_available).
  • ssl 모듈에서:
    • 이 모듈은 Python 3의 해당 모듈과 거의 완전히 동기화되어, TLSv1.x 설정, SSLContext 조작, Server Name Indication (SNI), 플랫폼 인증서 저장소 액세스, 피어 호스트명 검증을 위한 표준 라이브러리 지원 등을 Python 2 시리즈에 제공합니다.
    • 이 정책에 따라 백포트되지 않는 유일한 ssl 모듈 기능은 OpenSSL의 난수 생성 기능에 접근하는 ssl.RAND_* 함수들입니다. 대신 os.urandom()을 사용해야 합니다.

일반적인 유지보수 정책 변경으로서, Python 2.7의 새로운 유지보수 릴리스용 바이너리 인스톨러를 준비할 때 OpenSSL의 최신 기능 릴리스로 업그레이드할 수 있는 권한도 부여됩니다.

이 PEP는 Python 2.7에 새로운 기능을 백포트하는 것에 대한 일반적인 예외를 제안하지 않습니다. 백포트를 위해 제안되는 모든 새로운 기능은 여전히 독립적으로 정당화되어야 합니다. 특히, Python Package Index (PyPI)의 독립적으로 업데이트된 백포트에 의존하는 것이 왜 허용 가능한 해결책이 아닌지 설명해야 합니다.

구현 상태 (Implementation status)

이 PEP는 원래 모든 나열된 기능을 Python 2.7.7 유지보수 릴리스에 추가할 것을 제안했습니다. 그러나 PEP의 원래 생성 및 승인과 Python 2.7.7rc1 릴리스 사이의 제한된 시간으로 인해 이 접근 방식은 너무 야심 찬 것으로 판명되었습니다. 대신, 승인된 각 기능 백포트의 진행 상황은 Python 2.7을 대상으로 하는 독립적인 개선 사항으로 추적되고 있습니다.

Python 2.7.7에 구현됨:

  • Issue #21306: hmac.compare_digest 백포트
  • Issue #21462: Python 2.7 Windows 인스톨러의 OpenSSL 업그레이드

Python 2.7.8에 구현됨:

  • Issue #21304: hashlib.pbkdf2 백포트

Python 2.7.9에 구현됨 (개발 중):

  • Issue #21308: 지정된 ssl 모듈 기능 백포트
  • Issue #21307: 남은 지정된 hashlib 모듈 기능 백포트
  • Issue #21305: os.urandom 공유 파일 디스크립터 변경 백포트

하위 호환성 고려 사항 (Backwards compatibility considerations)

Python 3 시리즈와 마찬가지로, 백포트된 ssl.create_default_context() API는 생성된 SSL 컨텍스트의 프로토콜, 옵션, 암호 및 기타 설정을 유지보수 릴리스에서 더 높은 기본 보안 설정을 사용하도록 업데이트할 수 있는 하위 호환성 예외가 부여됩니다. 이는 원래 기능 릴리스 시점이 아닌 유지보수 릴리스 시점에 호환성과 보안의 균형을 적절하게 맞출 수 있도록 합니다.

이 PEP는 유지보수 릴리스에 대한 일반적인 하위 호환성 정책에 대한 다른 예외를 부여하지 않습니다. 대신, 기능 기반 검사(feature based checks)의 사용을 명시적으로 장려함으로써, 기존 인터페이스의 하위 호환성을 유지하면서도, 새로운 Python 2.7 유지보수 릴리스로 업그레이드할 때 현재 작동하는 소프트웨어의 손상 위험을 제한하면서, 더 안전한 크로스-버전 호환 Python 소프트웨어를 작성하기 쉽게 설계되었습니다.

이 제안이 새로운 기능을 Python 2.7 릴리스 시리즈로 백포트하는 것을 허용하는 모든 경우에, Python 버전을 명시적으로 확인할 필요 없이 “기능 감지(feature detection)” (예: 모듈 내의 특정 속성 확인)를 통해 작동하는 크로스-버전 호환 코드를 작성하는 것이 가능합니다.

원하는 기능이 누락된 경우 적절한 경고와 대체 동작(fallback behaviour)을 제공하는 것은 라이브러리 및 프레임워크 코드의 역할입니다. 일부 특히 보안에 민감한 소프트웨어는 원하는 보안 기능이 없는 경우 완전히 실패할 수 있지만, 대부분의 소프트웨어는 대신 경고를 내보내고 약간 저하된 보안 구성으로 계속 작동해야 합니다.

백포트된 API는 라이브러리 및 애플리케이션 코드가 관련 네트워크 보안 관련 기능의 존재를 감지한 후 다음 작업을 수행할 수 있도록 합니다.

  • 더 안전한 설정 명시적 옵트인(opt in) (기본 동작이 덜 안전한 이전 Python 유지보수 릴리스에서 향상된 보안 기능을 사용할 수 있도록 허용).
  • 덜 안전한 설정 명시적 옵트인 (낮은 보안 환경에서 최신 Python 기능 릴리스를 사용할 수 있도록 허용).
  • 기능의 기본 설정 결정 (이것은 Python 기능 릴리스를 결정하기 위해 명시적인 Python 버전 검사를 필요로 할 수 있지만, 특정 유지보수 릴리스를 확인할 필요는 없습니다).

다른 모듈(예: 상위 수준 네트워킹 라이브러리 및 데이터 형식 처리 라이브러리)에 대한 보안 관련 변경 사항은 Python Package Index (PyPI)에서 백포트 및 새로운 모듈로 계속 제공될 것입니다. 이는 Python 2 표준 라이브러리와 독립적으로 변화하는 개발 요구 사항을 처리하기 위해 계속 발전해야 하는 소프트웨어를 다루는 데 선호되는 접근 방식이기 때문입니다. 안전한 네트워킹 인프라가 특별한 고려를 받을 만한 특성을 검토하려면 “Motivation and Rationale” 섹션을 참조하십시오.

OpenSSL 호환성 (OpenSSL compatibility)

이 제안에 따라, OpenSSL은 Python 2.7 유지보수 릴리스에서 더 최신 기능 릴리스로 업그레이드될 수 있습니다. Linux 및 대부분의 다른 POSIX 시스템에서는 CPython이 기본적으로 시스템 제공 OpenSSL 라이브러리에 동적으로 연결되므로, 사용되는 OpenSSL의 특정 버전은 이미 다양합니다.

Windows 바이너리 인스톨러의 경우, _ssl_hashlib 모듈은 OpenSSL과 정적으로 연결되며 관련 심볼은 내보내지지 않습니다. Marc-Andre Lemburg는 egenix-pyopenssl 바이너리에서 최신 OpenSSL 릴리스로 업데이트해도 호환성 문제가 보고되지 않았다고 밝혔습니다.

Mac OS X 바이너리 인스톨러는 역사적으로 다른 POSIX 설치와 동일한 정책을 따랐으며 Apple이 제공하는 OpenSSL 라이브러리에 동적으로 연결되었습니다. 그러나 Apple은 이제 이러한 크로스 플랫폼 라이브러리 업데이트를 중단하고, 크로스 플랫폼 개발자조차도 플랫폼에서 최신 보안 인프라에 액세스하기 위해 Mac OS X 특정 인터페이스를 채택하도록 요구하고 있습니다. 따라서, 이 PEP와는 독립적으로, Mac OS X 바이너리 인스톨러는 이미 최신 OpenSSL 버전과 정적으로 링커되도록 전환될 예정이었습니다.

기타 고려 사항 (Other Considerations)

유지보수성 (Maintainability)

Alex Gaynor와 Donald Stufft를 포함한 여러 개발자들이 이 정책에 포함된 기능 백포트를 수행하고, 결과적으로 Python 2 시리즈에서 발생하는 추가 유지보수 부담을 지원하는 데 관심을 표명했습니다.

Steve Dower와 Brian Curtin은 Windows 인스톨러 생성에 도움을 주겠다고 제안하여 Martin von Löwis가 2.7 Windows 인스톨러 유지보수 작업에서 물러날 기회를 제공했습니다.

이 PEP는 주로 이러한 작업을 수행할 수 있도록 필요한 합의를 확립하는 것입니다. 다른 핵심 개발자들에게는, 이 정책 변경이 영향을 받는 모듈에 특별히 관심 있는 개발자들을 위한 결과 패치 검토 외에 추가적인 노력을 부과하지 않을 것입니다.

보안 릴리스 (Security releases)

이 PEP는 보안 릴리스 처리에 대한 어떤 변경도 제안하지 않습니다. 보안 릴리스는 여전히 중요한 보안 수정 사항만 포함하는 소스 전용 릴리스로 유지될 것입니다.

그러나 라이브러리 및 애플리케이션 개발자를 위한 권고 사항은, 보안 수정 전용 모드이거나 핵심 개발 팀에 의해 “수명 종료(end of life)”로 선언된 추가 Python 릴리스 시리즈에 이러한 변경 사항을 적용하기로 선택한 상업적 재배포자를 수용하도록 의도적으로 설계되었습니다.

재배포자가 이 옵션을 행사할지 여부는 개별 재배포자에게 달려 있습니다.

통합 테스트 (Integration testing)

타사 통합 테스트 서비스는 사용자에게 여러 Python 2.7 유지보수 릴리스(최소 2.7.6 및 2.7.7+)에 대해 테스트할 수 있는 기능을 제공해야 합니다. 이는 이 제안에 포함된 기능이 Python 2.7 시리즈로 백포트된 후에도, 라이브러리, 프레임워크 및 애플리케이션이 레거시 보안 인프라 처리(소프트웨어의 보안 민감도에 따라 실패하거나 우아하게 저하되는)를 올바르게 테스트할 수 있도록 보장하기 위함입니다.

낮은 위험 허용치를 가진 낮은 보안 환경 처리 (Handling lower security environments with low risk tolerance)

좋든 나쁘든(주로 나쁘게), 유지보수 릴리스의 회귀(regression) 위험이 약간 증가하는 것보다 잠재적 보안 결함의 위험을 더 용인하는 환경이 있습니다. 이 제안은 면제 대상 모듈과 관련하여 이러한 환경을 고려 대상에서 크게 제외합니다. 이 접근 방식은 공용 인터넷에 연결된 소프트웨어에는 완전히 부적절하며, 심층 방어(defence in depth) 보안 원칙에 따르면 대부분의 사설 네트워크에도 적절하지 않습니다.

하위 재배포자는 여전히 이러한 환경을 충족시키기로 선택할 수 있지만, 보안 관련 모듈을 다운그레이드하고 관련 회귀 테스트를 직접 처리해야 합니다. 주 CPython 지속적인 통합 인프라는 이 시나리오를 다루지 않을 것입니다.

동기 및 근거 (Motivation and Rationale)

이 PEP의 생성은 주로 Python 2 시리즈의 노후화된 SSL 지원 때문에 촉발되었습니다. 2014년 3월 현재, Python 2.7 SSL 모듈은 약 4년이 되었고, 여전히 인기 있는 Python 2.6 릴리스의 SSL 지원은 6년 전에 기능 세트가 고정되었습니다.

이들은 공용 인터넷을 통해 작동하는 안전한 네트워킹 소프트웨어에 양심적으로 권장할 수 있는 기반을 제공하기에는 너무 오래되었습니다. 특히, 진보된 지속적인 보안 위협이 이전에 이해했던 것보다 훨씬 더 널리 퍼져 있고 표적 공격이 무차별적이라는 것이 분명해지고 있는 시대에는 더욱 그렇습니다. 당시에는 합리적인 보안 인프라였지만, 최신 기술은 발전했으며, 어떤 이유로든 현재 Python 3으로 마이그레이션할 수 없는 사용자에게 더 최신 네트워크 보안 인프라를 효과적으로 제공할 메커니즘을 조사해야 합니다.

시스템 OpenSSL 설치를 사용하는 것이 Linux 플랫폼의 이러한 우려 사항 중 상당 부분을 해결하지만, 모든 문제를 해결하지는 못합니다(특히, 소프트웨어가 일부 상위 수준 보안 설정을 명시적으로 요구하기는 여전히 어렵습니다). 표준 라이브러리 지원은 PyOpenSSL 또는 Pycurl과 같은 타사 라이브러리를 사용하여 우회할 수 있지만, 이는 배포하기 어려운 의존성을 초래하며, 많은 사용자들이 자신이 이러한 라이브러리를 원할 수 있다는 사실을 모를 것입니다. 잠재적으로 순진한 사용자에게 이러한 라이브러리를 얻고 사용하는 방법을 설명하는 대신, 포함된 “배터리”를 수정하는 것이 더 나아 보입니다.

python.org에 게시된 Windows 및 Mac OS X용 바이너리 인스톨러의 경우, 사용되는 OpenSSL 버전은 Python 핵심 개발 팀의 전적인 통제하에 있지만, 현재는 해당 Python 기능 릴리스와 함께 처음 제공된 버전의 OpenSSL 유지보수 릴리스로 제한됩니다.

인기가 높아짐에 따라 책임도 증가하며, 이 제안은 Python의 인기와 채택 수준이 충분히 높아서 일부 설계 및 정책 결정이 Python 개발 커뮤니티를 넘어선 중요한 영향을 미친다는 사실을 인정하는 것을 목표로 합니다.

예를 들어, Python 2 ssl 모듈은 Server Name Indication (SNI) 표준을 지원하지 않습니다. 타사 requests 클라이언트 라이브러리를 사용하여 SNI 지원을 얻을 수 있지만, 실제로 그렇게 하려면 requests와 그 내장 종속성뿐만 아니라 6개 이상의 추가 라이브러리를 사용해야 합니다. 따라서 Python 2 시리즈의 지원 부족은 서버에서 SNI를 효과적으로 사용하는 데 방해가 되며, Python 2 클라이언트는 종종 이를 올바르게 처리하지 못합니다.

더 중요한 또 다른 예는 Python 2 표준 라이브러리에 SSL 호스트명 매칭이 없다는 것입니다. 현재 Python 2에서 해당 기능을 얻으려면 requests 또는 backports.ssl_match_hostname과 같은 타사 라이브러리에 의존해야 합니다.

Python 2 시리즈는 또한 Python 3 시리즈보다 보안에 민감한 비교에 대한 원격 타이밍 공격에 더 취약합니다. 타이밍 공격에 강한 hmac.compare_digest() 함수와 동등한 표준 라이브러리 기능이 없기 때문입니다. 적절하게 안전한 비교 함수를 타사 확장 프로그램으로 구현할 수 있지만, 많은 사용자는 이 문제를 고려하지 않고 일반적인 동등 비교를 사용합니다. 표준 라이브러리 솔루션이 자동으로 그 문제를 해결하지는 않지만, 문제가 지적되었을 때 해결 장벽을 훨씬 낮춥니다.

Python 2.7은 핵심 개발 팀이 제공한 유일한 장기 유지보수 릴리스이며, 역사적으로 더 짧은 유지보수 기간 동안 작동했던 것들이 이 더 긴 지원 기간 동안 작동하지 않는 것은 당연합니다. 이 PEP에 설명된 문제의 특정 사례에서, 가장 간단한 해결책은 네트워크 보안 관련 모듈의 장기 유지보수에는 기존 인터페이스의 하위 호환성을 유지하면서도 새로운 기능을 추가할 수 있는 능력이 필요하다는 것을 인정하는 것입니다.

이에 익숙한 사람들을 위해, 이 PEP에 설명된 접근 방식을 Red Hat의 장기 오픈 소스 지원 약속 처리 방식과 비교할 가치가 있습니다. RHEL 6.0 릴리스 자체가 10년의 지원을 받는 것이 아니라, 전체 RHEL 6 시리즈가 지원을 받습니다. 시리즈 내의 개별 RHEL 6.x 포인트 릴리스는 보안 개선 사항을 포함하여 다양한 새로운 기능을 받으면서도 기존 소프트웨어에 대한 엄격한 하위 호환성 보장을 충족합니다. 이 PEP에 포함된 제안은 장기 유지보수에 대한 우리의 접근 방식을 이러한 선례에 더욱 맞춥니다. 우리는 엄격한 하위 호환성 요구 사항을 유지하지만, 새로운 기능 추가에 대한 제한에 예외를 둡니다.

현재까지, 하위 재배포자들은 “Python 유지보수 릴리스에는 새로운 기능 없음”이라는 우리의 상위 정책을 존중했습니다. 이 PEP는 네트워크 보안 관련 기능의 경우 더 미묘한 정책이 적절하다는 것을 명시적으로 받아들이며, 설명된 특정 변경 사항은 Red Hat Enterprise Linux 및 그 하위 파생 제품에 잠재적으로 적합하도록 의도적으로 설계되었습니다.

왜 이러한 특정 변경 사항인가? (Why these particular changes?)

이 제안에 포함되기 위한 기능의 핵심 요구 사항은 Python으로 작성된 특정 애플리케이션 및 해당 애플리케이션이 실행되는 시스템을 넘어선 보안 영향을 미쳐야 한다는 것이었습니다. 따라서 네트워크 보안 프로토콜, 비밀번호 저장 및 관련 암호화 인프라에 중점을 둡니다. Python은 웹 서비스 및 클라이언트 개발에 인기 있는 선택이며, 따라서 널리 사용되는 Python 버전의 기능은 자체적으로 최신 버전의 Python 또는 다른 개발 언어를 사용하더라도 구 버전의 Python으로 작성된 클라이언트 또는 서버와 상호 운용해야 하는 다른 서비스의 보안 설계에 영향을 미칩니다.

이 요구 사항의 의도는 이 정책 도입이 유지보수 릴리스의 안정성 및 호환성에 미칠 수 있는 영향을 최소화하면서도 Python 2.7의 특정 측면에 관련된 일부 주요 보안 문제를 해결하는 것이었습니다. 최종 사용자들이 새 Python 2.7 유지보수 릴리스로 업데이트하는 것에 대해 동일한 릴리스 시리즈 내의 새 기능 릴리스로 업데이트하는 것만큼이나 신중해진다면, 이는 철저히 역효과를 낼 것입니다.

ssl 모듈 변경 사항은 Python 2 시리즈를 지난 4년간의 네트워크 보안 표준 발전과 동기화하고, 서버와 클라이언트 모두에서 이러한 표준이 널리 채택되도록 쉽게 만들기 위해 이 제안에 포함되었습니다. 유사하게 hashlib의 해시 알고리즘 가용성 지표는 애플리케이션이 Python 2와 3 모두에서 적절한 해시 정의를 감지하고 사용하기 쉽게 만들기 위해 포함되었습니다.

hmac.compare_digest()hashlib.pbkdf2_hmac()는 Python 2 서버 애플리케이션에서 안전한 비밀번호 저장 및 검사를 위한 장벽을 낮추는 데 도움이 되도록 포함되었습니다.

os.urandom() 변경 사항은 암호화 사용 사례에 필요한 고품질 난수를 제공하는 작업을 운영 체제 공급업체에 맡기도록 사용자들을 더욱 장려하기 위해 이 제안에 포함되었습니다. 충분히 무작위적이지 않은 난수의 사용은 모든 암호화 시스템을 손상시킬 가능성이 있으며, 운영 체제 개발자는 일반적인 Python 애플리케이션 런타임보다 해당 문제를 적절히 해결할 수 있는 더 많은 도구를 가지고 있습니다.

거부된 대안: 개발자에게 Python 3으로 마이그레이션할 것을 권고 (Rejected alternative: just advise developers to migrate to Python 3)

이 대안은 현상 유지를 나타냅니다. 불행히도, 하위 호환성 문제는 대규모 애플리케이션 및 통합 프로젝트에 있어 이것이 사소하지 않은 마이그레이션 프로세스임을 의미하기 때문에 실제로 실현 불가능하다는 것이 입증되었습니다. 마이그레이션 도구는 Python 2와 Python 3의 큰 공통 부분 집합에서 실행되도록 코드를 업데이트함으로써 대규모 애플리케이션까지도 기회주의적으로 점진적으로 (한 번에 전부가 아닌) 마이그레이션할 수 있는 지점까지 발전했지만, 최신 기술을 사용하는 것이 상업 환경에서는 종종 우선순위가 아닙니다.

이전에는 이것이 허용 가능한 해악으로 간주되었습니다. 영향을 받는 개발자들이 직면해야 할 불행한 문제였지만, 인프라 현대화를 주장하는 것은 그들과 그들의 경영진 사이의 문제로 여겨졌고, Python 3 시리즈가 발전함에 따라 이 주장은 자연스럽게 더 설득력이 생길 것이라고 보았습니다.

그러나 Python 2 표준 라이브러리의 한계가 인터넷 보안 표준의 발전에 미칠 수 있는 영향에 대해 완전히 인지하게 된 지금, 저는 플랫폼 및 애플리케이션 개발자들이 Python 3에서 이미 사용 가능한 네트워크 보안 개선 사항에 접근하기 위해 오직 애플리케이션의 유니코드 정확성(Unicode correctness)에 있는 모든 잠재적 결함을 해결해야 한다고 기대하는 것이 더 이상 합리적이라고 생각하지 않습니다.

Ubuntu (그리고 어느 정도 Debian도)는 모든 기본 시스템 서비스 및 스크립트를 Python 3으로 포팅하고, 기본 배포 이미지에서 Python 2를 제거하는 데 전념하고 있지만 (아카이브에서는 아님), 이것은 거대한 작업이며 Ubuntu 14.04 LTS 릴리스에서는 완료되지 않을 것입니다 (적어도 데스크톱 이미지의 경우 — 모바일 및 서버 이미지에서는 달성될 수 있습니다).

Fedora는 마이그레이션할 작업이 훨씬 더 많고, 관련 인프라 구성 요소를 마이그레이션하는 데 상당한 시간이 걸릴 것입니다. Red Hat 또한 안정적인 플랫폼에서 사용자들이 더 최신 버전의 Python을 더 쉽게 사용할 수 있도록 적극적으로 노력하고 있지만, 이러한 노력이 최종 사용자들의 버전 선택에 영향을 미치기 시작하는 데는 시간이 걸릴 것이며, 그러한 변경 사항은 통합 시스템 Python에서 필연적으로 실행되는 핵심 플랫폼 인프라에는 이점을 주지 않습니다.

OpenStack의 Python 3 마이그레이션도 아직 초기 단계이며, 광범위하고 상대적으로 강력한 자동화된 테스트 스위트를 가진 프로젝트임에도 불구하고, Python 2/3 호환 코드 베이스로 완전히 마이그레이션하는 데는 상당한 시간이 걸릴 만큼 충분히 큰 프로젝트입니다.

이것은 Python을 많이 사용하는 가장 유명한 오픈 소스 프로젝트 중 세 가지에 불과합니다. Python 2에서 Python 3으로의 마이그레이션을 지원하는 데 필요한 종류의 자동화된 회귀 테스트 스위트가 없는 많은 양의 레거시 코드가 존재할 가능성을 고려할 때, 재구현(아마도 Python 3으로)이 마이그레이션보다 더 쉬운 많은 경우가 있을 것입니다. 이 PEP의 핵심 요점은 그러한 상황이 영향을 받는 애플리케이션의 개발자와 사용자뿐만 아니라 더 많은 사람들에게 영향을 미친다는 것입니다. 오래된 네트워크 보안 인프라를 가진 클라이언트와 서버의 존재는 안전한 네트워크 서비스 개발자들이 보안 설계의 일부로 고려해야 하는 것이 되며, 이는 더 나은 보안 표준의 채택을 방해하는 문제입니다.

Terry Reedy가 지적했듯이, 현상 유지를 고수하려고 한다면, 상업적 재배포자들이 어쨌든 고객을 대신하여 이와 유사한 작업을 시도할 가능성이 높지만, 잠재적으로 일관되지 않고 임시적인 방식으로 이루어질 것입니다. 범위 정의 프로세스를 상위 프로젝트로 가져옴으로써, 우리는 상황을 해결하기 위한 접근 방식에 더 잘 영향을 미치고 재배포자들 간의 일관성을 보장하는 데 도움을 줄 수 있습니다.

문제는 실제이므로, 뭔가 변경되어야 하며, 이 PEP는 상황을 해결하기 위한 제가 선호하는 접근 방식을 설명합니다.

거부된 대안: Python 2.8 생성 및 릴리스 (Rejected alternative: create and release Python 2.8)

충분한 기업 지원이 있다면, Python 2.8을 생성하고 릴리스하는 것이 가능할 것입니다 (자원봉사자만으로는 그러한 프로젝트가 충분한 관심을 얻기 어려울 것입니다). 그러나 이는 실제로 문제를 해결하지 못할 것입니다. 목표는 Python 2를 사용하는 통합 제품 및 배포에 향상된 보안 기능을 통합하는 데 비교적 적은 영향을 미 미치는 방법을 제공하는 것이기 때문입니다.

새로운 Python 기능 릴리스로 업그레이드하는 것은 핵심 개발 팀에게 더 많은 작업을 의미할 뿐만 아니라, 대부분의 잠재적 최종 사용자가 완전히 건너뛸 가능성이 있는 더 파괴적인 업데이트를 의미할 것입니다.

Python 2.8 릴리스를 생성하려는 시도는 Python 3에서 많은 추가 기능(예: tracemalloc 및 개선된 코루틴 지원)을 백포트하라는 제안을 가져올 것이며, Python 2.7에서 이 가상의 2.8 릴리스로의 마이그레이션을 더욱 위험하고 파괴적으로 만들 것입니다.

이것은 권장되는 접근 방식이 아닙니다. 원래 목표(Python 2 시리즈에서 노후화된 네트워크 보안 인프라의 현재 광범위한 사용을 제거하는 것)를 달성하는 데 실제로 덜 효과적인 결과를 위해 상당한 추가 작업을 수반할 것이기 때문입니다.

더욱이, Red Hat 플랫폼에서 이 문제를 실제로 해결할 것을 약속할 수는 없지만, Python 2.8이 이 문제를 해결하려는 시도조차 저에게 어떤 유용성도 없을 것이라는 생각은 단호히 배제할 수 있습니다.

거부된 대안: PyPI를 통한 보안 개선 사항 배포 (Rejected alternative: distribute the security enhancements via PyPI)

이것이 처음에는 매력적이고 관리하기 쉬운 접근 방식으로 보이지만, 실제로는 몇 가지 중요한 문제가 있습니다.

첫째, 이것은 다양한 POSIX 플랫폼(Mac OS X 포함) 및 Windows에 걸쳐 기본 운영 체제와 통합되는 복잡하고 낮은 수준의 크로스 플랫폼 코드입니다. CPython BuildBot 플릿은 이미 해당 컨텍스트에서 지속적인 통합(CI)을 처리하도록 설정되어 있지만, 대부분의 무료로 사용 가능한 CI 서비스는 Linux만 제공하며, 아마도 Windows에 대한 유료 액세스를 제공할 것입니다. 이러한 서비스는 Python 및 기타 동적 언어가 제공하는 추상화 계층, 그리고 JVM이 제공하는 더 포괄적인 추상화에서 주로 실행되는 소프트웨어에는 합리적으로 잘 작동하지만, 여기에 관련된 종류의 코드에는 충분하지 않습니다.

네트워크 보안 지원을 위한 OpenSSL 종속성 또한 pip 기반 소프트웨어 배포 생태계에서 아직 잘 처리되지 않는 종류의 “복잡한 바이너리 종속성”에 해당합니다. 타사 바이너리 종속성에 의존하는 것은 PyPy와 같은 다른 인터프리터에서 실행될 때 pip에 잠재적인 호환성 문제를 야기합니다.

이 아이디어의 또 다른 실제적인 문제는 pip 자체가 표준 라이브러리의 ssl 지원에 의존한다는 사실입니다 (묶음으로 제공되는 requests 복사본에서 추가 지원을 받으며, requests는 다시 backport.ssl_match_hostname을 묶음으로 제공합니다). 따라서 어떤 대체 모듈이든 pip 내에 함께 묶여 있어야 합니다. 이것이 해결할 수 없는 어려움을 초래하지는 않겠지만 (벤더링할 또 다른 종속성일 뿐), 업데이트해야 할 OpenSSL의 또 다른 복사본을 의미할 것입니다.

이 접근 방식은 다른 모든 “이름을 변경하여 보안 개선” 접근 방식과 동일한 결함을 가지고 있습니다. 즉, 가장 도움이 필요한 사용자들을 완전히 놓치고, 인프라가 지원할 때 사용자들이 올바른 일을 하도록 장려하는 데 상당한 장벽을 높입니다 (왜냐하면 “다른 모듈 사용”은 “이 더 높은 보안 설정 켜기”보다 훨씬 더 큰 영향을 미치는 변경이기 때문입니다). 외부 모듈을 선호하여 표준 라이브러리의 노후화된 SSL 인프라를 더 이상 사용하지 않게 하는 것은 제자리에서 업그레이드하는 것과 관련된 회귀의 약간 증가된 위험을 수용하는 것보다 사용자에게 더 적대적일 것입니다.

마지막으로, 그리고 가장 중요한 것은, 이 접근 방식은 Python 2.8 릴리스 아이디어와 동일한 문제점을 가지고 있습니다. 즉, 실제 문제를 해결하지 못할 가능성이 높다는 것입니다. Python의 상업적 재배포자들은 Python과 기존의 추가 패키지 세트를 재배포하도록 설정되어 있습니다. 기존 세트에 새 패키지를 추가하는 것은 가능하지만, 이는 모든 재배포자에게 접근하여 그들의 재패키징 프로세스를 그에 따라 업데이트하도록 요청하는 것을 의미합니다. 대조적으로, 이 PEP에 설명된 접근 방식은 재배포자들이 제공된 네트워크 보안 인프라를 의도적으로 다운그레이드하여 보안 개선 사항에서 의도적으로 옵트아웃(opt out)하도록 요구할 것이며, 대부분의 재배포자는 그렇게 하지 않을 것입니다.

거부된 대안: “레거시 SSL 인프라” 브랜치 제공 (Rejected variant: provide a “legacy SSL infrastructure” branch)

이 PEP의 초기 버전에는 Python 2.7.6 네트워크 보안 인프라의 정확한 기능 세트를 보존하는 2.7-legacy-ssl 브랜치 개념이 포함되어 있었습니다.

제 의견으로는, 이것을 실제로 원하는 사람은 거의 확실히 실수를 저지르고 있는 것이며, 특정 상황에서 정말로 그것을 원한다고 주장한다면, 스스로 만들거나 하위 재배포자가 그들을 위해 만들도록 주선할 수 있습니다.

공개적으로 사용 가능하게 된다면, 그러한 모든 재빌드는 공식 Python 2.7 릴리스(더 최신 네트워크 보안 인프라를 포함하는)와 명확히 구별하기 위해 “Python 2.7 with Legacy SSL”로 지칭되어야 합니다.

이 PEP를 구현하는 첫 번째 Python 2.7 유지보수 릴리스 이후에는 Python 2.7.6 및 이전 릴리스를 “Python 2.7 with Legacy SSL”로 지칭하는 것도 적절할 것입니다.

거부된 대안: 특정 모듈을 Python 3과 완전히 동기화 (Rejected variant: synchronise particular modules entirely with Python 3)

이 PEP의 초기 버전은 hmac, hashlib, ssl 모듈을 해당 Python 3 모듈과 완전히 동기화할 것을 제안했습니다.

이 접근 방식은 예외를 위한 설득력 있는 사례를 구축하기에는 너무 모호하다는 것이 입증되었고, 따라서 현재의 더 명시적인 제안으로 대체되었습니다.

거부된 대안: 개방형 백포트 정책 (Rejected variant: open ended backport policy)

이 PEP의 초기 버전은 인터넷의 일반적인 보안에 영향을 미치는 미래 Python 3 개선 사항과 관련된 일반적인 정책 변경을 제안했습니다.

그 접근 방식은 불필요한 불확실성을 야기했으므로, 특정 구체적인 변경 세트를 백포트할 것을 제안하도록 단순화되었습니다. 미래의 기능 백포트 제안은 이 PEP를 선례로 참조할 수 있지만, Python 2.7 장기 지원 릴리스에 각 기능 추가에 대한 구체적인 사례를 제시해야 할 것입니다.

이해 관계 공개 (Disclosure of Interest)

이 PEP의 작성자는 현재 Red Hat에서 테스트 자동화 도구를 담당하고 있습니다. 이 제안이 수락되면, 저는 Red Hat이 Python 생태계의 전반적인 보안을 개선하는 데 도움이 될 이 기회를 활용하도록 강력히 장려할 것입니다. 그러나 저는 이 문제에 대해 Red Hat을 대표하지 않으며, Red Hat을 대신하여 어떤 약속도 할 수 없습니다.

감사 (Acknowledgements)

Python 3 시리즈에서 Python의 SSL 지원을 크게 개선하기 위한 Christian Heimes 및 다른 분들의 노력에 감사드립니다. 또한, 우리 SSL 모듈에서 제공하는 기본 설정의 의미와 2010년(Python 2.7) 또는 심지어 2008년(Python 2.6)에 정의된 SSL 인프라 사용을 용인하는 것이 웹 전체의 보안에 잠재적으로 미치는 영향에 대해 더 잘 이해하도록 도와준 Python 커뮤니티의 다양한 구성원들에게 감사드립니다.

Python 3.4에서 모듈 전체를 백포트하는 것보다 제안을 더 세분화할 수 있도록 필수 보안 기능의 더 제한된 세트를 식별해준 Donald Stufft와 Alex Gaynor에게 감사드립니다 (,).

Christian과 Donald는 또한 이 제안의 예비 초안에 대한 귀중한 피드백을 제공했습니다.

python-dev 메일링 리스트 스레드(,,,)에 참여한 분들뿐만 아니라 몬트리올에서 열린 PyCon 2014에서 이 문제를 논의한 다양한 분들에게도 감사드립니다.

참고 자료 (References)

PEP 466 discussion (round 1) (https://mail.python.org/pipermail/python-dev/2014-March/133334.html) PEP 466 discussion (round 2) (https://mail.python.org/pipermail/python-dev/2014-March/133389.html) Marc-Andre Lemburg’s OpenSSL feedback for Windows (https://mail.python.org/pipermail/python-dev/2014-March/133438.html) Ned Deily’s OpenSSL feedback for Mac OS X (https://mail.python.org/pipermail/python-dev/2014-March/133347.html) PEP 466 discussion (round 3) (https://mail.python.org/pipermail/python-dev/2014-March/133442.html) PEP 466 discussion (round 4) (https://mail.python.org/pipermail/python-dev/2014-March/133472.html) Donald Stufft’s recommended set of backported features (https://mail.python.org/pipermail/python-dev/2014-March/133500.html) Alex Gaynor’s recommended set of backported features (https://mail.python.org/pipermail/python-dev/2014-March/133503.html)

이 문서는 퍼블릭 도메인에 공개되었습니다.


Source: https://github.com/python/peps/blob/main/peps/pep-0466.rst Last modified: 2025-02-01 08:59:27 GMT

⚠️ 알림: 이 문서는 AI를 활용하여 번역되었으며, 기술적 정확성을 보장하지 않습니다. 정확한 내용은 반드시 원문을 확인하시기 바랍니다.

Comments