A versão 2.7
da biblioteca do Python SSL se tornou obsoleta.
Em vez disso, use a versão mais recente, atualmente 2.7.11
.
O App Engine aceita a biblioteca do Python SSL nativa para o tempo de execução do Python 2.7 por meio da biblioteca SSL, que você precisa adicionar ao app.
Como especificar a biblioteca SSL
Se você quiser usar o SSL nativo do Python, ative-o especificando ssl
para a configuração libraries
no app.yaml
do aplicativo. Você precisa usar a versão da biblioteca mais recente, atualmente a versão 2.7.11. Essa versão aceita as versões TLS 1.0, 1.1 e 1.2 e corresponde às versões SSL do Python 2.7.11 e posteriores:
libraries:
- name: ssl
version: latest
Como fornecer certificados de autoridade
Para executar um handshake SSL, você precisa ter um arquivo que contenha certificados de autoridade de certificação concatenados. Você pode fazer upload de seu próprio arquivo com seu aplicativo ou usar o arquivo fornecido pelo App Engine: /etc/ca-certificates.crt
.
Como executar um handshake SSL
O método wrap_socket
do Python 2.7 usa dois parâmetros de nome de arquivo que contêm a chave e o certificado do cliente. No ambiente do App Engine, isso é limitante, porque o aplicativo não pode gravar arquivos para fornecer dinamicamente chaves e certificados diferentes. Para contornar essa limitação, os parâmetros certfile
e keyfile
do método ssl.wrap_socket
podem ser objetos "tipo arquivo" que permitem que o aplicativo armazene certificados e chaves de outras maneiras que não apenas arquivos de aplicativo enviados. Um objeto "semelhante a um arquivo" é aquele que tem um método de "leitura" que retorna todo o certificado como uma string.
# Example of a dynamic key and cert.
datastore_record_k = ndb.Key('Employee', 'asalieri', 'Address', 1)
datastore_record = datastore_record_k.get()
key_str = datastore_record.key_str
cert_str = datastore_record.cert
ssl_server = ssl.wrap_socket(server_sock,
server_side=False,
keyfile=StringIO.StringIO(key_str),
certfile=StringIO.StringIO(cert_str),
cert_reqs=ssl.CERT_REQUIRED,
ssl_version=ssl.PROTOCOL_SSLv23,
ca_certs=CERTIFICATE_FILE)
Não é necessário especificar o parâmetro ssl_version
. Se você omiti-lo, o padrão da biblioteca 2.7.11 será PROTOCOL_SSLv23
. Você também pode especificar PROTOCOL_TLSv1
, PROTOCOL_TLSv1_1
ou PROTOCOL_TLSv1_2
.
A implementação do App Engine do método wrap_socket
inclui o parâmetro obrigatório ca_certs
, que é usado para especificar o arquivo especial que contém certificados de autoridade de certificação concatenados.
Como validar certificados
O aplicativo precisa validar certificados para evitar determinadas vulnerabilidades de segurança, como ataques "man in the middle".
Para fazer isso:
Edite o arquivo
app.yaml
, adicionando a variável de ambientePYTHONHTTPSVERIFY
definida como1
:env_variables: PYTHONHTTPSVERIFY: 1
Implante o aplicativo novamente.
Como alternativa para especificar a validação do certificado em app.yaml
, você pode chamar explicitamente a biblioteca SSL para fazer a validação, depois de realizar um handshake SSL bem-sucedido, da seguinte maneira:
ssl.match_hostname(ssl_server.getpeercert(), 'a.hostname.com')
O código acima usa o recurso match_hostname
, portado em retorno a partir do Python 3.2 para fazer parte do módulo SSL do Python 2.7.11 do App Engine. Essa chamada verifica se o certificado fornecido pelo peering corresponde a um dos hosts designados no certificado.
Como trabalhar em dev_appserver
É possível emitir solicitações HTTPS usando a API urlfetch. O comportamento de validação de certificado do Dev_server com httplib
usando a urlfetch é idêntico ao ambiente de produção do App Engine. O Dev_appserver não é compatível com solicitações que usam soquetes.