github.com/nginxinc/kubernetes-ingress@v1.12.5/tests/suite/ssl_utils.py (about) 1 """Describe methods to handle ssl connections.""" 2 3 import socket 4 import ssl 5 import OpenSSL 6 import requests 7 from requests.adapters import HTTPAdapter 8 from urllib.parse import urlparse 9 10 11 def get_certificate(ip_address, host, port, timeout=10) -> str: 12 """ 13 Get tls certificate. 14 :param ip_address: 15 :param host: 16 :param port: 17 :param timeout: 18 :return: str 19 """ 20 context = ssl.create_default_context() 21 context.check_hostname = False 22 context.verify_mode = ssl.CERT_NONE 23 conn = socket.create_connection((ip_address, port)) 24 server_hostname = host if ssl.HAS_SNI else None 25 sock = context.wrap_socket(conn, server_hostname=server_hostname) 26 sock.settimeout(timeout) 27 try: 28 der_cert = sock.getpeercert(True) 29 finally: 30 sock.close() 31 return ssl.DER_cert_to_PEM_cert(der_cert) 32 33 34 def get_server_certificate_subject(ip_address, host, port=443) -> dict: 35 """ 36 Get tls certificate subject object. 37 :param port: default is 443 38 :param ip_address: 39 :param host: 40 :return: dict 41 """ 42 certificate = get_certificate(ip_address, host, port) 43 x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, certificate) 44 return dict(x509.get_subject().get_components()) 45 46 class SNIAdapter(HTTPAdapter): 47 """ 48 An HTTP adapter for the requests library that ensures that the SNI of a TLS connection is set to the custom host 49 header. 50 Usage:: 51 >>> s = requests.Session() 52 >>> s.mount("https://", SNIAdapter()) 53 >>> resp = s.get("https://127.0.0.1:8443", headers={"host": "webapp.example.com"}, verify=False) 54 """ 55 def send(self, request, **kwargs): 56 # overrides the SNI to the value of the host header 57 # See urllib3.connection.HTTPSConnection.connect 58 self.poolmanager.connection_pool_kw["server_hostname"] = request.headers["host"] 59 return super(SNIAdapter, self).send(request, **kwargs) 60 61 62 def create_sni_session(): 63 """ 64 Creates a session that will ensure that the SNI of TLS connection is set to the custom host header. 65 :return: requests.sessions.Session 66 """ 67 s = requests.Session() 68 s.mount("https://", SNIAdapter()) 69 return s