mirror of
https://github.com/home-assistant/core
synced 2024-09-15 17:29:45 +02:00
Fix httpx client creating a new ssl context with each client (memory leak) (#90191)
* Fix httpx client creating a new ssl context with each client While working on https://github.com/home-assistant/core/issues/83524 it was discovered that each new httpx client creates a new ssl contextf1157dbc41/httpx/_transports/default.py (L261)
If an ssl context is passed in creating a new one is avoided heref1157dbc41/httpx/_config.py (L110)
This change makes httpx ssl no-verify behavior match aiohttp ssl no-verify behavior6da04694fd/aiohttp/connector.py (L892)
aiohttp solved this by wrapping the code that generates the ssl context in an lru_cache * compact
This commit is contained in:
parent
ca157f4d19
commit
1f2268a878
@ -273,7 +273,7 @@ def _async_get_connector(
|
||||
if verify_ssl:
|
||||
ssl_context: bool | SSLContext = ssl_util.get_default_context()
|
||||
else:
|
||||
ssl_context = False
|
||||
ssl_context = ssl_util.get_default_no_verify_context()
|
||||
|
||||
connector = aiohttp.TCPConnector(
|
||||
enable_cleanup_closed=True,
|
||||
|
@ -11,7 +11,7 @@ from typing_extensions import Self
|
||||
from homeassistant.const import APPLICATION_NAME, EVENT_HOMEASSISTANT_CLOSE, __version__
|
||||
from homeassistant.core import Event, HomeAssistant, callback
|
||||
from homeassistant.loader import bind_hass
|
||||
from homeassistant.util import ssl as ssl_util
|
||||
from homeassistant.util.ssl import get_default_context, get_default_no_verify_context
|
||||
|
||||
from .frame import warn_use
|
||||
|
||||
@ -65,8 +65,11 @@ def create_async_httpx_client(
|
||||
|
||||
This method must be run in the event loop.
|
||||
"""
|
||||
ssl_context = (
|
||||
get_default_context() if verify_ssl else get_default_no_verify_context()
|
||||
)
|
||||
client = HassHttpXAsyncClient(
|
||||
verify=ssl_util.get_default_context() if verify_ssl else False,
|
||||
verify=ssl_context,
|
||||
headers={USER_AGENT: SERVER_SOFTWARE},
|
||||
**kwargs,
|
||||
)
|
||||
|
@ -1,10 +1,31 @@
|
||||
"""Helper to create SSL contexts."""
|
||||
import contextlib
|
||||
from os import environ
|
||||
import ssl
|
||||
|
||||
import certifi
|
||||
|
||||
|
||||
def create_no_verify_ssl_context() -> ssl.SSLContext:
|
||||
"""Return an SSL context that does not verify the server certificate.
|
||||
|
||||
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.options |= ssl.OP_NO_SSLv2
|
||||
sslcontext.options |= ssl.OP_NO_SSLv3
|
||||
sslcontext.check_hostname = False
|
||||
sslcontext.verify_mode = ssl.CERT_NONE
|
||||
with contextlib.suppress(AttributeError):
|
||||
# This only works for OpenSSL >= 1.0.0
|
||||
sslcontext.options |= ssl.OP_NO_COMPRESSION
|
||||
sslcontext.set_default_verify_paths()
|
||||
return sslcontext
|
||||
|
||||
|
||||
def client_context() -> ssl.SSLContext:
|
||||
"""Return an SSL context for making requests."""
|
||||
|
||||
@ -18,6 +39,7 @@ def client_context() -> ssl.SSLContext:
|
||||
|
||||
# Create this only once and reuse it
|
||||
_DEFAULT_SSL_CONTEXT = client_context()
|
||||
_DEFAULT_NO_VERIFY_SSL_CONTEXT = create_no_verify_ssl_context()
|
||||
|
||||
|
||||
def get_default_context() -> ssl.SSLContext:
|
||||
@ -25,6 +47,11 @@ def get_default_context() -> ssl.SSLContext:
|
||||
return _DEFAULT_SSL_CONTEXT
|
||||
|
||||
|
||||
def get_default_no_verify_context() -> ssl.SSLContext:
|
||||
"""Return the default SSL context that does not verify the server certificate."""
|
||||
return _DEFAULT_NO_VERIFY_SSL_CONTEXT
|
||||
|
||||
|
||||
def server_context_modern() -> ssl.SSLContext:
|
||||
"""Return an SSL context following the Mozilla recommendations.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user