Usar Python SSL

La versión 2.7 de la biblioteca Python SSL se ha obsoleto. En su lugar, usa la versión más reciente, que actualmente es 2.7.11.

App Engine admite la biblioteca nativa Python SSL para el tiempo de ejecución de Python 2.7 a través de la biblioteca SSL, que debes añadir a tu aplicación.

Especificar la biblioteca SSL

Si quieres usar SSL nativo de Python, debes habilitarlo especificando ssl para la configuración de libraries en el archivo app.yaml de tu aplicación. Debes usar la versión más reciente de la biblioteca, que actualmente es la 2.7.11. Esta versión es compatible con las versiones 1.0, 1.1 y 1.2 de TLS, y corresponde a las versiones de SSL de Python 2.7.11 y posteriores:

libraries:
- name: ssl
  version: latest

Proporcionar certificados de autoridad

Para realizar un handshake SSL, debes tener un archivo que contenga certificados de autoridad de certificación concatenados. Puedes subir tu propio archivo con tu aplicación o usar el archivo que proporciona App Engine: /etc/ca-certificates.crt.

Realizar un handshake de SSL

El método wrap_socket de Python 2.7 toma dos parámetros de nombre de archivo que contienen la clave y el certificado del cliente. En el entorno de App Engine, esto es una limitación, ya que la aplicación no puede escribir archivos para proporcionar dinámicamente diferentes claves y certificados. Para evitar esta limitación, los parámetros certfile y keyfile del método ssl.wrap_socket pueden ser objetos de tipo archivo que permitan a la aplicación almacenar certificados y claves de otras formas que no sean solo archivos de aplicación subidos. Un objeto similar a un archivo es aquel que tiene un método "read" que devuelve todo el certificado como una cadena.

  # 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)

No es necesario que especifique el parámetro ssl_version. Si lo omite, la biblioteca 2.7.11 se establece de forma predeterminada en PROTOCOL_SSLv23. También puedes especificar PROTOCOL_TLSv1, PROTOCOL_TLSv1_1 o PROTOCOL_TLSv1_2.

La implementación de App Engine del método wrap_socket incluye el parámetro obligatorio ca_certs, que se usa para especificar el archivo especial que contiene los certificados concatenados de la autoridad de certificación.

Validar certificados

Tu aplicación debe validar los certificados para evitar ciertas vulnerabilidades de seguridad, como los ataques de intermediarios.

Para hacer esto:

  1. Edita el archivo app.yaml y añade la variable de entorno PYTHONHTTPSVERIFY definida como 1:

     env_variables:
       PYTHONHTTPSVERIFY: 1
    
  2. Vuelve a implementar tu aplicación.

En lugar de especificar la validación del certificado en tu app.yaml, puedes llamar explícitamente a la biblioteca SSL para que realice la validación después de haber completado correctamente la negociación SSL, como se indica a continuación:

    ssl.match_hostname(ssl_server.getpeercert(), 'a.hostname.com')

El código anterior usa la función match_hostname, que se ha portado de Python 3.2 para formar parte del módulo SSL de App Engine Python 2.7.11. Esta llamada se asegura de que el certificado proporcionado por el peer coincida con uno de los hosts designados en el certificado del peer.

Trabajar en dev_appserver

Puedes enviar solicitudes HTTPS mediante la API urlfetch. El comportamiento de validación de certificados del servidor de desarrollo mediante httplib con urlfetch es idéntico al del entorno de producción de App Engine. Dev_appserver no admite solicitudes que usen sockets.