Kubernetes Security


Kubernetes Security Challenges

Kubernetes introduces a large attack surface: the API server, etcd, kubelets, and container runtime all need protection.

RBAC Configuration

Implement least-privilege RBAC:




apiVersion: rbac.authorization.k8s.io/v1


kind: Role


metadata:


namespace: development


name: pod-reader


rules:


- apiGroups: [""]


resources: ["pods", "pods/log"]


verbs: ["get", "watch", "list"]


---


apiVersion: rbac.authorization.k8s.io/v1


kind: RoleBinding


metadata:


namespace: development


name: read-pods


subjects:


- kind: ServiceAccount


name: developer-sa


namespace: development


roleRef:


kind: Role


name: pod-reader


apiGroup: rbac.authorization.k8s.io





ClusterRole for cluster-wide resources:




apiVersion: rbac.authorization.k8s.io/v1


kind: ClusterRole


metadata:


name: metrics-reader


rules:


- nonResourceURLs: ["/metrics"]


verbs: ["get"]





Pod Security Standards

Enforce Pod Security Standards with admission controllers:




# Pod Security Admission


apiVersion: pods-security.admission.config.k8s.io/v1


kind: PodSecurityConfiguration


defaults:


enforce: "restricted"


enforce-version: "latest"


audit: "restricted"


audit-version: "latest"


warn: "restricted"


warn-version: "latest"


exemptions:


namespaces: ["kube-system", "kube-public"]








# Pod Security Standards - Restricted level


apiVersion: v1


kind: Pod


metadata:


name: secure-pod


labels:


pod-security.kubernetes.io/enforce: restricted


spec:


securityContext:


runAsNonRoot: true


seccompProfile:


type: RuntimeDefault


containers:


- name: app


image: myapp:latest


securityContext:


allowPrivilegeEscalation: false


capabilities:


drop: ["ALL"]


readOnlyRootFilesystem: true


runAsNonRoot: true


runAsUser: 1000





Network Policies

Isolate workloads with network policies:




apiVersion: networking.k8s.io/v1


kind: NetworkPolicy


metadata:


name: api-network-policy


namespace: production


spec:


podSelector:


matchLabels:


app: api


policyTypes:


- Ingress


- Egress


ingress:


- from:


- namespaceSelector:


matchLabels:


name: frontend


ports:


- protocol: TCP


port: 8080


egress:


- to:


- podSelector:


matchLabels:


app: database


ports:


- protocol: TCP


port: 5432





Audit Logging

Enable and monitor audit logs:




# audit-policy.yaml


apiVersion: audit.k8s.io/v1


kind: Policy


rules:


- level: RequestResponse


users: ["system:admin"]


resources:


- group: ""


resources: ["secrets", "configmaps"]




- level: Metadata


verbs: ["create", "delete", "patch", "update"]




- level: None


users: ["system:kube-proxy"]


verbs: ["watch"]




- level: None


requestSources: ["controller"]








# Audit log analyzer


import json


from collections import Counter




def analyze_audit_logs(log_lines):


suspicious_activities = []




for line in log_lines:


event = json.loads(line)




# Detect secret access patterns


if event.get("objectRef", {}).get("resource") == "secrets":


if event.get("verb") in ["get", "list"]:


suspicious_activities.append({


"type": "secret_access",


"user": event.get("user", {}).get("username"),


"count": 1


})




# Detect RBAC changes


if event.get("objectRef", {}).get("apiGroup") == "rbac.authorization.k8s.io":


suspicious_activities.append({


"type": "rbac_change",


"user": event.get("user", {}).get("username"),


"verb": event.get("verb")


})




return Counter(str(a) for a in suspicious_activities)





Conclusion

Kubernetes security requires a layered approach. Lock down RBAC with least privilege, enforce Pod Security Standards, isolate workloads with network policies, and enable comprehensive audit logging. Use admission controllers to enforce policies at deploy time. Monitor audit logs for suspicious activity patterns.