Kubernetes RBAC: Toegangscontrole Zonder Gedoe
ServiceAccounts, Roles en RoleBindings in Kubernetes — hoe het werkt, waar het misgaat en praktische voorbeelden om RBAC snel en veilig op te zetten.
Jean-Pierre Broeders
Freelance DevOps Engineer
Kubernetes RBAC: Toegangscontrole Zonder Gedoe
Standaard draait alles in Kubernetes onder het default ServiceAccount. Dat klinkt onschuldig, maar het is alsof iedereen op kantoor dezelfde sleutel heeft. Vroeg of laat gaat er iemand een deur open die dicht had moeten blijven.
RBAC — Role-Based Access Control — is de manier om dat te fixen. Niet sexy, wel noodzakelijk. En als het eenmaal staat, hoeft er eigenlijk nooit meer naar omgekeken te worden.
Waarom RBAC Ertoe Doet
Een veelgemaakte fout: een CI/CD pipeline die met cluster-admin rechten draait. Werkt prima, totdat iemand per ongeluk een kubectl delete namespace production uitvoert. Of totdat een gecompromitteerde pod volledige API-toegang heeft.
RBAC voorkomt dat soort rampen. Het principe is simpel: geef elke workload en elke gebruiker precies de rechten die nodig zijn. Niet meer.
De Bouwstenen
Vier resources vormen de kern:
| Resource | Scope | Wat het doet |
|---|---|---|
| Role | Namespace | Definieert permissies binnen één namespace |
| ClusterRole | Cluster-breed | Definieert permissies voor het hele cluster |
| RoleBinding | Namespace | Koppelt een Role aan een gebruiker of ServiceAccount |
| ClusterRoleBinding | Cluster-breed | Koppelt een ClusterRole aan een gebruiker of ServiceAccount |
Het verschil tussen Role en ClusterRole is puur scope. Een Role geldt voor één namespace, een ClusterRole voor alles. Dat klinkt triviaal, maar het vergeten van dit onderscheid is verantwoordelijk voor een hoop te brede rechten in productie.
Een Praktijkvoorbeeld
Stel: er draait een monitoring-agent die pods mag lezen maar niks mag wijzigen. De setup ziet er zo uit:
apiVersion: v1
kind: ServiceAccount
metadata:
name: monitoring-agent
namespace: monitoring
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: monitoring-pod-reader
subjects:
- kind: ServiceAccount
name: monitoring-agent
namespace: monitoring
roleRef:
kind: ClusterRole
name: pod-reader
apiGroup: rbac.authorization.k8s.io
Drie manifests, klaar. De monitoring-agent kan nu pods lezen in alle namespaces, maar verder niks. Geen secrets inzien, geen deployments aanpassen, geen nodes draineren.
ServiceAccounts: Het Vergeten Puzzelstukje
Elke pod draait onder een ServiceAccount. Zonder expliciete toewijzing wordt het default account van die namespace gebruikt. Dat account heeft standaard nauwelijks rechten, maar het punt is: alle pods delen het. Eén pod compromised betekent dat een aanvaller dezelfde rechten heeft als alle andere pods in die namespace.
De oplossing is simpel: maak een dedicated ServiceAccount per applicatie.
apiVersion: v1
kind: ServiceAccount
metadata:
name: payment-service
namespace: production
automountServiceAccountToken: false
Die laatste regel — automountServiceAccountToken: false — is belangrijk. Standaard mount Kubernetes een API-token in elke pod. Als de applicatie de Kubernetes API niet nodig heeft (en dat geldt voor de meeste), zet dit dan uit. Minder aanvalsvlak.
Veelgemaakte Fouten
Te brede wildcards. Het is verleidelijk om resources: ["*"] en verbs: ["*"] te gebruiken. Werkt altijd, maar geeft effectief cluster-admin rechten. Nooit doen in productie.
ClusterRoleBinding waar RoleBinding volstaat. Als een service alleen in z'n eigen namespace hoeft te werken, gebruik dan een RoleBinding. Geen reden om cluster-brede rechten te geven.
Vergeten om RBAC te testen. Na het aanmaken van roles kan getest worden of het klopt:
kubectl auth can-i list pods \
--as=system:serviceaccount:monitoring:monitoring-agent
# yes
kubectl auth can-i delete deployments \
--as=system:serviceaccount:monitoring:monitoring-agent
# no
Die can-i check is goud waard. Draai het na elke RBAC-wijziging.
Aggregated ClusterRoles
Een handige feature die weinig teams gebruiken: aggregation. Hiermee worden ClusterRoles automatisch samengevoegd op basis van labels.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: monitoring-extras
labels:
rbac.example.com/aggregate-to-monitoring: "true"
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: monitoring-aggregate
aggregationRule:
clusterRoleSelectors:
- matchLabels:
rbac.example.com/aggregate-to-monitoring: "true"
rules: [] # wordt automatisch gevuld
Handig als meerdere teams onafhankelijk rechten willen toevoegen aan dezelfde rol. Het voorkomt merge-conflicten in Git en maakt RBAC modulair.
Pod Security Standards
RBAC regelt wie wat mag doen via de API. Maar wat een pod zelf mag op OS-niveau — root draaien, host-networking, privileged containers — dat valt onder Pod Security Standards (PSS).
Sinds Kubernetes 1.25 is dit ingebouwd via de Pod Security Admission controller. Drie levels:
| Level | Beschrijving |
|---|---|
| privileged | Geen restricties (alleen voor system-level workloads) |
| baseline | Blokkeert de ergste dingen (hostNetwork, privileged containers) |
| restricted | Best practice — geen root, geen capabilities, read-only rootfs |
Toewijzen aan een namespace gaat via labels:
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/warn: restricted
De warn mode is handig om eerst te testen zonder dingen te breken.
Praktische Checklist
Een snelle checklist voor RBAC in productie:
- Elk team of service heeft een eigen ServiceAccount
automountServiceAccountToken: falsetenzij echt nodig- Roles in plaats van ClusterRoles waar mogelijk
- Geen wildcards in rules
kubectl auth can-ichecks in CI/CD pipeline- Pod Security Standards op
restrictedvoor productie-namespaces - RBAC manifests in version control, niet handmatig aangemaakt
Niets spectaculairs. Gewoon solide basis-hygiëne die voorkomt dat een kleine fout een grote ramp wordt. De meeste security-incidenten in Kubernetes-omgevingen komen niet door geavanceerde aanvallen, maar door te brede rechten die niemand ooit heeft ingeperkt.
