Secret là mọi thứ cho phép truy cập: mật khẩu thiết bị, TACACS+ key, API token NetBox/Cloudflare, private key TLS/SSH, chuỗi kết nối DB. Mục tiêu không chỉ là "mã hoá" mà là trả lời được: ai đọc được, đọc ở đâu, xoay vòng thế nào, lộ thì biết không.
Các mô hình lưu secret
flowchart LR K["age key / KMS / vault password"] --> A["File mã hoá trong Git (SOPS, ansible-vault)"] A -->|"giải mã lúc chạy"| B["Env / file tmpfs"] V["Vault / secret manager"] -->|"API + auth, lease"| B B --> P["Playbook, app, CI job"]
Hai trường phái:
- Encrypted-in-Git (SOPS, ansible-vault): secret mã hoá nằm cùng code, review qua PR, không cần server. Bài toán chuyển thành bảo vệ một key giải mã.
- Secret store tập trung (HashiCorp Vault/OpenBao, AWS Secrets Manager, GCP Secret Manager, Azure Key Vault): app lấy secret qua API lúc chạy, có audit log, có thể cấp dynamic secret (credential sinh ra theo yêu cầu, tự hết hạn).
So sánh
| Tiêu chí | Biến môi trường / .env |
ansible-vault | SOPS + age/KMS | Vault / secret manager |
|---|---|---|---|---|
| Nơi lưu | Ngoài repo (máy, CI secret) | Trong repo, mã hoá AES256 | Trong repo, mã hoá theo giá trị | Server riêng |
| Diff trong Git | Không có | Cả file là blob (trừ khi dùng encrypt_string) |
Thấy key, chỉ value bị mã hoá | Không áp dụng |
| Phân quyền theo người/môi trường | Thủ công | Vault ID, mỗi ID một password | creation_rules theo path, nhiều recipient |
Policy chi tiết theo path |
| Audit ai đọc | Không | Không | Không (chỉ Git log ai sửa) | Có |
| Xoay vòng / dynamic secret | Thủ công | Thủ công, rekey |
sops updatekeys, rotate |
Có, lease + TTL |
| Hạ tầng cần | Không | Không | Không (age) hoặc KMS | Cluster HA, unseal, backup |
| Hợp với | Dev local, CI đơn giản | Repo Ansible thuần | Repo GitOps đa công cụ (Ansible, Helm, Terraform, k8s) | Tổ chức nhiều team, yêu cầu audit/compliance |
Nguyên tắc chung
- Không commit plaintext, kể cả repo private. Bật gitleaks trong pre-commit để chặn từ máy dev.
- Biến môi trường là kênh truyền, không phải nơi lưu: chúng lộ qua
/proc/<pid>/environ, crash dump, log debug,docker inspect. Ưu tiên file mount0600hoặc tmpfs cho secret nhạy cảm. - Một secret, một mục đích: token riêng cho từng tool/môi trường, quyền tối thiểu, để khi lộ chỉ cần thu hồi đúng một cái.
- Có quy trình xoay vòng trước khi cần đến nó. Secret không xoay được là rủi ro tồn đọng.
- Key giải mã (age private key, vault password, KMS IAM) là secret quan trọng nhất: để trong password manager / CI secret, không nằm cạnh repo.
- Log và output của automation phải che giá trị bí mật (Ansible
no_log: true, CI masked variables).
Khi nào dùng gì
| Tình huống | Gợi ý |
|---|---|
| Repo Ansible nhỏ, 1-3 người | ansible-vault với --vault-id, password trong password manager |
| Repo GitOps dùng chung cho Ansible + Kubernetes + Terraform | SOPS + age (thêm KMS khi lên cloud). Xem SOPS + age và ansible-vault |
| CI/CD (GitHub Actions, GitLab CI) | CI secret store hoặc OIDC tới cloud/Vault, không lưu token dài hạn |
| Nhiều team, cần audit, credential DB/cloud ngắn hạn | Vault/OpenBao hoặc secret manager của cloud |
| Kubernetes | External Secrets Operator kéo từ Vault/cloud, hoặc SOPS qua Flux/Argo CD plugin; Secret chỉ là Base64, không phải mã hoá |
| Lỡ commit secret | Xoay vòng ngay, rồi mới dọn lịch sử: xử lý secret bị lộ trong Git |