密钥、密码、API Key、证书等敏感凭证是攻击者的首要目标。硬编码在代码中的凭证是安全事件中最常见的入侵途径之一。本文系统讲解企业级密钥管理的方案选型与实践。
1. 为什么要专门的密钥管理
1.1 常见问题
❌ 密钥硬编码在代码中
├── Git 历史永久记录
├── 即使删除,commit 中仍可恢复
└── 全团队可见
❌ 密钥存储在配置文件中
├── 配置文件权限管理困难
├── 多环境复用同一密钥
└── 离职员工可能保留副本
❌ 密钥永不过期
├── 一旦泄露,永久有效
└── 无法追踪谁在使用
1.2 理想密钥管理特性
| 特性 | 说明 |
|---|---|
| 加密存储 | 静态加密,密钥分片 |
| 访问控制 | 基于身份的细粒度权限 |
| 审计日志 | 谁、何时、访问了什么密钥 |
| 动态凭证 | 短期、自动过期 |
| 自动轮换 | 定期更换,无需停机 |
| 版本控制 | 密钥版本管理和回滚 |
| 高可用 | 集群部署,无单点故障 |
2. HashiCorp Vault
2.1 架构
┌─────────────────────────────────────────────────────────────┐
│ Vault Cluster │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Vault Node │ │ Vault Node │ │ Vault Node │ │
│ │ (Active) │◄──►│ (Standby) │◄──►│ (Standby) │ │
│ │ Leader │ │ (Raft) │ │ (Raft) │ │
│ └──────┬──────┘ └─────────────┘ └─────────────┘ │
│ │ │
│ │ Storage Backend (Raft/Consul/...) │
│ └────────────────────────────────────────────► │
│ │
│ Unseal Keys (Shamir's Secret Sharing) │
│ - 5 把 key,需要 3 把才能 unseal │
└─────────────────────────────────────────────────────────────┘
2.2 核心概念
| 概念 | 说明 |
|---|---|
| Secrets Engine | 存储/生成 Secrets 的插件(KV、Database、PKI、AWS…) |
| Auth Method | 认证方式(Token/K8s/AppRole/LDAP/GitHub/OIDC…) |
| Policies | 基于路径的 ACL |
| Token | 访问 Vault 的凭证,可设置 TTL 和权限 |
2.3 KV Secrets Engine
# 启用 KV v2(版本化)
vault secrets enable -path=secret -version=2 kv
# 写入密钥
vault kv put secret/app/database \
username=dbuser \
password=supersecret
# 读取密钥
vault kv get -format=json secret/app/database
# 版本管理
vault kv put secret/app/database password=newpass # 创建 v2
vault kv get -version=1 secret/app/database # 读取 v1
vault kv delete secret/app/database # 软删除
vault kv undelete -versions=2 secret/app/database # 恢复
vault kv destroy -versions=2 secret/app/database # 永久删除
2.4 动态数据库凭证
# 启用数据库引擎
vault secrets enable database
# 配置 PostgreSQL 连接
vault write database/config/my-postgresql \
plugin_name=postgresql-database-plugin \
allowed_roles="app" \
connection_url="postgresql://{{username}}:{{password}}@db:5432/mydb" \
username="vaultadmin" \
password="vaultpass"
# 创建角色(定义生成的凭证权限)
vault write database/roles/app \
db_name=my-postgresql \
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; \
GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
default_ttl=1h \
max_ttl=24h
# 获取动态凭证
vault read database/creds/app
# 返回:username=v-token-app-xxx, password=xxx, lease_duration=3600
# 应用使用 1 小时后,凭证自动过期,Vault 自动清理数据库用户
2.5 Kubernetes 集成
# Vault + K8s 认证 + External Secrets Operator
apiVersion: v1
kind: ServiceAccount
metadata:
name: vault-auth
namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: vault-auth-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: vault-auth
namespace: default
---
# External Secret 从 Vault 同步到 K8s Secret
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: vault-db-secret
spec:
refreshInterval: 1h
secretStoreRef:
kind: SecretStore
name: vault-backend
target:
name: db-credentials
data:
- secretKey: password
remoteRef:
key: secret/data/app/database
property: password
3. 云厂商密钥管理服务
3.1 AWS KMS + Secrets Manager
import boto3
# KMS 加密/解密
kms = boto3.client('kms')
# 加密
encrypted = kms.encrypt(
KeyId='alias/my-key',
Plaintext=b'my-secret'
)
# Secrets Manager
secrets = boto3.client('secretsmanager')
# 创建密钥
secrets.create_secret(
Name='prod/myapp/database',
SecretString='{"username":"admin","password":"xxx"}'
)
# 获取密钥(自动解密)
response = secrets.get_secret(SecretId='prod/myapp/database')
credentials = json.loads(response['SecretString'])
# 自动轮换
secrets.rotate_secret(
SecretId='prod/myapp/database',
RotationLambdaARN='arn:aws:lambda:...:rotation-function'
)
3.2 阿里云 KMS
// 阿里云 KMS SDK
Config config = new Config()
.setAccessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
.setAccessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"))
.setEndpoint("kms.cn-hangzhou.aliyuncs.com");
Client client = new Client(config);
// 解密数据密钥
DecryptRequest decryptReq = new DecryptRequest()
.setCiphertextBlob(cipherKey);
DecryptResponse decryptRsp = client.decrypt(decryptReq);
byte[] plainKey = Base64.decode(decryptRsp.getBody().getPlaintext());
4. 动态凭证与短期凭证
4.1 为什么需要动态凭证
静态凭证问题:
- 泄露后长期有效
- 无法追踪谁在使用
- 轮换需要所有应用同时更新
动态凭证优势:
- 短期有效(TTL)
- 每个客户端获得唯一凭证
- 泄露影响范围和时间窗口有限
- 使用记录可审计
4.2 实现模式
| 服务 | 动态凭证实现 |
|---|---|
| 数据库 | Vault Database Secret Engine |
| AWS | Vault AWS Secret Engine / IAM Role Chaining |
| SSH | Vault SSH Secret Engine(Signed SSH Certificates) |
| PKI / TLS | Vault PKI Secret Engine(短期证书) |
4.3 Vault PKI 短期证书
# 启用 PKI
vault secrets enable pki
vault secrets tune -max-lease-ttl=8760h pki
# 生成根证书
vault write -field=certificate pki/root/generate/internal \
common_name="example.com" \
ttl=8760h > ca.crt
# 创建角色(签发服务器证书)
vault write pki/roles/web-server \
allowed_domains=example.com \
allow_subdomains=true \
max_ttl=72h
# 客户端获取短期证书
vault write -format=json pki/issue/web-server \
common_name=app.example.com \
ttl=24h
# 返回:certificate, issuing_ca, private_key, ca_chain
5. HSM(硬件安全模块)
5.1 为什么需要 HSM
软件密钥存储风险:
- 内存中密钥可被 dump
- 进程调试可提取密钥
- 管理员可直接读取
HSM 优势:
- 密钥永不离开硬件
- 加密运算在硬件中进行
- 防篡改(物理破坏即销毁密钥)
- FIPS 140-2 Level 3 认证
5.2 主流 HSM
| 产品 | 类型 | 适用 |
|---|---|---|
| AWS CloudHSM | 云托管 | AWS 环境 |
| Azure Dedicated HSM | 云托管 | Azure 环境 |
| Thales Luna 7 | 硬件/云 | 企业级 |
| Entrust nShield | 硬件 | 金融/政府 |
| HashiCorp Vault + HSM | 混合 | 自动 unseal |
5.3 Vault + HSM Auto-unseal
# vault.hcl
seal "pkcs11" {
lib = "/usr/lib/softhsm/libsofthsm2.so"
slot = "0"
pin = "1234"
key_label = "vault-unseal-key"
hmac_key_label = "vault-hmac-key"
generate_key = "true"
}
6. 密钥轮换策略
密钥轮换策略:
手动轮换:
1. 生成新密钥
2. 更新所有使用方
3. 验证
4. 删除旧密钥
(风险:窗口期长,容易遗漏)
自动轮换(推荐):
1. 定期自动生成新密钥
2. 双密钥并行期(新旧同时有效)
3. 所有方自动获取新密钥
4. 旧密钥优雅退役
6.1 Vault 自动轮换
# 启用自动轮换
vault write database/rotate-role/app \
db_name=my-postgresql
# 手动触发轮换
vault write -f database/rotate-root/my-postgresql
# K8s External Secrets 自动同步
# 配置 refreshInterval,定期从 Vault 拉取最新密钥
7. 密钥管理 Checklist
| 检查项 | 建议 |
|---|---|
| 无硬编码密钥 | 使用环境变量或密钥管理服务 |
| 密钥加密存储 | 静态加密,密钥分片 |
| 短期凭证优先 | 使用 Vault/AWS IAM 动态生成 |
| 定期轮换 | 自动化,最小中断 |
| 访问审计 | 谁访问了什么密钥 |
| 最小权限 | 每个服务只访问所需密钥 |
| 紧急情况 | 密钥撤销/轮换预案 |
8. 总结
密钥管理的核心原则:
┌─────────────────────────────────────────────────────────┐
│ 密钥管理层次 │
├─────────────────────────────────────────────────────────┤
│ 最外层: 动态凭证(推荐) │
│ - Vault Database / AWS IAM / GCP Service Account │
│ - 短期、唯一、自动过期 │
│ │
│ 中间层: 集中式密钥管理 │
│ - HashiCorp Vault / AWS Secrets Manager / Azure KeyVault│
│ - 加密存储、访问控制、审计 │
│ │
│ 核心层: HSM(最高安全) │
│ - CloudHSM / Luna / nShield │
│ - FIPS 140-2, 密钥不出硬件 │
└─────────────────────────────────────────────────────────┘
好的密钥管理应该让开发者感受不到密钥的存在——自动注入、自动轮换、自动过期。任何需要手动复制粘贴密钥的场景都是安全隐患。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。