kubectl "Error from server (Forbidden)" - Fix RBAC in CI
Kubernetes authenticated the request but RBAC denied it. The identity CI uses has no Role/ClusterRole granting the verb on that resource in that namespace.
What this error means
kubectl reports Error from server (Forbidden): <resource> is forbidden: User "<id>" cannot <verb> resource "<res>". Authentication succeeded. This is an authorization (RBAC) failure, not a credentials problem.
Error from server (Forbidden): deployments.apps is forbidden: User
"system:serviceaccount:ci:deployer" cannot create resource "deployments" in API
group "apps" in the namespace "prod"Common causes
Missing RoleBinding for the verb/resource
The ServiceAccount has no Role/ClusterRole binding granting that verb (create/list/patch) on that resource. The message names exactly what was denied.
Right permission, wrong namespace
A namespaced RoleBinding grants access in one namespace but the action targets another. Cluster-wide access needs a ClusterRoleBinding.
How to fix it
Confirm what is missing with auth can-i
Check the exact verb/resource for the identity CI uses before changing any RBAC.
kubectl auth can-i create deployments \
-n prod --as=system:serviceaccount:ci:deployerGrant a least-privilege Role and bind it
Create a Role scoped to exactly the verbs/resources the pipeline needs, then bind the ServiceAccount.
kubectl create role deployer -n prod \
--verb=get,list,create,patch --resource=deployments,replicasets,pods
kubectl create rolebinding ci-deployer -n prod \
--role=deployer --serviceaccount=ci:deployerHow to prevent it
- Define least-privilege Roles for CI ServiceAccounts and review them in version control.
- Use
kubectl auth can-iin a pre-flight step to catch gaps before the deploy. - Match the binding scope (Role vs ClusterRole) to where the actions run.