Zero Trust trong thực tế: Mở rộng mTLS trên Kubernetes với SPIRE và SPIFFE

DevOps tutorial - IT technology blog
DevOps tutorial - IT technology blog

Vượt xa sự mong manh của bảo mật dựa trên địa chỉ IP

Bảo mật mạng truyền thống thường dựa trên chiến lược “lâu đài và hào nước”. Chúng ta xây dựng những bức tường lửa cao ngất và mặc định rằng mọi thứ bên trong chu vi đó đều an toàn. Tuy nhiên, trong môi trường Kubernetes hiện đại, địa chỉ IP chỉ là tạm thời. Một cluster đơn lẻ có thể khởi tạo và xóa bỏ tới 5.000 Pod mỗi ngày. Việc dựa vào Danh sách kiểm soát truy cập (ACL) dựa trên IP trong môi trường này là một công thức dẫn đến sự quá tải và các lỗ hổng bảo mật.

Zero Trust giải quyết vấn đề này bằng cách bỏ qua vị trí và tập trung vào định danh (identity). SPIFFE (Secure Production Identity Framework for Everyone) định nghĩa cấu trúc của định danh đó. SPIRE (SPIFFE Runtime Environment) là công cụ thực tế để cấp phát các định danh này. Sau khi vận hành hệ thống này trong môi trường production nửa năm, tôi thấy nó đáng tin cậy hơn nhiều so với việc quản lý một Service Mesh nặng nề như Istio chỉ để phục vụ mutual TLS (mTLS).

Thiết lập SPIRE trên Kubernetes

Để cấp phát định danh, chúng ta cần một nền tảng vững chắc. Trong Kubernetes, điều này có nghĩa là triển khai SPIRE Server đóng vai trò là Certificate Authority (CA) và các SPIRE Agent dưới dạng DaemonSet trên mọi node.

Điều kiện tiên quyết

  • Một Kubernetes cluster (khuyến nghị v1.22+).
  • Helm v3 để triển khai.
  • Nắm vững kiến thức cơ bản về cách hoạt động của Kubernetes ServiceAccounts.

Các bước triển khai

Sử dụng Helm charts chính thức là con đường đáng tin cậy nhất. Chúng xử lý các công việc phức tạp như cấu hình service accounts, roles và các volume mount quan trọng cho Workload API. Bắt đầu bằng việc thêm repository:

helm repo add spiffe https://spiffe.github.io/helm-charts-hardened/
helm repo update

Việc cô lập hạ tầng bảo mật là một thực hành tốt (best practice). Tôi luôn triển khai các thành phần này vào một namespace riêng biệt để tách biệt chúng khỏi lưu lượng ứng dụng thông thường:

kubectl create namespace spire

# Chúng tôi thường cấp phát 2Gi bộ nhớ cho server trong các cluster quy mô trung bình
helm install spire spiffe/spire -n spire \
  --set spire-server.ca_key_type=rsa-2048 \
  --set spire-agent.trust_domain=prod.itfromzero.com

Một bài học xương máu: hãy chọn trust_domain của bạn một cách cẩn thận. Nếu sau này bạn đổi từ example.org sang internal.net, bạn sẽ phải cấp lại mọi định danh trong hệ thống, gây ra một cơn ác mộng về đồng bộ hóa dữ liệu.

Điều phối định danh: Cấu hình

Khi các agent đã hoạt động, chúng sẽ giao tiếp với SPIRE Server để chứng minh định danh của node máy chủ. Nhưng làm thế nào một Pod cụ thể nhận được ID duy nhất của nó? Điều này được xử lý thông qua “Xác thực Workload” (Workload Attestation).

Định nghĩa Trust Domain

Hãy coi Trust Domain như gốc tin cậy (root of trust) của bạn, ví dụ: prod.itfromzero.com. Mọi định danh đều tuân theo định dạng SPIFFE ID: spiffe://trust-domain/path/to/workload. Nó sạch sẽ, có tính phân cấp và dễ dàng kiểm định.

Đăng ký Workload

Tự động hóa định danh luôn tốt hơn làm thủ công. SPIRE Controller Manager sẽ theo dõi các Pod mới và tự động tạo các mục đăng ký dựa trên label. Tuy nhiên, để thử nghiệm, bạn có thể muốn xem một mục đăng ký thủ công trông như thế nào:

# Đăng ký thủ công cho một dịch vụ thanh toán
kubectl exec -n spire spire-server-0 -- \
/opt/spire/bin/spire-server entry create \
    -spiffeID spiffe://prod.itfromzero.com/ns/payments/sa/processor \
    -parentID spiffe://prod.itfromzero.com/spire/agent/k8s_psat/my-cluster/node-name \
    -selector k8s:ns:payments \
    -selector k8s:sa:processor

Trong môi trường production, các lệnh thủ công là một rủi ro. Tôi thực sự khuyên dùng SPIRE Kubernetes Workload Registrar. Nó tự động ánh xạ định danh tới Pod, vì vậy pipeline CI/CD của bạn thậm chí không cần biết đến sự tồn tại của SPIRE.

Tự động hóa mTLS

Lợi ích thực sự là mTLS tự động. SPIRE cấp phát các SVID (SPIFFE Verifiable Identity Documents) dưới dạng chứng chỉ X.509. SPIRE Agent sẽ tự động xoay vòng (rotate) các chứng chỉ này sau mỗi vài giờ. Quan trọng nhất là private key chỉ nằm trong bộ nhớ của node và không bao giờ chạm vào Kubernetes Secret hay ổ đĩa cứng.

Hiệu suất thực tế và Giám sát

Sau 6 tháng, thắng lợi lớn nhất là sự chấm dứt hoàn toàn của việc quản lý thông tin xác thực tĩnh. Chúng tôi đã chuyển từ việc xoay vòng thủ công hơn 20 secret xuống còn con số không. Hệ thống đã xử lý hơn 1.000 lượt xoay vòng định danh mỗi ngày mà không cần bất kỳ sự can thiệp thủ công nào.

Xác thực định danh

Bạn cần biết liệu một Pod có thực sự sở hữu chứng chỉ của nó hay không. Tôi sử dụng một lệnh kiểm tra đơn giản từ bên trong container ứng dụng để xác minh trạng thái Workload API:

# Kiểm tra định danh từ container của ứng dụng
/opt/spire/bin/spire-agent api fetch x509 -socketPath /run/spire/sockets/agent.sock

Nếu lấy dữ liệu thành công, nó sẽ trả về SPIFFE ID và thời hạn chứng chỉ. Nếu bạn thấy lỗi “permission denied”, hãy kiểm tra lại các selector của mình. Thông thường, Pod đang chạy với một Service Account khác với cái bạn đã đăng ký.

Giám sát và Log

Nền tảng Zero Trust chỉ thực sự tốt khi nó có khả năng hiển thị rõ ràng. Tôi tập trung vào ba chỉ số cụ thể trong dashboard Grafana của mình:

  1. Registration Rate: Các mốc tăng vọt ở đây có thể cho thấy lỗi vòng lặp triển khai hoặc vấn đề về mở rộng quy mô.
  2. Attestation Latency: Chúng tôi đặt mục tiêu dưới 200ms. Nếu con số này tăng lên, có khả năng SPIRE Server đang bị nghẽn CPU.
  3. SVID Expiration: Chúng tôi thiết lập cảnh báo nếu bất kỳ định danh nào còn dưới 20% thời hạn sử dụng.

Hãy lưu ý rằng các SPIRE Agent lưu bộ nhớ đệm (cache) SVID cục bộ. Nếu SPIRE Server ngừng hoạt động trong 10 phút, các dịch vụ của bạn sẽ không bị gián đoạn ngay lập tức. Chúng sẽ tiếp tục sử dụng các chứng chỉ đã lưu trong cache cho đến khi hết hạn.

Bài học sau 6 tháng triển khai Production

Công nghệ đã sẵn sàng, nhưng sự thay đổi trong tư duy mới là thách thức thực sự. Các nhà phát triển không thể chỉ đơn giản dùng “curl” tới một endpoint nội bộ nữa; họ phải sử dụng các định danh được cung cấp bởi Workload API. Các công cụ như thư viện go-spiffe hoặc Envoy sidecars giúp quá trình chuyển đổi này trở nên dễ dàng hơn. Nếu bạn muốn vượt qua các quy tắc tường lửa cơ bản và thực sự thắt chặt bảo mật cho cluster của mình, bảo mật dựa trên định danh với SPIRE là con đường vững chắc nhất.

Share: