🎤Speaking at KubeCon EU 2026Lessons Learned Orchestrating Multi-Tenant GPUs on OpenShift AIView Session
Security advanced ⏱ 15 minutes K8s 1.28+

How to Configure Kubernetes API Access Control

Set up secure API server access with authentication and authorization. Configure RBAC, API groups, and audit logging for cluster security.

By Luca Berton

How to Configure Kubernetes API Access Control

Secure Kubernetes API access through authentication, authorization, and audit logging. Configure RBAC policies, manage API groups, and implement least-privilege access.

Authentication Methods

# Kubernetes supports multiple authentication strategies:

# 1. X.509 Client Certificates
# 2. Bearer Tokens (ServiceAccount, OIDC, Webhook)
# 3. Basic Auth (deprecated)
# 4. OpenID Connect (OIDC)
# 5. Authentication Proxy

# Check current authentication
kubectl auth whoami  # Kubernetes 1.27+

# Or older method
kubectl config view --minify -o jsonpath='{.contexts[0].context.user}'

X.509 Certificate Auth

# Generate client certificate
openssl genrsa -out developer.key 2048

openssl req -new -key developer.key -out developer.csr \
  -subj "/CN=developer/O=dev-team"

# Sign with cluster CA (requires cluster admin)
openssl x509 -req -in developer.csr -CA ca.crt -CAkey ca.key \
  -CAcreateserial -out developer.crt -days 365

# Add to kubeconfig
kubectl config set-credentials developer \
  --client-certificate=developer.crt \
  --client-key=developer.key

kubectl config set-context developer-context \
  --cluster=my-cluster \
  --user=developer

ServiceAccount Token Auth

# Create ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
  name: ci-user
  namespace: default
---
# Create long-lived token (if needed)
apiVersion: v1
kind: Secret
metadata:
  name: ci-user-token
  annotations:
    kubernetes.io/service-account.name: ci-user
type: kubernetes.io/service-account-token
# Get token
kubectl get secret ci-user-token -o jsonpath='{.data.token}' | base64 -d

# Or create short-lived token (preferred)
kubectl create token ci-user --duration=24h

RBAC Components

# Role: Namespace-scoped permissions
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-manager
  namespace: development
rules:
  - apiGroups: [""]           # Core API group
    resources: ["pods"]
    verbs: ["get", "list", "watch", "create", "update", "delete"]
  - apiGroups: [""]
    resources: ["pods/log", "pods/exec"]
    verbs: ["get", "create"]
  - apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["get", "list", "watch"]
---
# RoleBinding: Grants Role to subjects
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pod-manager-binding
  namespace: development
subjects:
  - kind: User
    name: developer
    apiGroup: rbac.authorization.k8s.io
  - kind: Group
    name: dev-team
    apiGroup: rbac.authorization.k8s.io
  - kind: ServiceAccount
    name: ci-user
    namespace: default
roleRef:
  kind: Role
  name: pod-manager
  apiGroup: rbac.authorization.k8s.io

ClusterRole and ClusterRoleBinding

# ClusterRole: Cluster-wide permissions
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cluster-reader
rules:
  - apiGroups: [""]
    resources: ["nodes", "namespaces", "persistentvolumes"]
    verbs: ["get", "list", "watch"]
  - apiGroups: ["apps"]
    resources: ["deployments", "replicasets", "statefulsets"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: cluster-reader-binding
subjects:
  - kind: Group
    name: readonly-users
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: cluster-reader
  apiGroup: rbac.authorization.k8s.io

API Groups and Resources

# List all API groups
kubectl api-resources --output=wide

# Common API groups:
# ""        (core) - pods, services, configmaps, secrets
# apps      - deployments, statefulsets, daemonsets
# batch     - jobs, cronjobs
# networking.k8s.io - ingresses, networkpolicies
# rbac.authorization.k8s.io - roles, rolebindings

# List resources in group
kubectl api-resources --api-group=apps

# Get API group versions
kubectl api-versions | grep apps

Resource Names and Subresources

# Restrict to specific resources by name
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: config-reader
rules:
  - apiGroups: [""]
    resources: ["configmaps"]
    resourceNames: ["app-config", "env-config"]  # Only these
    verbs: ["get"]
---
# Subresources (pods/log, pods/exec, etc.)
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-logs
rules:
  - apiGroups: [""]
    resources: ["pods/log"]  # Subresource
    verbs: ["get"]
  - apiGroups: [""]
    resources: ["pods/exec"]
    verbs: ["create"]  # Exec requires create verb

RBAC Verbs

# Available verbs:
# get      - Read single resource
# list     - List resources
# watch    - Watch for changes
# create   - Create resources
# update   - Update existing resources
# patch    - Patch resources
# delete   - Delete single resource
# deletecollection - Delete multiple resources

# Common verb combinations:
rules:
  # Read-only
  - verbs: ["get", "list", "watch"]
  
  # Full CRUD
  - verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
  
  # Write-only (rare)
  - verbs: ["create", "update", "delete"]

Aggregated ClusterRoles

# Base ClusterRole with label
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: monitoring-rules
  labels:
    rbac.example.com/aggregate-to-monitoring: "true"
rules:
  - apiGroups: ["monitoring.coreos.com"]
    resources: ["prometheusrules", "servicemonitors"]
    verbs: ["get", "list", "watch"]
---
# Aggregating ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: monitoring-admin
aggregationRule:
  clusterRoleSelectors:
    - matchLabels:
        rbac.example.com/aggregate-to-monitoring: "true"
rules: []  # Rules are aggregated from matching ClusterRoles

Test Permissions

# Check if you can perform action
kubectl auth can-i create pods
kubectl auth can-i delete deployments -n production

# Check as another user
kubectl auth can-i get pods --as=developer
kubectl auth can-i get pods --as=system:serviceaccount:default:ci-user

# List all permissions
kubectl auth can-i --list
kubectl auth can-i --list --as=developer -n development

# Check in specific namespace
kubectl auth can-i create deployments -n production

Audit Logging

# audit-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
  # Don't log read-only requests to certain resources
  - level: None
    resources:
      - group: ""
        resources: ["events", "nodes/status"]
    verbs: ["get", "list", "watch"]
  
  # Log auth failures
  - level: Metadata
    users: ["system:anonymous"]
  
  # Log secrets access at metadata level (no body)
  - level: Metadata
    resources:
      - group: ""
        resources: ["secrets"]
  
  # Log everything else at request level
  - level: Request
    omitStages:
      - RequestReceived

Common RBAC Patterns

# Developer access
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: developer
rules:
  - apiGroups: ["", "apps", "batch"]
    resources: ["*"]
    verbs: ["*"]
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get", "list"]  # Read only secrets
---
# CI/CD Pipeline
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: ci-deployer
rules:
  - apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["get", "list", "patch", "update"]
  - apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["get", "list", "create", "update"]
---
# Monitoring
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: monitoring
rules:
  - apiGroups: [""]
    resources: ["nodes", "pods", "services", "endpoints"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["nodes/metrics", "pods/metrics"]
    verbs: ["get"]

Debug RBAC Issues

# Check why access denied
kubectl describe rolebinding -n namespace
kubectl describe clusterrolebinding

# View role permissions
kubectl describe role pod-manager -n development
kubectl describe clusterrole cluster-reader

# Check subject's bindings
kubectl get rolebindings,clusterrolebindings -A \
  -o jsonpath='{range .items[?(@.subjects[*].name=="developer")]}{.metadata.name}{"\n"}{end}'

Summary

Kubernetes API access control uses authentication (who you are) and authorization (what you can do). Configure RBAC with Roles/ClusterRoles (define permissions) and RoleBindings/ClusterRoleBindings (grant to subjects). Use least-privilege principles - grant minimum necessary permissions. Test access with kubectl auth can-i. Enable audit logging to track API access. Common patterns include read-only cluster access, namespace-scoped developer access, and CI/CD deployment permissions.


📘 Go Further with Kubernetes Recipes

Love this recipe? There’s so much more! This is just one of 100+ hands-on recipes in our comprehensive Kubernetes Recipes book.

Inside the book, you’ll master:

  • ✅ Production-ready deployment strategies
  • ✅ Advanced networking and security patterns
  • ✅ Observability, monitoring, and troubleshooting
  • ✅ Real-world best practices from industry experts

“The practical, recipe-based approach made complex Kubernetes concepts finally click for me.”

👉 Get Your Copy Now — Start building production-grade Kubernetes skills today!

#api-server #authentication #authorization #rbac #security

Want More Kubernetes Recipes?

This recipe is from Kubernetes Recipes, our 750-page practical guide with hundreds of production-ready patterns.