Ngừng lưu trữ Secret trong Git: Hướng dẫn sử dụng 1Password Connect trên Kubernetes

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

Vượt xa Base64: Tại sao chiến lược quản lý Secret của bạn cần được nâng cấp

Hầu hết hành trình tiếp cận Kubernetes đều bắt đầu với tài nguyên Secret mặc định. Mặc dù dễ sử dụng, các secret gốc này thực chất chỉ là các chuỗi được mã hóa Base64 chứ không phải dữ liệu được mã hóa thực sự. Việc phụ thuộc vào chúng mà không có cấu hình bổ sung giống như việc đặt chìa khóa nhà dưới một tấm thảm chùi chân trong suốt vậy. Tôi đã thấy nhiều đội ngũ gặp khó khăn với tình trạng “tràn lan secret” (secret sprawl), nơi các API key nhạy cảm bị rò rỉ trong lịch sử Git hoặc bị ghi cứng (hardcode) trong các pipeline CI/CD.

Khi chuyển sang mô hình quản lý tập trung, bạn thường có ba lựa chọn:

  • Native Kubernetes Secrets: Đơn giản nhưng thiếu nhật ký kiểm tra (audit trail). Lưu trữ chúng trong Git—ngay cả qua các công cụ như SealedSecrets—tạo ra một quy trình làm việc cồng kềnh, nơi các nhà phát triển không thể dễ dàng biết được những gì hiện đang được triển khai.
  • HashiCorp Vault: Đây là giải pháp “nặng ký” cho các môi trường yêu cầu bảo mật cao. Tuy nhiên, chi phí vận hành rất lớn. Bạn cần một đội ngũ chuyên trách để quản lý các khóa unseal, xử lý storage backend và thiết lập các chính sách HCL phức tạp.
  • 1Password Connect: Đóng vai trò là một lớp đồng bộ giữa trình quản lý mật khẩu thân thiện với người dùng và hạ tầng tự động của bạn. Nó cho phép các đội ngũ DevOps sử dụng giao diện 1Password quen thuộc trong khi vẫn đẩy được các secret đó vào Kubernetes theo cách lập trình.

Tôi đã triển khai mô hình này trong các môi trường production từ các startup nhỏ đến các doanh nghiệp quy mô vừa. Nó luôn đạt được sự cân bằng hoàn hảo giữa năng suất của nhà phát triển và các yêu cầu bảo mật khắt khe.

Những đánh đổi trong thực tế

Không có công cụ nào là hoàn hảo cho mọi tình huống. 1Password Connect thường là giải pháp “vừa vặn” cho các đội ngũ muốn bảo mật mà không muốn gánh nặng vận hành một cụm Vault đầy đủ.

Ưu điểm

  • Giao diện thân thiện: Các kiểm toán viên bảo mật có thể xem xét quyền truy cập thông qua giao diện web trực quan. Họ không cần phải học kubectl hay giải mã các chuỗi ký tự trên terminal.
  • Cập nhật tức thì: Khi một nhà phát triển cập nhật mật khẩu cơ sở dữ liệu trong ứng dụng 1Password, thay đổi sẽ được cập nhật đến cụm Kubernetes trong khoảng 10 giây.
  • Sự cô lập: Bạn có thể giới hạn việc tích hợp cho các “Vault” cụ thể. Điều này đảm bảo cụm production của bạn không bao giờ nhìn thấy các thông tin đăng nhập cá nhân hoặc quản trị.

Nhược điểm

  • Phụ thuộc bên ngoài: Nếu API toàn cầu của 1Password ngoại tuyến, bạn không thể đồng bộ các secret mới. Tuy nhiên, các secret hiện tại vẫn được lưu tạm (cache) trong cụm, vì vậy ứng dụng của bạn sẽ không bị sập.
  • Tài nguyên tiêu thụ: Bạn phải chạy hai container nhỏ. Theo kinh nghiệm của tôi, chúng thường tiêu tốn tổng cộng chưa đến 150MB RAM, một con số không đáng kể đối với hầu hết các cụm.

Kiến trúc sẵn sàng cho Production

Bên dưới hệ thống, quy trình dựa trên hai thành phần chính do 1Password cung cấp:

  1. Connect Server: Một deployment chứa các container connect-apiconnect-sync. Nó đóng vai trò là cổng bảo mật giữa cụm của bạn và máy chủ của 1Password.
  2. 1Password Operator: Một Kubernetes controller theo dõi một Custom Resource Definition (CRD) có tên là OnePasswordItem. Nó tự động tạo ra các secret gốc của Kubernetes dựa trên dữ liệu từ 1Password của bạn.

Tôi khuyên bạn nên triển khai các thành phần này vào một namespace riêng biệt có tên 1password-system. Hãy sử dụng các chính sách RBAC nghiêm ngặt để đảm bảo chỉ các service account được ủy quyền mới có thể giao tiếp với Connect API.

Từng bước: Triển khai 1Password Connect

1. Tạo thông tin xác thực

Bắt đầu tại dashboard dành cho nhà phát triển của 1Password. Tạo một tích hợp “Connect” mới và chọn các Vault cụ thể mà bạn muốn chia sẻ. Bạn sẽ nhận được một file 1password-credentials.json và một Access Token. Hãy coi chúng như mật khẩu root; nếu chúng bị lộ, toàn bộ kho secret của bạn sẽ gặp nguy hiểm.

2. Triển khai Connect Server

Helm là cách nhanh nhất để bắt đầu. Đầu tiên, hãy tạo namespace và một secret để lưu trữ file tích hợp của bạn.

kubectl create namespace 1password-system

# Tải file thông tin xác thực của bạn lên một cách an toàn
kubectl create secret generic op-credentials \
  --from-file=1password-credentials.json=./1password-credentials.json \
  -n 1password-system

# Thêm repository chính thức
helm repo add 1password https://1password.github.io/connect-helm-charts/
helm repo update

Bây giờ, hãy cài đặt Connect server. Thay thế phần giữ chỗ bằng Access Token thực tế của bạn.

helm install connect 1password/connect \
  --namespace 1password-system \
  --set-file connect.credentials=1password-credentials.json \
  --set connect.token.value="token-cua-ban-tai-day"

3. Cài đặt 1Password Operator

Operator xử lý logic chuyển đổi các item từ 1Password thành Kubernetes secret. Việc cài đặt riêng biệt giúp logic quản lý của bạn luôn sạch sẽ.

helm install operator 1password/onepassword-operator \
  --namespace 1password-system \
  --set connect.url="http://connect.1password-system.svc.cluster.local:8080" \
  --set connect.token="token-cua-ban-tai-day"

4. Đồng bộ Secret đầu tiên

Thay vì tạo các secret YAML thủ công, giờ đây bạn định nghĩa một OnePasswordItem. Manifest này chỉ định cho Operator chính xác item nào trong vault của bạn cần lấy.

apiVersion: onepassword.com/v1
kind: OnePasswordItem
metadata:
  name: db-credentials
  namespace: default
spec:
  itemPath: "vaults/Production/items/Database"
  outputs:
    - name: password
      path: "fields/password"
    - name: username
      path: "fields/username"

Áp dụng file YAML này. Chỉ trong vài giây, Operator sẽ tạo ra một Kubernetes Secret tiêu chuẩn có tên là db-credentials. Ứng dụng của bạn có thể gắn (mount) secret này dưới dạng biến môi trường hoặc volume mà không cần biết đến sự tồn tại của 1Password.

Những bài học kinh nghiệm từ thực tế

Việc vận hành hệ thống này trong môi trường production đã dạy cho tôi một vài bài học quan trọng về độ tin cậy và bảo mật.

Phân đoạn các Vault của bạn

Đừng bao giờ kết nối một vault “Chung” (General) với Kubernetes. Hãy tạo các vault riêng cho từng môi trường như K8S-Staging hoặc K8S-Prod. Điều này giúp giới hạn “phạm vi ảnh hưởng” (blast radius) nếu một cụm bị xâm nhập.

Theo dõi trạng thái đồng bộ

If token của bạn hết hạn hoặc mạng gặp sự cố, việc cập nhật secret sẽ thất bại trong im lặng. Tôi khuyên bạn nên thiết lập cảnh báo Prometheus cho chỉ số op_connect_sync_errors_total. Nếu giá trị này lớn hơn 0 trong hơn 5 phút, đội ngũ của bạn cần phải kiểm tra ngay.

Tận dụng lịch sử phiên bản

1Password lưu giữ toàn bộ lịch sử của mọi thay đổi. Nếu việc di chuyển cơ sở dữ liệu (database migration) gặp trục trặc do thay đổi thông tin đăng nhập, bạn có thể khôi phục (revert) item trong giao diện 1Password. Operator sẽ đồng bộ giá trị cũ trở lại cụm trong vòng chưa đầy 15 giây, giúp bạn tránh được một đợt ngừng hoạt động kéo dài.

Thắt chặt RBAC

Giới hạn những ai có quyền tạo tài nguyên OnePasswordItem. Nếu một người dùng xấu có thể tạo các tài nguyên này trong một namespace, về lý thuyết họ có thể lấy bất kỳ secret nào từ các vault được liên kết với instance Connect đó.

Lời kết

Quản lý secret không nên là một công việc thủ công nhàm chán. Bằng cách sử dụng 1Password Connect, bạn mang đến cho các nhà phát triển một công cụ quen thuộc trong khi vẫn duy trì tiêu chuẩn bảo mật cao. Nó loại bỏ hoàn toàn nhu cầu lưu trữ secret trong Git và cung cấp nhật ký kiểm tra rõ ràng, có thể tìm kiếm được cho mọi thông tin đăng nhập trong hệ thống của bạn.

Share: