Skip to content

fix: cert pool changes requiring pebble restart - #870

Closed
hpidcock wants to merge 1 commit into
canonical:masterfrom
hpidcock:reload-cert-pool
Closed

fix: cert pool changes requiring pebble restart#870
hpidcock wants to merge 1 commit into
canonical:masterfrom
hpidcock:reload-cert-pool

Conversation

@hpidcock

Copy link
Copy Markdown
Member

This is a WIP, and I'm not entirely happy with having to extract logic from the std library.

TLS root cert pool refresh on replan

When the system CA certificate bundle changes, HTTP clients in checkstate, loki, and opentelemetry previously held a stale *http.Transport for the lifetime of the process. This PR adds automatic refresh on replan.

What changed

internals/httputil — new package providing Transport, a lazy-loading http.RoundTripper:

  • Initial cert pool comes from x509.SystemCertPool() (stdlib memoised call, correct at startup).
  • On Refresh(), cert files are stat-checked first; if any mtime/size changed, individual certs are re-parsed, diffed against the tracked set, and additions/removals are logged via logger.Noticef. A new *http.Transport (cloned from http.DefaultTransport) is swapped in and idle connections on the old one are closed.
  • Before first RoundTrip, Refresh() is a no-op (lazy loading).

tools/gencertloader — code-generation tool that extracts loadSystemRoots, certFiles, certDirectories, and supporting helpers directly from $GOROOT/src/crypto/x509/root_unix.go and root_linux.go via AST transformation. Every mutation is self-documenting: the original stdlib line is preserved as a comment above the replacement. Run via go generate ./internals/httputil.

checkstate, logstate, loki, opentelemetry — each manager gains a *httputil.Transport created at construction; PlanChanged calls transport.Refresh() before any other work.

flowchart TD
    A[OS cert bundle updated]:::accent2
    B[Operator adds/edits layer]:::accent2
    C[planMgr.PlanChanged]:::accent1

    C --> D[checkstate.PlanChanged]:::accent0
    C --> E[logstate.PlanChanged]:::accent0

    D --> F[httputil.Transport.Refresh]:::accent3
    E --> F

    F --> G{cert files\nchanged?}:::accent3
    G -- no --> H[no-op]:::accent4
    G -- yes --> I[parse certs\ndiff fingerprints\nlog added/removed]:::accent3
    I --> J[swap *http.Transport\nclose idle conns]:::accent3

    J --> K[httpChecker.check]:::accent5
    J --> L[loki.Client.Flush]:::accent5
    J --> M[otel.Client.Flush]:::accent5

    A --> B --> C
Loading

@hpidcock hpidcock linked an issue May 27, 2026 that may be closed by this pull request
@MichaelThamm

MichaelThamm commented May 27, 2026

Copy link
Copy Markdown

This PR adds automatic refresh on replan.

This direction is fine for us, thanks for this @hpidcock

@MichaelThamm

MichaelThamm commented May 27, 2026

Copy link
Copy Markdown

@hpidcock If this merges, how would we be able to make use of this? Is this bound to Juju versions: would we need to rebuild our rocks?

Is there a way for us to work around this issue for now? E.g., remove a LogTarget or something similar?

@hpidcock

Copy link
Copy Markdown
Member Author

We're exploring this as the solution, so closing this now.

@hpidcock hpidcock closed this Jun 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Potential gap in TLS context for log forwarding

2 participants