Files
orca/internal/engine/actor.go
T
Jon Chery 5232fcb808 fix(P04): wire ACL enforcement + WebAuthn reg auth + audit actor (REQ-153)
R-023: Zero-trust enforcement operationally wired.

ACL enforcement (C-45 staged rollout):
- acl.Check wired into all 5 daemon handlers (dispatch/jobs/nodes/tasks)
- health endpoints exempt (liveness probes not gated)
- ACL log-only mode default (config acl.enforce=false); enforce after
  bootstrap ACL verified
- sshpush auth: ORCA_OIDC_TOKEN validated against JWKS before apply
- txn apply: Authorize hook validates OIDC token before running pull
- acl.json mode 0600 (was 0644)
- flock on acl.json for concurrent grant/revoke
- bootstrap ACL: init grants cluster-admin to orca-admins group + SVID

Audit actor identity:
- currentActor reads OIDC sub from credentials.json (was hardcoded "cli")
- threaded through all audit.Record calls via context

WebAuthn registration auth:
- BeginRegistration/FinishRegistration require authenticated session
- fail-closed 401 when no authFunc configured

New files: internal/daemon/acl.go, internal/cli/authactor.go,
internal/engine/actor.go, internal/identity/authtoken.go,
internal/sshpush/auth.go, internal/txn/auth_test.go

---ci---
project: orca
phase: 4
milestone: v0.13
status: complete
requirements:
  covered: [153]
---/ci---
2026-08-07 20:33:39 +00:00

34 lines
1.1 KiB
Go

// Package engine — actor.go provides the context key + helper for
// threading the audit actor (OIDC sub or SPIFFE SVID) through the
// engine layer (P04, T5; C-44). Previously the registry hardcoded
// "cli" as the actor; this lets CLI commands inject the verified
// operator identity via context so audit entries attribute actions
// to the real human/operator.
package engine
import "context"
// actorCtxKey is the context key for the audit actor.
type actorCtxKey struct{}
// WithActor returns a context carrying the audit actor. The CLI
// calls this in PersistentPreRun after resolving the OIDC sub from
// the credentials file. When the context carries no actor, the
// registry falls back to "cli" (legacy).
func WithActor(ctx context.Context, actor string) context.Context {
if actor == "" {
return ctx
}
return context.WithValue(ctx, actorCtxKey{}, actor)
}
// ActorFromCtx returns the audit actor from the context, or "cli"
// when no actor is set (legacy fallback for paths that haven't been
// wired yet).
func ActorFromCtx(ctx context.Context) string {
if v, ok := ctx.Value(actorCtxKey{}).(string); ok && v != "" {
return v
}
return "cli"
}