114 lines
4.3 KiB
Markdown
114 lines
4.3 KiB
Markdown
# CASAN Control Plane
|
|
|
|
Status: production-capable packaged authentication and trust configuration;
|
|
external infrastructure remains operator-provisioned.
|
|
|
|
## Deployment modes
|
|
|
|
### Local development
|
|
|
|
- Default bind: `127.0.0.1`.
|
|
- `CASAN_CP_AUTH_MODE=local` is allowed only on loopback and outside production.
|
|
- Local actor headers are explicitly development identity and are not a
|
|
production authentication claim.
|
|
|
|
### Networked or production
|
|
|
|
- `CASAN_CP_AUTH_MODE=jwt` is mandatory.
|
|
- Production requires RS256 verification, a mounted public key, exact issuer
|
|
and audience, and a clock skew from 0 through 300 seconds.
|
|
- Missing or invalid configuration refuses startup before NestJS listens.
|
|
- HS256 is retained only for deterministic non-production tests.
|
|
|
|
## Packaged identity boundary
|
|
|
|
```text
|
|
Browser
|
|
-> enterprise OIDC
|
|
-> oauth2-proxy session
|
|
-> Nginx auth_request
|
|
removes X-CASAN-* and forwarded identity headers
|
|
forwards signed Bearer access token
|
|
-> NestJS AuthProvider
|
|
verifies RS256 signature, iss, aud, sub, exp, nbf and iat
|
|
-> VerifiedClaims
|
|
-> CASAN RBAC role mapping and scoped request identity
|
|
```
|
|
|
|
Nginx is a TLS/session boundary, not the identity authority for the API. The
|
|
API ignores caller-supplied identity assertions and derives actor, role,
|
|
tenant and project only after token verification.
|
|
|
|
## Authentication implementation
|
|
|
|
`backend/src/common/auth-provider.ts` defines:
|
|
|
|
- `AuthProvider` and `JwtAuthProvider`.
|
|
- Typed `VerifiedClaims` and `AuthenticationDecision`.
|
|
- RS256/HS256 signature verification using Node's standard crypto APIs.
|
|
- Issuer, audience, expiry, not-before, issued-at and bounded-skew checks.
|
|
- Safe tenant/project syntax validation.
|
|
- Structured authentication audit evidence without raw tokens.
|
|
- Middleware that overwrites request identity only from verified claims.
|
|
|
|
`auth-context.ts` refuses direct header use in JWT mode unless the middleware
|
|
has marked the identity verified. Existing RBAC services then map verified
|
|
groups and continue to produce governance/authorization evidence.
|
|
|
|
## Production configuration
|
|
|
|
Required runtime variables:
|
|
|
|
```text
|
|
CASAN_PROFILE=prod
|
|
CASAN_CP_AUTH_MODE=jwt
|
|
CASAN_CP_JWT_ISSUER=https://...
|
|
CASAN_CP_JWT_AUDIENCE=...
|
|
CASAN_CP_JWT_PUBLIC_KEY_FILE=/run/casan-idp/idp-public.pem
|
|
CASAN_CP_JWT_ROLE_CLAIM=groups
|
|
CASAN_CP_JWT_TENANT_CLAIM=casan_tenant
|
|
CASAN_CP_JWT_PROJECT_CLAIM=casan_project
|
|
CASAN_CP_JWT_CLOCK_SKEW_SECONDS=60
|
|
```
|
|
|
|
The host path is configured as `CASAN_CP_IDP_PUBLIC_KEY` and mounted read-only.
|
|
oauth2-proxy must set xauthrequest output and pass the access token. Images for
|
|
API, UI and oauth2-proxy must be digest-pinned.
|
|
|
|
`production-preflight.sh` validates:
|
|
|
|
- TLS hostname, expiry and matching private key.
|
|
- IdP public key readability and RSA public-key format.
|
|
- HTTPS OIDC issuer, secure cookies and token forwarding.
|
|
- Matching oauth2-proxy client ID and API audience.
|
|
- Matching issuer and bounded JWT clock skew.
|
|
- External Vault/KMS signing and S3 Object Lock provider selection.
|
|
- Live short-lived non-root Vault token lookup.
|
|
- A real Object Lock COMPLIANCE anchor write.
|
|
- Digest-pinned images and valid Compose/Nginx configuration.
|
|
|
|
## Authentication evidence
|
|
|
|
Each production authentication decision appends a JSONL record under
|
|
`CASAN_STATE_ROOT/logs/auth/decisions.jsonl` with category, policy, decision,
|
|
reason, actor, issuer, scope and request method/path. Tokens and secrets are
|
|
never written. A failure to authenticate returns HTTP 401 with a stable reason
|
|
code; it is not converted to viewer access.
|
|
|
|
## Local production-like smoke
|
|
|
|
`docker-compose.control-panel.local.yml` uses the same bearer-token path. The
|
|
smoke script generates an ephemeral RSA keypair, mounts the private key into
|
|
the mock IdP and the public key into the API, and enables token forwarding.
|
|
This validates the boundary without treating the mock IdP as production.
|
|
|
|
## Residual limitations
|
|
|
|
- Public-key rotation currently requires replacing the mounted key and
|
|
restarting the API; automated JWKS discovery and rollover are not present.
|
|
- Enterprise IdP, managed TLS, Vault and S3 are not provisioned by the repo.
|
|
- Local tests validate crypto and provider contracts, but do not prove a real
|
|
tenant's claim mapping, token lifecycle, network policy or key rotation.
|
|
- The Control Plane is production-capable for this packaged deployment model;
|
|
it is not yet a universal multi-runtime scheduler or supervisor.
|