feat(server): mTLS client-cert agent identity, remove agentcore.c handshake (VS-63) #86
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/VS-63-remove-agent-handshake"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Completes the last open acceptance criterion of VS-63 (AC5: remove the
agentcore.chandshake). ACs 1-4 (agent CA, enrollment token, CSR-signing endpoint) shipped in #83; AC5 was deferred because it was coupled to the agent mTLS listener, which has since landed in VS-62 (#84). This makes the verified mTLS client cert the sole agent identity and deletes the handshake.What changed
agent_identity::AgentCertAcceptor(new) wraps the rustls acceptor on the agent listener: after the TLS handshake it reads the verified leaf certificate off the negotiated connection and injects it into request extensions asAgentClientCert. The listener'sWebPkiClientVerifier(VS-62) already guarantees that leaf chains to the dedicated agent CA; axum-server's default connect-info only plumbs the peerSocketAddr, so this wrapper is what surfaces the cert to the handler.agent_ws_handlerderives the node id from the leaf CommonName (the value the agent CA stamps from the CSR subject, perAgentCa::sign_csr) and rejects any agent connection that arrives without a verified client cert.agent::handle_sessionno longer runs a handshake. Identity comes from the cert; the agent's first frame isAuthInfo, which now carries registration metadata only (group id, capabilities, hostname, platform, version) since the connection is already authenticated by mTLS. OnAuthInfothe node is registered and marked online. Subsequent post-auth frames dispatch exactly as before.agent_handshake.rsis deleted (theAuthRequest/AuthVerify/ServerId/ServerIdHintserver handling plus its 997 lines of tests). The wire structs stay invervain-agent-protountil the agent half (VA-67) drops them.Contract for VA-67
The post-mTLS registration contract the agent must speak: connect over mTLS with the enrolled client cert (CN =
node//<hash>), then send a singleAuthInfoframe. No challenge-response. This unblocks VA-67, which was correctly blocked on this server half being undelivered.Tests
agent_identityunit tests: CommonName extraction for valid, empty, and garbage certs.agent_mtlstest: drives a real WebSocket over mTLS with an agent-CA-issued client cert, sends onlyAuthInfo, and asserts the node row is registered under the cert's CN with the reported group id.just pre-commitgreen (fmt, clippy-D warnings, build, tests).Follow-up
The now-inert
settings.tls.insecureSkipHashCheckconfig knob and theagent_skip_hash_checkfields were left in place to keep this change bounded; their removal (plus the orphanedvervain_agent_handshake_failed_totalmetric) is tracked in VS-66.🤖 Generated with Claude Code