TLS(전송 계층 보안) 구성
이 페이지의 내용
개요
이 가이드 에서는 TLS 사용 방법을 학습 수 있습니다. 프로토콜 을 사용하여 MongoDB deployment 에 대한 연결을 보호합니다.
연결에 TLS를 활성화하면 PyMongo는 다음 조치를 수행합니다.
TLS를 사용하여 MongoDB deployment에 연결
배포서버의 인증서를 확인합니다.
인증서가 배포를 인증하는지 확인합니다.
TLS를 위해 MongoDB deployment 를 구성하는 방법을 학습 보려면 MongoDB Server 매뉴얼의 TLS 구성 가이드 를 참조하세요.
중요
TLS/SSL, PKI(공개 키 인프라) 인증서 및 인증 기관(CA)에 대한 전체 설명은 이 문서의 범위를 벗어납니다. 이 페이지에서는 TLS/SSL에 대한 사전 지식이 있고 유효한 인증서에 액세스할 수 있다고 가정합니다.
TLS 활성화
MongoDB 인스턴스에 대한 연결에 TLS를 사용하려면 tls
연결 옵션을 True
로 설정합니다. MongoClient
생성자에 인수를 전달하거나 연결 string 의 매개변수를 사용하는 두 가지 방법으로 이 작업을 수행할 수 있습니다.
client = pymongo.MongoClient("mongodb://<db_username>:<db_password>@<hostname:<port>", tls=True)
client = pymongo.MongoClient("mongodb://<db_username>:<db_password>@<hostname>:<port>?tls=true")
팁
연결 string 에 SRV 연결 형식을 지정하는 +srv
수정이 포함된 경우 기본적으로 연결에서 TLS가 활성화됩니다.
SRV 연결 형식에 학습 보려면 MongoDB Server 설명서에서 SRV 연결 형식 을 참조하세요.
CA 파일 지정
TLS 핸드셰이크 중에 MongoDB deployment는 애플리케이션에 인증서 키 파일을 제공하여 ID를 설정합니다. 일반적으로 배포 인증서는 잘 알려진 CA에서 서명했으며 애플리케이션은 이 CA를 사용하여 인증서의 유효성을 검사합니다.
그러나 테스트 중에는 자체 CA 역할을 할 수 있습니다. 이 경우 다른 CA에서 서명한 인증서 대신 자신의 CA 인증서를 사용하도록 PyMongo에 지시해야 합니다.
이렇게 하려면 tlsCAFile
연결 옵션을 사용하여 루트 인증서 체인이 포함된 .pem
파일의 경로를 지정합니다. MongoClient
생성자에 인수를 전달하거나 연결 string 의 매개변수를 사용하는 두 가지 방법으로 이 작업을 수행할 수 있습니다.
client = pymongo.MongoClient("mongodb://<db_username>:<db_password>@<hostname>:<port>", tls=True, tlsCAFile="/path/to/ca.pem")
uri = "mongodb://<db_username>:<db_password>@<hostname>:<port>/?tls=true&tlsCAFile=/path/to/ca.pem" client = pymongo.MongoClient(uri)
인증서 철회 확인
X.509 인증서를 더 이상 신뢰할 수 없는 경우(예: 개인 키가 손상된 경우) CA는 인증서를 해지합니다. PyMongo에는 서버의 인증서가 해지되었는지 확인하는 두 가지 방법이 있습니다.
OCSP
온라인 인증서 상태 프로토콜(OCSP)을 사용하여 서버 인증서의 유효성을 검사하려면 다음 예와 같이 ocsp
옵션을 사용하여 PyMongo를 설치해야 합니다.
python -m pip install pymongo[ocsp]
인증서 유효성 검사 프로세스는 연결하려는 MongoDB Server의 버전에 따라 다릅니다.
MongoDB v4.4 이상: 서버가 타임스탬프가 지정된 OCSP 응답을 인증서에 스테이플링합니다. PyMongo는 OCSP 응답을 기준으로 인증서의 유효성을 검사합니다. CA가 인증서를 해지했거나 OCSP 응답이 유효하지 않은 경우 TLS 핸드셰이크가 실패합니다.
MongoDB v4.3 이하 버전: 서버가 PyMongo가 직접 연결하는 OCSP 엔드포인트를 제공합니다. 그런 다음 PyMongo는 OCSP 응답과 비교하여 인증서의 유효성을 검사합니다. CA가 인증서를 해지하지 않은 경우 OCSP 응답이 유효하지 않거나 잘못된 경우에도 TLS 핸드셰이크가 계속됩니다.
PyMongo가 OCSP 엔드포인트에 연결하는 것을 중지하려면 tlsDisableOCSPEndpointCheck
연결 옵션을 True
로 설정합니다. MongoClient
생성자에 인수를 전달하거나 연결 string 의 매개변수를 사용하는 두 가지 방법으로 이 작업을 수행할 수 있습니다.
client = pymongo.MongoClient("mongodb://<db_username>:<db_password>@<hostname>:<port>", tls=True, tlsDisableOCSPEndpointCheck=True)
uri = "mongodb://example.com/?tls=true&tlsDisableOCSPEndpointCheck=true" client = pymongo.MongoClient(uri)
참고
tlsDisableOCSPEndpointCheck
옵션이 True
로 설정되어 있더라도 PyMongo는 여전히 서버의 인증서에 스테이플링된 모든 OCSP 응답을 확인합니다.
인증서 해지 목록
OCSP를 사용하는 대신 PyMongo에 서버의 인증서를 CA에서 게시한 인증서 해지 목록(CRL)과 비교하여 확인하도록 지시할 수 있습니다. 이렇게 하려면 tlsCRLFile
연결 옵션을 사용하여 CA에서 .pem
또는 .der
파일의 경로를 지정합니다. MongoClient
생성자에 인수를 전달하거나 연결 string 의 매개변수를 사용하는 두 가지 방법으로 이 작업을 수행할 수 있습니다.
client = pymongo.MongoClient("mongodb://<db_username>:<db_password>@<hostname>:<port>", tls=True, tlsCRLFile="/path/to/crl.pem")
uri = "mongodb://example.com/?tls=true&tlsCRLFile=/path/to/crl.pem" client = pymongo.MongoClient(uri)
참고
동일한 TLS 핸드셰이크에서 CRL과 OCSP 를 모두 사용할 수는 없습니다.
클라이언트 인증서 제시
일부 MongoDB 배포에서는 모든 연결 애플리케이션이 ID를 증명하는 클라이언트 인증서를 제시해야 합니다. PyMongo가 제시할 클라이언트 인증서를 지정하려면 tlsCertificateKeyFile
옵션을 인증서 및 비공개 키가 포함된 .pem
파일의 파일 경로로 설정합니다. MongoClient
생성자에 인수를 전달하거나 연결 string 의 매개변수를 사용하는 두 가지 방법으로 이 작업을 수행할 수 있습니다.
client = pymongo.MongoClient("mongodb://<db_username>:<db_password>@<hostname>:<port>", tls=True, tlsCertificateKeyFile='/path/to/client.pem')
uri = ("mongodb://<db_username>:<db_password>@<hostname:<port>/?" "tls=true" "&tlsCertificateKeyFile=path/to/client.pem") client = pymongo.MongoClient(uri)
중요
클라이언트 인증서와 비공개 키는 동일한 .pem
파일에 있어야 합니다. 서로 다른 파일에 저장되어 있는 경우에는 연결해야 합니다. 다음 예는 Unix 시스템에서 키 파일과 인증서 파일을 combined.pem
라는 세 번째 파일로 연결하는 방법을 보여줍니다.
cat key.pem cert.pem > combined.pem
키 비밀번호 제공
인증서 파일의 비공개 키가 암호화된 경우 비밀번호를 제공해야 합니다. 이렇게 하려면 tlsCertificateKeyFilePassword
연결 옵션을 사용하여 암호화된 비공개 키의 비밀번호 또는 암호를 지정합니다. MongoClient
생성자에 인수를 전달하거나 연결 string 의 매개변수를 사용하는 두 가지 방법으로 이 작업을 수행할 수 있습니다.
client = pymongo.MongoClient("mongodb://<db_username>:<db_password>@<hostname:<port>", tls=True, tlsCertificateKeyFile='/path/to/client.pem', tlsCertificateKeyFilePassword=<passphrase>)
uri = ("mongodb://<db_username>:<db_password>@<hostname:<port>/?" "tls=true" "&tlsCertificateKeyFile=path/to/client.pem" "&tlsCertificateKeyFilePassword=<passphrase>") client = pymongo.MongoClient(uri)
안전하지 않은 TLS 허용
TLS가 활성화되면 PyMongo는 서버가 제공하는 인증서를 자동으로 확인합니다. 코드를 테스트할 때 이 확인을 비활성화할 수 있습니다. 이를 안전하지 않은 TLS라고 합니다.
안전하지 않은 TLS가 활성화된 경우, PyMongo는 서버가 X.509 인증서를 제시하기만 요구합니다. 드라이버는 다음 중 하나에 해당하는 경우에도 인증서를 수락합니다.
서버의 호스트 이름과 인증서의 주체 이름(또는 주체 대체 이름)이 일치하지 않는 경우
인증서가 만료되었거나 아직 유효하지 않습니다.
인증서의 체인에 신뢰할 수 있는 루트 인증서가 없는 경우
인증서 용도가 서버 식별에 유효하지 않은 경우
참고
안전하지 않은 TLS가 활성화된 경우에도 클라이언트와 서버 간의 통신은 TLS로 암호화됩니다.
안전하지 않은 TLS를 활성화하려면 tlsInsecure
연결 옵션을 True
로 설정합니다. MongoClient
생성자에 인수를 전달하거나 연결 string 의 매개변수를 사용하는 두 가지 방법으로 이 작업을 수행할 수 있습니다.
client = pymongo.MongoClient("mongodb://<db_username>:<db_password>@<hostname:<port>", tls=True, tlsInsecure=True)
uri = ("mongodb://<db_username>:<db_password>@<hostname>:<port>/?" "tls=true" "&tlsInsecure=true") client = pymongo.MongoClient(uri)
인증서 유효성 검사만 비활성화하려면 tlsAllowInvalidCertificates
옵션을 True
로 설정하고 tlsInsecure
옵션을 False
로 설정하거나 생략합니다.
client = pymongo.MongoClient("mongodb://<db_username>:<db_password>@<hostname>:<port>", tls=True, tlsAllowInvalidCertificates=True)
uri = ("mongodb://<db_username>:<db_password>@<hostname>:<port>/?" "tls=true" "&tlsAllowInvalidCertificates=true") client = pymongo.MongoClient(uri)
호스트 이름 확인만 비활성화하려면 tlsAllowInvalidHostnames
옵션을 True
로 설정하고 tlsInsecure
옵션을 False
로 설정하거나 생략합니다.
client = pymongo.MongoClient("mongodb://<db_username>:<db_password>@<hostname>:<port>", tls=True, tlsAllowInvalidHostnames=True)
uri = ("mongodb://<db_username>:<db_password>@<hostname>:<port>/?" "tls=true" "&tlsAllowInvalidHostnames=true") client = pymongo.MongoClient(uri)
경고
프로덕션 환경에서는 사용하지 마세요.
프로덕션 환경에서는 tlsInsecure
, tlsAllowInvalidCertificates
및 tlsAllowInvalidHostnames
옵션을 항상 False
로 설정합니다.
프로덕션 환경에서 이러한 옵션 중 하나를 True
로 설정하면 애플리케이션이 안전하지 않고 만료된 인증서와 유효한 클라이언트 인스턴스로 가장하는 외부 프로세스에 잠재적으로 취약해집니다.
TLS 문제 해결
CAERTIFICATE_VERIFY_FAILED
다음과 유사한 오류 메시지는 OpenSSL이 서버의 인증서를 확인할 수 없음을 의미합니다.
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed
이는 OpenSSL이 시스템의 루트 인증서에 액세스할 수 없거나 인증서가 최신 버전이 아니기 때문에 자주 발생합니다.
Linux를 사용하는 경우 Linux 공급업체로부터 최신 루트 인증서 업데이트를 설치했는지 확인합니다.
macOS를 사용하고 python.org에서 다운로드한 Python v3.7 이상을 실행하는 경우, 다음 명령을 실행하여 루트 인증서를 설치합니다.
open "/Applications/Python <YOUR PYTHON VERSION>/Install Certificates.command"
팁
이 문제에 대한 자세한 내용은 Python 문제 29065 를 참조하세요.
이식 가능한 pypy를 사용하는 경우 환경 변수를 설정하여 OpenSSL에 루트 인증서를 찾을 수 있는 위치를 알려야 할 수 있습니다. 다음 코드 예시에서는 certifi 모듈 을 설치하는 방법을 보여줍니다. PyPi에서 SSL_CERT_FILE
환경 변수를 내보냅니다.
$ pypy -m pip install certifi $ export SSL_CERT_FILE=$(pypy -c "import certifi; print(certifi.where())")
팁
이 문제에 대한 자세한 내용은 portable-pypy 문제 15 를 참조하세요.
TLSV1_ALERT_PROTOCOL_VERSION
다음과 유사한 오류 메시지는 Python에서 사용하는 OpenSSL 버전이 서버에 연결할 수 있을 만큼 새로운 TLS 프로토콜을 지원하지 않음을 의미합니다.
[SSL: TLSV1_ALERT_PROTOCOL_VERSION] tlsv1 alert protocol version
업계 모범 사례는 일부 MongoDB 배포에서 이전 TLS 프로토콜을 비활성화할 것을 권장하며 일부 규정에서는 요구하고 있습니다. 일부 배포는 TLS 1.0 을 비활성화할 수 있고, 다른 배포는 TLS 1.0 및 TLS 1.1 을 비활성화할 수 있습니다.
PyMongo가 최신 TLS 버전을 사용하기 위해 애플리케이션을 변경할 필요는 없지만, 일부 운영 체제 버전은 이를 지원할 만큼 새로운 OpenSSL 버전을 제공하지 않을 수 있습니다.
macOS v10.12 을 사용하는 경우 (High Sierra) 이하 버전인 경우, python.org에서 Python을 설치합니다. 홈브루, macports 또는 유사한 소스.
Linux 또는 macOS가 아닌 다른 Unix를 사용하는 경우 다음 명령을 사용하여 OpenSSL 버전을 확인합니다.
openssl version
앞의 명령이 1.0.1 보다 작은 버전 번호를 표시하는 경우, TLS 1.1 이상에 대한 지원은 제공되지 않습니다. 최신 버전으로 업그레이드하거나 OS 공급업체에 솔루션을 문의하세요.
Python 인터프리터의 TLS 버전을 확인하려면 requests
모듈을 설치하고 다음 코드를 실행합니다.
python -c "import requests; print(requests.get('https://www.howsmyssl.com/a/check', verify=False).json()['tls_version'])"
TLS 1.1 이상이 표시됩니다.
잘못된 상태 응답
다음과 유사한 오류 메시지는 인증서 해지 확인에 실패했음을 의미합니다.
[('SSL routines', 'tls_process_initial_server_flight', 'invalid status response')]
자세한 내용은 이 가이드의 OCSP 섹션을 참조하세요.
SSLV3_ALERT_HANDSHAKE_FAILURE
Python v3.10 이상을 v4.0 이전의 MongoDB 버전과 함께 사용하는 경우, 다음 메시지와 유사한 오류가 표시될 수 있습니다.
SSL handshake failed: localhost:27017: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:997) SSL handshake failed: localhost:27017: EOF occurred in violation of protocol (_ssl.c:997)
MongoDB Server 로그에 다음 오류가 표시될 수도 있습니다.
2021-06-30T21:22:44.917+0100 E NETWORK [conn16] SSL: error:1408A0C1:SSL routines:ssl3_get_client_hello:no shared cipher
Python v 의 ssl 모듈에 대한 변경 사항3.10 v4 이전의 MongoDB 버전과 호환되지 않을 수 있습니다.0. 이 문제를 해결하려면 다음 단계 중 하나 이상을 시도해 보세요.
Python을 v3.9 이하 버전으로 다운그레이드
MongoDB Server를 v4.2 이상으로 업그레이드
PyOpenSSL을 사용하는 OCSP 옵션을 사용하여 PyMongo를 설치합니다.
안전하지 않은 레거시 재협상 비활성화
OpenSSL v3 이상을 사용하는 경우 다음 메시지와 유사한 오류가 표시될 수 있습니다.
[SSL: UNSAFE_LEGACY_RENEGOTIATION_DISABLED] unsafe legacy renegotiation disabled
이러한 유형의 오류는 실수로 레거시 TLS 재협상 을 시행하다 하는 오래되었거나 버그가 있는 SSL 프록시로 인해 발생합니다.
이 문제를 해결하려면 다음 단계를 수행하세요.
중요
옵션을 설정하면 보안에 UnsafeLegacyServerConnect
영향 을 미치기 unsafe legacy renegotiation disabled
때문입니다. 오류를 주소 하기 위한 최후의 수단으로 이 해결 방법을 사용하세요.
API 문서
PyMongo용 TLS를 구성하는 방법에 대해 자세히 알아보려면 다음 API 설명서를 참조하세요.