Ansible 中的机密信息掩码
Ansible Playbook 经常需要密码和 API 令牌来连接服务器、部署应用程序。这些值也可能出现在任务输出中,例如某条命令返回了包含密码的错误信息。
为了解决这个问题,Ansible 正在加入机密信息掩码功能。它会将输出中已知的机密值替换为 $REDACTED$,同时保留消息的其余内容,方便阅读。任务仍然使用原始值。
这项功能由 Secret Masking API 拉取请求引入,该请求于 2026 年 9 月 10 日合并。截至本文撰写时,它已在 ansible-core 2.22 开发构建版本中提供,但尚未包含在稳定版中。
下面先看一个简单的 Playbook,再介绍我们计划如何在 Semaphore UI 中使用这项功能。
首先,注册一个机密值
Ansible 需要知道哪些值应该被掩码处理。新的 API 会注册来自已知机密来源的值,例如使用 Vault 加密的变量,以及标记为 no_log 的模块参数。
对于普通变量,我们可以使用 register_secret 过滤器。通过 --extra-vars 传入的变量也需要注册;仅仅将它命名为 db_password 并不够。
在这个例子中,我们使用一个虚构的数据库密码。创建名为 masking.yml 的 Playbook:
- name: Try secret masking
hosts: localhost
gather_facts: false
vars:
db_password: "example-db-password-123456"
tasks:
- name: Register the password before using it
ansible.builtin.set_fact:
db_password: "{{ db_password | ansible.builtin.register_secret }}"
- name: Show a message containing the password
ansible.builtin.debug:
msg: "Connecting to db.internal with password={{ db_password }}"
第一个任务注册密码。过滤器返回原始值,因此 Playbook 仍然可以用它连接数据库。必须在任何任务输出该值之前完成注册。
使用 ansible-core 2.22 开发构建版本运行 Playbook:
ansible-playbook -i localhost, -c local masking.yml
第二个任务将显示以下消息:
Connecting to db.internal with password=$REDACTED$
这里输出密码仅用于演示掩码效果。在实际的 Playbook 中,应从你的机密信息来源获取密码,并避免主动输出凭据。
与 Semaphore UI 集成
Semaphore UI 已经知道你将哪些变量标记为了机密。我们计划在未来版本中利用这些信息,自动向 Ansible 注册相应的值。
为此,我们将使用 Ansible 的 _SECRETS_INPUT_FILES 选项。该选项通过环境变量 _ANSIBLE_SECRETS_INPUT_FILES 配置,让 Ansible 能够在 Playbook 启动前读取机密值列表。
输入可以采用 YAML 或 JSON 格式。包含示例密码的文档如下:
version: 1
secrets:
- example-db-password-123456
这个列表告诉 Ansible 要对哪些值进行掩码处理。变量本身仍然单独传递给 Playbook。
计划中的集成将涵盖以下来源的机密值:
- 变量组(Variable Groups)——保存下来供任务使用的机密值。
- 问卷(Surveys)——启动任务时输入的机密答案。
对于这些值,你无需在每个 Playbook 中添加使用 register_secret 的任务。
我们在 ansible-core 2.22 开发构建版本中测试了这种方法。已注册的值在 debug 消息、命令结果、错误消息、详细输出和 Ansible 日志文件中都进行了掩码处理。通过管道传递列表也能正常工作,无需在磁盘上写入单独的机密文件。
该选项目前是内部选项,可能发生变化。Semaphore UI 计划在未来版本中提供支持,并且需要兼容的 Ansible 版本。
示例:部署应用程序
假设我们有一个用于部署应用程序的任务模板(Task Template)。部署脚本使用保存在变量组中的机密 API 令牌。
采用计划中的集成后,任务将按以下流程运行:
- Semaphore UI 将令牌传递给 Playbook。
- 在执行前,它还会通过
_SECRETS_INPUT_FILES将令牌提供给 Ansible 的掩码列表。 - Playbook 使用真实令牌运行部署脚本。
- 如果脚本在输出中包含该令牌,Ansible 会在显示结果时对其进行掩码处理。
例如,令牌过期时,任务日志中可能出现以下消息:
Deployment rejected: service=payments environment=staging token=$REDACTED$ reason=token expired
我们可以看到哪次部署失败以及失败原因,而不必向所有阅读日志的人暴露令牌。通过问卷的机密字段输入的临时令牌也将采用同样的流程。
限制
掩码处理针对的是已注册的值。开发版实现会跳过长度不足四个字符的机密值,而编码后或经过其他转换的值可能需要单独注册。
它也不保护进程参数、Playbook 写入的文件或 Ansible 之外生成的日志中的凭据。对于需要隐藏全部输出的任务,请继续使用 no_log: true。
通过这项集成,在 Semaphore UI 中标记为机密的值也将被 Ansible 的掩码系统识别。这有助于避免凭据出现在任务日志中,同时保留排查问题所需的信息。

