G
GuideDevOps
Lesson 13 of 17

RBAC

Part of the Kubernetes tutorial series.

What is RBAC?

RBAC (Role-Based Access Control) is how you manage permissions in Kubernetes. It controls:

  • Who can access the cluster (authentication via K8s API)
  • What they can do (authorization via RBAC)
  • On which resources (Pods, Deployments, Secrets, etc.)

Security principle: Always follow the Principle of Least Privilege. Never give more permissions than necessary.


RBAC Components

1. Roles and ClusterRoles

A Role defines what actions can be performed on which resources.

Role (namespace-scoped):

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
  namespace: default
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]

ClusterRole (cluster-wide):

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]

2. RoleBindings and ClusterRoleBindings

A binding connects a Role to users/service accounts.

RoleBinding (namespace-scoped):

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: pod-reader
subjects:
- kind: User
  name: alice@company.com
  apiGroup: rbac.authorization.k8s.io
- kind: Group
  name: developers
  apiGroup: rbac.authorization.k8s.io

ClusterRoleBinding:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: read-pods-global
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: pod-reader
subjects:
- kind: User
  name: bob@company.com
  apiGroup: rbac.authorization.k8s.io

How RBAC Works

When a user makes a request to the Kubernetes API:

User makes request
     │
     ▼
Is the user authenticated? (valid certificate, token, etc.)
     │
     ├─ No → Reject (Unauthorized)
     │
     ▼ Yes
Does the user's role allow this action?
     │
     ├─ No → Reject (Forbidden)
     │
     ▼ Yes
Is the action on an allowed resource?
     │
     ├─ No → Reject (Forbidden)
     │
     ▼ Yes
Execute the action ✓

Service Accounts

When applications (Pods) interact with the Kubernetes API, they use Service Accounts.

Default Service Account

Each namespace has a default service account:

kubectl get serviceaccounts
kubectl get serviceaccounts -n kube-system

Output:

NAME      SECRETS   AGE
default   1         10d

Create a Service Account

kubectl create serviceaccount my-app

Or via YAML:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-app-sa
  namespace: default

Use Service Account in Pod

apiVersion: v1
kind: Pod
metadata:
  name: myapp
spec:
  serviceAccountName: my-app-sa
  containers:
  - name: app
    image: myapp:1.0

The Pod automatically gets a token mounted at /var/run/secrets/kubernetes.io/serviceaccount/token

Pod Accessing the Kubernetes API

import requests
import os
 
# Read the token
with open('/var/run/secrets/kubernetes.io/serviceaccount/token', 'r') as f:
    token = f.read()
 
# Read the CA certificate
ca_cert = '/var/run/secrets/kubernetes.io/serviceaccount/ca.crt'
 
# Get the API server address
api_server = os.environ['KUBERNETES_SERVICE_HOST']
api_port = os.environ['KUBERNETES_SERVICE_PORT']
 
# Make a request to the API
url = f'https://{api_server}:{api_port}/api/v1/pods'
headers = {'Authorization': f'Bearer {token}'}
 
response = requests.get(
    url,
    headers=headers,
    verify=ca_cert  # Use CA cert for HTTPS verification
)
 
print(response.json())

Common RBAC Patterns

Pattern 1: Read-Only Access

Users can view resources but not modify them:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: viewer
rules:
- apiGroups: [""]
  resources: ["pods", "pods/logs", "services"]
  verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
  resources: ["deployments", "statefulsets"]
  verbs: ["get", "list", "watch"]

Pattern 2: Namespace Admin

User can manage everything in one namespace but nothing else:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: namespace-admin
  namespace: development
rules:
- apiGroups: [""]
  resources: ["*"]
  verbs: ["*"]
- apiGroups: ["apps"]
  resources: ["*"]
  verbs: ["*"]
- apiGroups: ["batch"]
  resources: ["*"]
  verbs: ["*"]

Pattern 3: Deployment Manager

Users can create/update/delete Deployments but not touch Secrets:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: deployment-manager
  namespace: default
rules:
- apiGroups: ["apps"]
  resources: ["deployments", "replicasets", "statefulsets"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
  resources: ["services"]
  verbs: ["get", "list", "watch"]
# Cannot create or access Secrets

Pattern 4: Pod Exec (Debugging)

Developers can exec into Pods for debugging:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-debugger
  namespace: development
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list"]
- apiGroups: [""]
  resources: ["pods/exec"]
  verbs: ["create", "get"]

Pattern 5: Secret Manager

Only specific people can access Secrets:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: secret-manager
  namespace: production
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "list", "create", "update", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: secret-manager-binding
  namespace: production
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: secret-manager
subjects:
- kind: Group
  name: platform-team
  apiGroup: rbac.authorization.k8s.io

Pre-built Cluster Roles

Kubernetes comes with useful built-in roles:

kubectl get clusterroles | head -20

Common built-in roles:

  • system:masters - Full cluster access
  • view - Read-only access to most resources
  • edit - Read-write access to Deployments, Pods, Services
  • admin - Full admin access to a namespace
  • cluster-admin - Full admin access to entire cluster

Using Built-in Roles

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: devs-can-edit
  namespace: development
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: edit  # Built-in edit role
subjects:
- kind: Group
  name: developers
  apiGroup: rbac.authorization.k8s.io

Verifying Permissions

Check Your Permissions

# What can I do?
kubectl auth can-i get pods
# yes
 
kubectl auth can-i delete secrets
# no
 
kubectl auth can-i create deployments --namespace=production
# no

Check Another User's Permissions

# What can alice@company.com do?
kubectl auth can-i get pods --as=alice@company.com
kubectl auth can-i delete deployments --as=alice@company.com

Check Specific Resources

# Can I get specific pod?
kubectl auth can-i get pods/my-pod

API Groups and Resources

When creating roles, you need to specify:

  • apiGroups: Which API group (core, apps, batch, etc.)
  • resources: Which resource types (pods, deployments, etc.)
  • verbs: Which actions (get, list, create, delete, etc.)

Common API Groups and Resources

Core API (apiGroups: [""]):

  • pods
  • services
  • secrets
  • configmaps
  • namespaces

Apps API (apiGroups: ["apps"]):

  • deployments
  • statefulsets
  • daemonsets
  • replicasets

Batch API (apiGroups: ["batch"]):

  • jobs
  • cronjobs

RBAC API (apiGroups: ["rbac.authorization.k8s.io"]):

  • roles
  • rolebindings
  • clusterroles
  • clusterrolebindings

Wildcard Usage

rules:
- apiGroups: ["*"]       # All API groups
  resources: ["*"]       # All resources
  verbs: ["*"]           # All verbs
# This is effectively cluster-admin

Testing RBAC

Test Setup

# Create test namespace
kubectl create namespace test-rbac
 
# Create restrictive service account
kubectl create serviceaccount limited-user -n test-rbac
 
# Give it minimal permissions
kubectl create role minimal-reader -n test-rbac --verb=get --resource=pods
 
kubectl create rolebinding minimal-reader-binding -n test-rbac \
  --role=minimal-reader \
  --serviceaccount=test-rbac:limited-user

Get Service Account Token

# Get token
TOKEN=$(kubectl -n test-rbac create token limited-user --duration=1h)
echo $TOKEN
 
# Set as default auth
kubectl config set-credentials limited-user --token=$TOKEN
kubectl config set-context test-context --cluster=<cluster> --user=limited-user
kubectl config use-context test-context
 
# Now test what they can do
kubectl get pods                    # Should work
kubectl get pods -n default         # Should fail (different namespace)
kubectl delete pod my-pod           # Should fail (no delete permission)

Audit Logging

Enable audit logging to track RBAC decisions:

# /etc/kubernetes/audit-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: RequestResponse
  omitStages:
  - RequestReceived
  resources:
  - group: ""
    resources: ["secrets"]
  namespaces: ["production"]
 
- level: Metadata
  omitStages:
  - RequestReceived
  verbs: ["create", "update", "patch", "delete"]
 
- level: Metadata
  omitStages:
  - RequestReceived

Configure API server:

--audit-policy-file=/etc/kubernetes/audit-policy.yaml
--audit-log-path=/var/log/kubernetes/audit.log
--audit-log-maxage=7
--audit-log-maxbackup=10

Security Best Practices

\u2705 Principle of Least Privilege

  • Only grant minimum permissions needed
  • Regularly review and revoke unnecessary permissions

\u2705 Use Service Accounts for Applications

  • Never use default service account
  • Create dedicated service accounts per application

\u2705 Namespace Isolation

  • Use different service accounts per namespace
  • Use Network Policies in addition to RBAC

\u2705 Audit RBAC Changes

  • Log all role and binding changes
  • Alert on suspicious permission grants

\u2705 Regular Permission Audits

  • Review who has what permissions
  • Remove accounts for departed team members

\u274c Don't Use cluster-admin

  • Except for cluster administrators
  • Most users should have namespace-level roles

\u274c Don't Put Passwords in Environment Variables

  • Use Secrets RBAC to control access
  • Audit who accesses Secrets

\u274c Don't Share Service Accounts

  • Each application gets its own SA
  • Makes audit and revocation easier