Daevix Docs

Attribution, not authentication

After reading this page you can explain how the enclave names the agent behind every connection and metadata request, and why that naming rests on where the agent runs instead of a secret that the agent presents.

View as Markdown Edit on Tangled

The rule that shapes identity

Daevix runs arbitrary, untrusted customer code. An agent can read its own filesystem and environment, inspect its own memory, and try to reach the network. The platform observes and governs that code, so whoever controls the code benefits from escaping that observation.

That threat model leads to one rule: the agent does not hold a credential. If it did, an attacker who owned the agent could exfiltrate and replay it. Authentication requires the caller to present something. An attacker who owns the agent can also present anything that the agent can present.

So the enclave does not authenticate agents. It attributes every action to an agent using properties of where the agent runs, enforced by layers below the agent’s code: the per-agent socket mount, the Cilium datapath, and the provisioning-time hardware measurement. The agent presents nothing. Three enforcement planes carry this out.

Plane 1: the mount names the agent

The broker creates one IMDS unix socket per agent and mounts only that socket into that agent’s pod, at the well-known path /run/dvx/imds.sock. The broker owns the socket-to-agent mapping. Pod and VM isolation keep the agent from reaching any other agent’s socket.

When the agent asks its IMDS “who am I?”, the service answers from the mapping of the socket that the question arrived on. The identity signal is which listener the connection used. The socket mount carries the identity. Peer credentials on the socket are kept only as an optional sanity check, because peer pids and uids across the Kata VM boundary are virtualized and not meaningful.

The IMDS socket is local IPC inside the namespace. It is not network egress, so the egress policy of Plane 2 does not apply to it.

Plane 2: the datapath names the agent

Every agent runs in its own namespace with Cilium default-deny egress. The only permitted route out is through the enclave gateways. An agent’s code cannot route a packet anywhere else; the eBPF datapath drops it.

East-west traffic is not masqueraded, so the gateway sees each connection’s real pod IP as the TCP source. A pod IP alone is not an identity, so the gateway joins the source IP to an attribution index. The index is built from CiliumEndpoint objects, which carry the pod’s IPs, its Daevix labels, and its numeric Cilium security identity. Cilium validates that identity in the kernel, and the workload cannot forge it.

The join determines how the gateway audits the flow. A named connection is audited with actor: "agent:<uid>" plus the org and the numeric security_id. When attribution is in force and no agent endpoint claims the source IP, the gateway denies the flow with reason no_identity and audits the denial. The platform does not govern a flow that it cannot name, so an unnameable flow is denied rather than forwarded by source IP alone.

Mediation and attribution use the same mechanism. The same layer forces the path and names the agent.

Plane 3: the measurement anchors both planes

Planes 1 and 2 both rest on a mapping: this socket, or this Cilium identity, belongs to this agent. The broker establishes that mapping at provisioning, after it verifies a Kata TEE remote-attestation report against expected reference values. Only a pod whose measured guest matches gets a socket and a mapping. The agent never participates in its own enrollment, so there is no bootstrap secret to steal.

What attribution does not give you

Attribution establishes who did this for the enclave datapath. It does not give the agent a credential that it can present anywhere else. The distinction shows up whenever the platform itself needs a bearer token:

  • An external service that authenticates callers (a cloud API, the controlplane’s operator API) needs something to present. The trusted plane mints that credential (for the operator API, the controlplane mints it and the gateway fetches and presents it), so the agent still holds nothing. See Agent as operator for the operator API case.
  • The controlplane records the actor kind from the credential, not from client input. An agent-operator token authenticates as kind agent-operator, and the audit actor renders as agent:<uid>; a human token renders as user:<uid>. A caller cannot choose its own kind.
  • Attribution ends at pod teardown. The identity is the socket, the Cilium identity, and the measured guest, so removing the pod removes all three in the same operation. There is no secret to rotate and none to revoke.

Authentication proves a claim that a caller carries. Attribution observes where the action physically came from. Daevix relies on attribution for the datapath and mints authentication, briefly, only inside the trusted plane when an external boundary requires it.