Skip to main content

kube-escalate

Just-in-Time privilege escalation for Kubernetes. Grant temporary, time-limited cluster access with automatic expiry, a full audit trail via Kubernetes Events, and Prometheus metrics — no CRDs, no database, no external dependencies.

Instead of standing cluster-admin for anyone who might occasionally need it, users request an elevated role for a bounded window. The role is removed automatically when the window closes.

Is this for you?​

✅ Good fit❌ Not a fit
You need temporary cluster-admin access without a permanent bindingYou need multi-person approval workflows
Your cluster's API server trusts OIDC, X.509 client certs, or any other authenticatorYou want a Web UI or dashboard
You want automatic expiry enforced by the cluster, not a calendar reminderYou need per-role or per-user TTL policy (v1 enforces one global ceiling)
You want a full audit trail without an external log store for events aloneYou need Kubernetes < 1.26
You run Kubernetes on any distribution (RKE2, EKS, GKE, AKS, …)

Quickstart​

# 1. Install the operator
helm install kube-escalate oci://ghcr.io/layer87-labs/charts/kube-escalate \
--namespace kube-escalate --create-namespace

# 2. Install the plugin (Linux amd64) — a client-side binary, no archive
VERSION=0.5.0
gh release download "$VERSION" --repo layer87-labs/kube-escalate \
--pattern "kubectl-escalate_${VERSION}_linux-amd64" --pattern 'sha256sum.txt'
grep "kubectl-escalate_${VERSION}_linux-amd64$" sha256sum.txt | sha256sum -c -
install -m 0755 "kubectl-escalate_${VERSION}_linux-amd64" ~/.local/bin/kubectl-escalate

# 3. See where you may escalate to
kubectl escalate targets

# 4. Escalate for 1 hour
kubectl escalate \
--to cluster-admin \
--duration 1h \
--reason "Deploying CNPG update"

Revoke the escalation when you are done — or wait for automatic expiry.

Installing the operator alone grants nothing

The operator only enforces the TTL on bindings that already exist — it never grants anyone the ability to create one. Before anyone can run kubectl escalate, you must give them RBAC to do so, and you should install the hardening ValidatingAdmissionPolicy alongside it. Both are covered in RBAC prerequisites and Hardening — read those before rolling this out to real users.

How it works​

  1. The plugin calls the Kubernetes SelfSubjectReview API to resolve your identity. The API server populates the response from your validated token — it cannot be forged via CLI arguments.
  2. The plugin creates a standard ClusterRoleBinding (cluster-wide) or RoleBinding (with --namespace), labelled kube-escalate/managed=true and annotated with the expiry timestamp, your identity, and your reason. The binding grants the role immediately.
  3. The operator watches every object carrying that label, enforces a TTL ceiling, deletes the binding on expiry, and emits Kubernetes Events and Prometheus metrics for every lifecycle transition.
kubectl escalate ──► SelfSubjectReview ──► ClusterRoleBinding / RoleBinding
(verified identity) kube-escalate/managed=true
expires-at annotation
│
operator reconciler
enforces the TTL ceiling
deletes on expiry
emits Kubernetes Events

Feature overview​

FeatureDetails
Tamper-proof identityCaller resolved via SelfSubjectReview — API server verifies the token, identity can't be supplied by the caller
Automatic expiryOperator requeues at exactly the effective expiry instant; no polling gap
TTL ceilingOperator clamps any requested expiry beyond maxDuration (default 24h), cluster-wide
Finalizer lifecycleDistinguishes TTL expiry from manual revocation; correct metrics and events in both cases
Kubernetes EventsEscalationExpired, EscalationRevoked, EscalationClamped emitted on every lifecycle change
Prometheus metricsactive_escalations gauge, escalations_total, expired_total, revoked_total, duration_seconds
No CRDUses standard ClusterRoleBinding / RoleBinding — works on any CNCF-conformant cluster
No databaseAll state lives in Kubernetes etcd
Provider-agnostic identityWorks with any OIDC provider, or X.509 client certs, trusted by the API server
HA operatorLeader election, PodDisruptionBudget, configurable replica count
Namespace-scoped--namespace <ns> creates a RoleBinding instead of a ClusterRoleBinding

Components​

ComponentDescription
Operatorcontroller-runtime Deployment — watches managed bindings, enforces the TTL ceiling
kubectl-escalatekubectl plugin — escalate, status, revoke subcommands
Helm chartInstalls the operator with RBAC, probes, metrics, PDB, NetworkPolicy

kube-escalate ships no admission webhook, CRD, or database. The security boundary is native Kubernetes RBAC, optionally hardened with a ValidatingAdmissionPolicy — see Hardening.