在 Azure Pipeline 中使用表示法对容器映像进行签名和验证

Azure DevOps 中的表示法任务是一项内置任务,用于在 Azure Pipeline 中对容器映像和其他开放容器计划 (OCI) 项目进行签名和验证。 表示法任务利用表示法 CLI 执行这些操作,确保项目由受信任的实体签名,并且自创建以来未被篡改。

本文将指导你创建一个 Azure 管道,该管道生成容器映像,将其推送到 ACR,并使用表示法和 Azure 密钥库 插件添加签名,从而为项目提供一层安全性和完整性。 管道的目标是:

  1. 生成容器映像并将其推送到Azure 容器注册表(ACR)。
  2. 使用表示法和表示法 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 注册表的访问权限,如下所示:

    1. 登录到你的组织 (https://dev.azure.com/{yourorganization}) 并选择你的项目。
    2. 选择左下角的设置按钮。
    3. 转到 管道,然后选择“ 服务连接”。
    4. 选择 “新建服务连接 ”,然后选择“ Docker 注册表”。
    5. 接下来选择Azure 容器注册表
    6. 身份验证类型中选择服务主体,并输入服务主体详细信息,包括 Azure 订阅和 ACR 注册表。
    7. 输入引用此服务连接时使用的用户友好连接名称。
  • 在 Azure Pipelines 中创建 Azure 资源管理器服务连接,以授权访问 Azure 密钥库:

    1. 选择“服务主体”(自动)。
    2. 接下来,选择“ 订阅 ”并从下拉列表中找到 Azure 订阅。
    3. 从下拉列表中选择可用的资源组。
    4. 输入在引用此服务连接时要使用的用户友好 服务连接名称
    5. 保存它以完成创建。
  • 按照以下步骤向服务主体授予访问策略:

    1. 打开创建的 Azure 资源管理器服务连接,然后单击“管理服务主体以输入 Azure 服务主体门户。
    2. 复制 Application (client) ID。 它将用于授予服务主体的权限。
    3. 打开 Azure 密钥库 门户并输入“访问策略”页。
    4. 使用和certificate get权限创建新的访问策略。 secret getkey sign
    5. 使用上一步中的 Application (client) ID 粘贴向服务主体授予此新的访问策略。
    6. 保存它以完成创建。

在此处了解有关服务连接 的详细信息。

创建管道并使用表示法任务

按照以下步骤为 git 存储库创建 Azure 管道:

  1. 导航到 AOD 组织中的项目。
  2. 从左侧菜单中选择“管道”,然后选择“新建管道”。
  3. 选择 git 存储库。 我们使用 Azure DevOps 存储库来方便演示。
  4. 如果不熟悉 Azure DevOps,请使用初学者管道配置管道。 单击“ 保存并运行”查看并创建管道。

注意

该示例假定默认分支为 main. 如果不是,请按照指南更新默认分支。

可通过两种方式通过编辑 Azure 管道来添加表示法任务:

使用 Azure DevOps(ADO)面板:ADO 面板提供一个用户界面,可在其中向管道添加任务。 可以使用此接口搜索表示法任务并将其添加到管道。

从示例 Azure Pipeline 文件复制:如果有已包含表示法任务的示例 Azure Pipeline 文件,则可以从示例文件复制这些任务并将其粘贴到管道文件中。

选项 1:使用 Azure DevOps(ADO)编辑面板

Docker在右侧的管道编辑面板中搜索任务。 将其 login 命令与 Docker 注册表服务连接配合使用,通过 ACR 进行身份验证。

  1. 从容器注册表下拉列表中选择在上一步中创建的 Docker 注册表 服务连接。
  2. login“命令”下拉列表中进行选择。
  3. 单击“添加”,将带有命令的 Docker 任务login添加到管道文件左侧。

同样,再次从管道编辑面板搜索 Docker 任务。 使用其 buildAndPush 命令将源代码自动生成到映像,并将其推送到目标 ACR 存储库。 它将生成一个映像摘要,该摘要将用于在下一步中登录。

  1. 将存储库名称输入到 容器存储库
  2. 命令下拉列表中选择 buildAndPush
  3. 指定 Dockerfile 的文件路径。 例如,如果 Dockerfile 存储在根文件夹中,则使用 ./Dockerfile
  4. 单击“添加”,将带有命令的 Docker 任务buildAndPush添加到管道文件左侧。

Notation在右侧的管道编辑面板中搜索任务。

  1. 从下拉列表命令中选择“安装”以运行
  2. 单击“ 添加”notation install 任务添加到管道。
  3. 同样,再次从管道编辑面板中搜索 Notation 任务,然后选择“ 签名”。
  4. 可以跳过项目引用,因为我们使用由 Docker 任务生成并推送到注册表的最新摘要对映像进行签名。 相反,可以使用 手动指定摘要 <registry_host>/<repository>@<digest>
  5. 填写表单中的插件配置。 我们将使用在上一步中创建的默认 AKV 插件和服务连接。 将密钥 ID 从 AKV 复制到 密钥 ID
  6. 选中“自签名证书”框,因为我们使用自签名证书来方便演示。 相反,如果要使用 CA 颁发的证书,可以在证书捆绑文件路径中 输入证书路径
  7. 单击“添加”以向左添加notation sign管道文件。

选项 2:编辑示例 Azure Pipeline 文件

  1. 如果熟悉 Azure Pipelines 和表示法,则从模板管道文件开始是有效的。
  2. 将文档中提供的管道模板复制到自己的管道文件。 此模板旨在使用表示法任务,这些任务用于对容器映像进行签名和验证。
  3. 复制模板后,根据下面提供的引用和注释填写所需的值。
请参阅选项 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 中运行管道并验证其执行。

  1. 填写管道中的输入后,保存并运行它以触发管道。
  2. 转到 正在运行的管道的“作业 ”页。 在这里,可以看到每个步骤的执行。 此管道将生成并签名最新的生成或指定的摘要,然后将签名的映像及其关联的签名推送到注册表。
  3. 成功执行后,可以看到附加到Azure 容器注册表(ACR)的映像,并附加了 CBOR 对象签名和加密(CO标准版)格式签名。

验证签名的映像

同样,若要验证签名的图像,可以使用编辑面板或编辑管道文件将表示法 verify 任务添加到管道。 管道将使用你提供的信任策略和信任存储来验证已签名的映像。

准备表示法信任策略和信任存储

通常,验证程序与签名者不同。 出于演示目的,我们在此示例中使用了相同的管道和 ADO 存储库。 按照以下步骤在管道中创建表示法 信任策略信任存储以及添加 verify 任务:

  1. 在当前的 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": [
                "*"
            ]
        }
    ]
}
  1. 在当前的 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
  1. 将证书上传到我们在上一步中创建的信任存储文件夹 /.pipeline/truststore/x509/ca/$<yourTrustStore>/

添加表示法验证任务

  1. 再次从管道编辑面板中搜索表示法任务,然后选择“ 验证”。
  2. 使用已签名映像的摘要填写项目引用
  3. 在信任策略文件路径输入值.pipeline/trustpolicy/trustpolicy.json
  4. 在信任存储文件夹路径输入值.pipeline/truststore/
  5. 单击“添加”将表示法验证添加到管道文件左侧。

将按如下所示保存。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 面板或编辑管道文件将表示法任务添加到管道。 管道将使用你提供的信任策略和信任存储生成、推送、签名和验证映像。 此过程可确保项目由受信任的实体签名,并且自创建后未被篡改。