diff --git a/homeassistant/util/ssl.py b/homeassistant/util/ssl.py index 2b503716063..6bfbec88a33 100644 --- a/homeassistant/util/ssl.py +++ b/homeassistant/util/ssl.py @@ -61,16 +61,11 @@ SSL_CIPHER_LISTS = { @cache -def create_no_verify_ssl_context( - ssl_cipher_list: SSLCipherList = SSLCipherList.PYTHON_DEFAULT, -) -> ssl.SSLContext: - """Return an SSL context that does not verify the server certificate. +def _create_no_verify_ssl_context(ssl_cipher_list: SSLCipherList) -> ssl.SSLContext: + # This is a copy of aiohttp's create_default_context() function, with the + # ssl verify turned off. + # https://github.com/aio-libs/aiohttp/blob/33953f110e97eecc707e1402daa8d543f38a189b/aiohttp/connector.py#L911 - This is a copy of aiohttp's create_default_context() function, with the - ssl verify turned off. - - https://github.com/aio-libs/aiohttp/blob/33953f110e97eecc707e1402daa8d543f38a189b/aiohttp/connector.py#L911 - """ sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) sslcontext.check_hostname = False sslcontext.verify_mode = ssl.CERT_NONE @@ -84,12 +79,16 @@ def create_no_verify_ssl_context( return sslcontext -@cache -def client_context( +def create_no_verify_ssl_context( ssl_cipher_list: SSLCipherList = SSLCipherList.PYTHON_DEFAULT, ) -> ssl.SSLContext: - """Return an SSL context for making requests.""" + """Return an SSL context that does not verify the server certificate.""" + return _create_no_verify_ssl_context(ssl_cipher_list=ssl_cipher_list) + + +@cache +def _client_context(ssl_cipher_list: SSLCipherList) -> ssl.SSLContext: # Reuse environment variable definition from requests, since it's already a # requirement. If the environment variable has no value, fall back to using # certs from certifi package. @@ -104,6 +103,14 @@ def client_context( return sslcontext +def client_context( + ssl_cipher_list: SSLCipherList = SSLCipherList.PYTHON_DEFAULT, +) -> ssl.SSLContext: + """Return an SSL context for making requests.""" + + return _client_context(ssl_cipher_list=ssl_cipher_list) + + # Create this only once and reuse it _DEFAULT_SSL_CONTEXT = client_context() _DEFAULT_NO_VERIFY_SSL_CONTEXT = create_no_verify_ssl_context() diff --git a/tests/util/test_ssl.py b/tests/util/test_ssl.py index 4d43859cc44..4a88e061cbc 100644 --- a/tests/util/test_ssl.py +++ b/tests/util/test_ssl.py @@ -51,3 +51,12 @@ def test_no_verify_ssl_context(mock_sslcontext) -> None: mock_sslcontext.set_ciphers.assert_called_with( SSL_CIPHER_LISTS[SSLCipherList.INTERMEDIATE] ) + + +def test_ssl_context_caching() -> None: + """Test that SSLContext instances are cached correctly.""" + + assert client_context() is client_context(SSLCipherList.PYTHON_DEFAULT) + assert create_no_verify_ssl_context() is create_no_verify_ssl_context( + SSLCipherList.PYTHON_DEFAULT + )