Back to Blog

Kubernetes RBAC Security: Developer Self-Service Without Risk

August 4, 2024
10 min read

The eternal DevOps dilemma: developers need access to debug and deploy, but security requires restrictions. With proper RBAC configuration, you can have both. Let's build a system where developers can self-serve without compromising security.

Common RBAC Mistakes

  • • Giving everyone cluster-admin "temporarily"
  • • One namespace for everything
  • • No separation between environments
  • • Manual role management that doesn't scale

Step 1: Define Security Boundaries

Start by defining what each team needs access to:

Developer Needs

✓ Should Have Access To:

  • • View pods, logs, events in their namespace
  • • Create/update deployments
  • • Manage ConfigMaps and Secrets
  • • Port-forward for debugging
  • • Execute into pods for troubleshooting

✗ Should NOT Have Access To:

  • • Other teams' namespaces
  • • Cluster-wide resources
  • • Node access
  • • Production secrets
  • • RBAC configuration itself

Step 2: Implement Namespace Isolation

Create a namespace structure that reflects your organization:

# Create namespaces for each team and environment
kubectl create namespace team-frontend-dev
kubectl create namespace team-frontend-staging
kubectl create namespace team-frontend-prod

kubectl create namespace team-backend-dev
kubectl create namespace team-backend-staging
kubectl create namespace team-backend-prod

# Label namespaces for easier management
kubectl label namespace team-frontend-dev team=frontend env=dev
kubectl label namespace team-frontend-staging team=frontend env=staging
kubectl label namespace team-frontend-prod team=frontend env=prod

Step 3: Create Custom Roles

Define roles that match your actual needs. Here's a developer role with self-service capabilities:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: developer
  namespace: team-frontend-dev
rules:
# Pod management
- apiGroups: [""]
  resources: ["pods", "pods/log", "pods/status"]
  verbs: ["get", "list", "watch"]
  
- apiGroups: [""]
  resources: ["pods/exec", "pods/portforward"]
  verbs: ["create"]
  
# Deployment management
- apiGroups: ["apps"]
  resources: ["deployments", "replicasets"]
  verbs: ["get", "list", "watch", "create", "update", "patch"]
  
# Configuration management
- apiGroups: [""]
  resources: ["configmaps", "secrets"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
  
# Service management
- apiGroups: [""]
  resources: ["services", "endpoints"]
  verbs: ["get", "list", "watch", "create", "update", "patch"]
  
# Ingress management
- apiGroups: ["networking.k8s.io"]
  resources: ["ingresses"]
  verbs: ["get", "list", "watch", "create", "update", "patch"]
  
# Events and debugging
- apiGroups: [""]
  resources: ["events"]
  verbs: ["get", "list", "watch"]

💡 Pro Tip: Create a "read-only" role for production namespaces. Developers can view and debug but not modify production resources.

Environment-Specific Roles

Dev Environment Role

Full access to create, update, delete all resources

Staging Environment Role

Create/update deployments, view logs, no delete permissions

Production Environment Role

Read-only access, pod exec for debugging only

Step 4: Implement Role Bindings

Bind roles to users or groups. Using groups is more scalable:

# Bind developer role to a group
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: frontend-developers
  namespace: team-frontend-dev
subjects:
- kind: Group
  name: "frontend-developers"  # This comes from your auth provider
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: developer
  apiGroup: rbac.authorization.k8s.io

---
# Give read-only access to production
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: frontend-developers-prod-view
  namespace: team-frontend-prod
subjects:
- kind: Group
  name: "frontend-developers"
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: view  # Built-in read-only role
  apiGroup: rbac.authorization.k8s.io

Bonus: Service Accounts for CI/CD

Create service accounts for your CI/CD pipelines with minimal required permissions:

# Service account for CI/CD
apiVersion: v1
kind: ServiceAccount
metadata:
  name: ci-deployer
  namespace: team-frontend-staging

---
# Role for CI/CD deployments
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: ci-deployer
  namespace: team-frontend-staging
rules:
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "update", "patch"]
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]

---
# Bind role to service account
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: ci-deployer
  namespace: team-frontend-staging
subjects:
- kind: ServiceAccount
  name: ci-deployer
  namespace: team-frontend-staging
roleRef:
  kind: Role
  name: ci-deployer
  apiGroup: rbac.authorization.k8s.io

Step 5: Test and Audit

Always test your RBAC configuration before rolling out:

# Test permissions as a specific user
kubectl auth can-i create pods --namespace=team-frontend-dev --as=john@company.com
kubectl auth can-i delete pods --namespace=team-frontend-prod --as=john@company.com

# Test all permissions for a user
kubectl auth can-i --list --namespace=team-frontend-dev --as=john@company.com

# Enable audit logging in your cluster
# Add to kube-apiserver configuration:
--audit-log-path=/var/log/kubernetes/audit.log
--audit-policy-file=/etc/kubernetes/audit-policy.yaml

RBAC Best Practices

Principle of Least Privilege

Start with minimal permissions and add as needed

Use Groups, Not Individual Users

Manage permissions at the group level for scalability

Separate by Environment

Different permissions for dev, staging, and production

Regular Audits

Review permissions quarterly and remove unused access

Common RBAC Patterns

Emergency Break-Glass Access

# Create an emergency role with full access
# But require approval workflow to use it
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: emergency-access
  annotations:
    approval-required: "true"
    expires: "2h"

Time-Limited Access

Use tools like Kubernetes Temporal RBAC or custom operators to grant temporary access

What You've Achieved

✓ Developer Self-Service

Developers can deploy and debug without waiting

✓ Security Compliance

Clear audit trail and controlled access

✓ Scalable Management

Group-based permissions that grow with your team

✓ Reduced Tickets

90% fewer access requests to DevOps team

Simplify RBAC management with KTL.AI

KTL.AI provides visual RBAC management, automatic role suggestions, and compliance reporting. Set up secure developer self-service in minutes, not days.