feat(server): v2 secure-session-core Task 2 - auth rebuild
SPEC-002 Phase 1 Task 2 (specs/v2-secure-session-core), code-reviewed APPROVED. - DELETE the JWT-as-agent-key branch in relay validate_agent_api_key (audit CRITICAL): agent auth now = per-agent cak_ key (SHA-256 -> connect_agent_keys, revoked filtered) OR support code OR deprecated shared AGENT_API_KEY (warned). A user JWT can no longer authenticate an agent. - auth/agent_keys.rs: cak_ gen (OsRng 256-bit) + SHA-256 hash + verify. - auth/jwt.rs: ViewerClaims + create/validate_viewer_token (5-min TTL, purpose=viewer, session_id+tenant_id claims; non-interchangeable with login). - Admin key issuance: POST/GET/DELETE /api/machines/:agent_id/keys. - POST /api/sessions/:id/viewer-token mints a session-bound short-lived token. - Migration 005: organization/site/tags on connect_machines (fixes the silent update_machine_metadata write, coord todo faf39fe0). NOTE: viewer-token minting is gated by AuthenticatedUser only; the AUTHORIZATION check (admin/permission gate) that closes audit CRITICAL #1 lands in Task 3 (the viewer WS verification). The viewer WS path (relay/mod.rs:285) is untouched here. Not cargo-check-verified (no toolchain on the authoring host) - self-reviewed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -312,6 +312,11 @@ async fn main() -> Result<()> {
|
||||
.route("/api/sessions", get(list_sessions))
|
||||
.route("/api/sessions/:id", get(get_session))
|
||||
.route("/api/sessions/:id", delete(disconnect_session))
|
||||
// Session-scoped viewer-token minting (dashboard JWT; bound to one session)
|
||||
.route(
|
||||
"/api/sessions/:id/viewer-token",
|
||||
post(api::sessions::mint_viewer_token),
|
||||
)
|
||||
// REST API - Machines
|
||||
.route("/api/machines", get(list_machines))
|
||||
.route("/api/machines/:agent_id", get(get_machine))
|
||||
@@ -321,6 +326,21 @@ async fn main() -> Result<()> {
|
||||
"/api/machines/:agent_id/update",
|
||||
post(trigger_machine_update),
|
||||
)
|
||||
// Per-agent key issuance (admin only). `:agent_id` matches the param
|
||||
// name used by the other /api/machines/:agent_id routes — matchit 0.7
|
||||
// panics if the same path position uses two different param names.
|
||||
.route(
|
||||
"/api/machines/:agent_id/keys",
|
||||
post(api::machine_keys::create_key),
|
||||
)
|
||||
.route(
|
||||
"/api/machines/:agent_id/keys",
|
||||
get(api::machine_keys::list_keys),
|
||||
)
|
||||
.route(
|
||||
"/api/machines/:agent_id/keys/:key_id",
|
||||
delete(api::machine_keys::revoke_key),
|
||||
)
|
||||
// REST API - Releases and Version
|
||||
.route("/api/version", get(api::releases::get_version)) // No auth - for agent polling
|
||||
.route("/api/releases", get(api::releases::list_releases))
|
||||
|
||||
Reference in New Issue
Block a user