Skip to content
Latchkey

kubectl "attempting to grant RBAC permissions not currently held" in CI

Kubernetes prevents privilege escalation: you cannot create a Role/RoleBinding that grants permissions you do not already hold (unless you have the escalate/bind verb). A CI identity creating a broad binding it cannot itself perform is rejected by this guard.

What this error means

kubectl apply of a Role/ClusterRole or its binding fails with Error from server (Forbidden): user "..." (groups=...) is attempting to grant RBAC permissions not currently held. The identity authenticates fine - RBAC refuses to let it hand out rights it lacks.

kubectl output
Error from server (Forbidden): clusterroles.rbac.authorization.k8s.io "deployer"
is forbidden: user "system:serviceaccount:ci:bootstrap" (groups=["system:authenticated"])
is attempting to grant RBAC permissions not currently held:
{APIGroups:["apps"], Resources:["deployments"], Verbs:["*"]}

Common causes

Creating a binding broader than the creator

The escalation-prevention guard blocks creating a Role/binding whose rules exceed what the creating identity already has, to stop a low-privilege account from granting itself more.

Bootstrap identity lacks escalate/bind

Granting rights you do not hold requires the escalate (for roles) or bind (for bindings) verb on the relevant role. A CI bootstrap SA without those cannot install RBAC.

How to fix it

Grant the installer identity sufficient rights

Give the CI bootstrap identity the permissions it needs to grant (or the bind/escalate verb on the specific role) - deliberately and scoped.

Terminal
# allow binding a specific clusterrole without holding all its perms
kubectl create clusterrole bind-deployer --verb=bind \
  --resource=clusterroles.rbac.authorization.k8s.io --resource-name=deployer
kubectl create clusterrolebinding ci-bind --clusterrole=bind-deployer \
  --serviceaccount=ci:bootstrap

Or apply RBAC with an authorized identity

  1. Have RBAC manifests applied by an identity that already holds the granted permissions (or is admin), e.g. a one-time bootstrap by a human/admin pipeline.
  2. Keep the routine deploy SA scoped to non-RBAC actions.
  3. Check with kubectl auth can-i that the installer holds what it tries to grant.

How to prevent it

  • Separate RBAC installation (privileged bootstrap) from routine deploys (least-privilege).
  • Use the narrow bind/escalate verb on specific roles instead of broad admin.
  • Keep RBAC manifests in version control and apply them with an appropriately authorized identity.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →