Configurar o TLS (Transport Layer Security)
Nesta página
- Visão geral
- Habilitar TLS
- Especifique um arquivo CA
- Verifique a revogação do certificado
- OCSP
- Lista de revogação de certificados
- Apresentar um Certificado de Cliente
- Forneça uma senha de chave
- Permitir TLS Inseguro
- Solucionar problemas de TLS
- CERTIFICATE_VERIFY_FAILED
- TLSV1_ALERT_PROTOCOL_VERSION
- Resposta de status inválida
- SSLV3_ALERT_HANDSHAKE_FAILURE
- Renegociação legada insegura desativada
- Documentação da API
Visão geral
Neste guia, você aprenderá a usar o TLS protocolo para proteger sua conexão com um sistema do MongoDB .
Quando você habilita o TLS para uma conexão, o PyMongo executa as seguintes ações:
Usa TLS para se conectar ao MongoDB deployment
Verifica o certificado do sistema
Garante que o certificado certifique o sistema
Para saber como configurar seu sistema MongoDB para TLS, consulte o guia de configuração TLS no manual do MongoDB Server .
Importante
Uma descrição completa de certificados TLS/SSL, PKI (Public Key Infrastructure) e Autoridades de Certificação (CAs) está além do escopo deste documento. Esta página pressupõe conhecimento prévio de TLS/SSL e acesso a certificados válidos.
Habilitar TLS
Para habilitar o TLS para a conexão com sua instância do MongoDB, defina a opção de conexão tls
como True
. Você pode fazer isso de duas maneiras: passando um argumento para o construtor MongoClient
ou por meio de um parâmetro em sua connection 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")
Dica
Se a string de conexão incluir a modificação +srv
, que especifica o formato de conexão SRV, o TLS será habilitado na sua conexão por padrão.
Para saber mais sobre o formato de conexão SRV, consulte Formato de conexão SRV na documentação do MongoDB Server .
Especifique um arquivo CA
Durante a negociação TLS, o sistema do MongoDB apresenta um arquivo de chave de certificado para seu aplicativo para estabelecer sua identidade. Normalmente, o certificado de um sistema é assinado por uma CA conhecida, e seu aplicativo depende dessa CA para validar o certificado.
No entanto, durante os testes, você pode querer agir como sua própria CA. Nesse caso, você deve instruir o PyMongo a usar seus certificados de CA em vez dos assinados por outra CA.
Para fazer isso, use a opção de conexão tlsCAFile
para especificar o caminho para um arquivo .pem
que contém a cadeia de certificados raiz. Você pode fazer isso de duas maneiras: passando um argumento para o construtor MongoClient
ou por meio de um parâmetro em sua connection 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)
Verifique a revogação do certificado
Quando um certificado X.509 não é mais confiável - por exemplo, se sua chave privada foi comprometida - a CA revoga o certificado. O PyMongo inclui duas maneiras de verificar se o certificado de um servidor foi revogado.
OCSP
Para usar o Protocolo de Status do Certificado On-line (OCSP) para validar um certificado de servidor, você deve instalar o PyMongo com a opção ocsp
, conforme mostrado no exemplo a seguir:
python -m pip install pymongo[ocsp]
O processo de validação do certificado varia dependendo da versão do MongoDB Server à qual você está se conectando:
MongoDB v4.4 ou posterior: o servidor grampeia uma resposta OCSP com registro de data e hora em seu certificado. O PyMongo valida o certificado em relação à resposta do OCSP. Se a CA tiver revogado o certificado ou se a resposta OCSP for inválida, a negociação TLS falhará.
MongoDB v4.3 ou anterior: o servidor fornece um endpoint OCSP, com o qual o PyMongo entra em contato diretamente. O PyMongo então valida o certificado em relação à resposta do OCSP. Se a CA não tiver revogado o certificado, a negociação TLS continuará, mesmo que a resposta OCSP seja inválida ou malformada.
Para impedir que o PyMongo entre em contato com o endpoint OCSP, defina a opção de conexão tlsDisableOCSPEndpointCheck
como True
. Você pode fazer isso de duas maneiras: passando um argumento para o construtor MongoClient
ou por meio de um parâmetro em sua connection 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)
Observação
Mesmo que a opção tlsDisableOCSPEndpointCheck
esteja definida como True
, o PyMongo ainda verificará qualquer resposta OCSP grampeada no certificado de um servidor.
Lista de revogação de certificados
Em vez de usar o OCSP, você pode instruir o PyMongo a verificar o certificado do servidor em relação a uma Lista de revogação de certificados (CRL) publicada pela CA. Para fazer isso, use a opção de conexão tlsCRLFile
para especificar o caminho para um arquivo .pem
ou .der
da CA. Você pode fazer isso de duas maneiras: passando um argumento para o construtor MongoClient
ou por meio de um parâmetro em sua connection 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)
Observação
Você não pode usar um CRL e um OCSP no mesmo handshake TLS.
Apresentar um Certificado de Cliente
Algumas implementações do MongoDB exigem que cada aplicativo de conexão apresente um certificado de cliente que comprove sua identidade. Para especificar o certificado do cliente para o PyMongo apresentar, defina a opção tlsCertificateKeyFile
para o caminho do arquivo .pem
que contém seu certificado e chave privada. Você pode fazer isso de duas maneiras: passando um argumento para o construtor MongoClient
ou por meio de um parâmetro em sua connection 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)
Importante
Seu certificado de cliente e chave privada devem estar no mesmo arquivo .pem
. Se estiverem armazenados em arquivos diferentes, você deverá concatená-los. O exemplo a seguir mostra como concatenar um arquivo de chave e um arquivo de certificado em um terceiro arquivo chamado combined.pem
em um sistema Unix:
cat key.pem cert.pem > combined.pem
Forneça uma senha de chave
Se a chave privada em seu arquivo de certificado estiver criptografada, você deverá fornecer uma senha. Para fazer isso, use a opção de conexão tlsCertificateKeyFilePassword
para especificar a senha ou frase secreta para a chave privada criptografada. Você pode fazer isso de duas maneiras: passando um argumento para o construtor MongoClient
ou por meio de um parâmetro em sua connection 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)
Permitir TLS Inseguro
Quando o TLS está habilitado, o PyMongo verifica automaticamente o certificado apresentado pelo servidor. Ao testar seu código, você pode desativar essa verificação. Isso é conhecido como TLS inseguro.
Quando o TLS inseguro está habilitado, o PyMongo exige apenas que o servidor apresente um certificado X.509 . O driver aceita um certificado mesmo que alguma das seguintes afirmações seja verdadeira:
O nome do host do servidor e o nome do assunto (ou nome alternativo do assunto) no certificado não correspondem.
O certificado expirou ou ainda não é válido.
O certificado não tem um certificado raiz confiável na cadeia.
A finalidade do certificado não é válida para identificação do servidor.
Observação
Mesmo quando o TLS inseguro está habilitado, a comunicação entre o cliente e o servidor é criptografada com TLS.
Para habilitar o TLS inseguro, defina a opção de conexão tlsInsecure
como True
. Você pode fazer isso de duas maneiras: passando um argumento para o construtor MongoClient
ou por meio de um parâmetro em sua connection 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)
Para desabilitar somente a validação do certificado, defina a opção tlsAllowInvalidCertificates
como True
e defina a opção tlsInsecure
como False
ou omita-a:
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)
Para desabilitar somente a verificação do nome de host, configure a opção tlsAllowInvalidHostnames
para True
e configure a opção tlsInsecure
para False
ou omita:
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)
Aviso
Não use em produção
Sempre defina as opções tlsInsecure
, tlsAllowInvalidCertificates
e tlsAllowInvalidHostnames
como False
em produção.
Definir qualquer uma dessas opções como True
em um ambiente de produção torna seu aplicativo desprotegido e potencialmente vulnerável a certificados expirados e a processos externos que se apresentam como instâncias de cliente válidas.
Solucionar problemas de TLS
CERTIFICATE_VERIFY_FAILED
Uma mensagem de erro semelhante à seguinte significa que o OpenSSL não conseguiu verificar o certificado do servidor:
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed
Isso geralmente acontece porque o OpenSSL não consegue acessar os certificados raiz do sistema ou porque os certificados estão desatualizados.
Se você usar Linux, certifique-se de ter as atualizações de certificado raiz mais recentes instaladas do seu fornecedor de Linux.
Se você usa macOS e se está executando o Python v3.7 ou posterior baixado de python.org, execute o seguinte comando para instalar certificados raiz:
open "/Applications/Python <YOUR PYTHON VERSION>/Install Certificates.command"
Dica
Para obter mais informações sobre este problema, consulte Problema do Python 29065.
Se você usar o embedded-pypy, talvez seja necessário definir uma variável de ambiente para informar ao OpenSSL onde encontrar certificados raiz. O seguinte exemplo de código mostra como instalar o módulo de certificação do PyPi e exporte a SSL_CERT_FILE
variável de ambiente :
$ pypy -m pip install certifi $ export SSL_CERT_FILE=$(pypy -c "import certifi; print(certifi.where())")
Dica
Para obter mais informações sobre esse problema, consulte problema portátil-pypy 15.
TLSV1_ALERT_PROTOCOL_VERSION
Uma mensagem de erro semelhante à seguinte significa que a versão OpenSSL usada pelo Python não suporta um protocolo TLS novo o suficiente para se conectar ao servidor:
[SSL: TLSV1_ALERT_PROTOCOL_VERSION] tlsv1 alert protocol version
As melhores práticas do setor recomendam, e algumas regulamentações exigem, que os protocolos TLS mais antigos sejam desabilitados em algumas implantações do MongoDB. Algumas implantações podem desativar o TLS 1.0, enquanto outras podem desativar o TLS 1.0 e o TLS 1.1.
Nenhuma alteração no aplicativo é necessária para que o PyMongo use as versões mais recentes do TLS, mas algumas versões do sistema operacional podem não fornecer uma versão do OpenSSL nova o suficiente para habilitá-las.
Se você usa macOS v10.12 (High Sierra) ou anterior, instale o Python a partir de python.org, homebrew, macports ou uma fonte semelhante.
Se você usa Linux ou outro Unix não macOS, use o seguinte comando para verificar sua versão do OpenSSL:
openssl version
Se o comando anterior mostrar um número de versão inferior a 1.0.1, suporte para TLS 1.1 ou mais recente não está disponível. Atualize para uma versão mais recente ou entre em contato com o fornecedor do sistema operacional para obter uma solução.
Para verificar a versão TLS do seu interpretador Python, instale o módulo requests
e execute o seguinte código:
python -c "import requests; print(requests.get('https://www.howsmyssl.com/a/check', verify=False).json()['tls_version'])"
Você deve ver TLS 1.1 ou posterior.
Resposta de status inválida
Uma mensagem de erro semelhante à seguinte significa que a verificação de revogação do certificado falhou:
[('SSL routines', 'tls_process_initial_server_flight', 'invalid status response')]
Para obter mais detalhes, consulte a seção OCSP deste guia.
SSLV3_ALERT_HANDSHAKE_FAILURE
Ao usar o Python v3.10 ou posterior com versões do MongoDB anteriores à v4.0, você pode ver erros semelhantes às seguintes mensagens:
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)
Os registros do MongoDB Server também podem mostrar o seguinte erro:
2021-06-30T21:22:44.917+0100 E NETWORK [conn16] SSL: error:1408A0C1:SSL routines:ssl3_get_client_hello:no shared cipher
Alterações feitas no módulo ssl no Python v3.10 pode causar incompatibilidades com versões do MongoDB anteriores à v4.0. Para resolver esse problema, tente uma ou mais das seguintes etapas:
Faça downgrade do Python para a3.9 ou anterior
Atualize o MongoDB Server para v4.2 ou posterior
Instalar o PyMongo com a opção OCSP , que depende do PyOpenSSL
Renegociação legada insegura desativada
Ao usar o OpenSSL v3 ou posterior, você poderá ver um erro semelhante à seguinte mensagem:
[SSL: UNSAFE_LEGACY_RENEGOTIATION_DISABLED] unsafe legacy renegotiation disabled
Esses tipos de erros ocorrem devido a proxies SSL desatualizados ou com erros que impõem erroneamente a renegociação do TLS legado .
Para resolver esse problema, execute as seguintes etapas:
Use a UnsafeLegacyServerConnect
opção
Crie um arquivo de configuração que inclua a opção UnsafeLegacyServerConnect
. O exemplo seguinte mostra como configurar a opção UnsafeLegacyServerConnect
:
openssl_conf = openssl_init [openssl_init] ssl_conf = ssl_sect [ssl_sect] system_default = system_default_sect [system_default_sect] Options = UnsafeLegacyServerConnect
Importante
Como a UnsafeLegacyServerConnect
configuração da opção tem implicações de segurança, use esta solução alternativa como último recurso para solucionar unsafe legacy renegotiation disabled
erros.
Documentação da API
Para saber mais sobre como configurar o TLS para o PyMongo, consulte a seguinte documentação da API: