Kubernetes RBAC
How Kubernetes RBAC governs what telectl — and each of its Telegram users — is allowed to do. This is the security core of the bot.
The principle
telectl never decides who may do what. Kubernetes RBAC does.
The bot talks to the API server through client-go using the identities described below. For every operation, the API server evaluates RBAC for the impersonated identity and answers allow or deny. The bot has zero hardcoded permissions.
Two layers of RBAC
1. The bot’s own identity
The bot runs as one identity (a ServiceAccount in the cluster, or your kubeconfig user). That identity needs:
- read/write on the resources the bot manages (pods, deployments, …)
impersonateon the identities it will act as (for per-user RBAC)
The Helm chart generates this via rbac.create: true (a ClusterRole +
ClusterRoleBinding + the impersonate rule).
2. The impersonated identities (per-user RBAC)
When impersonation is on, each Telegram user maps to a K8s identity
(user + groups) via impersonation.user_mapping. The bot sends
Impersonate-User / Impersonate-Group headers, and the API server checks
that identity’s bindings.
| Object | Kind | Purpose |
|---|---|---|
readonly-user (SA) |
ServiceAccount | identity that only reads |
readonly-user (role) |
ClusterRole | get/list/watch only, no mutation, no /scale |
readonly-user (binding→SA) |
ClusterRoleBinding | direct checks --as=...:readonly-user |
readonly-user-group |
ClusterRoleBinding | binds the role to Group viewers — this is what impersonation matches |
admin-user (SA) |
ServiceAccount | identity with full access |
admin-user binding |
ClusterRoleBinding | SA → cluster-admin |
telectl-impersonator |
ClusterRole | lets the bot’s SA impersonate exactly admin-user, readonly-user, sa:readonly |
telectl-impersonator binding |
ClusterRoleBinding | binds the role to the bot SA |
The critical gotcha: SA binding vs Group binding
There are two ways to bind a role, and mixing them up breaks impersonation:
- Bind a ServiceAccount → matches an identity acting as that SA.
- Bind a Group (e.g.
viewers) → matches an identity carrying that group.
The bot impersonates the user readonly-user with group viewers.
If you only bind the role to the SA readonly-user, the impersonated user
has zero permissions — the classic “can’t read anything” bug. You must
also bind the role to the viewers group.
# The fix — bind the role to the GROUP the bot impersonates:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: readonly-user-group
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: viewers # the group the bot sends
roleRef:
kind: ClusterRole
name: readonly-user
apiGroup: rbac.authorization.k8s.io
Restricting WHICH identities the bot may impersonate
The impersonator role restricts resourceNames so the bot can’t impersonate
arbitrary identities:
- apiGroups: [""]
resources: ["users", "groups", "serviceaccounts"]
verbs: ["impersonate"]
resourceNames:
- "admin-user"
- "readonly-user"
- "system:serviceaccount:default:readonly"
Note: the Helm chart’s
impersonaterule (whenimpersonation.enabled) grants impersonate broadly; for tight deployments, addresourceNamesto lock the bot down to only the identities you actually map (see Impersonation).
Verify with kubectl auth can-i
Faithful pre-check (uses the same impersonation headers the bot sends):
# read-only user (group viewers)
kubectl auth can-i get pods -n production --as=readonly-user --as-group=viewers # yes
kubectl auth can-i delete pods -n production --as=readonly-user --as-group=viewers # no
kubectl auth can-i scale deploy frontend -n production --as=readonly-user --as-group=viewers # no
# admin
kubectl auth can-i delete pods -n production --as=admin-user --as-group=system:masters # yes
Settings that turn RBAC on/off
| Config | Effect |
|---|---|
rbac.create: true (Helm) |
create the bot’s ClusterRole + binding + impersonate rule |
impersonation.enabled: true |
route every request through per-user impersonation |
impersonation.user_mapping |
map each Telegram user → identity |
Related
- Impersonation & RBAC — the security-model deep dive
- Security — threat model + least-privilege
- Helm Chart Guide — chart RBAC options