项目签名和验证提供了在项目目录中为文件签名的功能,然后可以验证内容是否有任何形式的改变,或者文件被意外地从项目中删除或添加到项目。这需要使用一个私有进行签名并使用与它匹配的公钥进行验证。
对于项目维护者,对内容进行签名的方式是,通过命令行界面 (CLI) 提供的一个名为 ansible-sign
的工具程序进行。
CLI 旨在方便地使用加密技术,如 GNU Privacy Guard (GPG) 等技术来验证项目中的文件是否已被改变或破坏。当前,GPG 是唯一支持的签名和验证方法。
Ansible Automation 控制器用于验证签名的内容。当匹配的公钥与已签名项目相关联后,控制器会验证被签名的文件是否被改变,以及文件是否被意外添加或删除。如果签名无效或文件被改变,项目将无法更新,使用这个项目的作业将无法启动。通过项目的验证状态,可以确保只有安全的、没有被修改的内容才会在作业中运行。
假设已配置了仓库签名和验证(请参阅以下),更改项目的常见工作流将变成:
用户设置了一个项目仓库,并希望对一个文件进行修改。
用户进行更改,运行 ansible-sign project gpg-sign /path/to/project
,它将更新校验和清单并进行签名。
用户将向仓库提交进行的更改以及更新的校验和清单,以及签名。
当用户同步项目时,控制器(在这个情况中已配置)会拉取新的更改,检查与控制器中项目关联的公钥是否与校验和清单签名的私钥匹配(防止对校验和清单本身进行了修改),然后重新计算清单中每个文件的校验和,以确保校验和匹配(确保文件没有被修改)。 它还会确保所有文件都被考虑:文件包括或排除了以下讨论的 MANIFEST.in
文件中指定的文件 ; 如果有文件已被意外添加或删除,验证将失败。
RHEL 节点必须正确订阅:
RHEL 订阅并启用了 baseos 和 appstream 软件仓库启
Ansible Automation Platform 订阅并启用了正确的 Ansible Automation Platform 频道:
ansible-automation-platform-2.3-for-rhel-8-x86_64-rpms for RHEL 8 ansible-automation-platform-2.3-for-rhel-9-x86_64-rpms for RHEL 9
对内容进行签名需要一个有效的 GPG 公钥/私钥。详情请参阅 How to create GPG keypairs。
请参阅 GnuPG documentation 以了解有关 GPG 密钥的更多信息。
您可以使用以下命令验证您是否具有有效的 GPG 密钥对和默认 GnuPG 密钥环:
$ gpg --list-secret-keys如果上述命令没有输出,或只输出了一行
trustdb was created
,则代表在您的默认密钥环中没有 secret 密钥。在这种情况下,请先参考 How to create GPG keypairs 以了解如何创建新密钥对。如果命令的输出超出以上内容,代表您已有一个有效的 secret 密钥,您可以使用ansible-sign
继续。
要将 GPG 密钥用于控制器中的内容并验证,您必须在 CLI 中运行以下命令:
$ gpg --list-keys
$ gpg --export --armour <key fingerprint> > my_public_key.asc
在控制器用户界面中,点左侧导航栏中的 Credentials,然后点 Add 按钮。
提供有意义的名称(例如:“Infrastructure team public GPG key”)
在 Credential Type 字段中,选择 GPG Public Key。
点 Browse 找到并选择公钥文件(例如 my_public_key.asc
)
完成后请点击 Save。
现在,这个凭证可以在 projects 中选择,内容验证将会在将来的项目同步时自动进行。
注解
使用项目缓存 SCM 超时来控制您希望控制器重新验证已签名的内容的频率。当项目配置为在启动时更新时(任何配置了该项目的作业模板),您可以启用缓存超时设置,这告诉它在自上次更新后 N 秒后更新。如果验证太频繁,则可以通过在项目的 Option Details 框中的 Cache Timeout 字段中指定一个超时时间来进行调整。
ansible-sign
CLI 工具¶ansible-sign
工具为用户提供了签名和验证项目是否已签名的选项。
运行以下命令来安装 ansible-sign
:
$ dnf install ansible-sign
验证 ansible-sign
已成功安装:
$ ansible-sign --version
输出类似以下内容(可能具有不同的版本号):
ansible-sign 0.1
这表明您已成功安装了 ansible-sign
。
顾名思义,为项目签名涉及一个 Ansible 项目目录。如需更复杂的项目目录结构的示例,请参阅 Ansible documentation。
以下示例项目有一个非常简单的结构。它包括一个清单文件,以及 playbook 目录下的两个简单的 playbook:
$ cd sample-project/
$ tree -a .
.
├── inventory
└── playbooks
└── get_uptime.yml
└── hello.yml
1 directory, 3 files
注解
本节中使用的命令假设您的工作目录是您的项目的根目录。作为一个规则,ansible-sign project
命令始终将项目根目录视为其最后一个参数,因此我们可以使用 .
表示当前工作目录。
ansible-sign
保护内容不受篡改的方式是,对项目中所有安全的文件进行校验和(SHA256),将它们编译到校验和清单文件中,最后再对该清单文件进行签名。
对内容进行签名的第一步是,创建一个文件,该文件为 ansible-sign
指定要保护的文件。该文件应称为 MANIFEST.in
,并位于项目根目录中。
在内部,ansible-sign
使用 Python distlib 库的 distlib.manifest
模块,因此 MANIFEST.in
必须遵循这个库指定的语法。有关 MANIFEST.in
文件指令的说明,请参阅 Python Packaging User Guide。
在示例项目中,包含两个指令,MANIFEST.in
文件类似如下:
include inventory
recursive-include playbooks *.yml
使用这个文件,生成您的验证和清单文件并对其进行签名。这些步骤通过一个 ansible-sign
命令实现:
$ ansible-sign project gpg-sign .
[OK ] GPG signing successful!
[NOTE ] Checksum manifest: ./.ansible-sign/sha256sum.txt
[NOTE ] GPG summary: signature created
现在,该项目已被签名。
请注意,gpg-sign
子命令位于 project
子命令下。对于签名项目内容,每个命令都将以 ansible-sign project
开头。如上所述,作为一个规则,每个 ansible-sign project
命令都会将项目根目录作为其最终参数。
如前所述,ansible-sign
默认会使用您的默认密钥环,并使用第一个可用的 secret 密钥为项目签名。您可以使用 --fingerprint
选项指定一个特定的 secret 密钥进行签名,甚至可以使用 --gnupg-home
选项进行完全独立的 GPG 主目录。
注解
如果您使用一个桌面环境,则 GnuPG 会自动提示您输入 secret 密钥的密码短语。如果此功能无法正常工作,或者在没有桌面环境的情况下工作(例如,通过 SSH),您可以在以上命令的 gpg-sign
后使用 -p/--prompt-passphrase
标志,这会使 ansible-sign
提示输入密码。
查看项目目录的结构后,请注意创建了一个新的 .ansible-sign
目录。该目录包含校验和清单,以及一个独立的 GPG 签名。
$ tree -a .
.
├── .ansible-sign
│ ├── sha256sum.txt
│ └── sha256sum.txt.sig
├── inventory
├── MANIFEST.in
└── playbooks
├── get_uptime.yml
└── hello.yml
如果要验证已签名的 Ansible 项目没有被更改,您可以使用 ansible-sign
检查签名是否有效,以及文件的校验和是否与正确的值匹配。特别是,可以使用 ansible-sign project gpg-verify
命令自动验证这两个条件。
$ ansible-sign project gpg-verify .
[OK ] GPG signature verification succeeded.
[OK ] Checksum validation succeeded.
注解
默认情况下,ansible-sign
使用默认 GPG 密钥环查找匹配的公钥。您可以使用 --keyring
选项指定一个密钥环文件,或使用 --gnugpg-home
选项指定不同的 GPG 主目录。
如果因为任何原因验证失败,则会显示信息以帮助您进行调试。通过在命令 ansible-sign
后使用全局 --debug
标志来输出更多信息。
注解
在项目中使用 GPG 凭据时,内容验证将会在未来的项目同步上自动进行。
在具有高度可信的 CI 环境(如 OpenShift、Jenkins 等)中,可以自动化签名的流程。例如,您可以将使用的 CI 平台中将您的 GPG 私钥存储为一个 secret,并在 CI 环境中将其导入到 GnuPG 中。然后,您可以在一般的 CI 工作流/容器/环境中运行签名工作流。
当使用 GPG 对项目进行签名时,ANSIBLE_SIGN_GPG_PASSPHRASE
环境变量 可以设置为签名密钥的密码短语。这可以在 CI 管道中注入(masked/secured)。
根据具体情况,在签名和验证期间,ansible-sign
将以不同的退出代码返回。这在 CI 和自动化上下文中也很有用,因为 CI 环境根据故障进行不同的操作(例如,对于一些错误会发送警报,但对其他错误会静默)。
以下是 ansible-sign
当前使用的退出代码,它们被视为稳定:
退出代码 |
大约含义 |
示例情境 |
---|---|---|
0 |
成功 |
|
1 |
常规故障 |
|
2 |
验证和验证失败 |
|
3 |
签名验证失败 |
|
4 |
签名进程失败 |
|