本文系统讲解 Ansible Vault 敏感信息加密全流程,覆盖创建加密文件、加密现有 yml、playbook 中引用加密变量、vault_password_file 免密操作、多密码库分层管理、CI/CD 流水线集成等生产高频场景。指出明文密码入库、密码硬编码进 playbook、多人共用同一密码、密钥管理混乱等常见安全问题,并给出从开发到生产的完整密钥治理方案。掌握 Vault,ansible-playbook 才能从"能跑"升级为"安全合规、可入库、可审计"的工程化实践。
前言
Ansible 用久了,你迟早会碰到一个问题:
数据库密码、API 密钥、SSH 私钥、TLS 证书------这些敏感信息到底放哪?
直接写在 playbook 里?那 git 一提交,全公司都能看到。写在 group_vars 里?一样的问题。写在环境变量里?跨机器同步又是个麻烦事。
Ansible 官方早就给了解决方案:Vault。它是 Ansible 内置的加密工具,用 AES 256 加密 yml 文件,明文只在执行时临时解密。
说明:本文基于 Ansible 2.15+ 稳定版,Vault 命令语法长期稳定。
一、什么是 Ansible Vault
1.1 核心概念
Vault 本质是一个命令行工具,对 yml 文件做对称加密。加密后的文件长这样:
$ANSIBLE_VAULT;1.1;AES256
6139383564633237396530663865633339656566363138376235346130396463
3632383534366533393162613563656366323834376562633435323736316130
...
全是密文,任何人拿到文件都看不到内容。只有执行 ansible-playbook 时输入密码,或者指定密码文件,才会临时解密到内存里跑 task。
✅ 结论:Vault 加密的是文件级别的,不是单个变量。要么整个文件加密,要么整个目录加密,没有"只加密某一行"的功能。
1.2 Vault 解决什么问题
| 场景 | 没有 Vault | 有 Vault |
|---|---|---|
| 数据库密码 | 明文写在 yml,git 提交就泄露 | 加密存储,只有持密码的人能解密 |
| API 密钥 | 硬编码进 playbook,到处都是 | 统一放一个加密 vars 文件 |
| SSH 私钥 | 散落在各机器 ~/.ssh | 加密后入库,执行时临时解密 |
| 多人协作 | 密码微信群里发,聊天记录满天飞 | 密码单独走密码管理工具,代码库只存密文 |
二、创建加密文件
2.1 新建加密文件
最基础的用法:直接创建一个加密的 yml 文件。
bash
ansible-vault create group_vars/all/vault.yml
执行后会让你输入 vault 密码(两次),然后自动打开默认编辑器(vi/vim)写内容。写完保存退出,文件就是加密状态了。
文件内容写什么?敏感变量:
yaml
---
db_password: "S3cr3t@2026"
api_key: "sk-xxxxxxxxxxxxxx"
ssh_private_key: |
-----BEGIN OPENSSH PRIVATE KEY-----
...
-----END OPENSSH PRIVATE KEY-----
2.2 查看加密文件内容
想看看里面写了啥?用 view 而不是 cat:
bash
ansible-vault view group_vars/all/vault.yml
会提示输入密码,然后明文输出到终端,不会写回文件。
坑点提醒:别用 cat 看加密文件 ,输出的全是密文,看了也白看。必须用 ansible-vault view。
2.3 编辑加密文件
要修改内容?不要先解密再改,直接用 edit:
bash
ansible-vault edit group_vars/all/vault.yml
输入密码后打开编辑器,改完保存自动重新加密。全程不需要手动解密步骤。
三、加密/解密现有文件
3.1 把已经存在的明文文件加密
你的 group_vars/db.yml 已经写了一堆明文密码,现在想加密?
bash
ansible-vault encrypt group_vars/db.yml
输入密码后,文件直接变成密文。原来的明文没了,不可逆。
✅ 结论:加密前务必备份明文,不然加密后你自己都打不开(除非记得密码)。
3.2 批量加密整个目录
生产项目里敏感文件不止一个,批量处理:
bash
# 加密整个 vault 目录
ansible-vault encrypt group_vars/vault/*.yml
# 批量解密(一般不用,除非你明确想恢复明文)
ansible-vault decrypt group_vars/vault/*.yml
3.3 修改密码
密码定期轮换?不用解密再加密,直接 rekey:
bash
ansible-vault rekey group_vars/all/vault.yml
先输入旧密码,再输入新密码,一步搞定。
四、在 playbook 中使用加密变量
4.1 基本引用方式
Vault 加密的文件,用法和普通 vars 文件完全一样。Ansible 执行时自动识别加密文件:
yaml
---
- name: 部署应用
hosts: web_servers
vars_files:
- group_vars/all/common.yml # 普通变量,明文
- group_vars/all/vault.yml # 加密变量,Vault
tasks:
- name: 连接数据库
ansible.builtin.command: "mysql -u root -p{{ db_password }}"
执行 playbook 时:
bash
ansible-playbook site.yml --ask-vault-pass
参数 -ask-vault-pass(简写 --ask-vault-pass)会提示你输入 vault 密码。输入后,所有加密变量在内存里解密,task 正常跑。
4.2 用密码文件免交互
每次执行都手动输密码太烦了,尤其是 CI/CD 流水线里。用 vault_password_file:
bash
# 先创建一个本地密码文件(权限设为 600,只有你能读)
echo "MyVaultPass2026" > ~/.vault_pass
chmod 600 ~/.vault_pass
# 执行时指定密码文件
ansible-playbook site.yml --vault-password-file ~/.vault_pass
这样就不用手动输密码了。
坑点提醒:密码文件本身绝对不能提交到 git ,加到 .gitignore 里。它和你的服务器 root 密码是一个级别的。
4.3 在 ansible.cfg 里配置默认密码文件
每次都加 --vault-password-file 参数太麻烦,写到配置里:
ini
# ansible.cfg
[defaults]
vault_password_file = ~/.vault_pass
以后执行 ansible-playbook site.yml 就自动用这个密码文件,不用每次加参数。
五、多密码库:分层管理不同环境
5.1 为什么需要多密码库
生产环境一般分三套:dev、test、prod。三套的敏感信息不一样,密码也不应该共用同一个。
Ansible 支持给不同的加密文件用不同的 vault 密码,叫 "multi-vault":
bash
# dev 环境的 vault 文件
ansible-vault create --vault-id dev@~/.vault_dev_pass group_vars/dev/vault.yml
# test 环境
ansible-vault create --vault-id test@~/.vault_test_pass group_vars/test/vault.yml
# prod 环境
ansible-vault create --vault-id prod@~/.vault_prod_pass group_vars/prod/vault.yml
--vault-id 的格式是:标签@密码文件路径。标签是给这个密码起的名字,方便后面引用。
5.2 执行时指定多个密码
三套文件用了三个不同密码,执行的时候怎么指定?
bash
ansible-playbook site.yml \
--vault-id dev@~/.vault_dev_pass \
--vault-id test@~/.vault_test_pass \
--vault-id prod@~/.vault_prod_pass
Ansible 会自动匹配:解密某个文件时,用对应标签的密码。
✅ 结论:多密码库的核心思路是环境隔离------dev 的人拿不到 prod 的密码,即使代码库被 clone 了也白搭。
六、与 CI/CD 流水线集成
6.1 典型场景
GitLab CI / GitHub Actions 里跑 playbook,不能手动输密码。怎么把 vault 密码传进去?
思路:把 vault 密码存在 CI 的环境变量里,不入库、不写 yml。
以 GitLab CI 为例:
yaml
# .gitlab-ci.yml
stages:
- deploy
deploy_prod:
stage: deploy
script:
- echo "$VAULT_PASS" > .vault_pass
- chmod 600 .vault_pass
- ansible-playbook -i inventory/prod site.yml --vault-password-file .vault_pass
- rm -f .vault_pass # 用完立刻删
only:
- main
$VAULT_PASS 是在 GitLab 项目的 Settings → CI/CD → Variables 里配置的,加密存储,不会出现在日志里。
6.2 安全注意事项
CI 集成有几个容易翻车的点:
- 密码不要出现在日志里 :
echo $VAULT_PASS这种命令,如果 CI 配置了 debug 模式,密码会直接打印出来。用echo "$VAULT_PASS" > file而不是直接 echo。 - 密码文件用完就删 :上面例子里
rm -f .vault_pass,防止后续 step 泄露。 - 最小权限原则:CI 用的那个 vault 账号,只给它 prod 环境的解密权限,不给 dev/test 的。
- 定期轮换密码 :每季度换一次 vault 密码,用
rekey批量处理。
七、常见坑点速查
- 加密文件忘记密码:Ansible 没有后门,密码丢了文件就废了。密码管理走专业工具(1Password、Vault 密码管理器)。
- 把密码文件提交到 git :
.vault_pass、.vault_pass_dev这类文件必须加.gitignore。 - 明文密码和加密密码混在同一个文件:要么全加密,要么全明文。混合写容易导致你以为加密了其实没有。
- 多人共用同一个 vault 密码:人员离职时密码没法单独回收。生产环境建议每人一个 vault-id,或者接入企业密码管理系统。
- vault 文件权限不对 :
~/.vault_pass必须是 600,不然其他用户能读。 - 在 CI 里硬编码密码:绝对禁止。必须用 CI 的加密变量,不能写在 yml 里。
- 加密了但没在 ansible.cfg 配置密码文件 :执行时忘了加
--vault-password-file,报错 "Decryption failed",以为文件坏了。
八、结语
Vault 是 Ansible 安全体系的基石。用熟了之后你会发现,敏感信息管理不再是"到处藏密码",而是一套清晰的分层结构:
- 代码库:只存加密后的密文,随便 clone 不怕泄露。
- 密码管理工具:存 vault 密码,走企业级密码系统,不入代码库。
- CI/CD 变量:流水线执行时临时注入,用完即焚。
我的建议:
- 项目第一天就上 Vault,不要等密码泄露了才补。
- dev/test/prod 三套环境三套密码,不要图省事共用一个。
- vault_password_file 权限 600,加到 .gitignore,这是底线。
- CI/CD 里的密码用加密变量管理,绝对不要写在 yml 里。
Ansible 的哲学是"简单、可预测",Vault 就是这个哲学在安全领域的延伸------不用你自己设计加密方案,官方内置的 AES 256 足够生产级用。
如果觉得有用,欢迎点赞收藏,后续会继续更新 Ansible 进阶系列(roles 拆分、变量优先级、动态 inventory)。