Skip to content

tls: add filter_state certificate selector for dynamic cert provisioning#44124

Draft
kanurag94 wants to merge 10 commits intoenvoyproxy:mainfrom
kanurag94:tls-bumping-dynamic-module
Draft

tls: add filter_state certificate selector for dynamic cert provisioning#44124
kanurag94 wants to merge 10 commits intoenvoyproxy:mainfrom
kanurag94:tls-bumping-dynamic-module

Conversation

@kanurag94
Copy link
Copy Markdown
Contributor

@kanurag94 kanurag94 commented Mar 26, 2026

Adds envoy.tls.certificate_selectors.filter_state — a new TLS certificate selector that reads PEM-encoded certificate chain and private key from connection filter state during the TLS handshake. This enables dynamic certificate provisioning by listener filters (e.g., for TLS bumping, on-the-fly cert generation, or per-SNI cert selection).

It is basically a lightweight cert selector for cases where PEM is already available in filter state, complementing on_demand (which handles the async SDS case)

This extension is sponsored by @wbpcode (thank you!)

Signed-off-by: Anurag Aggarwal <kanurag94@gmail.com>
@repokitteh-read-only
Copy link
Copy Markdown

As a reminder, PRs marked as draft will not be automatically assigned reviewers,
or be handled by maintainer-oncall triage.

Please mark your PR as ready when you want it to be reviewed!

🐱

Caused by: #44124 was opened by kanurag94.

see: more, trace.

@kanurag94 kanurag94 changed the title ssl: add filter_state certificate selector for dynamic cert provisioning tls: add filter_state certificate selector for dynamic cert provisioning Mar 26, 2026
Signed-off-by: Anurag Aggarwal <kanurag94@gmail.com>
Signed-off-by: Anurag Aggarwal <kanurag94@gmail.com>
@kyessenov
Copy link
Copy Markdown
Contributor

Where does the PEM come from originally and how is it rotated? I think #43557 used a local certificate provider, so passing a provider name might be easier. Otherwise, you'd have to handle rotation in the filter.

Signed-off-by: Anurag Aggarwal <kanurag94@gmail.com>
@kanurag94
Copy link
Copy Markdown
Contributor Author

kanurag94 commented Mar 27, 2026

Thank you so much @kyessenov for taking a look at this!

Where does the PEM come from originally and how is it rotated? I think #43557 used a local certificate provider, so passing a provider name might be easier. Otherwise, you'd have to handle rotation in the filter.

The idea is to have this as a plain plumbing point — any listener filter that already has cert material can hand it to the TLS handshake via filter state, no SDS needed. I was planning a dynamic module listener filter as a follow-up example, but it works with anything that writes to connection filter state (set_filter_state, Wasm, native C++, etc.).

Where does the PEM come from?

A listener filter writes it to connection filter state before the handshake. The intended use case is a dynamic module listener filter that generates certs in-process — planned as a follow-up example. But any listener filter that can write to filter state works (native C++, set_filter_state, Wasm). This can enable TLS Bumping.

How is it rotated?

The selector caches compiled SSL_CTXs per-worker keyed by cert name. New certs take effect on cache eviction (max_cache_size) or onConfigUpdate(). The selector doesn't manage cert expiry — the listener filter is responsible for providing valid certs.

Thanks for linking #43557 — wasn't aware of it. That's a cleaner approach for the specific TLS bumping case since it keeps generation and selection in one component. I thought about this as an alternative solution but I felt we can use dynamic_modules to do the heavy plumbing and make this a small injection point. Keep the code changes very small and flexible.

TLDR:

  • local_signer (Support TLS Bumping  #43557) — selector generates certs internally
  • filter_state (this PR) — cert source is external to the selector, a listener filter already has the PEM

I kept it separate from on_demand because its SecretManager is built around async SDS (main-thread posting, runOnAllThreads propagation) — mixing in a synchronous filter-state read path felt wrong.

Signed-off-by: Anurag Aggarwal <kanurag94@gmail.com>
Signed-off-by: Anurag Aggarwal <kanurag94@gmail.com>
Signed-off-by: Anurag Aggarwal <kanurag94@gmail.com>
Signed-off-by: Anurag Aggarwal <kanurag94@gmail.com>
Signed-off-by: Anurag Aggarwal <kanurag94@gmail.com>
Signed-off-by: Anurag Aggarwal <kanurag94@gmail.com>
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.

2 participants