feat(casan): establish assurance kernel and harden control plane

This commit is contained in:
thanhnv
2026-08-02 23:24:51 +07:00
parent 8b477f3800
commit 5745519126
51 changed files with 4076 additions and 180 deletions
+23 -13
View File
@@ -10,20 +10,26 @@ This document defines the boundary between the local workstation experience and
flowchart LR
B["Browser"] -->|TLS + OIDC cookie| N["Nginx"]
N -->|auth_request| O["oauth2-proxy"]
N -->|overwritten identity headers| A["Control Panel API"]
N -->|signed bearer token; identity headers removed| A["Control Panel API"]
A -->|verify RS256 + issuer + audience + time claims| I["VerifiedClaims"]
A -->|tenant-scoped encrypted store| S["CASAN state"]
A -->|random bridge token, local only| H["Mac host bridge"]
H -->|official CLI auth| P["Codex / Claude"]
```
The API must not be published directly. Nginx is the only ingress and overwrites `X-CASAN-Actor`, `X-CASAN-Groups`, and `X-CASAN-Role`. The API refuses a non-loopback strict bind unless `CASAN_CP_TRUST_AUTH_PROXY=1` is explicit.
The API must not be published directly. Nginx is the only ingress and removes
`X-CASAN-*` and forwarded identity headers. The API refuses every production or
non-loopback bind unless `CASAN_CP_AUTH_MODE=jwt` has a valid cryptographic
verifier. Proxy headers alone are never authenticated identity.
## Implemented controls
- TLS at Nginx; production accepts only TLS 1.2/1.3.
- OIDC authentication through oauth2-proxy.
- Secure, HttpOnly, SameSite=Lax session cookies with bounded expiry/refresh.
- Browser-supplied identity headers are overwritten at Nginx.
- Browser-supplied identity headers are removed at Nginx.
- The API verifies RS256 signature, issuer, audience, subject, expiry,
not-before/issued-at bounds and clock skew before deriving request identity.
- CSP, frame denial, MIME sniffing protection, referrer and browser permission restrictions.
- API request body capped at 1 MiB.
- SSE buffering disabled for trace streams; no intermediate proxy cache.
@@ -53,21 +59,26 @@ Before production deployment:
2. Do not deploy `provider-auth-bridge.py`.
3. Use managed OpenAI/Anthropic credentials from Vault/KMS or workload identity.
4. Use an enterprise IdP and explicit group-to-role mapping.
5. Use a CA-issued certificate and a fixed production hostname.
6. Set a digest-pinned `CASAN_CP_API_IMAGE`, `CASAN_CP_UI_IMAGE`, and `CASAN_CP_OAUTH2_PROXY_IMAGE`.
7. Keep the API on a private container/network segment with Nginx as its only caller.
8. Restrict egress from the API to allowlisted model providers, Vault/KMS, object storage and required observability endpoints.
9. Store state on encrypted storage; send audit heads to KMS/WORM/Object Lock.
10. Export rate-limit, auth failure, bridge-disabled and audit-chain metrics to alerting.
11. Back up and restore-test tenant state before enabling write actions.
12. Run the production preflight and security suites against the exact deployment images.
5. Mount the IdP RS256 public key and configure exact issuer/audience; coordinate
key rotation with an API restart until JWKS rollover is implemented.
6. Use a CA-issued certificate and a fixed production hostname.
7. Set a digest-pinned `CASAN_CP_API_IMAGE`, `CASAN_CP_UI_IMAGE`, and `CASAN_CP_OAUTH2_PROXY_IMAGE`.
8. Keep the API on a private container/network segment with Nginx as its only caller.
9. Restrict egress from the API to allowlisted model providers, Vault/KMS, object storage and required observability endpoints.
10. Store state on encrypted storage; send audit heads to KMS/WORM/Object Lock.
11. Export rate-limit, auth failure, bridge-disabled and audit-chain metrics to alerting.
12. Back up and restore-test tenant state before enabling write actions.
13. Run the production preflight and security suites against the exact deployment images.
## Known residual risks
- Local bridge authorization is bearer-token based; a process with access to the token file can call it.
- In-memory rate windows reset when the API or bridge restarts. Production should also rate-limit at ingress.
- Goal output is stored in tenant-scoped local state but is not currently envelope-encrypted as a whole.
- A compromised container on the private Control Panel network may attempt to forge proxy headers. Production network policy must keep unrelated workloads off that network.
- Static public-key rotation requires a coordinated file replacement and API
restart; automated JWKS rollover is not implemented.
- A compromised ingress container can interfere with availability or bearer
forwarding, but cannot mint a valid IdP signature without the IdP key.
- Developer account subscriptions have provider-specific quotas and are not an availability SLA.
- The local mock IdP and self-signed TLS do not prove enterprise SSO readiness.
@@ -83,4 +94,3 @@ packages/casan-harness/scripts/bash/local-full.sh start
This terminates the bridge, deletes the old token and creates a new one. Then inspect `tmp/control-panel-local/auth-bridge/model-audit.jsonl` for unexpected provider/status/hash activity. The log contains no raw prompts.
If a goal audit chain is suspected of tampering, stop new goal submissions, preserve `.specify/logs/audit/goal-orchestrator.jsonl` and its head, and compare each `prev_hash`/`record_hash` before restoring service.