Cluster Hardening for CKS¶
π Controlling Access to the Kubernetes API - Authentication, authorization, and admission control overview
API Server Security¶
π API Server Authentication - Supported authentication strategies
Authentication Methods¶
X.509 Client Certificates¶
- Most common for cluster components and admin users
- Certificates signed by the cluster CA
- CN (Common Name) used as username, O (Organization) used as group
- Configured with
--client-ca-fileon the API server
Service Account Tokens¶
- Used by pods to authenticate to the API server
- JWT tokens mounted into pods automatically (unless disabled)
- Bound tokens are time-limited and audience-scoped
- Created with
kubectl create tokenor automatically mounted
OpenID Connect (OIDC)¶
- External identity provider integration
- Supports providers like Dex, Keycloak, Azure AD
- Configured with
--oidc-issuer-url,--oidc-client-id, etc. - Good for enterprise user management
Static Token Files and Basic Auth¶
- INSECURE - Should never be used in production
--token-auth-fileand--basic-auth-fileare deprecated approaches- CKS exam may test knowledge of disabling these
Authorization Modes¶
π Authorization Overview - Authorization modes and configuration
RBAC (Role-Based Access Control)¶
- Standard authorization mode for production clusters
- Configured with
--authorization-mode=RBAC - Controls access based on roles bound to users, groups, or service accounts
Node Authorization¶
- Special-purpose authorizer for kubelet requests
- Configured with
--authorization-mode=Node - Limits kubelet to accessing only resources related to its own node
Webhook Authorization¶
- External HTTP callback for authorization decisions
- Useful for integration with external policy engines
- Configured with
--authorization-mode=Webhook
Always Use Multiple Modes¶
- Recommended:
--authorization-mode=Node,RBAC - Modes are evaluated in order; if one denies, the next is checked
- Never use
--authorization-mode=AlwaysAllowin production
API Server Hardening Flags¶
Critical Security Flags:
--anonymous-auth=false # Disable anonymous requests
--enable-admission-plugins=... # Enable required admission controllers
--audit-policy-file=/path/to/policy # Enable audit logging
--encryption-provider-config=/path # Enable secrets encryption
--profiling=false # Disable profiling endpoint
--insecure-port=0 # Disable insecure port (deprecated but check)
--kubelet-certificate-authority=... # Verify kubelet serving certificates
RBAC Deep Dive¶
π Using RBAC Authorization - Complete RBAC reference
Role and ClusterRole¶
Role - Namespace-scoped permissions:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: app
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get"]
ClusterRole - Cluster-wide permissions:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: node-reader
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]
API Groups Reference¶
| Resource | API Group | Common Verbs |
|---|---|---|
| pods, services, secrets, configmaps | "" (core) | get, list, create, update, delete |
| deployments, replicasets, daemonsets | apps | get, list, create, update, delete, patch |
| ingresses, networkpolicies | networking.k8s.io | get, list, create, update, delete |
| roles, rolebindings | rbac.authorization.k8s.io | get, list, create, bind |
| clusterroles, clusterrolebindings | rbac.authorization.k8s.io | get, list, create, bind |
RBAC Escalation Prevention¶
Kubernetes prevents privilege escalation through RBAC: - Users can only create/update roles with permissions they already have - bind verb on roles is required to create bindings to a role - escalate verb is required to grant permissions you do not have - These checks prevent a user from granting themselves more access
π RBAC Good Practices - Security recommendations for RBAC
Auditing RBAC¶
# List all ClusterRoleBindings with cluster-admin role
kubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name=="cluster-admin") | .metadata.name'
# Check what a service account can do
kubectl auth can-i --list --as=system:serviceaccount:default:my-sa
# Check specific permission
kubectl auth can-i create deployments --as=system:serviceaccount:app:developer -n app
# Find all subjects with cluster-admin
kubectl get clusterrolebindings -o wide | grep cluster-admin
Service Account Security¶
π Service Accounts - Service account management π Configure Service Accounts for Pods - Pod-level service account configuration
Default Service Account Risks¶
- Every namespace has a
defaultservice account - Pods automatically mount the default service account token
- Default service account often has more permissions than needed
- Token auto-mounting provides API access from every pod
Hardening Service Accounts¶
Disable Token Automounting:
# On the ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-sa
namespace: app
automountServiceAccountToken: false
# Or on the Pod (overrides SA setting)
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
serviceAccountName: my-sa
automountServiceAccountToken: false
Create Dedicated Service Accounts:
# Create per-workload service account
kubectl create sa app-sa -n app
# Bind minimal role
kubectl create role app-role --verb=get,list --resource=configmaps -n app
kubectl create rolebinding app-binding --role=app-role --serviceaccount=app:app-sa -n app
Projected Service Account Tokens¶
- Bound to specific audience (API server, external service)
- Time-limited (default 1 hour, auto-refreshed)
- Bound to the pod - token is invalidated when pod is deleted
- More secure than legacy non-expiring tokens
Admission Controllers¶
π Admission Controllers Reference - Complete list of admission controllers
Key Admission Controllers for CKS¶
| Controller | Purpose |
|---|---|
PodSecurity | Enforces Pod Security Standards |
NodeRestriction | Limits kubelet to modifying its own node and pods |
ImagePolicyWebhook | External image policy validation |
ValidatingAdmissionWebhook | Custom validation (used by Gatekeeper) |
MutatingAdmissionWebhook | Custom mutation (used by Istio sidecar injection) |
Enabling Admission Controllers¶
# In API server manifest
--enable-admission-plugins=NodeRestriction,PodSecurity,ServiceAccount
Kubernetes Version Upgrades¶
π Upgrading kubeadm clusters - Step-by-step upgrade process
Upgrade Process¶
- Upgrade kubeadm on control plane node
- Run
kubeadm upgrade planto check available versions - Run
kubeadm upgrade apply v1.XX.Yon control plane - Drain worker nodes one at a time
- Upgrade kubelet and kubectl on each node
- Uncordon nodes to resume scheduling
Version Skew Policy¶
- kubelet can be up to 2 minor versions behind API server
- kubectl can be 1 minor version ahead or behind API server
- Always upgrade control plane before worker nodes
- Never skip minor versions during upgrades
Key Takeaways¶
- API Server - Secure with proper authentication, authorization, and admission control
- RBAC - Always use least privilege; audit regularly for excessive permissions
- Service Accounts - Disable token automounting; create dedicated SAs per workload
- Admission Controllers - Enable NodeRestriction, PodSecurity, and webhook controllers
- Upgrades - Keep clusters updated; follow version skew policy
- Audit - Use
kubectl auth can-ito verify permissions are correct