fix(urllib): log the default-certificates fallback once, after every bundle failed
Each failed candidate used to claim "falling back to default certificates" even when the next candidate (certifi on macOS) loaded fine. Per-failure warnings now say "trying the next bundle"; the default-certificates warning is emitted once at the final (None, None) return. Level unchanged (WARNING). PROOF: test_default_certificates_fallback_is_logged_once_after_all_bundles_fail fails on the previous per-candidate wording and passes with this change; tests/hermes_cli/test_urllib_security.py 22 passed.
This commit is contained in:
@@ -167,9 +167,9 @@ def _build_https_context(candidates: tuple[str, ...]) -> tuple[ssl.SSLContext |
|
||||
try:
|
||||
return ssl.create_default_context(cafile=path), path
|
||||
except (OSError, ssl.SSLError) as exc:
|
||||
logger.warning(
|
||||
"CA bundle could not be loaded from %s: %s — falling back to default certificates", path, exc
|
||||
)
|
||||
logger.warning("CA bundle could not be loaded from %s: %s — trying the next bundle", path, exc)
|
||||
if candidates:
|
||||
logger.warning("No configured CA bundle could be loaded — falling back to default certificates")
|
||||
return None, None
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import logging
|
||||
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
||||
import ssl
|
||||
from threading import Thread
|
||||
@@ -600,6 +601,30 @@ def test_fallback_bundle_change_does_not_invalidate_the_memo(monkeypatch, tmp_pa
|
||||
assert calls == [str(preferred)]
|
||||
|
||||
|
||||
def test_default_certificates_fallback_is_logged_once_after_all_bundles_fail(monkeypatch, caplog):
|
||||
"""A failed candidate says "trying the next bundle"; the default-certificates line is emitted once."""
|
||||
import hermes_cli.urllib_security as urllib_security
|
||||
|
||||
def create_default_context(*, cafile=None):
|
||||
raise ssl.SSLError(f"bad bundle {cafile}")
|
||||
|
||||
monkeypatch.setattr(ssl, "create_default_context", create_default_context)
|
||||
|
||||
with caplog.at_level(logging.WARNING, logger=urllib_security.logger.name):
|
||||
assert urllib_security._build_https_context(("/a.pem", "/b.pem")) == (None, None)
|
||||
|
||||
messages = [record.getMessage() for record in caplog.records]
|
||||
per_failure = [m for m in messages if "trying the next bundle" in m]
|
||||
assert [m.split(":")[0] for m in per_failure] == [
|
||||
"CA bundle could not be loaded from /a.pem",
|
||||
"CA bundle could not be loaded from /b.pem",
|
||||
]
|
||||
assert [m for m in messages if "falling back to default certificates" in m] == [
|
||||
"No configured CA bundle could be loaded — falling back to default certificates"
|
||||
]
|
||||
assert all(record.levelno == logging.WARNING for record in caplog.records)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("candidates", "first_load_fails_for", "expected_load_sequence"),
|
||||
[
|
||||
|
||||
Reference in New Issue
Block a user