Add trustBundle as a SystemInfo volume data source - #941
Open
Max Thompson (thompsonmax) wants to merge 2 commits into
Open
Add trustBundle as a SystemInfo volume data source#941Max Thompson (thompsonmax) wants to merge 2 commits into
Max Thompson (thompsonmax) wants to merge 2 commits into
Conversation
Max Thompson (thompsonmax)
force-pushed
the
ctb-source
branch
2 times, most recently
from
August 20, 2026 20:00
9cfd863 to
eb71544
Compare
Max Thompson (thompsonmax)
force-pushed
the
ctb-source
branch
from
August 20, 2026 20:42
ec49fb3 to
80fcb1e
Compare
Max Thompson (thompsonmax)
marked this pull request as ready for review
August 20, 2026 20:47
Max Thompson (thompsonmax)
requested review from
Taahir Ahmed (ahmedtd),
Bowei Du (bowei) and
haiyanmeng
August 20, 2026 20:48
Max Thompson (thompsonmax)
force-pushed
the
ctb-source
branch
from
August 20, 2026 21:01
80fcb1e to
87bfffc
Compare
A trustBundle data source projects the trust anchors of a named trust bundle to a PEM file in the volume — inspired by the Kubernetes clusterTrustBundle projected volume source, but source-neutral: the template names a bundle, and where it is fetched from is a deployment concern behind ateapi, not part of the API (agent-substrate#932). Supported names are allowlisted in ateapi rather than the CRD schema, so the eventual configurable backend registry widens them without an API change. Initially the only supported bundle is egress-mitm.ate.dev (the egress gateway CA bundle, agent-substrate#823), resolved from the ClusterTrustBundle that atecontroller's EgressMITMTrustReconciler (agent-substrate#946) derives from the egress-mitm-ca-pool Secret — the signer-linked object name (egress-mitm.ate.dev:mitm:primary-bundle) is a backend detail the allowlist mapping keeps out of the template API. Resolution goes through an informer-backed lister and sanitizes the way kubelet sanitizes projections: CERTIFICATE blocks only, deduplicated, headers stripped (internal/pemutil). The wire spec carries only {path, pem_bundle} resolved bytes; atelet writes them at a stable path with the per-file temp+rename discipline (find-paths safe) and never talks to any bundle backend. Actor start fails closed, naming the bundle, when the name is not allowlisted, the backend is unavailable in this deployment (certificates.k8s.io/v1beta1 is feature-gated; ateapi probes at startup and degrades instead of hanging), or the bundle is missing, empty, or free of certificates. The identity e2e drives the real chain end to end: it provisions the egress-mitm-ca-pool Secret, waits for the reconciler to publish the derived bundle, asserts the projected file in both CI lanes, then rotates the pool and asserts a resumed actor observes the new contents at the same path — writing the bundle directly is not an option, since the reconciler reverts or deletes hand-written contents. Bundle contents refresh on every Run/Restore; live refresh for running actors is agent-substrate#932 PR 2. ateapi gains RBAC to read clustertrustbundles.certificates.k8s.io.
…ed bundle The identity suite verifies trust-anchor DELIVERY (pool -> reconciler -> bundle -> resolution -> projection); this adds the CONSUMPTION half for agent-substrate#871: an actor completes a TLS handshake with the sdsmint egress gateway's per-SNI minted leaf using ONLY the anchors projected through its trustBundle SystemInfo volume — on both sandbox classes, since delivery differs per class (gVisor RO bind vs the micro-VM unified virtio-fs share). The probe gains /fetch?url=&roots=bundle|system, which GETs over the actor's normal egress path with TLS roots from the projected bundle or the image's system roots. The new egressmitm suite asserts the pair that makes the result unambiguous: roots=bundle succeeds (and would fail under a passthrough gateway, whose relayed public certificates the bundle cannot validate — so a pass also certifies interception is on), while roots=system fails certificate verification (the minted leaf chains to no public CA; under passthrough it would succeed). The sdsmint gateway variant replaces the passthrough gateway cluster-wide, so CI deploys it as a separate step after both standard lanes and runs only this suite against it — once per sandbox class, gated by E2E_EGRESS_MITM. The suite ensures (never replaces) the CA pool: sdsmintd signs with the pool mounted into the gateway pod, and replacing it would race kubelet's Secret propagation into that mount.
Max Thompson (thompsonmax)
force-pushed
the
ctb-source
branch
from
August 20, 2026 21:31
87bfffc to
37df9b3
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #932 (PR 1 of 3). Adds the user-declarable
trustBundledata source for SystemInfo volumes (#802) and the end-to-end proof that the projected anchors work against the MITM egress gateway. Live refresh for running actors (PR 2) and auto-injection (PR 3) come separately.What this adds
A SystemInfo volume data source that projects the trust anchors of a named trust bundle to a PEM file:
Inspired by the Kubernetes clusterTrustBundle projected volume source, but source-neutral: the template names a bundle; where it's fetched from is a deployment concern behind ateapi, not part of the API.
Design points
egress-mitm.ate.dev(the egress gateway CA bundle, Add an SDS server that mints a short-lived leaf per SNI on demand at handshake time #823), mapped to the ClusterTrustBundle that atecontroller'sEgressMITMTrustReconciler(Add EgressMITMTrustReconciler #946) derives from theegress-mitm-ca-poolSecret. The signer-linked object name stays a backend detail; the future backend registry widens the allowlist without an API change.internal/pemutil); the wire carries only{path, pem_bundle}; atelet writes bytes at a stable path with the temp+rename discipline from feat: add systemInfo volume source with actorIdentity data source #803 (find-paths safe) and never talks to any backend. Contents refresh on every Run/Restore.dataSourcesMaxItems tightened 32→8 while adding the trustBundle member. Vacuous in practice (the old schema couldn't admit more than one entry), but flagged since it's ratchet-shaped.E2E — delivery and consumption
Delivery (identity suite, both sandbox classes): provisions the
egress-mitm-ca-poolSecret and drives the real #946 reconciler (writing the bundle directly isn't possible — the reconciler reverts hand-edits), asserts the projected file byte-exact, then rotates the pool across a suspend/resume to prove refresh-on-restore. Since the probe fixture is shared and fail-closed,e2e.DeployProbeitself ensures the bundle exists for whatever suite deploys it.Consumption (new
egressmitmsuite, both sandbox classes): deploys the sdsmint (MITM) egress gateway and proves an actor completes a TLS handshake with the gateway's per-SNI minted leaf using ONLY the projected anchors — plus a system-roots negative control that must fail. The pair is unambiguous in both directions: the positive can't pass under passthrough (the bundle holds no public CAs), and the negative can't fail under passthrough.Not in this PR