Skip to content

Commit b8fb825

Browse files
committed
proper TLS configuration
1 parent 16b6121 commit b8fb825

File tree

2 files changed

+16
-21
lines changed

2 files changed

+16
-21
lines changed

ops/_tracing/export.py

+12-20
Original file line numberDiff line numberDiff line change
@@ -119,30 +119,22 @@ def ssl_context(self, ca: str | None) -> ssl.SSLContext:
119119
return context
120120

121121
def _ssl_context(self, ca: str | None) -> ssl.SSLContext:
122-
# FIXME: What should our protocol range be?
123-
# this means TLS {v1, v1.1, v1.2}
124-
# Do we need to set v1_2 or v1_3 explicitly?
125-
# Py 3.10 update the secure cipher list
126-
# Do we need to set ciphers explicitly for Py 3.8?
127-
# We'd match https://wiki.mozilla.org/Security/Server_Side_TLS "Modern".
128-
# FIXME SSLContext(args) or create_default_context(args)?
122+
# NOTE: ssl.create_default_context() doesn't allow setting the context.protocol in a way
123+
# that's the same across Python 3.8 and 3.10 onwards. Whip the context up by hand.
129124
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
125+
context.minimum_version = ssl.TLSVersion.TLSv1_3
126+
context.set_alpn_protocols(['http/1.1'])
127+
context.verify_flags |= ssl.VERIFY_X509_STRICT
128+
if (partial_chain := getattr(ssl, "VERIFY_X509_PARTIAL_CHAIN", None)):
129+
# Available starting from Python 3.10. The partial chain flag allows trusting the
130+
# intermediate CAs in the CA list without the matching root CA
131+
context.verify_flags |= partial_chain
130132

131-
if ca:
133+
if ca is not None:
132134
context.load_verify_locations(cadata=ca)
133135
else:
134-
# FIXME: we should probably allow ca=None
135-
# and then we'd pick up system or certifi certs?
136-
raise ValueError(f'FIXME: unsupported {ca=}')
137-
138-
# FIXME: what's recommended?
139-
# context.set_ciphers(...)
140-
# FIXME: we need to set NPN if we're setting ALPN?
141-
# Does this work the same way across Py 3.8~3.13?
142-
context.set_npn_protocols('http/1.1')
143-
context.set_alpn_protocols(['http/1.1'])
144-
# TODO: check that we don't need these:
145-
# .set_sni_callback
136+
context.load_default_certs()
137+
146138
return context
147139

148140
def do_export(self, buffered_id: int, data: bytes, mime: str) -> None:

ops/charm.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -1222,8 +1222,11 @@ def set_destination(self, *, url: Optional[str], ca: Optional[str] = None) -> No
12221222
Args:
12231223
url: The URL of the "collector", the destination for tracing data.
12241224
Example: 'http://localhost:4318/v1/traces'
1225-
ca: The PEM-formatted server certificate authority list.
1225+
ca: The PEM-formatted server certificate authority list content.
12261226
This argument is in effect only if the ``url`` is an HTTPS URL.
1227+
1228+
To use the system CA list, supply ``ca=None``. To use the Mozilla CA list distributed in
1229+
the ``certifi`` package, use ``ca=Path(certifi.where()).read_text()``.
12271230
"""
12281231
with tracer.start_as_current_span('ops.SetupTracingEvent.set_destination') as span:
12291232
span.set_attribute('url', url or '')

0 commit comments

Comments
 (0)