👨‍💻Intro
Temporary admin access in Kubernetes is messy.You grant a RoleBinding for debugging and forget to remove it congratulations, you now have a hidden cluster admin forever.
I wanted to fix that with Kyverno no CronJobs, no cleanup scripts.
This guide explains how to enforce temporary RoleBindings both at the cluster level and the namespace level, using Kyverno policies that clean up automatically.
⚙️ Why Kyverno?
Manual cleanup jobs are fragile.
They rely on human discipline, timing, and extra components like scripts or CronJobs.Kyverno solves this at the policy level by using its inbuilt features
It watches resources in real time and can automatically delete expired RoleBindings based on their labels.
No sidecars, no containers, no scripting just YAML that enforces itself.
🏗️ High-Level Overview
- Give Kyverno permission to delete RoleBindings and ClusterRoleBindings.
- Use Kyverno’s built-in cleanup capability (cleanup.kyverno.io/ttl) to define expiration times.
- Kyverno will automatically remove the temporary elevated access when the TTL expires.
đź”§ Implementation
Tested on:
Kyverno: v1.15.2
Kubernetes: v1.34
Step1: Install Kyverno
helm repo add kyverno https://kyverno.github.io/kyverno/
helm repo update
helm install kyverno kyverno/kyverno -n kyverno --create-namespace
Step2: Grant Cleanup Permissions
Kyverno’s cleanup controller requires permission to delete RoleBindings and ClusterRoleBindings.
Create a ClusterRole and bind it to Kyverno’s service account (kyverno-cleanup-controller) in the kyverno namespace.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: kyverno-cleanup-access
rules:
- apiGroups: ["rbac.authorization.k8s.io"]
resources:
- rolebindings
verbs:
- delete
- get
- list
- watch
- apiGroups: ["rbac.authorization.k8s.io"]
resources:
- clusterrolebindings
verbs:
- delete
- get
- list
- watch
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kyverno-cleanup-access-binding
subjects:
- kind: ServiceAccount
name: kyverno-cleanup-controller
namespace: kyverno
roleRef:
kind: ClusterRole
name: kyverno-cleanup-temp-access
apiGroup: rbac.authorization.k8s.io
Step3: Create Temporary RoleBindings
I’ll create a RoleBinding (and assume the Role already exists). For elevated access, I’ll use the built-in edit Role as the example.
kubectl create ns test-ns
kubectl create sa test
creating roles and rolebindings
kubectl create rolebinding edit-access-binding --clusterrole=edit --serviceaccount=test-ns:test --namespace=test-ns
kubectl create clusterrolebinding edit-access-clusterbinding --clusterrole=edit --serviceaccount=test-ns:test
Step4: Add TTL Labels
Label these RoleBindings with Kyverno’s built-in TTL label.
This determines how long they should exist before automatic cleanup.
kubectl label rolebinding edit-access-binding cleanup.kyverno.io/ttl=60m -n test-ns
kubectl label clusterrolebinding edit-access-clusterbinding cleanup.kyverno.io/ttl=60m
After 60 minutes, Kyverno will automatically delete both bindings — no scripts required.
đź§ľ Summary:
Kyverno natively supports automatic cleanup using the cleanup.kyverno.io/ttl label.
By granting it proper permissions, you can enforce expiration policies for RoleBindings, ClusterRoleBindings, or any other resources that need timed deletion.
This approach:
- Eliminates manual cleanup scripts
- Prevents forgotten privileged bindings
- Keeps your cluster secure and self-governing
No external scheduler. No drift. Just policy.
Top comments (0)