Security Model
Defense layers
Section titled “Defense layers”| Layer | Protection |
|---|---|
| Network | NetworkPolicy (deny all ingress by default), optional TLS |
| Transport | HSTS, secure cookies, compression after ETag |
| Authentication | OIDC / impersonation / local modes, HMAC-SHA256 sessions |
| Authorization | Kubernetes RBAC via user impersonation |
| Input validation | K8s name validation, PromQL sanitization, body size limits |
| CSRF | Non-simple header required for mutations |
| Rate limiting | Per-IP token bucket (100/s, burst 200) |
| XSS | CSP with nonces, security headers |
| Secrets | Never logged, crypto/rand only |
| Session | Revocation deny-list, configurable TTL, HttpOnly/Secure/SameSite=Strict |
Authentication modes
Section titled “Authentication modes”| Mode | Use case | Mechanism |
|---|---|---|
local | Development | All requests as "local-user" with "system:masters" group |
oidc | Production | JWT Bearer token validated against OIDC provider (JWKS refreshed periodically) |
impersonation | Behind proxy | X-Forwarded-User / X-Forwarded-Groups from trusted proxies (CIDR allowlist) |
Kubernetes impersonation
Section titled “Kubernetes impersonation”All K8s mutations use user impersonation:
KubeGlass ServiceAccount → Impersonate-User: <userID> → Impersonate-Group: <group1>, <group2> → K8s API evaluates against user's RBAC rulesThe service account needs impersonate verb on users and groups resources.
What’s impersonated vs. not
Section titled “What’s impersonated vs. not”| Operation | Client used | Reason |
|---|---|---|
| Create, delete, patch, exec, cordon, drain | Impersonated | User’s RBAC enforced |
| List, get, watch | Service account | Full cluster visibility for shared dashboards |
| Helm actions | Impersonated | Helm action config carries impersonation headers |
| WebSocket exec/streams | Impersonated | Dynamic/stream clients with user headers |
Threat model
Section titled “Threat model”| Threat | Mitigation |
|---|---|
| Compromised kubeconfig | Credential scrubbing after client init; tokens never logged; session-scoped storage |
| XSS / DOM injection | CSP nonce-based policy; HttpOnly/Secure/SameSite=Strict cookies |
| WebSocket hijack | Origin validation; name validation before watch/exec; per-user impersonation |
| PromQL injection | Two-layer sanitization (regex reject + allowlist); 64KB/4096 char limits; 30-day range cap |
| Session fixation | Per-tab sessionStorage; HMAC-SHA256 signing; server-side revocation |
| RBAC case confusion | Case-insensitive subject matching with warn log on mismatch |
| Helm/exec bypass | Impersonation headers on all Helm configs and exec REST configs |
| Denial of service | Per-IP rate limiting; paginated listing; batched pruning; bounded queues |
| Supply chain | go.sum + package-lock.json committed; govulncheck + npm audit in CI; Cosign + SLSA L3 |
Input validation
Section titled “Input validation”All API boundary inputs are validated:
- K8s names -
validateK8sName()rejects names with path traversal, unicode tricks, or invalid characters - Namespaces - Same validation as resource names
- PromQL - Two-layer sanitizer: regex blocklist + allowlist; size/complexity/time-range limits
- WebSocket params - Name validation before watch/exec upgrade
- Request bodies - Size limit (1 MiB default), JSON parsing with strict decoder
HTTP server timeouts
Section titled “HTTP server timeouts”| Timeout | Value | Rationale |
|---|---|---|
| ReadTimeout | 15s | Full request read deadline |
| ReadHeaderTimeout | 5s | Slowloris defense |
| WriteTimeout | 0 | WebSocket/SSE need indefinite lifetimes |
| IdleTimeout | 120s | Keep-alive idle |
| MaxHeaderBytes | 1 MB | Header size limit |
WriteTimeout is disabled at server level. REST API protection uses http.TimeoutHandler
per-route (30s) for API endpoints specifically.
Related
Section titled “Related” Multi-Tenancy Per-user isolation with RBAC enforcement
Data Flow Middleware pipeline and session management
Configuration Auth mode, TLS, and rate limit settings