From 0df794e5a4fe4597ee65b0d492fbf0d0989d5ca0 Mon Sep 17 00:00:00 2001 From: Jordan Borean Date: Thu, 18 May 2023 08:17:25 +1000 Subject: urls - remove deprecated client key calls (#80751) --- changelogs/fragments/urls-client-cert-py12.yml | 2 ++ lib/ansible/module_utils/urls.py | 28 +++++++++++++++----------- test/units/module_utils/urls/test_Request.py | 14 ++++++------- 3 files changed, 24 insertions(+), 20 deletions(-) create mode 100644 changelogs/fragments/urls-client-cert-py12.yml diff --git a/changelogs/fragments/urls-client-cert-py12.yml b/changelogs/fragments/urls-client-cert-py12.yml new file mode 100644 index 0000000000..aab129ed96 --- /dev/null +++ b/changelogs/fragments/urls-client-cert-py12.yml @@ -0,0 +1,2 @@ +bugfixes: +- urls.py - fixed cert_file and key_file parameters when running on Python 3.12 - https://github.com/ansible/ansible/issues/80490 diff --git a/lib/ansible/module_utils/urls.py b/lib/ansible/module_utils/urls.py index 0e5fbb74c4..0197d86e10 100644 --- a/lib/ansible/module_utils/urls.py +++ b/lib/ansible/module_utils/urls.py @@ -535,15 +535,18 @@ HTTPSClientAuthHandler = None UnixHTTPSConnection = None if hasattr(httplib, 'HTTPSConnection') and hasattr(urllib_request, 'HTTPSHandler'): class CustomHTTPSConnection(httplib.HTTPSConnection): # type: ignore[no-redef] - def __init__(self, *args, **kwargs): + def __init__(self, client_cert=None, client_key=None, *args, **kwargs): httplib.HTTPSConnection.__init__(self, *args, **kwargs) self.context = None if HAS_SSLCONTEXT: self.context = self._context elif HAS_URLLIB3_PYOPENSSLCONTEXT: self.context = self._context = PyOpenSSLContext(PROTOCOL) - if self.context and self.cert_file: - self.context.load_cert_chain(self.cert_file, self.key_file) + + self._client_cert = client_cert + self._client_key = client_key + if self.context and self._client_cert: + self.context.load_cert_chain(self._client_cert, self._client_key) def connect(self): "Connect to a host on a given (SSL) port." @@ -564,10 +567,10 @@ if hasattr(httplib, 'HTTPSConnection') and hasattr(urllib_request, 'HTTPSHandler if HAS_SSLCONTEXT or HAS_URLLIB3_PYOPENSSLCONTEXT: self.sock = self.context.wrap_socket(sock, server_hostname=server_hostname) elif HAS_URLLIB3_SSL_WRAP_SOCKET: - self.sock = ssl_wrap_socket(sock, keyfile=self.key_file, cert_reqs=ssl.CERT_NONE, # pylint: disable=used-before-assignment - certfile=self.cert_file, ssl_version=PROTOCOL, server_hostname=server_hostname) + self.sock = ssl_wrap_socket(sock, keyfile=self._client_key, cert_reqs=ssl.CERT_NONE, # pylint: disable=used-before-assignment + certfile=self._client_cert, ssl_version=PROTOCOL, server_hostname=server_hostname) else: - self.sock = ssl.wrap_socket(sock, keyfile=self.key_file, certfile=self.cert_file, ssl_version=PROTOCOL) + self.sock = ssl.wrap_socket(sock, keyfile=self._client_key, certfile=self._client_cert, ssl_version=PROTOCOL) class CustomHTTPSHandler(urllib_request.HTTPSHandler): # type: ignore[no-redef] @@ -602,10 +605,6 @@ if hasattr(httplib, 'HTTPSConnection') and hasattr(urllib_request, 'HTTPSHandler return self.do_open(self._build_https_connection, req) def _build_https_connection(self, host, **kwargs): - kwargs.update({ - 'cert_file': self.client_cert, - 'key_file': self.client_key, - }) try: kwargs['context'] = self._context except AttributeError: @@ -613,7 +612,7 @@ if hasattr(httplib, 'HTTPSConnection') and hasattr(urllib_request, 'HTTPSHandler if self._unix_socket: return UnixHTTPSConnection(self._unix_socket)(host, **kwargs) if not HAS_SSLCONTEXT: - return CustomHTTPSConnection(host, **kwargs) + return CustomHTTPSConnection(host, client_cert=self.client_cert, client_key=self.client_key, **kwargs) return httplib.HTTPSConnection(host, **kwargs) @contextmanager @@ -979,7 +978,7 @@ def atexit_remove_file(filename): pass -def make_context(cafile=None, cadata=None, ciphers=None, validate_certs=True): +def make_context(cafile=None, cadata=None, ciphers=None, validate_certs=True, client_cert=None, client_key=None): if ciphers is None: ciphers = [] @@ -1006,6 +1005,9 @@ def make_context(cafile=None, cadata=None, ciphers=None, validate_certs=True): if ciphers: context.set_ciphers(':'.join(map(to_native, ciphers))) + if client_cert: + context.load_cert_chain(client_cert, keyfile=client_key) + return context @@ -1514,6 +1516,8 @@ class Request: cadata=cadata, ciphers=ciphers, validate_certs=validate_certs, + client_cert=client_cert, + client_key=client_key, ) handlers.append(HTTPSClientAuthHandler(client_cert=client_cert, client_key=client_key, diff --git a/test/units/module_utils/urls/test_Request.py b/test/units/module_utils/urls/test_Request.py index d2c4ea3801..a8bc3a0b6b 100644 --- a/test/units/module_utils/urls/test_Request.py +++ b/test/units/module_utils/urls/test_Request.py @@ -33,6 +33,7 @@ def install_opener_mock(mocker): def test_Request_fallback(urlopen_mock, install_opener_mock, mocker): here = os.path.dirname(__file__) pem = os.path.join(here, 'fixtures/client.pem') + client_key = os.path.join(here, 'fixtures/client.key') cookies = cookiejar.CookieJar() request = Request( @@ -46,8 +47,8 @@ def test_Request_fallback(urlopen_mock, install_opener_mock, mocker): http_agent='ansible-tests', force_basic_auth=True, follow_redirects='all', - client_cert='/tmp/client.pem', - client_key='/tmp/client.key', + client_cert=pem, + client_key=client_key, cookies=cookies, unix_socket='/foo/bar/baz.sock', ca_path=pem, @@ -68,8 +69,8 @@ def test_Request_fallback(urlopen_mock, install_opener_mock, mocker): call(None, 'ansible-tests'), # http_agent call(None, True), # force_basic_auth call(None, 'all'), # follow_redirects - call(None, '/tmp/client.pem'), # client_cert - call(None, '/tmp/client.key'), # client_key + call(None, pem), # client_cert + call(None, client_key), # client_key call(None, cookies), # cookies call(None, '/foo/bar/baz.sock'), # unix_socket call(None, pem), # ca_path @@ -358,10 +359,7 @@ def test_Request_open_client_cert(urlopen_mock, install_opener_mock): assert ssl_handler.client_cert == client_cert assert ssl_handler.client_key == client_key - https_connection = ssl_handler._build_https_connection('ansible.com') - - assert https_connection.key_file == client_key - assert https_connection.cert_file == client_cert + ssl_handler._build_https_connection('ansible.com') def test_Request_open_cookies(urlopen_mock, install_opener_mock): -- cgit v1.2.1