Utilisation de SSL Python

La version 2.7 de la bibliothèque SSL Python est obsolète. Au lieu de cela, utilisez la dernière version, actuellement 2.7.11.

App Engine prend en charge la bibliothèque SSL Python native pour l'environnement d'exécution de Python 2.7 via la bibliothèque SSL, que vous devez ajouter à votre application.

Spécification de la bibliothèque SSL

Si vous souhaitez utiliser le SSL Python natif, vous devez l'activer en spécifiant ssl pour la configuration des bibliothèques (libraries) dans le fichier app.yaml de votre application. Vous devez utiliser la dernière version de la bibliothèque, qui est actuellement la version 2.7.11. Cette version prend en charge les versions 1.0, 1.1 et 1.2 de TLS et correspond aux versions SSL à partir de Python 2.7.11 :

libraries:
- name: ssl
  version: latest

Fournir des certificats d'autorité

Pour pouvoir établir un handshake SSL, vous devez disposer d’un fichier contenant des certificats d’autorité de certification concaténés. Vous pouvez importer votre propre fichier avec votre application ou utiliser le fichier fourni par App Engine : /etc/ca-certificates.crt.

Effectuer un handshake SSL

La méthode wrap_socket de Python 2.7 utilise deux paramètres de nom de fichier contenant la clé et le certificat du client. Dans l'environnement App Engine, cela est limitatif, car l'application n'est pas en mesure d'écrire des fichiers pour fournir dynamiquement des clés et des certificats différents. Pour contourner cette limitation, les paramètres certfile et keyfile de la méthode ssl.wrap_socket peuvent être des objets de type "fichier" qui permettent à l'application de stocker des certificats et des clés autrement que dans des fichiers d'application importés. (Un objet de type "fichier" est un objet ayant une méthode "en lecture" renvoyant l'intégralité du certificat sous forme de chaîne.)

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

Vous n'avez pas besoin de spécifier le paramètre ssl_version. Si vous l'omettez, la bibliothèque 2.7.11 utilise par défaut PROTOCOL_SSLv23. Vous pouvez également spécifier PROTOCOL_TLSv1, PROTOCOL_TLSv1_1 ou PROTOCOL_TLSv1_2.

La mise en œuvre de la méthode wrap_socket par App Engine inclut le paramètre requis ca_certs, qui permet de spécifier le fichier spécial contenant les certificats concaténés d'autorités de certification.

Valider les certificats

Votre application doit valider les certificats pour prévenir certaines vulnérabilités de sécurité, telles que les attaques "man in the middle".

Procédez comme suit :

  1. Modifiez votre fichier app.yaml en ajoutant la variable d'environnement PYTHONHTTPSVERIFY définie sur 1 :

     env_variables:
       PYTHONHTTPSVERIFY: 1
    
  2. Redéployez votre application.

Au lieu de spécifier la validation des certificats dans votre fichier app.yaml, vous pouvez appeler explicitement la bibliothèque SSL pour effectuer la validation, une fois que vous avez réussi un handshake SSL, comme suit :

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

Le code ci-dessus utilise la fonctionnalité match_hostname, rétroportée depuis Python 3.2 pour faire partie du module SSL Python 2.7.11 d'App Engine. Cet appel garantit que le certificat fourni par l'homologue correspond à l'un des hôtes désignés dans le certificat de l'homologue.

Travailler sur dev_appserver

Vous pouvez émettre des requêtes HTTPS à l'aide de urlfetch de l'API ; le comportement de validation du certificat de Dev_server à l'aide de httplib en utilisant urlfetch est identique à l'environnement de production App Engine. Dev_appserver n'est pas compatible avec les requêtes utilisant des sockets.