HashiCorp Vault密钥管理:服务器敏感信息集中管理与动态数据库凭证实战
密码和密钥散落在.env文件、配置文件、代码仓库中,是企业安全的最大隐患之一。HashiCorp Vault提供集中化密钥管理、动态凭证生成和完整审计日志,是保护敏感信息的工业级解决方案。
一、Vault解决的核心问题
- 密钥集中管理:所有密码、Token、证书统一存储在Vault,不再散落各处
- 动态凭证:应用启动时从Vault获取临时数据库密码(TTL 1小时),无需在代码中存储静态密码
- 访问控制:细粒度的策略控制,不同应用只能访问自己需要的密钥
- 完整审计:所有密钥访问操作记录日志,满足合规要求
- 密钥轮换:到期自动轮换,减少密钥泄露的影响范围
二、Docker部署Vault
<code">mkdir -p /srv/vault/{config,data,logs} && cd /srv/vault<code"># config/vault.hcl
ui = true
storage "file" {
path = "/vault/data"
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_disable = false
tls_cert_file = "/vault/tls/fullchain.pem"
tls_key_file = "/vault/tls/privkey.pem"
}
api_addr = "https://vault.yourdomain.com:8200"
cluster_addr = "https://vault.yourdomain.com:8201"
log_level = "INFO"
log_file = "/vault/logs/vault.log"
# 审计日志
audit {
type = "file"
options = {
file_path = "/vault/logs/audit.log"
}
}<code"># docker-compose.yml
version: '3.8'
services:
vault:
image: hashicorp/vault:1.16
restart: unless-stopped
cap_add:
- IPC_LOCK # 防止密钥被swap到磁盘
environment:
VAULT_ADDR: https://127.0.0.1:8200
volumes:
- ./config:/vault/config:ro
- ./data:/vault/data
- ./logs:/vault/logs
- /etc/letsencrypt/live/vault.yourdomain.com:/vault/tls:ro
ports:
- "127.0.0.1:8200:8200"
command: vault server -config=/vault/config/vault.hcl
healthcheck:
test: ["CMD", "vault", "status"]
interval: 30s
timeout: 10s
retries: 3<code">docker compose up -d
三、初始化Vault
<code"># 进入容器初始化Vault(只需执行一次)
export VAULT_ADDR='https://127.0.0.1:8200'
export VAULT_SKIP_VERIFY=true # 自签名证书时使用
docker exec -it vault-vault-1 vault operator init \
-key-shares=5 \ # 生成5份解封密钥
-key-threshold=3 # 需要其中3份才能解封
# 输出(务必安全保存!):
# Unseal Key 1: abc123...
# Unseal Key 2: def456...
# Unseal Key 3: ghi789...
# Unseal Key 4: jkl012...
# Unseal Key 5: mno345...
# Initial Root Token: hvs.XXXXXXXXXXXXXX
# 解封Vault(每次重启后需要执行3次,各使用不同的密钥)
docker exec -it vault-vault-1 vault operator unseal # 输入密钥1
docker exec -it vault-vault-1 vault operator unseal # 输入密钥2
docker exec -it vault-vault-1 vault operator unseal # 输入密钥3
# 使用Root Token登录
export VAULT_TOKEN="hvs.XXXXXXXXXXXXXX"
docker exec -e VAULT_TOKEN=$VAULT_TOKEN vault-vault-1 vault status四、KV密钥存储
<code"># 启用KV v2密钥引擎
vault secrets enable -path=secret kv-v2
# 存储应用密钥
vault kv put secret/myapp/database \
host="数据库内网IP" \
port="3306" \
name="appdb" \
username="appuser" \
password="数据库密码"
vault kv put secret/myapp/redis \
host="127.0.0.1" \
port="6379" \
password="Redis密码"
vault kv put secret/myapp/stripe \
secret_key="sk_live_xxxxx" \
webhook_secret="whsec_xxxxx"
# 读取密钥
vault kv get secret/myapp/database
vault kv get -field=password secret/myapp/database
# 查看历史版本
vault kv metadata get secret/myapp/database五、动态数据库凭证
<code"># 启用数据库密钥引擎
vault secrets enable database
# 配置MySQL连接
vault write database/config/myapp-mysql \
plugin_name=mysql-database-plugin \
connection_url="{{username}}:{{password}}@tcp(数据库内网IP:3306)/" \
allowed_roles="myapp-readonly,myapp-readwrite" \
username="vault-manager" \
password="管理用户密码"
# 在MySQL中创建Vault管理用户
# mysql -u root -p -e "
# CREATE USER 'vault-manager'@'%' IDENTIFIED BY '管理用户密码';
# GRANT CREATE USER, GRANT OPTION ON *.* TO 'vault-manager'@'%';
# GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO 'vault-manager'@'%' WITH GRANT OPTION;
# FLUSH PRIVILEGES;"
# 创建只读角色(TTL 1小时,最长8小时)
vault write database/roles/myapp-readonly \
db_name=myapp-mysql \
creation_statements="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}'; GRANT SELECT ON appdb.* TO '{{name}}'@'%';" \
revocation_statements="DROP USER IF EXISTS '{{name}}'@'%';" \
default_ttl=1h \
max_ttl=8h
# 读写角色
vault write database/roles/myapp-readwrite \
db_name=myapp-mysql \
creation_statements="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}'; GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO '{{name}}'@'%';" \
revocation_statements="DROP USER IF EXISTS '{{name}}'@'%';" \
default_ttl=1h \
max_ttl=8h
# 获取动态凭证(每次获取都生成新的临时用户)
vault read database/creds/myapp-readonly
# 输出:
# lease_duration: 1h
# username: v-appuser-AbCdEf12345
# password: 临时随机密码六、策略管理(访问控制)
<code"># 创建应用专用策略(只能读取自己的密钥)
cat > /tmp/myapp-policy.hcl << 'EOF'
# 允许读取应用密钥
path "secret/data/myapp/*" {
capabilities = ["read", "list"]
}
# 允许获取动态数据库凭证
path "database/creds/myapp-readwrite" {
capabilities = ["read"]
}
# 允许续签自己的Token
path "auth/token/renew-self" {
capabilities = ["update"]
}
EOF
vault policy write myapp-policy /tmp/myapp-policy.hcl
# 创建应用Token(绑定策略)
vault token create \
-policy=myapp-policy \
-ttl=24h \
-renewable=true \
-display-name=myapp-production七、PHP应用集成Vault
<code"><?php // 从Vault获取数据库密码(动态凭证) class VaultClient { private string $vaultAddr; private string $token; public function __construct(string $vaultAddr, string $token) { $this->vaultAddr = rtrim($vaultAddr, '/');
$this->token = $token;
}
public function getDatabaseCredentials(): array {
$response = $this->request('GET', '/v1/database/creds/myapp-readwrite');
return [
'username' => $response['data']['username'],
'password' => $response['data']['password'],
'lease_id' => $response['lease_id'],
'ttl' => $response['lease_duration'],
];
}
public function getSecret(string $path): array {
$response = $this->request('GET', "/v1/secret/data/{$path}");
return $response['data']['data'];
}
private function request(string $method, string $path): array {
$ch = curl_init("{$this->vaultAddr}{$path}");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_HTTPHEADER => ["X-Vault-Token: {$this->token}"],
CURLOPT_TIMEOUT => 5,
]);
$body = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($code !== 200) {
throw new RuntimeException("Vault请求失败:HTTP {$code}");
}
return json_decode($body, true);
}
}
// 使用示例
$vault = new VaultClient(
'https://vault.yourdomain.com:8200',
$_ENV['VAULT_TOKEN']
);
// 获取临时数据库凭证
$creds = $vault->getDatabaseCredentials();
$pdo = new PDO(
"mysql:host=数据库IP;dbname=appdb;charset=utf8mb4",
$creds['username'],
$creds['password']
);
// 获取Stripe密钥
$stripe = $vault->getSecret('myapp/stripe');
\Stripe\Stripe::setApiKey($stripe['secret_key']);八、总结
Vault将密钥管理从"散落在各种配置文件里"升级为"集中管控、动态生成、全程审计"的企业级方案。动态数据库凭证是最有价值的功能——即使某个应用的Vault Token泄露,攻击者获取的数据库密码也只有1小时有效期。IDC.Net的香港VPS提供完整的安全基础设施,配合Vault可以建立符合金融和医疗行业合规要求的密钥管理体系。
版权声明:
作者:后浪云
链接:https://idc.net/help/442889/
文章版权归作者所有,未经允许请勿转载。
THE END
