Triển khai OPA Gatekeeper trên Kubernetes Cluster
Bước đầu tiên là cài đặt OPA Gatekeeper Operator để quản lý vòng đời của Gatekeeper trên cluster. Chúng ta sẽ sử dụng Helm chart chính thức để đảm bảo tính tương thích và dễ dàng nâng cấp.
Việc này tạo ra các Custom Resource Definitions (CRDs) cần thiết cho ConstraintTemplate và Constraint, đồng thời khởi tạo controller để theo dõi và thực thi các chính sách.
Kết quả mong đợi: Namespace gatekeeper-system được tạo và các pod của Gatekeeper (controller, mutating-webhook, validating-webhook) đang ở trạng thái Running.
helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts
helm repo update
helm install gatekeeper gatekeeper/gatekeeper-crds --namespace gatekeeper-system --create-namespace
helm install gatekeeper gatekeeper/gatekeeper --namespace gatekeeper-system --create-namespace --set installCRDs=false
Kiểm tra trạng thái cài đặt bằng cách liệt kê các pod trong namespace gatekeeper-system.
kubectl get pods -n gatekeeper-system
Đợi hệ thống ổn định
Sau khi cài đặt, cần chờ khoảng 1-2 phút để các webhook của Gatekeeper được đăng ký và sẵn sàng.
Webhook cần thời gian để khởi động và thiết lập kết nối với API server của Kubernetes để bắt các yêu cầu deploy.
Kết quả mong đợi: Tất cả các pod đều có trạng thái Running và READY 1/1.
kubectl wait --for=condition=ready pod --all -n gatekeeper-system --timeout=60s
Verify kết quả cài đặt
Để xác nhận Gatekeeper đã hoạt động, ta sẽ kiểm tra xem các CRD đã được tạo chưa.
CRD là định nghĩa tài nguyên mở rộng cho phép Kubernetes hiểu các loại tài nguyên mới như ConstraintTemplate và Constraint.
Kết quả mong đợi: Danh sách các CRD liên quan đến Gatekeeper xuất hiện, bao gồm constrainttemplates.gatekeeper.sh và constraints.gatekeeper.sh.
kubectl get crd | grep gatekeeper
Cấu hình ConstraintTemplate cho Cosign Signature
Chúng ta cần tạo một ConstraintTemplate để định nghĩa logic kiểm tra chữ ký của container image. Template này sẽ sử dụng Rego language của OPA để gọi API của Cosign hoặc kiểm tra các annotation.
Mục đích là tạo một "mẫu" chính sách có thể tái sử dụng, định nghĩa các biến đầu vào (như namespace, image) và các điều kiện bắt buộc phải thỏa mãn.
Kết quả mong đợi: Tài nguyên ConstraintTemplate tên là k8srequiredsignatures được tạo thành công.
cat
Trong bài viết này, để đơn giản hóa việc setup Cosign verify trong Rego (vì cần thư viện phức tạp), ta sẽ sử dụng một ConstraintTemplate kiểm tra metadata annotation mà Tekton/Cosign đã gắn vào image hoặc pod. Tuy nhiên, để đảm bảo tính chặt chẽ, ta sẽ dùng một template kiểm tra việc tồn tại của chữ ký thông qua biến môi trường hoặc annotation đặc thù.
Tuy nhiên, để thực thi chính sách "từ chối deploy image chưa được ký" một cách chuẩn xác nhất với Gatekeeper hiện tại, chúng ta thường kết hợp với Admission Controller của Cosign hoặc dùng Rego để gọi API. Dưới đây là phiên bản ConstraintTemplate chuẩn hơn, tập trung vào việc kiểm tra tên image và yêu cầu chữ ký (giả định signature đã được verify bởi webhook trước đó hoặc kiểm tra registry).
cat
Verify rằng ConstraintTemplate đã được tạo thành công.
kubectl get constrainttemplate k8srequiredsignatures
Tạo Constraint để thực thi chính sách
Sau khi có template, ta cần tạo một Constraint cụ thể để áp dụng chính sách đó vào cluster. Constraint này sẽ liệt kê các image được phép deploy và yêu cầu chúng phải có chữ ký hợp lệ.
Đây là bước thiết lập quy tắc: "Chỉ cho phép deploy các image nằm trong danh sách trắng và phải có chữ ký Cosign hợp lệ".
Kết quả mong đợi: Tài nguyên K8sRequiredSignatures tên là require-signed-images được tạo và Gatekeeper bắt đầu bắt các request deploy mới.
cat
Trong ví dụ trên, key: "cosign.pub" là tham số để Rego biết về public key, nhưng logic thực tế trong Rego (ở bước trên) đã đơn giản hóa bằng cách kiểm tra annotation. Nếu bạn dùng Cosign verify trực tiếp, logic Rego sẽ phức tạp hơn. Ở đây, chúng ta giả định rằng image đã được ký bởi Tekton (Phần 4) và có annotation tương ứng.
Để test chính sách ngay lập tức, ta sẽ thử deploy một Pod với image chưa được ký (hoặc không có annotation chữ ký).
kubectl run test-unsigned --image=busybox --rm -i
Kết quả mong đợi: Lệnh deploy bị từ chối với lỗi admission webhook "validation.gatekeeper.sh" denied the request: Image busybox is not signed or signature is invalid...
kubectl describe pod test-unsigned
Deploy Pod với image đã ký (giả lập)
Để test trường hợp thành công, ta cần tạo Pod với annotation giả lập chữ ký (vì trong môi trường demo này chưa chạy Cosign verify thực tế).
Annotation cosign.sigstore.dev/signature sẽ đánh dấu image này là đã được kiểm tra chữ ký bởi quy trình trước đó.
Kết quả mong đợi: Pod được tạo thành công và trạng thái là Running.
cat
kubectl get pod test-signed
Verify kết quả thực thi chính sách
Kiểm tra lại danh sách các Constraint đang hoạt động và trạng thái của chúng.
Gatekeeper sẽ báo lỗi nếu Constraint bị vi phạm liên tục, giúp admin phát hiện sớm các nỗ lực deploy không an toàn.
Kết quả mong đợi: Constraint require-signed-images hiện diện và có thể xem chi tiết vi phạm nếu có.
kubectl get constraints
kubectl get constraintviolations
Điều hướng series:
Mục lục: Series: Series: Xây dựng nền tảng Secure Software Supply Chain với Sigstore, Cosign, Tekton và OPA Gatekeeper trên Kubernetes để đảm bảo an toàn vòng đời phần mềm
« Phần 4: Tự động hóa quy trình ký image với Tekton Pipeline
Phần 6: Mở rộng chính sách với OPA Gatekeeper: Enforce và Audit »