Cấu hình Cert-Manager để tự động gia hạn chứng chỉ Server
Chúng ta cần triển khai Cert-Manager để quản lý vòng đời chứng chỉ TLS cho Kong Gateway, đảm bảo chứng chỉ luôn hợp lệ mà không gây gián đoạn dịch vụ.
Cài đặt Cert-Manager vào cluster Kubernetes bằng Helm, chỉ định namespace và các CRDs cần thiết.
helm repo add jetstack https://charts.jetstack.io
helm repo update
helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --version v1.14.2 --set installCRDs=true
Kết quả: Namespace `cert-manager` được tạo và các pods của cert-manager chạy ở trạng thái `Running`.
Tạo Secret chứa Private Key của CA (Certificate Authority) nội bộ để Cert-Manager ký chứng chỉ cho Server. Giả sử chúng ta đã có file CA từ phần trước.
kubectl create secret generic kong-ca --from-file=ca.crt=/path/to/ca.crt --from-file=ca.key=/path/to/ca.key --namespace kong
Kết quả: Secret `kong-ca` được tạo trong namespace `kong`.
Định nghĩa ClusterIssuer sử dụng CA nội bộ để ký chứng chỉ. Đây là cấu hình quan trọng để Cert-Manager biết cách tạo chứng chỉ Server.
cat
Kết quả: ClusterIssuer `kong-selfsigned-issuer` được tạo, sẵn sàng ký chứng chỉ cho toàn cluster.
Tạo Certificate resource yêu cầu chứng chỉ Server cho Kong. Cert-Manager sẽ tự động tạo Secret chứa certificate và private key.
cat
Kết quả: Cert-Manager tạo Secret `kong-tls-secret` trong namespace `kong` chứa file `tls.crt` và `tls.key`. Chứng chỉ sẽ tự động gia hạn trước khi hết hạn 15 ngày.
Verify kết quả
Trạng thái chứng chỉ phải là `Ready` và Secret đã được tạo.
kubectl get certificate kong-tls -n kong
kubectl get secret kong-tls-secret -n kong
Kết quả mong đợi: `Status` của Certificate là `Ready` và Secret có các key `tls.crt`, `tls.key`.
Xử lý chứng chỉ Client động thông qua External Provider
Đối với chứng chỉ Client (mTLS), việc tự động hóa phức tạp hơn vì mỗi client có một chứng chỉ riêng. Chúng ta sẽ sử dụng Cert-Manager với một template động hoặc tích hợp với External Provider (ví dụ: Vault hoặc Custom Controller) để cấp phát.
Trong kịch bản này, chúng ta giả định sử dụng Cert-Manager để cấp phát chứng chỉ Client cho một service cụ thể (ví dụ: `payment-service`) và lưu vào Secret riêng biệt. Trong môi trường production, bạn có thể thay thế `ClusterIssuer` bằng `External` provider như Vault.
Tạo Certificate cho Client của dịch vụ thanh toán. Chứng chỉ này sẽ được Client sử dụng để xác thực với Kong.
cat
Kết quả: Secret `payment-client-secret` được tạo, chứa chứng chỉ client hợp lệ với usage `client auth`.
Để tự động hóa việc cấp phát cho nhiều client động, bạn cần viết một Custom Controller hoặc sử dụng webhook. Dưới đây là ví dụ cấu hình Issuer sử dụng Vault (giả định Vault đã được setup) để thay thế CA nội bộ nếu cần mở rộng.
cat
Kết quả: ClusterIssuer `vault-issuer` được tạo, sẵn sàng yêu cầu chứng chỉ từ Vault API khi có Certificate resource trỏ đến nó.
Verify kết quả
Đảm bảo chứng chỉ Client có đúng usage và đã được ký bởi CA đúng.
kubectl get secret payment-client-secret -n kong -o yaml
openssl x509 -in /tmp/client.crt -text -noout | grep "Extended Key Usage"
Kết quả mong đợi: Trong output của openssl, dòng `Extended Key Usage` phải chứa `TLS Web Client Authentication`.
Cấu hình Kong để tự động tải lại cấu hình khi chứng chỉ thay đổi
Kong Gateway cần được cấu hình để tự động phát hiện sự thay đổi của Secret chứa chứng chỉ và reload cấu hình mà không cần restart pod. Điều này được thực hiện thông qua mechanism `watch` của Kong Operator hoặc cấu hình ConfigMap nếu dùng Helm trực tiếp.
Chúng ta sẽ cập nhật ConfigMap của Kong Gateway để trỏ vào Secret mới được Cert-Manager tạo (`kong-tls-secret`).
Chỉnh sửa ConfigMap `kong` trong namespace `kong` để ánh xạ Secret chứng chỉ vào biến môi trường hoặc cấu hình Upstream/Service tương ứng.
cat
Kết quả: ConfigMap được cập nhật, Kong Controller sẽ phát hiện thay đổi.
Đối với Kong Operator (khuyến nghị), hãy tạo resource `KongCertificate` trỏ vào Secret của Cert-Manager. Operator sẽ tự động sync và reload Kong.
cat
Kết quả: Kong Certificate resource được tạo, Kong Ingress Controller hoặc Gateway sẽ tự động tải cấu hình mới khi Secret thay đổi.
Cấu hình Service trong Kong để sử dụng chứng chỉ này cho mTLS. Chúng ta dùng annotation hoặc plugin `mutual-tls`.
cat
Kết quả: Service được gắn chứng chỉ Server và yêu cầu Client chứng thực mTLS.
Verify kết quả
Kiểm tra logs của Kong Gateway để đảm bảo không có lỗi khi load certificate và cấu hình đã được apply.
kubectl logs -n kong -l app=kong-gateway | grep -i "certificate"
kubectl exec -it -n kong -- kong config db query services -o yaml
Kết quả mong đợi: Logs không có lỗi `cert not found` hoặc `invalid cert`. Query service trả về cấu hình có `certificate` và `ca_certificates`.
Đảm bảo tính liên tục của dịch vụ khi chứng chỉ hết hạn
Để đảm bảo dịch vụ không bị ngắt khi chứng chỉ hết hạn, chúng ta cần cấu hình `renewBefore` trong Certificate resource sao cho Cert-Manager gia hạn trước khi chứng chỉ hiện tại hết hạn ít nhất 1-2 ngày.
Trong phần cấu hình Certificate ở mục 1, chúng ta đã thiết lập `renewBefore: 360h` (15 ngày). Đây là thời gian an toàn. Khi chứng chỉ còn 15 ngày nữa hết hạn, Cert-Manager sẽ tự động yêu cầu ký mới và cập nhật Secret.
Khi Secret được cập nhật, Kong Gateway (thông qua Kong Operator hoặc mechanism watch) sẽ phát hiện hash của Secret thay đổi và thực hiện `reload` cấu hình.
Để kiểm tra tính liên tục, chúng ta sẽ mô phỏng việc chứng chỉ sắp hết hạn bằng cách can thiệp vào thời gian của cert-manager hoặc tạo một chứng chỉ mới với ngày hết hạn sớm.
Thực hiện thủ công việc tạo một chứng chỉ mới để trigger quá trình reload, giả lập hành vi tự động của Cert-Manager.
kubectl delete certificate kong-tls -n kong
kubectl apply -f - # (Áp dụng lại file Certificate với duration ngắn hơn để test)
# Giả sử bạn áp dụng lại file với duration: 2h, renewBefore: 30m
Kết quả: Cert-Manager sẽ tạo chứng chỉ mới và cập nhật Secret `kong-tls-secret`.
Kiểm tra trạng thái của Kong Proxy để đảm bảo nó đã nhận được cấu hình mới mà không cần restart pod.
kubectl logs -n kong -l app=kong-gateway --tail=50 | grep "Configuration reload"
kubectl get pods -n kong -o wide | grep -v "Restart"
Kết quả mong đợi: Logs xuất hiện dòng `Configuration reload` hoặc `reloading kong`, và số lần restart của pod vẫn bằng 0.
Thực hiện test kết nối mTLS ngay sau khi chứng chỉ mới được cấp để đảm bảo không có khoảng chết (downtime).
curl -v --cert /path/to/new-client-cert.pem --key /path/to/new-client-key.pem --cacert /path/to/ca.crt https://kong-gateway.internal/api/payment
Kết quả mong đợi: HTTP 200 OK, không có lỗi `certificate has expired` hoặc `certificate signature failed`.
Verify kết quả
Đảm bảo quá trình chuyển đổi chứng chỉ (cũ -> mới) diễn ra mượt mà, không có request nào bị drop trong khoảng thời gian ngắn khi Cert-Manager đang xử lý gia hạn.
kubectl describe certificate kong-tls -n kong
kubectl get events -n kong --field-selector involvedObject.name=kong-tls
Kết quả mong đợi: Event log cho thấy quá trình `Issuing`, `Renewing` và `Updated` diễn ra liên tục, không có trạng thái `Failed`.
Điều hướng series:
Mục lục: Series: Xây dựng nền tảng Secure API Gateway với Kong, OPA và mTLS trên Kubernetes
« Phần 5: Xây dựng luồng xử lý an toàn với mTLS và Policy
Phần 7: Giám sát, Logging và Troubleshooting nâng cao »