Giao diện
Thực hành: RBAC & Security
🎯 Mục tiêu
🎯 Sau bài thực hành này, bạn sẽ:
- Tạo Role, RoleBinding và ServiceAccount theo Least Privilege
- Cấu hình SecurityContext: non-root, readOnlyRootFilesystem, drop capabilities
- Kiểm chứng rằng Pod đã được hardening đúng cách
Mô tả bài tập
Team phát triển cần deploy ứng dụng mới. Bạn (Platform Engineer) phải thiết lập quyền truy cập RBAC giới hạn và đảm bảo Pod tuân thủ security hardening standards trước khi lên production.
Yêu cầu
Bài 1: ServiceAccount & RBAC
Tạo namespace dev-team, ServiceAccount, Role và RoleBinding:
yaml
# 1. Tạo namespace
apiVersion: v1
kind: Namespace
metadata:
name: dev-team
---
# 2. Tạo ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
name: developer-sa
namespace: dev-team
automountServiceAccountToken: false
---
# 3. TODO: Tạo Role cho phép:
# - pods: get, list, watch, create, delete
# - services: get, list
# - deployments: get, list, create, update
# - KHÔNG được: delete deployments, access secrets
---
# 4. TODO: Tạo RoleBinding gắn Role với ServiceAccountKiểm tra:
bash
# Phải trả về "yes"
kubectl auth can-i list pods --as=system:serviceaccount:dev-team:developer-sa -n dev-team
# Phải trả về "no"
kubectl auth can-i delete deployments --as=system:serviceaccount:dev-team:developer-sa -n dev-team
kubectl auth can-i get secrets --as=system:serviceaccount:dev-team:developer-sa -n dev-teamBài 2: Pod Security Hardening
Tạo Pod với đầy đủ security hardening:
yaml
apiVersion: v1
kind: Pod
metadata:
name: hardened-app
namespace: dev-team
spec:
serviceAccountName: developer-sa
securityContext:
# TODO: Pod-level security
# runAsNonRoot, runAsUser, fsGroup
containers:
- name: app
image: nginx:1.24-alpine
ports:
- containerPort: 8080
securityContext:
# TODO: Container-level security
# allowPrivilegeEscalation, readOnlyRootFilesystem
# capabilities: drop ALL
volumeMounts:
- name: tmp
mountPath: /tmp
- name: cache
mountPath: /var/cache/nginx
- name: run
mountPath: /var/run
volumes:
- name: tmp
emptyDir: {}
- name: cache
emptyDir: {}
- name: run
emptyDir: {}Kiểm tra:
bash
# Phải FAIL (non-root)
kubectl exec hardened-app -n dev-team -- whoami # Không phải root
# Phải FAIL (readOnly filesystem)
kubectl exec hardened-app -n dev-team -- touch /usr/share/nginx/html/hack.txtBài 3: Audit — Phát hiện Pod không an toàn
Viết command kiểm tra tất cả Pod trong cluster đang chạy với root:
bash
# TODO: Viết kubectl command để tìm Pods chạy root
# Hint: kubectl get pods --all-namespaces -o jsonpath=...Tìm Pod nào có automountServiceAccountToken: true (mặc định):
bash
# TODO: Liệt kê Pods có service account token mountedGợi ý
💡 Xem gợi ý
- Bài 1: Role
apiGroups: [""]cho core resources (pods, services),apiGroups: ["apps"]cho deployments - Bài 2: NGINX alpine cần ghi vào
/var/cache/nginx,/var/run,/tmp— mount emptyDir cho các path này khi dùng readOnlyRootFilesystem - Bài 2: Dùng user 101 (nginx user trong alpine image), fsGroup 101
- Bài 3: JSONPath:
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.securityContext.runAsNonRoot}{"\n"}{end}' - automountServiceAccountToken mặc định là true nếu không set explicit
Lời giải
✅ Xem lời giải
Bài 1: RBAC hoàn chỉnh
yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: developer-role
namespace: dev-team
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
resources: ["services"]
verbs: ["get", "list"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "create", "update"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: developer-binding
namespace: dev-team
subjects:
- kind: ServiceAccount
name: developer-sa
namespace: dev-team
roleRef:
kind: Role
name: developer-role
apiGroup: rbac.authorization.k8s.ioBài 2: Hardened Pod
yaml
apiVersion: v1
kind: Pod
metadata:
name: hardened-app
namespace: dev-team
spec:
serviceAccountName: developer-sa
securityContext:
runAsNonRoot: true
runAsUser: 101
runAsGroup: 101
fsGroup: 101
containers:
- name: app
image: nginx:1.24-alpine
ports:
- containerPort: 8080
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
volumeMounts:
- name: tmp
mountPath: /tmp
- name: cache
mountPath: /var/cache/nginx
- name: run
mountPath: /var/run
volumes:
- name: tmp
emptyDir: {}
- name: cache
emptyDir: {}
- name: run
emptyDir: {}Bài 3: Audit Commands
bash
# Tìm Pods chạy root
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}/{.metadata.name}: runAsNonRoot={.spec.securityContext.runAsNonRoot}{"\n"}{end}' | grep -v "true"
# Tìm Pods có token mounted
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}/{.metadata.name}: automount={.spec.automountServiceAccountToken}{"\n"}{end}'