Access & Exposure¶
Two coupled hardening controls, both Free on every install: an in-product IP access layer (allowlist / denylist / auto-ban) with a sliding idle timeout, and a service-only exposure mode so you can front KubeManta with your own edge/WAF.
Defense in depth, not a WAF
App-level IP filtering has no L7 pattern detection, no DDoS absorption, and no geo-fencing. For internet-facing production, put a real edge/WAF in front — service-only mode (below) is designed to make that easy.
In-product IP access control¶
IP access control runs before authentication, so a denied IP is rejected with a flat 403 before any login work happens. It resolves the real client IP (honoring security.trustedProxyCidrs) and evaluates it against a policy that is stored encrypted at rest in-cluster.
Policy¶
| Field | Meaning |
|---|---|
allowlist |
If non-empty, only these IPs/CIDRs are allowed. Empty = allow all. |
denylist |
Always wins — a denylisted IP is blocked even if allowlisted. |
auto_ban |
Per-trigger threshold / window / ban-duration for failed_login, auth_flood, rate_abuse. |
session_idle_timeout |
Sliding idle timeout in seconds (see below). |
Live bans¶
Auto-ban hits and manual bans are recorded durably, each with a reason, a hit count, and an expiry (a ban with no expiry is permanent). Bans survive pod restarts.
Login lockout attributes failures to the real client IP and feeds the failed_login trigger, producing a durable auto-ban.
Fail-safe & exemptions¶
- Fail-safe: any config-load or DB error degrades to allow-all (today's behavior) — never lock-all.
- Always exempt: loopback and RFC1918 private ranges, so
kubectl exec/port-forwardcan never be locked out. /healthzis always skipped;/auth/*is not (so a banned IP can't even reach the login form).
Admin API¶
| Endpoint | Purpose |
|---|---|
GET/PUT /admin/access-control |
Read / write the policy. |
POST /admin/access-control/bans |
Add a manual ban. |
DELETE /admin/access-control/bans/{ip} |
Lift a ban. |
All admin-gated, and surfaced in Admin → Access Control.
Anti-lockout escape hatch¶
If you lock yourself out, a CLI escape hatch ships day one:
kubectl exec -n kubemanta-system deploy/kubemanta-agent -- python3 -m app.clear_bans
# add --reset-policy to also reset access_control back to allow-all
Sliding idle timeout¶
Sessions carry a last-activity marker, so the idle timeout is enforced on every request:
- A session that has been idle longer than
session_idle_timeoutis rejected (401); an active session is transparently extended (sliding). - The absolute 24-hour session lifetime is the hard ceiling — both checks apply, the stricter one wins.
Seed it with security.sessionIdleTimeout (default 1800); it's runtime-editable in Admin → Access Control (the stored value wins after first load).
sessionIdleTimeout: 0 disables the idle check
0 must render as SESSION_IDLE_TIMEOUT="0" (disabled) — the absolute 24-hour TTL still applies. A client-side inactivity timer in the UI is the UX layer; this server-side check is the backstop.
Service-only exposure (ingress.enabled=false)¶
Set ingress.enabled=false to render only the agent + UI Services — no Ingress, BackendConfig, or ManagedCertificate. Point your own ingress / load balancer / Gateway / WAF at them.
ingress:
enabled: false
service:
type: ClusterIP # or NodePort | LoadBalancer
annotations: # e.g. internal-only LB
networking.gke.io/load-balancer-type: "Internal"
ui:
service:
type: ClusterIP
annotations: {}
Routing when you front it yourself:
- The terminal WebSocket path
/api/agent/terminal/wsmust reach the agent Service directly. - All other traffic goes to the UI Service.
You MUST set security.trustedProxyCidrs
Service-only mode is only correct if security.trustedProxyCidrs is set to your edge's egress CIDR(s). Otherwise KubeManta attributes every request to the proxy IP — collapsing audit attribution and letting one client's failed logins auto-ban the shared edge IP for everyone.
KubeManta only trusts X-Forwarded-For when the socket peer is inside one of these CIDRs, and then takes the rightmost untrusted address — so a direct caller cannot spoof its identity.
Out of scope¶
MFA and BYO ingress-class passthrough / Gateway API HTTPRoute / attach-to-existing-LB are deferred. For identity-provider login see Enterprise SSO.