DEV Community

jai sandesh
jai sandesh

Posted on

Zero-Trust in Practice: Enforcing Time-Bound RoleBindings with Kyverno

👨‍💻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

  1. Give Kyverno permission to delete RoleBindings and ClusterRoleBindings.
  2. Use Kyverno’s built-in cleanup capability (cleanup.kyverno.io/ttl) to define expiration times.
  3. 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

Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
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
Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

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)