From 1eaaa00687e8d86c09c18d4b79f160856d991c2d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 6 Aug 2024 09:00:37 -0500 Subject: [PATCH] Detect blocking ssl context creation in the event loop (#123240) --- homeassistant/block_async_io.py | 19 +++++++++++++++++++ tests/test_block_async_io.py | 24 ++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/homeassistant/block_async_io.py b/homeassistant/block_async_io.py index 5b8ba535b5a..6ea0925574e 100644 --- a/homeassistant/block_async_io.py +++ b/homeassistant/block_async_io.py @@ -8,6 +8,7 @@ import glob from http.client import HTTPConnection import importlib import os +from ssl import SSLContext import sys import threading import time @@ -143,6 +144,24 @@ _BLOCKING_CALLS: tuple[BlockingCall, ...] = ( strict_core=False, skip_for_tests=True, ), + BlockingCall( + original_func=SSLContext.load_default_certs, + object=SSLContext, + function="load_default_certs", + check_allowed=None, + strict=False, + strict_core=False, + skip_for_tests=True, + ), + BlockingCall( + original_func=SSLContext.load_verify_locations, + object=SSLContext, + function="load_verify_locations", + check_allowed=None, + strict=False, + strict_core=False, + skip_for_tests=True, + ), ) diff --git a/tests/test_block_async_io.py b/tests/test_block_async_io.py index ef4f9df60f6..78b8711310b 100644 --- a/tests/test_block_async_io.py +++ b/tests/test_block_async_io.py @@ -5,6 +5,7 @@ import glob import importlib import os from pathlib import Path, PurePosixPath +import ssl import time from typing import Any from unittest.mock import Mock, patch @@ -330,6 +331,29 @@ async def test_protect_loop_walk( assert "Detected blocking call to walk with args" not in caplog.text +async def test_protect_loop_load_default_certs( + hass: HomeAssistant, caplog: pytest.LogCaptureFixture +) -> None: + """Test SSLContext.load_default_certs calls in the loop are logged.""" + with patch.object(block_async_io, "_IN_TESTS", False): + block_async_io.enable() + context = ssl.create_default_context() + assert "Detected blocking call to load_default_certs" in caplog.text + assert context + + +async def test_protect_loop_load_verify_locations( + hass: HomeAssistant, caplog: pytest.LogCaptureFixture +) -> None: + """Test SSLContext.load_verify_locations calls in the loop are logged.""" + with patch.object(block_async_io, "_IN_TESTS", False): + block_async_io.enable() + context = ssl.create_default_context() + with pytest.raises(OSError): + context.load_verify_locations("/dev/null") + assert "Detected blocking call to load_verify_locations" in caplog.text + + async def test_open_calls_ignored_in_tests(caplog: pytest.LogCaptureFixture) -> None: """Test opening a file in tests is ignored.""" assert block_async_io._IN_TESTS