第十二章:Vault 加密与安全
学习使用 Ansible Vault 加密敏感数据,确保安全。
最后更新: 2024-01-26
页面目录
Ansible Vault 加密与安全
Ansible Vault 是用于加密敏感数据的功能,确保密码、密钥等敏感信息的安全。
Vault 概述
┌─────────────────────────────────────────────────────────────────┐
│ Ansible Vault │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 明文文件 ─────► ansible-vault ─────► 加密文件 │
│ encrypt decrypt │
│ │
│ ┌─────────────┐ │
│ │ Sensitive │ │
│ │ Data │ ───► AES-256 加密 ───► Vault File │
│ │ Passwords │ │
│ │ Keys │ │
│ │ Tokens │ │
│ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
创建加密文件
基本命令
# 创建加密文件
ansible-vault create secrets.yml
# 编辑加密文件
ansible-vault edit secrets.yml
# 查看加密文件
ansible-vault view secrets.yml
创建流程
# 创建文件,会提示输入密码
$ ansible-vault create vault.yml
New Vault password: ****
Confirm New Vault password: ****
# 文件内容
---
db_password: "supersecret"
api_token: "abc123xyz"
加密现有文件
# 加密文件
ansible-vault encrypt secrets.yml
# 加密多个文件
ansible-vault encrypt secrets.yml prod_secrets.yml
# 加密整个目录
ansible-vault encrypt_string
解密和使用
解密文件
# 解密文件(会提示密码)
ansible-vault decrypt secrets.yml
# 解密到指定文件
ansible-vault decrypt secrets.yml --output=secrets_decrypted.yml
在 Playbook 中使用
# 运行时输入密码
ansible-playbook site.yml --ask-vault-pass
# 使用密码文件
ansible-playbook site.yml --vault-password-file ~/.vault_pass
# 同时使用多个密码
ansible-playbook site.yml \
--vault-id prod@prompt \
--vault-id dev@.vault_pass
Vault ID 和多密码
使用 Vault ID
# 创建带 ID 的加密文件
ansible-vault create --vault-id prod@prompt prod_vault.yml
ansible-vault create --vault-id dev@prompt dev_vault.yml
多密码策略
# 生产环境
ansible-vault create --vault-id production@prompt prod_vault.yml
# 开发环境
ansible-vault create --vault-id development@prompt dev_vault.yml
密码文件配置
# 创建密码文件
echo "my_production_password" > ~/.vault_pass_prod
chmod 600 ~/.vault_pass_prod
# 使用密码文件
ansible-playbook site.yml --vault-id prod@~/.vault_pass_prod
ansible.cfg 配置
[defaults]
# 密码文件路径
vault_password_file = ~/.vault_pass
# 或使用脚本
vault_password_file = ~/.vault_pass.sh
# 如果有多个 vault
[privilege_escalation]
# ...
Vault 密码脚本
#!/bin/bash
# ~/.vault_pass.sh
# 根据环境返回不同密码
if [ "$1" = "prod" ]; then
echo "prod_password"
elif [ "$1" = "dev" ]; then
echo "dev_password"
else
echo "default_password"
fi
chmod +x ~/.vault_pass.sh
实践:敏感数据管理
项目结构
project/
├── ansible.cfg
├── site.yml
├── group_vars/
│ └── all/
│ └── vault.yml # 加密的通用变量
├── host_vars/
│ ├── web1/
│ │ └── vault.yml # 加密的主机变量
│ └── db1/
│ └── vault.yml
├── roles/
│ └── webserver/
│ └── defaults/
│ └── main.yml
└── vars/
└── prod_vault.yml # 生产环境加密文件
vault.yml 示例
# group_vars/all/vault.yml
---
vault_db_password: "MySecureDBPassword123!"
vault_api_key: "sk_prod_abcdef123456"
vault_aws_access_key: "AKIAIOSFODNN7EXAMPLE"
vault_aws_secret_key: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
vault_jwt_secret: "your-super-secret-jwt-signing-key"
vault_smtp_password: "smtp_password_123"
引用加密变量
# 在 Playbook 或任务中使用
---
- name: Configure database
hosts: dbservers
vars_files:
- group_vars/all/vault.yml
tasks:
- name: Set MySQL root password
mysql_user:
name: root
host: localhost
password: "{{ vault_db_password }}"
login_unix_socket: /var/run/mysqld/mysqld.sock
分层 Vault
# group_vars/all/vault.yml
---
vault_shared_secret: "shared_across_all"
# group_vars/production/vault.yml
---
vault_db_password: "prod_db_password"
vault_api_key: "prod_api_key"
# group_vars/staging/vault.yml
---
vault_db_password: "staging_db_password"
vault_api_key: "staging_api_key"
Vault 命令参考
创建和编辑
# 创建加密文件
ansible-vault create file.yml
# 编辑加密文件
ansible-vault edit file.yml
# 查看加密文件
ansible-vault view file.yml
加密和解密
# 加密文件
ansible-vault encrypt file.yml
# 解密文件
ansible-vault decrypt file.yml
# 加密多个文件
ansible-vault encrypt file1.yml file2.yml
# 加密字符串
ansible-vault encrypt_string 'my_secret' --name 'password'
密码管理
# 更改密码
ansible-vault rekey file.yml
# 批量更改密码
ansible-vault rekey file1.yml file2.yml
# 创建密码文件
echo "password" > vault_pass
chmod 600 vault_pass
信息查看
# 查看加密文件信息
ansible-vault view --vault-id prod@prompt file.yml
Playbook 集成
完整示例
# site.yml
---
- name: Deploy application with secrets
hosts: webservers
become: yes
vars_files:
- group_vars/all/vault.yml
- group_vars/all/non_secret.yml
tasks:
- name: Create secrets directory
file:
path: /etc/myapp/secrets
state: directory
mode: '0700'
- name: Write secret to file
copy:
content: |
DB_PASSWORD={{ vault_db_password }}
API_KEY={{ vault_api_key }}
dest: /etc/myapp/secrets/.env
mode: '0600'
no_log: true
- name: Configure application
template:
src: config.j2
dest: /etc/myapp/config.yml
运行时指定 Vault
# 交互式输入密码
ansible-playbook site.yml --ask-vault-pass
# 使用密码文件
ansible-playbook site.yml --vault-password-file ~/.vault_pass
# 使用 Vault ID
ansible-playbook site.yml --vault-id dev@prompt
# 生产环境需要两个 vault
ansible-playbook site.yml \
--vault-id prod@prompt \
--vault-id prod_secrets@~/.vault_pass_prod
最佳实践
1. 使用强密码
# 生成强随机密码
python3 -c "import secrets; print(secrets.token_urlsafe(32))"
# 使用密码管理器生成
# 1Password, LastPass, Bitwarden 等
2. 分离敏感数据
# 好的实践
# group_vars/all/vault.yml - 加密所有敏感数据
# group_vars/all/public.yml - 非敏感配置
# 不推荐的实践
# 直接在 vars 中写密码
vars:
db_password: "secret" # 不安全!
3. 使用 Vault ID 分离环境
# 生产
ansible-vault create --vault-id production@prompt prod_vault.yml
# 测试
ansible-vault create --vault-id test@prompt test_vault.yml
# 开发
ansible-vault create --vault-id dev@prompt dev_vault.yml
4. 保护密码文件
# 设置正确权限
chmod 600 ~/.vault_pass
chmod 700 ~/.vault_pass.sh
# 不提交到 Git
echo ".vault_pass*" >> .gitignore
5. CI/CD 集成
# GitLab CI 示例
# .gitlab-ci.yml
variables:
ANSIBLE_VAULT_PASSWORD: ${CI_VAULT_PASSWORD}
run_ansible:
script:
- echo $ANSIBLE_VAULT_PASSWORD > vault_pass
- ansible-playbook site.yml --vault-password-file vault_pass
常见问题
忘记 Vault 密码
无法恢复,必须使用备份密码或重新设置。
多个 Vault 文件冲突
# 确保变量名唯一
# 使用前缀区分
vault_prod_db_password
vault_stg_db_password
Vault 文件过大
# 使用外部密钥管理
# AWS KMS, HashiCorp Vault, CyberArk 等
- name: Fetch secret from AWS
shell: |
aws secretsmanager get-secret-value \
--secret-id prod/db-password \
--query SecretString \
--output text
register: db_password
no_log: true
下一步
现在你已经掌握了 Vault 加密的使用。接下来让我们学习 Ansible Galaxy。