agent-substrate / agent-substrate/substrate
High-density actors are invisible to workload attestation - no per-actor attestable property is exposed to the node
- 主要语言
- Go
- 星标
- 1.8k
- 派生
- 316
- 平均合并
- 2 天 43 分钟
- 30 天内合并 PR
- 287
描述
## Summary
Substrate currently supports actor identity in control-plane and runtime-mediated forms, but does not expose a distinct **node-attestable** per-actor property that standard SPIRE workload selectors can use to distinguish actors inside the same runtime pod.
When Substrate runs many actors inside one sandboxed runtime pod, platform-level workload identity systems (SPIFFE/SPIRE via the Kubernetes workload attestor) can attest the POD, but cannot attest an individual ACTOR. Every attestable property available to the node attestor (namespace, service account, pod labels, cgroup path) is shared by all actors in the runtime. The consequence is structural, not merely a configuration issue: **no SPIRE selector can express "this Substrate actor", because no selector can invent a node-observable property the runtime does not expose.**
## Scope clarification: what Substrate already provides
This issue is NOT claiming Substrate lacks actor identity machinery. It has real, useful identity features - they are just not consumable by node-level workload attestation:
- `/run/ate/actor-id` is a per-actor, read-only bind mount so the actor can learn its own ID (`docs/api-guide.md`; `internal/ateompath/ateompath.go` `ActorIdentityDirPath`). This tells the actor who it is - it does not let the node prove to a third party which actor a process belongs to (a file the workload can read is not an attestation source, and the mount is inside the sandbox, not observable by a SPIRE agent's workload attestor).
- The control plane mints **Actor Identity JWTs and certificates** (`pkg/proto/ateapipb/ateapi.proto`, `service ActorIdentity`: `MintJWT` authenticated as the pod currently running the actor; `MintCert` mediated by the atelet with worker↔actor assignment verified both ways; `internal/substratex509/substratex509.go` carries pod- and actor-identity certificate extensions). This is control-plane-rooted identity - its trust chain runs through ateapi/atelet, not through a workload attestor that a standard SPIRE deployment can plug into.
- Identity metadata for observability exists across suspend/resume cycles (`docs/observability.md`).
- Actor workloads are launched from control-plane state (`cmd/ateapi/internal/controlapi/workload_spec.go`), not from anything a per-actor node selector could match.
The gap is specifically the bridge between these two worlds: none of the above is exposed as a node-observable, per-actor attestation source suitable for standard workload selectors.
## What we observed (reproducible)
- A SPIRE registration entry intended for one actor, scoped with the only selectors actually available (e.g. `k8s:ns:`), issues that actor's SVID to EVERY workload in the namespace. We verified a bystander pod receiving a foreign actor identity over the plain Workload API. A per-actor SPIFFE ID with a per-namespace selector reads stronger than it is - it is credential sharing wearing an identity system.
- Pod labels do not help: a pod that merely DECLARES a per-actor label is handed that actor's identity. A label a pod asserts about itself is not an authentication.
## Why it matters
Multi-actor density is a core Substrate capability. Governance and evidence systems increasingly need per-actor identity in the SPIFFE trust domain the rest of the platform speaks: which actor performed an action, attested by the platform rather than asserted by the process, and verifiable by services that already trust a SPIRE issuer. Today the only sound design we found is an identity BROKER: a separately attested pod that holds no actor identity itself, names per-actor registration entries whose selectors are unsatisfiable by construction, and mints per-actor credentials via SPIRE's delegated identity API after authenticating the actor at a different layer. That works (we run it), and it is conceptually close to what `ActorIdentity.MintCert` already does inside Substrate's own trust chain - but it re-centralizes what workload attestation was meant to decentralize, and every deployment has to re-derive it.
## Options for closing the gap
Any ONE of these would make per-actor identity first-class for SPIFFE consumers:
1. **Expose a per-actor attestable property to the node**: e.g. run each actor under a distinct, runtime-managed cgroup path or unix credential that a node attestor plugin can observe, with the actor id resolvable from it.
2. **A Substrate workload-attestor plugin** (SPIRE agent plugin) that answers "which actor is this process" from the runtime's own authoritative state - effectively bridging the existing atelet/ateapi knowledge into workload attestation.
3. **Document the broker pattern as the sanctioned approach**, including the invariant that actor entries must never be satisfiable by workload selectors - so deployments stop shipping the per-namespace-selector foot-gun.
## Environment
Agent Substrate at commit `3cb7433bd8a81a1f9aa54ef98418fbde8205fc42` (2026-07-06); the repo evidence above was re-checked against current main (`8541d6d9`), where the `ActorIdentity` service and `substratex509` live. SPIRE 1.14.1 (verified against the running spire-server binary), gVisor runsc release-20260622, Kubernetes (kind).
Happy to share the minimal reproduction (two pods + one registration entry) if useful.
贡献指南
评估
这个 Issue 还没有评估数据。