[stacked on #803] Add clusterTrustBundle as a SystemInfo volume data source - #941
Draft
Max Thompson (thompsonmax) wants to merge 7 commits into
Draft
[stacked on #803] Add clusterTrustBundle as a SystemInfo volume data source#941Max Thompson (thompsonmax) wants to merge 7 commits into
Max Thompson (thompsonmax) wants to merge 7 commits into
Conversation
This commit defines a new volume type, SystemInfoVolume, that will serve a similar purpose as Projected volumes in Kubernetes. It will support writing information from multiple sources to automatically-updating files in the Actor's filesystem. For a first pass, I have converted the existing hardcoded Actor ID file to be one of the available information sources in a SystemInfoVolume. Further work will add Actor Identity JWTs and Actor Identity certificates.
Complete the initial actorIdentity data source support: - e2e: declare a systemInfo volume in the identity probe's ActorTemplate, mounted at /run/ate, replacing the removed automatic identity mount so the restore-identity regression gate exercises the new API. - Validate actorIdentity paths at admission: must be a clean relative Unix path (no absolute paths, '..', '.', '//', ':', or control characters), and paths must be unique within a volume. Previously bad paths were only rejected by the atomic writer at Run/Restore time. - Unit tests for the ateapi systemInfo conversion and for atelet's system-info volume population (extracted into writeSystemInfoVolume). - Update the stale micro-VM known-gap comment to reference systemInfo volumes instead of the removed /run/ate identity mount.
Per the API discussion on agent-substrate#802: substrate has no "actor ID" concept -- resource identity is (atespace, name) plus a server-generated UID. Replace the actorIdentity data source with an actorMetadata source that projects each identity field to its own file, downwardAPI-style: systemInfo: dataSources: - actorMetadata: items: - field: name # enum: name | atespace | uid path: actor-name - CRD: ActorMetadataDataSource with a field enum and per-item path; admission validation for unknown fields, duplicate fields, duplicate paths, and non-clean/absolute paths; at most one actorMetadata entry per volume keeps paths unique volume-wide. - atelet proto: ActorMetadataDataSource/ActorMetadataItem with a field enum; ateapi converts CRD items to wire items. - atelet: writeSystemInfoVolume projects name/atespace/uid from the Run/Restore request; unknown fields (newer ateapi) are skipped rather than written empty. - e2e: the identity probe projects and serves all three fields; the suite now also asserts atespace matches and the projected UID equals the control plane's authoritative UID per actor, distinct across actors seeded from the same snapshot. - docs: api-guide section rewritten for actorMetadata. This also frees the "identity" naming for the planned credential data sources (actorIdentityToken, actorIdentityCertificate), which relate to the existing ateapi.ActorIdentity service.
SystemInfo volumes were gVisor-only; per the agent-substrate#802 discussion, micro-VM support lands with Part 1 rather than as a follow-up. The mechanism mirrors the durable-dir share: - ateom proto: containers carry system_info_volume_mounts (volume name + mount path), populated by atelet's buildAteomWorkloadSpec. - ateom-microvm serves ateompath.SystemInfoVolumeRootsDir(actorUID) over a third virtiofsd (cache=auto: atelet rewrites the contents underneath the guest on every restore). The agent mounts the share at sandbox creation, and each declaring container gets a READ-ONLY bind from the share's per-volume subdirectory to its declared mount path. - Restore restarts the share's virtiofsd and rewrites its vhost-user socket in the snapshot's VM config (matched by fs tag). Nothing is restored from the snapshot itself: atelet has already regenerated the files with the resumed actor's values, which is the point of system-info volumes. - Checkpoint deliberately ignores the share: the volume roots live outside the durable-dir tree precisely so the durable tar can never capture generated identity data. - Replace the stale "KNOWN GAP" comment in spec.go: dropping host-path binds in the kata spec shaper is fine because volumes reach micro-VM containers via the shares, not spec.Mounts.
Add a README pinning the upstream source (k8s.io/kubernetes pkg/volume/util, delta verified against kubernetes/kubernetes@52ba9013) and enumerating every class of local modification, plus maintenance rules (mechanical adaptations only in upstream-derived files; behavioral changes go in substrate-owned files) and a re-sync procedure. Mark each copied file with a greppable '// substrate:' header so the patch surface is discoverable without diffing against upstream.
A clusterTrustBundle data source projects the trust anchors of a named
ClusterTrustBundle (certificates.k8s.io/v1beta1) to a PEM file in a
SystemInfo volume -- the substrate analog of the Kubernetes
clusterTrustBundle projected volume source:
systemInfo:
dataSources:
- clusterTrustBundle:
name: my-trust-bundle
path: ca.pem
ateapi resolves the bundle at actor start through a new informer-backed
lister and sanitizes the PEM the way kubelet does for projections (only
CERTIFICATE blocks, deduplicated, headers stripped -- internal/pemutil).
The wire spec carries only {path, pem_bundle}: atelet writes the
resolved bytes via the existing atomic writer and never talks to the
Kubernetes API. Starting the actor fails with an error naming the
bundle when it is missing, empty, or contains no certificates.
Because certificates.k8s.io/v1beta1 is feature-gated (enabled by
hack/create-kind-cluster.sh), ateapi probes for the API at startup and
degrades to a nil lister when absent -- registering the informer
blindly would hang WaitForCacheSync and with it ateapi boot. envtest
now serves the API so the functional suite matches real clusters.
Validation extends the SystemInfo CEL rules: clean relative paths,
unique paths across all data sources (dataSources MaxItems drops 32->8
to keep the cross-source rule inside the CEL cost budget), and the
ate-api-server ClusterRole gains read access to clustertrustbundles.
The identity e2e suite now creates a fixture bundle (junk PEM and a
duplicate certificate around a real one), projects it into the probe,
and asserts the delivered file is the sanitized PEM byte-for-byte.
Part of agent-substrate#932 (PR 1); the SystemInfo volume mechanism is agent-substrate#802.
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; doesn't close it). The SystemInfo volume mechanism this builds on is #802.
New changes:
clusterTrustBundledata source for SystemInfo volumes. It projects a named ClusterTrustBundle (certificates.k8s.io/v1beta1) to a PEM file, the substrate analog of the Kubernetes clusterTrustBundle projected volume source. Selection is by name; signerName and label selectors can come later if needed.internal/pemutil). The wire spec carries{path, pem_bundle}, so atelet writes bytes and never talks to the Kubernetes API. A bundle that is missing, empty, or free of certificates fails the actor start with an error that names it.hack/create-kind-cluster.shalready enables on kind.dataSourcesmaxItems drops from 32 to 8 because the cross-source duplicate rule exceeded the apiserver's CEL cost budget at 32.Not included (tracked in #932):
ate-egress-trustvolume (PR 3), which addresses the open item from egress: MITM tunneled TLS with per-SNI certificate minting #871.Review notes: the failure paths (missing bundle, API unavailable) are unit-tested rather than e2e-tested, since a missing bundle wedges the template's golden boot and costs minutes of suite time for little signal.
internal/atunnel's unix-socket failures on macOS are pre-existing on upstream main)