App Engine supports the native Python OpenSSL for the Python 2.7 runtime via
the ssl library, which you must add to your app.
Specifying the SSL library
If you want to use native python SSL, you must enable it using the
libraries configuration in your application's app.yaml
file where you specify the library name "ssl". There are two libraries
available, version 2.7 supports TLS v1.0 only:
libraries:
- name: ssl
version: 2.7
Version 2.7.11 supports TLS v1.0, v1.1, and v1.2:
libraries:
- name: ssl
version: 2.7.11
Providing authority certificates
In order to perform an SSL handshake, you must have file that contains
concatenated certificate authority certificates. You can
upload your own file with your application, or you can use the
file provided by App Engine: /etc/ca-certificates.crt.
Performing an SSL handshake
The python 2.7 wrap_socket method takes two file name
parameters that contain the client's key and certificate. In the App Engine
environment, this is limiting since the application is not able to write files
to dynamically provide different keys and certificates. To get around this
limitation, the certfile and keyfile parameters for
the ssl.wrap_socket method can be "file-like" objects that allow
the application to store certificates and keys in other ways than in just
uploaded application files. (A "file-like" object is one that has a "read"
method returning the entire certificate as a 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_TLSv1,
ca_certs=CERTIFICATE_FILE)
You do not need to specify the ssl_version parameter. If you leave it out, the 2.7 library
defaults to PROTOCOL_TLSv1.
The 2.7.11 library defaults to PROTOCOL_SSLv23. You can also specify PROTOCOL_TLSv1,
PROTOCOL_TLSv1_1, or PROTOCOL_TLSv1_2.
The App Engine implementation of the wrap_socket method includes the
required parameter ca_certs, which is used to specify the special file containing
concatenated certificate authority certificates.
Validating the certificate
After you've performed a successful SSL handshake, you must validate that the certificate supplied by the peer matches one of the designated hosts in the peer's certificate. This provides security and can prevent "man in the middle" attacks.
Use the match_hostname which is backported from Python 3.2 and is part of the Engine 2.7 SSL module. It is
available in both version 2.7 and 2.7.11:
ssl.match_hostname(ssl_server.getpeercert(), 'a.hostname.com')