"""Helper to create SSL contexts.""" import ssl import certifi def client_context(): """Return an SSL context for making requests.""" context = _get_context() context.verify_mode = ssl.CERT_REQUIRED context.check_hostname = True context.load_verify_locations(cafile=certifi.where(), capath=None) return context def server_context(): """Return an SSL context for being a server.""" context = _get_context() context.options |= ssl.OP_CIPHER_SERVER_PREFERENCE return context def _get_context(): """Return an SSL context following the Mozilla recommendations. TLS configuration follows the best-practice guidelines specified here: https://wiki.mozilla.org/Security/Server_Side_TLS Modern guidelines are followed. """ context = ssl.SSLContext(ssl.PROTOCOL_TLS) # pylint: disable=no-member context.options |= ( ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 ) if hasattr(ssl, 'OP_NO_COMPRESSION'): context.options |= ssl.OP_NO_COMPRESSION context.set_ciphers( "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:" "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:" "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:" "ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:" "ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256" ) return context