文章围绕 Ansible 中的密钥管理展开,先介绍 Ansible Vault 的用途、AES256 加密机制、文件级与变量级加密、vault password 的使用方式,以及在 playbook、环境隔离和执行命令中的典型实践。

Ansible 是一个开源自动化工具,Red Hat 将其作为 Red Hat Ansible Automation Platform 的一部分提供。它已经成为全球无数服务器上配置管理和应用部署的首选方案之一。其无 Agent 架构和易于阅读的 YAML playbook 让各种规模的团队都能轻松上手。但和你技术栈中的任何其他工具一样,它也需要访问敏感凭证,也就是你的 secrets。
secrets 就像能打开技术栈不同部分的钥匙。这些凭证包括 API keys、SSH certificates 以及云服务提供商的 token。妥善管理它们,对于在不引入不必要障碍的前提下维护安全性至关重要。
挑战在于:如何在保持 Ansible 简洁高效的同时,安全地保管这些 secrets。这就是为什么正确的 secrets 管理变得至关重要,尤其是像 SOC 2、GDPR 和 HIPAA 这样的框架和法规,往往要求加密、访问控制和可审计性等强有力的控制措施。
Ansible 提供了名为 Ansible Vault 的原生解决方案,用于加密敏感数据。然而,像 Infisical 这样的现代 secret 管理平台则提供了更高级的能力,包括自动轮换、集中管理和详细的审计日志。
在本指南中,我们将探讨这两种方法及其权衡,并帮助你为自动化需求选择合适的方案。
Ansible Vault 是 Ansible 内置的加密功能,可用于保护项目中的敏感数据。它不会以明文形式存储密码、密钥和其他 secrets,而是使用 AES256 密码(AES-256)对这些信息进行加密。只要妥善保护并及时轮换 vault 密码,将加密后的 secret 文件存入版本控制系统就是合理的。
Ansible Vault 在两个层面上工作:
你也可以使用多个 vault ID 来管理不同环境或团队对应的不同密码,从而在组织和保护 secrets 时获得更大的灵活性。
首先,为敏感数据创建一个加密变量文件:
## 使用交互式密码提示创建一个新的加密文件
ansible-vault create group_vars/production/secrets.yml
## 或者加密一个已有文件
ansible-vault encrypt group_vars/production/database.yml
运行这些命令时,Ansible 会提示你输入 vault 密码。这个密码就是解密 secrets 的密钥,因此请妥善保管。
有时你只需要保护特定值,而不是整个文件。使用 Ansible Vault,你可以加密单个字符串:
## 加密单个值
ansible-vault encrypt_string 'P@ssw0rd123!' --name 'database_password'
## 这会输出可直接粘贴到 playbook 中的 YAML:
database_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
66386439653236336...
一旦文件被加密,你就需要 vault 密码来查看或修改它们。可以使用 Ansible CLI 的 rekey、decrypt 和 edit 功能来完成这些操作。
## 编辑一个加密文件(会在你的默认编辑器中打开)
ansible-vault edit secrets.yml
## 查看内容而不编辑
ansible-vault view secrets.yml
## 永久解密一个文件(谨慎使用!)
ansible-vault decrypt secrets.yml
## 更改加密密码
ansible-vault rekey secrets.yml
接下来,我们来看看如何在典型的 playbook 中使用 vault 加密变量。首先,需要配置 vars_files。
---
- name: 配置 Web 应用
hosts: webservers
vars_files:
- vars/common.yml
- vars/secrets.yml # 此文件已加密
tasks:
- name: 部署数据库配置
template:
src: database.conf.j2
dest: /etc/app/database.conf
mode: '0600'
no_log: true # 防止 secrets 出现在日志中
然后,我们需要使用 Ansible 的目录结构按环境组织 secrets。结构如下:
ansible-project/
├── group_vars/
│ ├── all/
│ │ └── common.yml
│ ├── production/
│ │ ├── vars.yml
│ │ └── secrets.yml # 已加密
│ └── staging/
│ ├── vars.yml
│ └── secrets.yml # 使用不同密码加密
接下来,在执行时可以通过几种方式提供 vault 密码。主要有三种策略:
--ask-vault-pass 提示输入密码--vault-password-file 提供密码文件--vault-id 为不同环境提供不同 ID,并配合密码文件使用## 交互式密码提示
ansible-playbook deploy.yml --ask-vault-pass
## 密码文件(请妥善保管,不要放入版本控制!)
echo 'your_vault_password' > .vault_pass
chmod 600 .vault_pass
ansible-playbook deploy.yml --vault-password-file .vault_pass
## 为不同环境使用多个 vault ID
ansible-playbook deploy.yml \
--vault-id production@.vault_pass_prod \
--vault-id staging@.vault_pass_stage
处理 Ansible secrets 时,有两个关键实践。
在涉及 secrets 的任务上设置 no_log: true,以减少敏感值在输出和日志中泄露的可能性(但需要注意,某些调试模式和边界情况下仍可能暴露数据)。
- name: 处理敏感数据的任务
mysql_user:
name: appuser
password: "{{ mysql_password }}"
priv: '*.*:ALL'
no_log: true # 关键:防止密码出现在输出中
其次,在使用 shell 命令时,你可以向外部工具传递环境变量:
- name: 为外部工具使用环境变量
shell: |
export API_KEY="{{ api_secret }}"
./deploy-script.sh
environment:
API_KEY: "{{ api_secret }}"
no_log: true
虽然 Ansible Vault 解决了加密 secrets 这一直接问题,但它也带来了显著的运维挑战:
不过,这些问题都可以通过将 Ansible 与更强大的方案(如 Infisical)集成来轻松解决。
对于需要更强大 secrets 管理能力的团队,Infisical 提供了原生的 Ansible 集成,在保持易用性的同时解决了 Vault 的局限性。
将专用 secrets 管理器(如 Infisical)与 Ansible 结合使用,可以解决核心挑战。具体来说,它提供:
要设置 Infisical 和 Ansible,只需要两个简单步骤。
从 Ansible Galaxy(Ansible 的包管理器)安装 Infisical collection。
## 安装 collection
$ ansible-galaxy collection install infisical.vault
## 安装所需的 Python 包
$ pip install infisicalsdk
然后,用从 Infisical 获取的 dynamic secret 替换静态加密文件。这样一来,secrets 就可以由 Infisical 来管理了。
- name: 使用 Infisical secrets 部署
hosts: webservers
gather_facts: false
tasks:
- name: 登录 Infisical(缓存认证一次)
infisical.vault.login:
url: "https://app.infisical.com"
auth_method: universal_auth
universal_auth_client_id: "{{ vault_client_id }}"
universal_auth_client_secret: "{{ vault_client_secret }}"
register: infisical_login
no_log: true
- name: 以字典形式读取 secrets
infisical.vault.read_secrets:
login_data: "{{ infisical_login.login_data }}"
project_id: "proj_abc123"
env_slug: "production"
path: "/database"
as_dict: true
register: db_secrets
no_log: true
- name: 使用 secret
debug:
msg: "DB 密码已设置(已脱敏)"
vars:
db_password: "{{ db_secrets.secrets.PRIMARY_PASSWORD }}"
对于非常小的团队或简单项目,Ansible Vault 可能已经足够。它内置、直接,而且不需要额外基础设施。如果你刚开始保护 playbook,可以从这里起步。
然而,对于生产环境,建议考虑像 Infisical 这样的专用 secrets 管理方案。专用方案提供:
从 Vault 迁移到专用 secrets 管理器并不一定要一刀切。许多团队会先在开发环境中使用 Vault,同时在生产环境中使用企业级解决方案,并随着需求增长逐步迁移。
在使用 Ansible 时保护 secrets 并非可选项。这是负责任的基础设施自动化的基本要求。现在就从一些容易实现的改进入手,比如消除应用中的硬编码凭证。将 Ansible Vault 作为基础防护,确保所有敏感数据在进入版本控制之前都已加密。
随着自动化实践的成熟,评估 Vault 的局限性是否正在阻碍你。像 Infisical 这样的现代 secrets management 平台,可以消除手动轮换 secret 的负担,同时提供企业环境所需的审计轨迹和访问控制。
记住:最好的 secrets 管理策略,是你的团队真正会使用的策略。选择能够增强而非阻碍你自动化工作流的工具,并让安全成为开发流程中无缝的一部分。
- 原文链接: infisical.com/blog/ansib...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!