diff --git a/command_line_assistant/daemon/http/session.py b/command_line_assistant/daemon/http/session.py index 4a306fe..09ae341 100644 --- a/command_line_assistant/daemon/http/session.py +++ b/command_line_assistant/daemon/http/session.py @@ -1,6 +1,7 @@ """Handle the http sessions that the daemon issues to the backend.""" import logging +from ssl import SSLError import urllib3 from requests.sessions import Session @@ -8,6 +9,7 @@ from command_line_assistant.config import Config from command_line_assistant.constants import VERSION from command_line_assistant.daemon.http.adapters import RetryAdapter, SSLAdapter +from command_line_assistant.dbus.exceptions import RequestFailedError USER_AGENT = f"clad/{VERSION}" #: Define the custom user agent for clad @@ -46,10 +48,20 @@ def get_session(config: Config) -> Session: session.verify = False return session - ssl_adapter = SSLAdapter( - cert_file=config.backend.auth.cert_file, # type: ignore - key_file=config.backend.auth.key_file, # type: ignore - ) + try: + ssl_adapter = SSLAdapter( + cert_file=config.backend.auth.cert_file, # type: ignore + key_file=config.backend.auth.key_file, # type: ignore + ) + except SSLError as e: + raise RequestFailedError( + "Failed to load certificate in cert chain. If needed, regenerate the certificate with subscription-manager and try again." + ) from e + except FileNotFoundError as e: + raise RequestFailedError( + f"Couldn't find certificate files at '{config.backend.auth.cert_file.parent}' folder." # pyright: ignore[reportAttributeAccessIssue] + ) from e + # Mount the adapter for the given endpoint. session.mount(config.backend.endpoint, ssl_adapter) diff --git a/tests/daemon/http/test_session.py b/tests/daemon/http/test_session.py index 2bd2c19..faacab7 100644 --- a/tests/daemon/http/test_session.py +++ b/tests/daemon/http/test_session.py @@ -5,6 +5,7 @@ from command_line_assistant.constants import VERSION from command_line_assistant.daemon.http.session import get_session +from command_line_assistant.dbus.exceptions import RequestFailedError def test_session_headers(mock_config): @@ -73,3 +74,26 @@ def test_various_endpoints(mock_config, endpoint): # Verify that the endpoint is used for mounting adapters assert any(pattern == endpoint for pattern, _ in session.adapters.items()) + + +def test_session_with_corrupted_ssl_certificate(mock_config): + mock_config.backend.auth.cert_file.write_text("whatever pem") + mock_config.backend.auth.key_file.write_text("whatever secret") + mock_config.backend.auth.verify_ssl = True + + with pytest.raises( + RequestFailedError, match="Failed to load certificate in cert chain." + ): + get_session(mock_config) + + +def test_session_with_missing_ssl_certificate(tmp_path, mock_config): + cert_file = tmp_path / "missing" / "cert.pem" + key_file = tmp_path / "missing" / "key.pem" + + mock_config.backend.auth.cert_file = cert_file + mock_config.backend.auth.key_file = key_file + mock_config.backend.auth.verify_ssl = True + + with pytest.raises(RequestFailedError, match="Couldn't find certificate files at"): + get_session(mock_config)