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