HashiCorp Vault 機密管理完整指南

使用 HashiCorp Vault 管理機密資訊、動態憑證、加密即服務,保護應用程式敏感資料

專案簡介

HashiCorp Vault 是一個機密管理和資料保護平台。提供安全存取 token、密碼、憑證、加密金鑰等敏感資料的方式,支援動態機密生成和加密即服務。

GitHub Stars: 35K+

核心功能

  • 機密儲存 - 安全存放敏感資料
  • 動態機密 - 自動生成短期憑證
  • 加密服務 - Transit 引擎加解密
  • 身份驗證 - 多種認證方式
  • 稽核日誌 - 完整操作記錄

快速部署

Docker(開發模式)

1
2
3
4
5
6
7
docker run -d \
  --cap-add=IPC_LOCK \
  -e 'VAULT_DEV_ROOT_TOKEN_ID=myroot' \
  -e 'VAULT_DEV_LISTEN_ADDRESS=0.0.0.0:8200' \
  -p 8200:8200 \
  --name vault \
  hashicorp/vault

Docker Compose(生產模式)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
version: '3.8'
services:
  vault:
    image: hashicorp/vault
    cap_add:
      - IPC_LOCK
    ports:
      - "8200:8200"
    environment:
      - VAULT_ADDR=http://0.0.0.0:8200
    volumes:
      - ./vault/config:/vault/config
      - vault-data:/vault/data
    command: server

volumes:
  vault-data:

設定檔

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# vault/config/config.hcl
ui = true

listener "tcp" {
  address     = "0.0.0.0:8200"
  tls_disable = 1
}

storage "file" {
  path = "/vault/data"
}

api_addr = "http://0.0.0.0:8200"

初始化與解封

初始化

1
2
3
4
export VAULT_ADDR='http://127.0.0.1:8200'

# 初始化(產生 5 把金鑰,需要 3 把解封)
vault operator init -key-shares=5 -key-threshold=3

解封

1
2
3
vault operator unseal <key-1>
vault operator unseal <key-2>
vault operator unseal <key-3>

登入

1
vault login <root-token>

KV 機密引擎

啟用 KV v2

1
vault secrets enable -path=secret kv-v2

儲存機密

1
2
3
vault kv put secret/myapp/config \
  username="admin" \
  password="s3cr3t"

讀取機密

1
2
3
4
5
6
7
vault kv get secret/myapp/config

# JSON 格式
vault kv get -format=json secret/myapp/config

# 特定欄位
vault kv get -field=password secret/myapp/config

版本控制

1
2
3
4
5
6
7
8
# 列出版本
vault kv metadata get secret/myapp/config

# 讀取舊版本
vault kv get -version=1 secret/myapp/config

# 刪除特定版本
vault kv delete -versions=2 secret/myapp/config

動態機密

資料庫機密引擎

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# 啟用引擎
vault secrets enable database

# 設定 MySQL 連線
vault write database/config/mysql-db \
    plugin_name=mysql-database-plugin \
    connection_url="{{username}}:{{password}}@tcp(mysql:3306)/" \
    allowed_roles="mysql-role" \
    username="vault" \
    password="vault-password"

# 建立角色
vault write database/roles/mysql-role \
    db_name=mysql-db \
    creation_statements="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}'; GRANT SELECT ON mydb.* TO '{{name}}'@'%';" \
    default_ttl="1h" \
    max_ttl="24h"

# 取得動態憑證
vault read database/creds/mysql-role

AWS 機密引擎

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 啟用引擎
vault secrets enable aws

# 設定 AWS
vault write aws/config/root \
    access_key=AKIAIOSFODNN7EXAMPLE \
    secret_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY \
    region=us-east-1

# 建立角色
vault write aws/roles/s3-read \
    credential_type=iam_user \
    policy_document=-<<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "*"
    }
  ]
}
EOF

# 取得 AWS 憑證
vault read aws/creds/s3-read

Transit 加密引擎

啟用引擎

1
vault secrets enable transit

建立加密金鑰

1
vault write -f transit/keys/my-key

加密資料

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 加密(base64 編碼輸入)
vault write transit/encrypt/my-key \
    plaintext=$(echo "secret data" | base64)

# 解密
vault write transit/decrypt/my-key \
    ciphertext="vault:v1:abc123..."

# 解碼結果
echo "c2VjcmV0IGRhdGE=" | base64 -d

身份驗證

Token

1
2
3
4
5
6
7
8
# 建立 Token
vault token create -policy=my-policy -ttl=1h

# 查看 Token
vault token lookup <token>

# 撤銷 Token
vault token revoke <token>

AppRole

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# 啟用 AppRole
vault auth enable approle

# 建立角色
vault write auth/approle/role/my-app \
    token_policies="my-policy" \
    token_ttl=1h \
    token_max_ttl=4h

# 取得 Role ID
vault read auth/approle/role/my-app/role-id

# 取得 Secret ID
vault write -f auth/approle/role/my-app/secret-id

# 登入
vault write auth/approle/login \
    role_id=xxx \
    secret_id=yyy

Kubernetes

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 啟用 K8s 認證
vault auth enable kubernetes

# 設定
vault write auth/kubernetes/config \
    kubernetes_host="https://kubernetes:443" \
    kubernetes_ca_cert=@ca.crt

# 建立角色
vault write auth/kubernetes/role/my-app \
    bound_service_account_names=my-app \
    bound_service_account_namespaces=default \
    policies=my-policy \
    ttl=1h

政策管理

建立政策

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# my-policy.hcl
path "secret/data/myapp/*" {
  capabilities = ["create", "read", "update", "delete", "list"]
}

path "database/creds/mysql-role" {
  capabilities = ["read"]
}

path "transit/encrypt/my-key" {
  capabilities = ["update"]
}

path "transit/decrypt/my-key" {
  capabilities = ["update"]
}
1
vault policy write my-policy my-policy.hcl

應用程式整合

Python

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import hvac

client = hvac.Client(url='http://localhost:8200', token='myroot')

# 讀取機密
secret = client.secrets.kv.v2.read_secret_version(path='myapp/config')
password = secret['data']['data']['password']

# 寫入機密
client.secrets.kv.v2.create_or_update_secret(
    path='myapp/config',
    secret={'username': 'admin', 'password': 'new-password'}
)

Kubernetes Sidecar

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
apiVersion: v1
kind: Pod
metadata:
  annotations:
    vault.hashicorp.com/agent-inject: "true"
    vault.hashicorp.com/role: "my-app"
    vault.hashicorp.com/agent-inject-secret-config: "secret/data/myapp/config"
spec:
  serviceAccountName: my-app
  containers:
    - name: app
      image: my-app
      volumeMounts:
        - name: vault-secrets
          mountPath: /vault/secrets

相關連結

延伸閱讀

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy