11import time
2+ import ssl
23import urllib3
34from urllib3 .exceptions import ReadTimeoutError , SSLError as UrllibSSLError
45import warnings
1516from ..exceptions import ConnectionError , ImproperlyConfigured , ConnectionTimeout , SSLError
1617from ..compat import urlencode
1718
19+
20+ def create_ssl_context (** kwargs ):
21+ """
22+ A helper function around creating an SSL context
23+
24+ https://docs.python.org/3/library/ssl.html#context-creation
25+
26+ Accepts kwargs in the same manner as `create_default_context`.
27+ """
28+ ctx = ssl .create_default_context (** kwargs )
29+ return ctx
30+
31+
1832class Urllib3HttpConnection (Connection ):
1933 """
2034 Default connection class using the `urllib3` library and the http protocol.
@@ -47,7 +61,7 @@ class Urllib3HttpConnection(Connection):
4761 def __init__ (self , host = 'localhost' , port = 9200 , http_auth = None ,
4862 use_ssl = False , verify_certs = True , ca_certs = None , client_cert = None ,
4963 client_key = None , ssl_version = None , ssl_assert_hostname = None ,
50- ssl_assert_fingerprint = None , maxsize = 10 , headers = None , ** kwargs ):
64+ ssl_assert_fingerprint = None , maxsize = 10 , headers = None , ssl_context = None , ** kwargs ):
5165
5266 super (Urllib3HttpConnection , self ).__init__ (host = host , port = port , use_ssl = use_ssl , ** kwargs )
5367 self .headers = urllib3 .make_headers (keep_alive = True )
@@ -62,33 +76,49 @@ def __init__(self, host='localhost', port=9200, http_auth=None,
6276 self .headers [k .lower ()] = headers [k ]
6377
6478 self .headers .setdefault ('content-type' , 'application/json' )
65- ca_certs = CA_CERTS if ca_certs is None else ca_certs
6679 pool_class = urllib3 .HTTPConnectionPool
6780 kw = {}
68- if use_ssl :
81+
82+ # if providing an SSL context, raise error if any other SSL related flag is used
83+ if ssl_context and (verify_certs or ca_certs or ssl_version ):
84+ raise ImproperlyConfigured ("When using `ssl_context`, `use_ssl`, `verify_certs`, `ca_certs` and `ssl_version` are not permitted" )
85+
86+ # if ssl_context provided use SSL by default
87+ if use_ssl or ssl_context :
88+ if not ca_certs and not ssl_context and verify_certs :
89+ # If no ca_certs and no sslcontext passed and asking to verify certs
90+ # raise error
91+ raise ImproperlyConfigured ("Root certificates are missing for certificate "
92+ "validation. Either pass them in using the ca_certs parameter or "
93+ "install certifi to use it automatically." )
94+ if verify_certs or ca_certs or ssl_version :
95+ warnings .warn ('Use of `verify_certs`, `ca_certs`, `ssl_version` have been deprecated in favor of using SSLContext`' , DeprecationWarning )
6996 pool_class = urllib3 .HTTPSConnectionPool
97+
98+ if not ssl_context :
99+ # if SSLContext hasn't been passed in, create one.
100+ cafile = CA_CERTS if ca_certs is None else ca_certs
101+ # need to skip if sslContext isn't avail
102+ try :
103+ ssl_context = create_ssl_context (cafile = cafile )
104+ except AttributeError :
105+ ssl_context = None
106+
107+ if not verify_certs and ssl_context is not None :
108+ ssl_context .check_hostname = False
109+ ssl_context .verify_mode = ssl .CERT_NONE
110+ warnings .warn (
111+ 'Connecting to %s using SSL with verify_certs=False is insecure.' % host )
112+
70113 kw .update ({
71114 'ssl_version' : ssl_version ,
72115 'assert_hostname' : ssl_assert_hostname ,
73116 'assert_fingerprint' : ssl_assert_fingerprint ,
117+ 'ssl_context' : ssl_context ,
118+ 'cert_file' : client_cert ,
119+ 'ca_certs' : ca_certs ,
120+ 'key_file' : client_key ,
74121 })
75-
76- if verify_certs :
77- if not ca_certs :
78- raise ImproperlyConfigured ("Root certificates are missing for certificate "
79- "validation. Either pass them in using the ca_certs parameter or "
80- "install certifi to use it automatically." )
81-
82- kw .update ({
83- 'cert_reqs' : 'CERT_REQUIRED' ,
84- 'ca_certs' : ca_certs ,
85- 'cert_file' : client_cert ,
86- 'key_file' : client_key ,
87- })
88- else :
89- warnings .warn (
90- 'Connecting to %s using SSL with verify_certs=False is insecure.' % host )
91-
92122 self .pool = pool_class (host , port = port , timeout = self .timeout , maxsize = maxsize , ** kw )
93123
94124 def perform_request (self , method , url , params = None , body = None , timeout = None , ignore = ()):
0 commit comments