Version 2.7
of the Python SSL library has been
deprecated.
Instead, use the latest version, currently 2.7.11
.
App Engine supports the native Python SSL library 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 by specifying ssl
for
the libraries
configuration in your application's app.yaml
. You should use
the latest library version, which is currently
version 2.7.11. This
version supports TLS versions 1.0, 1.1, and 1.2 and corresponds to the SSL
versions from Python 2.7.11 and onwards:
libraries:
- name: ssl
version: latest
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_SSLv23,
ca_certs=CERTIFICATE_FILE)
You don't need to specify the ssl_version
parameter. If you omit it, 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 certificates
Your app should validate certificates to prevent certain security vulnerabilities such as "man in the middle" attacks.
To do this:
Edit your
app.yaml
file, adding the environment variablePYTHONHTTPSVERIFY
set to1
:env_variables: PYTHONHTTPSVERIFY: 1
Redeploy your app.
Alternatively to specifying cert validation in your app.yaml
, you could
explicitly call the SSL library to do the validation, after you've performed a
successful SSL handshake, as follows:
ssl.match_hostname(ssl_server.getpeercert(), 'a.hostname.com')
The above code uses the match_hostname
feature, backported from Python 3.2 to
be part of the App Engine Python 2.7.11 SSL module. This call makes sure the
certificate supplied by the peer matches one of the designated hosts in the
peer's certificate.
Working on dev_appserver
You can issue HTTPS requests using the urlfetch
API, Dev_server's certificate validation behaviour using httplib
using urlfetch
is identical to the production App Engine environment. Dev_appserver
does not support requests using sockets.