在 Azure Pipeline 中使用表示法对容器映像进行签名和验证
Azure DevOps 中的表示法任务是一项内置任务,用于在 Azure Pipeline 中对容器映像和其他开放容器计划 (OCI) 项目进行签名和验证。 表示法任务利用表示法 CLI 执行这些操作,确保项目由受信任的实体签名,并且自创建以来未被篡改。
本文将指导你创建一个 Azure 管道,该管道生成容器映像,将其推送到 ACR,并使用表示法和 Azure 密钥库 插件添加签名,从而为项目提供一层安全性和完整性。 管道的目标是:
- 生成容器映像并将其推送到Azure 容器注册表(ACR)。
- 使用表示法和表示法 Azure 密钥库 插件对映像进行签名。 然后,签名会自动推送到 ACR。
先决条件
- 在 Azure 密钥库中创建密钥库,并生成自签名签名密钥和证书。 可以使用本文档创建自签名密钥和证书以进行测试。 如果你有 CA 颁发的证书,请参阅本文档了解详细信息。
- 在 Azure 容器注册表 (ACR) 中创建注册表。
- 确保拥有 Azure DevOps 存储库或 GitHub 存储库。
创建服务连接
在 Azure Pipelines 中创建服务连接,该连接允许管道访问外部服务(如 Azure 容器注册表(ACR),可以按照以下步骤操作:
使用 ACR 凭据在 Azure 容器注册表 (ACR) 中对映像进行签名。
使用 Azure Pipelines 中的 Docker 任务登录到 ACR。 Docker 任务是 Azure Pipelines 中的内置任务,可用于生成、推送和拉取 Docker 映像等。
在 Azure Pipeline 中建立 Docker 注册表服务连接,以授予表示法任务对 ACR 注册表的访问权限,如下所示:
- 登录到你的组织 (
https://dev.azure.com/{yourorganization}
) 并选择你的项目。 - 选择左下角的设置按钮。
- 转到 管道,然后选择“ 服务连接”。
- 选择 “新建服务连接 ”,然后选择“ Docker 注册表”。
- 接下来选择Azure 容器注册表。
- 在身份验证类型中选择服务主体,并输入服务主体详细信息,包括 Azure 订阅和 ACR 注册表。
- 输入引用此服务连接时使用的用户友好连接名称。
- 登录到你的组织 (
在 Azure Pipelines 中创建 Azure 资源管理器服务连接,以授权访问 Azure 密钥库:
- 选择“服务主体”(自动)。
- 接下来,选择“ 订阅 ”并从下拉列表中找到 Azure 订阅。
- 从下拉列表中选择可用的资源组。
- 输入在引用此服务连接时要使用的用户友好 服务连接名称 。
- 保存它以完成创建。
按照以下步骤向服务主体授予访问策略:
- 打开创建的 Azure 资源管理器服务连接,然后单击“管理服务主体”以输入 Azure 服务主体门户。
- 复制
Application (client) ID
。 它将用于授予服务主体的权限。 - 打开 Azure 密钥库 门户并输入“访问策略”页。
- 使用和
certificate get
权限创建新的访问策略。secret get
key sign
- 使用上一步中的
Application (client) ID
粘贴向服务主体授予此新的访问策略。 - 保存它以完成创建。
在此处了解有关服务连接 的详细信息。
创建管道并使用表示法任务
按照以下步骤为 git 存储库创建 Azure 管道:
- 导航到 AOD 组织中的项目。
- 从左侧菜单中选择“管道”,然后选择“新建管道”。
- 选择 git 存储库。 我们使用 Azure DevOps 存储库来方便演示。
- 如果不熟悉 Azure DevOps,请使用初学者管道配置管道。 单击“ 保存并运行”查看并创建管道。
注意
该示例假定默认分支为 main
. 如果不是,请按照指南更新默认分支。
可通过两种方式通过编辑 Azure 管道来添加表示法任务:
使用 Azure DevOps(ADO)面板:ADO 面板提供一个用户界面,可在其中向管道添加任务。 可以使用此接口搜索表示法任务并将其添加到管道。
从示例 Azure Pipeline 文件复制:如果有已包含表示法任务的示例 Azure Pipeline 文件,则可以从示例文件复制这些任务并将其粘贴到管道文件中。
选项 1:使用 Azure DevOps(ADO)编辑面板
Docker
在右侧的管道编辑面板中搜索任务。 将其 login
命令与 Docker 注册表服务连接配合使用,通过 ACR 进行身份验证。
- 从容器注册表下拉列表中选择在上一步中创建的 Docker 注册表 服务连接。
login
从“命令”下拉列表中进行选择。- 单击“添加”,将带有命令的 Docker 任务
login
添加到管道文件左侧。
同样,再次从管道编辑面板搜索 Docker
任务。 使用其 buildAndPush
命令将源代码自动生成到映像,并将其推送到目标 ACR 存储库。 它将生成一个映像摘要,该摘要将用于在下一步中登录。
- 将存储库名称输入到 容器存储库。
- 从命令下拉列表中选择 buildAndPush。
- 指定 Dockerfile 的文件路径。 例如,如果 Dockerfile 存储在根文件夹中,则使用
./Dockerfile
。 - 单击“添加”,将带有命令的 Docker 任务
buildAndPush
添加到管道文件左侧。
Notation
在右侧的管道编辑面板中搜索任务。
- 从下拉列表命令中选择“安装”以运行。
- 单击“ 添加” 将
notation install
任务添加到管道。 - 同样,再次从管道编辑面板中搜索
Notation
任务,然后选择“ 签名”。 - 可以跳过项目引用,因为我们使用由 Docker 任务生成并推送到注册表的最新摘要对映像进行签名。 相反,可以使用 手动指定摘要
<registry_host>/<repository>@<digest>
。 - 填写表单中的插件配置。 我们将使用在上一步中创建的默认 AKV 插件和服务连接。 将密钥 ID 从 AKV 复制到 密钥 ID。
- 选中“自签名证书”框,因为我们使用自签名证书来方便演示。 相反,如果要使用 CA 颁发的证书,可以在证书捆绑文件路径中 输入证书路径 。
- 单击“添加”以向左添加
notation sign
管道文件。
选项 2:编辑示例 Azure Pipeline 文件
- 如果熟悉 Azure Pipelines 和表示法,则从模板管道文件开始是有效的。
- 将文档中提供的管道模板复制到自己的管道文件。 此模板旨在使用表示法任务,这些任务用于对容器映像进行签名和验证。
- 复制模板后,根据下面提供的引用和注释填写所需的值。
请参阅选项 1 的签名任务模板(单击此处)。
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
steps:
# log in to registry
- task: Docker@2
inputs:
containerRegistry: <your_docker_registry_service_connection>
command: 'login'
# build and push artifact to registry
- task: Docker@2
inputs:
repository: <your_repository_name>
command: 'buildAndPush'
Dockerfile: './Dockerfile'
# install notation
- task: Notation@0
inputs:
command: 'install'
version: '1.1.0'
# automatically detect the artifact pushed by Docker task and sign the artifact.
- task: Notation@0
inputs:
command: 'sign'
plugin: 'azureKeyVault'
akvPluginVersion: <azure_key_vault_plugin_version>
azurekvServiceConection: <your_akv_service_connection>
keyid: <your_key_id>
selfSigned: true
注意
除了使用 Docker 任务外,还可以通过手动指定项目引用来 artifactRefs
对指定的映像摘要进行签名,如下所示。
请参阅示例(单击此处)。
# sign the artifact
- task: Notation@0
inputs:
artifactRefs: '<registry_host>/<repository>@<digest>'
command: 'sign'
plugin: 'azureKeyVault'
akvPluginVersion: <azure_key_vault_plugin_version>
azurekvServiceConection: <akv_service_connection>
keyid: <key_id>
selfSigned: true
触发管道
按照步骤在 Azure DevOps 中运行管道并验证其执行。
- 填写管道中的输入后,保存并运行它以触发管道。
- 转到 正在运行的管道的“作业 ”页。 在这里,可以看到每个步骤的执行。 此管道将生成并签名最新的生成或指定的摘要,然后将签名的映像及其关联的签名推送到注册表。
- 成功执行后,可以看到附加到Azure 容器注册表(ACR)的映像,并附加了 CBOR 对象签名和加密(CO标准版)格式签名。
验证签名的映像
同样,若要验证签名的图像,可以使用编辑面板或编辑管道文件将表示法 verify
任务添加到管道。 管道将使用你提供的信任策略和信任存储来验证已签名的映像。
准备表示法信任策略和信任存储
通常,验证程序与签名者不同。 出于演示目的,我们在此示例中使用了相同的管道和 ADO 存储库。 按照以下步骤在管道中创建表示法 信任策略、 信任存储以及添加 verify
任务:
- 在当前的 ADO 存储库中,创建一个用于存储表示法信任策略
.pipeline/trustpolicy/
的示例文件夹.pipeline
。 创建示例信任策略 JSON 文件trustpolicy.json
。 使用自己的值填写信任策略模板,并将其保存在文件夹中。
注意
请注意,表示信任存储目前支持三种类型的标识,包括证书颁发机构(CA)、签名身份验证和时间戳颁发机构(TSA)根证书。 出于演示目的,我们在下面的信任策略和信任存储中使用证书颁发机构(CA x509/ca
)。 有关详细信息,请参阅 信任存储 。
请参阅信任策略模板(单击此处)。
{
"version": "1.0",
"trustPolicies": [
{
"name": "<yourPolicyName>",
"registryScopes": [ "<yourRegistry>.azurecr.io/<yourArtifact>" ],
"signatureVerification": {
"level" : "strict"
},
"trustStores": [ "ca:<yourTrustStore>"],
"trustedIdentities": [
"*"
]
}
]
}
- 在当前的 ADO 存储库中,为表示法信任存储
/.pipeline/truststore/x509/ca/$<yourTrustStore>/
创建一个新文件夹来存储证书。 如果按照本文档中的签名步骤对映像进行签名,请使用以下命令从 Azure 密钥库 (AKV) 下载自签名证书:
KEY_NAME=<key_name_you_picked_when_creating_the_key>
AKV_NAME=<akv_name_where_certificate_is_stored>
CERT_ID=$(az keyvault certificate show -n $KEY_NAME --vault-name $AKV_NAME --query 'id' -o tsv)
CERT_PATH=./${KEY_NAME}.pem
az keyvault certificate download --file $CERT_PATH --id $CERT_ID --encoding PEM
- 将证书上传到我们在上一步中创建的信任存储文件夹
/.pipeline/truststore/x509/ca/$<yourTrustStore>/
。
添加表示法验证任务
- 再次从管道编辑面板中搜索表示法任务,然后选择“ 验证”。
- 使用已签名映像的摘要填写项目引用。
- 在信任策略文件路径中输入值
.pipeline/trustpolicy/trustpolicy.json
。 - 在信任存储文件夹路径中输入值
.pipeline/truststore/
。 - 单击“添加”将表示法验证添加到管道文件左侧。
将按如下所示保存。notation verify
请参阅示例(单击此处)。
# sign the artifact
- task: Notation@0
inputs:
command: 'verify'
artifactRefs: '<registry_host>/<repository>@<digest>'
trustPolicy: .pipeline/trustpolicy.json
trustStore: .pipeline/truststore/
触发管道(已更新)
可以再次触发管道来验证已签名的映像。 成功执行后,可以从正在运行的管道的“作业”页查看日志。 管道将使用你提供的信任策略和信任存储来验证已签名的映像。
结束语
本文介绍如何在 Azure Pipeline 中使用表示法对容器映像进行签名和验证。 可以使用 Azure DevOps 面板或编辑管道文件将表示法任务添加到管道。 管道将使用你提供的信任策略和信任存储生成、推送、签名和验证映像。 此过程可确保项目由受信任的实体签名,并且自创建后未被篡改。