mirror of
https://github.com/sredevopsorg/deepseek-kubernetes-sandbox.git
synced 2026-11-03 01:13:24 +00:00
fix(gateway)!: replace token cookies with revocable sessions and harden abuse controls
- Replace user:token cookies with opaque server-side sessions, revocable on logout, delete, recreate and expiry; bind every credential to the path user and add cross-user regression tests. - Rate-limit /users and /login, add optional signup invite codes and form same-origin checks, and unify login failures to 401. - Require explicit ALLOW_INSECURE_COOKIES for plain HTTP, use __Host-dsh_gw_session when secure, and fix secure cookie deletion. - Strip client-supplied forwarding/SSO headers, add an optional upstream allowlist, per-user in-flight and WebSocket message caps, credential-free handshake errors, and sweep-time state pruning. - Digest-pin base images, hash-pin gateway dependencies, verify DSH_COMMIT in the build, and run the gateway image as non-root with a pinned Python base. - Update manifests, production checklist, architecture/security docs and add an SSO preflight script. BREAKING CHANGE: existing dsh_gw_session=<user>:<token> cookies are invalid; users must sign in again. Unknown users on POST /login now return 401 instead of 404, and the gateway refuses COOKIE_SECURE=false unless ALLOW_INSECURE_COOKIES=1.
This commit is contained in:
38
SECURITY.md
38
SECURITY.md
@@ -22,22 +22,40 @@ disclosure once a fix is available.
|
||||
tenant. Keep the gateway's RBAC namespace-scoped and treat pod logs as
|
||||
sensitive. Replacing log scraping with an upstream token API is tracked in
|
||||
the [example architecture document](examples/dsh-agents-as-a-service/docs/architecture.md#upstream-feature-request-remove-log-scraping).
|
||||
- **Browser sessions are server-side.** The gateway session cookie holds an
|
||||
opaque session id, not a user name or token; it is not accepted as a bearer
|
||||
token. Sessions are revoked on logout, user delete, `/recreate` and expiry,
|
||||
but they live in gateway memory, so a gateway restart logs every browser out
|
||||
and scaling beyond one replica requires a shared store. Do not treat the
|
||||
cookie as durable or cross-replica state.
|
||||
- **SSO header trust boundary.** AUTH_PROXY_HEADER makes the gateway trust an
|
||||
identity header (for example X-Forwarded-User). Enable it only when the
|
||||
gateway Service is reachable exclusively through the authenticating proxy;
|
||||
otherwise any client can spoof the header. The SSO exposure variant ships a
|
||||
NetworkPolicy that restricts gateway access to oauth2-proxy pods; a custom
|
||||
exposure needs an equivalent.
|
||||
gateway Service is reachable exclusively through the authenticating proxy
|
||||
and its NetworkPolicy; otherwise any client can spoof the header. The SSO
|
||||
exposure variant's policy is required, not optional: an exposure without it
|
||||
is demo-only. Run `examples/dsh-agents-as-a-service/scripts/preflight-sso.sh`
|
||||
after applying the variant; it checks the Secrets, gateway env, TLS
|
||||
reference, leftover placeholders and accidental second paths.
|
||||
- **Insecure-cookie guard.** TLS terminates outside the gateway. Set
|
||||
COOKIE_SECURE=true for HTTPS and remove ALLOW_INSECURE_COOKIES; the gateway
|
||||
refuses to start with COOKIE_SECURE=false unless ALLOW_INSECURE_COOKIES=1 is
|
||||
explicitly set, which exists only for the plain-HTTP local demo. Never expose
|
||||
that combination outside localhost.
|
||||
- **Abuse controls are in-process.** AUTH_RATE_LIMIT/AUTH_RATE_WINDOW,
|
||||
SIGNUP_INVITE_CODE, MAX_IN_FLIGHT_PER_USER and WS_MAX_MESSAGE_BYTES bound
|
||||
casual abuse and resource exhaustion on the single gateway replica. They
|
||||
reset on restart and are not an ingress rate limiter, WAF, quota system or
|
||||
audit log; add those for an internet-facing deployment.
|
||||
- **Shared provider keys.** The example injects DEEPSEEK_API_KEY and any keys in
|
||||
the optional dsh-provider-keys-extra Secret into every tenant sandbox (a
|
||||
warm-pool constraint). Treat tenants as mutually trusting until per-tenant
|
||||
credentials or an egress proxy exist.
|
||||
- **Optional isolation is opt-in.** gVisor, nodeSelector, the sandbox/exposure
|
||||
NetworkPolicies and extra provider keys are opt-in. Without a
|
||||
NetworkPolicy-capable CNI or a gVisor runtime, the base example is not
|
||||
tenant-isolated; see examples/dsh-agents-as-a-service/docs/optional-hardening.md.
|
||||
- **TLS is external.** Terminate TLS at an Ingress or Gateway and set
|
||||
COOKIE_SECURE=true. Plain HTTP outside localhost exposes session cookies.
|
||||
- **The base example is demo-only, not hardened.** gVisor, nodeSelector, the
|
||||
sandbox/exposure NetworkPolicies, the gateway egress policy and extra provider
|
||||
keys are opt-in. Without gVisor and the network policies there is no
|
||||
tenant-to-tenant isolation; the sandboxes share the host kernel and can reach
|
||||
cluster-internal endpoints. Production requirements are enumerated in the
|
||||
[production checklist](examples/dsh-agents-as-a-service/docs/optional-hardening.md#6-production-checklist).
|
||||
- **No secrets in the repository.** The repository only ships empty Secret
|
||||
manifests and *.yaml.example files.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user