你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
本文是一系列关于确保容器映像和其他开放容器计划(OCI)项目的完整性和真实性的一部分。 对于完整情况,请从概述开始,该 概述解释了签名为何重要并概述了各种方案。
对容器映像进行签名的过程有助于确保其真实性和完整性。 在部署期间,将验证添加到容器映像的数字签名。 签名有助于验证映像是否来自受信任的发布者,并且未修改。
本文讨论签名过程中涉及的以下工具:
表示法 是由 公证项目社区 开发的开源供应链安全工具,由Microsoft提供支持。 它支持对容器映像和其他项目进行签名和验证。
如果要在持续集成和持续交付(CI/CD)管道中使用 Notation 来签署容器镜像,请遵循 Azure Pipelines 或 GitHub Actions 的指南进行操作。
Azure Key Vault 是用于存储具有签名密钥的证书的服务。 Notation 可以通过 Key Vault 插件(
notation-azure-kv)使用这些密钥来签名和验证容器镜像及其他工件。Azure 容器注册表是一个专用注册表,可用于将签名附加到容器映像和其他项目,以及查看这些签名。
在这篇文章中,你将学会如何:
- 安装 Notation 命令行界面(CLI)和 Key Vault 插件。
- 在 Key Vault 中创建自签名证书。
- 使用 容器注册表任务生成和推送容器映像。
- 使用 Notation CLI 和 Key Vault 插件对容器镜像进行签署。
- 使用 Notation CLI 根据签名验证容器镜像。
- 使用时间戳。
Prerequisites
- 创建或使用 容器注册表 来存储容器映像和签名。
- 创建或使用 密钥保管库 来管理证书。
- 安装和配置最新的 Azure CLI 版本,或在 Azure Cloud Shell 中运行命令。
安装 Notation CLI 和 Key Vault 插件
在 Linux AMD64 环境中安装 Notation v1.3.2。 若要下载适用于其他环境的包,请按照 符号安装指南进行安装。
# Download, extract, and install curl -Lo notation.tar.gz https://github.com/notaryproject/notation/releases/download/v1.3.2/notation_1.3.2_linux_amd64.tar.gz tar xvzf notation.tar.gz # Copy the Notation binary to the desired bin directory in $PATH, for example cp ./notation /usr/local/bin在 Linux AMD64 环境中安装 Key Vault 插件 (
notation-azure-kv) v1.2.1。注意
可以在插件的发布页面找到插件的 URL 和 SHA256 校验和。
notation plugin install --url https://github.com/Azure/notation-azure-kv/releases/download/v1.2.1/notation-azure-kv_1.2.1_linux_amd64.tar.gz --sha256sum 67c5ccaaf28dd44d2b6572684d84e344a02c2258af1d65ead3910b3156d3eaf5列出可用的插件,并确认
notation-azure-kv列表中是否包含带有版本的1.2.1插件:notation plugin ls
配置环境变量
为方便执行本文中的命令,请提供 Azure 资源的值以匹配现有的容器注册表和 Key Vault 资源。
配置 Key Vault 资源名称:
AKV_SUB_ID=myAkvSubscriptionId AKV_RG=myAkvResourceGroup # Name of the existing key vault used to store the signing keys AKV_NAME=myakv # Name of the certificate created in the key vault CERT_NAME=wabbit-networks-io CERT_SUBJECT="CN=wabbit-networks.io,O=Notation,L=Seattle,ST=WA,C=US" CERT_PATH=./${CERT_NAME}.pem配置容器注册表和映像资源名称:
ACR_SUB_ID=myAcrSubscriptionId ACR_RG=myAcrResourceGroup # Name of the existing registry (example: myregistry.azurecr.io) ACR_NAME=myregistry # Existing full domain of the container registry REGISTRY=$ACR_NAME.azurecr.io # Container name inside the container registry where the image will be stored REPO=net-monitor TAG=v1 IMAGE=$REGISTRY/${REPO}:$TAG # Source code directory that contains the Dockerfile to build IMAGE_SOURCE=https://github.com/wabbit-networks/net-monitor.git#main
使用 Azure CLI 登录
az login
有关详细信息,请参阅 使用 Azure CLI 向 Azure 进行身份验证。
授予对容器注册表和 Key Vault 的访问权限
使用容器注册表和 Key Vault 时,必须授予适当的权限,以帮助确保安全和控制的访问。 可以根据特定方案为各种实体(例如用户主体、服务主体或托管标识)授予访问权限。 在本文中,已登录的 Azure 用户已授权访问。
授权访问容器注册表
对于启用了 Microsoft Entra 属性访问控制 (ABAC) 的注册表,在容器注册表中生成和签署容器映像需要 Container Registry Repository Reader 和 Container Registry Repository Writer 角色。
对于未启用 ABAC 的注册表,需要 AcrPull 和 AcrPush 角色。
有关 ABAC 的详细信息,请参阅 Microsoft Entra 基于属性的存储库权限访问控制(预览版)。
设置包含容器注册表资源的订阅:
az account set --subscription $ACR_SUB_ID分配角色。 在角色分配中使用的正确角色取决于注册表是否已启用 ABAC。
USER_ID=$(az ad signed-in-user show --query id -o tsv) ROLE1="Container Registry Repository Reader" # For ABAC-enabled registries. Otherwise, use "AcrPull" for non-ABAC-enabled registries. ROLE2="Container Registry Repository Writer" # For ABAC-enabled registries. Otherwise, use "AcrPush" for non-ABAC-enabled registries. az role assignment create --role "$ROLE1" --role "$ROLE2" --assignee $USER_ID --scope "/subscriptions/$ACR_SUB_ID/resourceGroups/$ACR_RG/providers/Microsoft.ContainerRegistry/registries/$ACR_NAME"
授权访问“Key Vault”
本部分探讨两个选项,用于授权访问 Key Vault。
使用 Azure RBAC(建议)
使用自签名证书进行签名需要以下角色:
-
Key Vault Certificates Officer,用于创建和读取证书 -
Key Vault Certificates User用于读取现有证书 -
Key Vault Crypto User用于签名操作
若要详细了解使用 Azure 基于角色的访问控制(RBAC)进行 Key Vault 访问,请参阅 使用 Azure 基于角色的访问控制提供对 Key Vault 密钥、证书和机密的访问权限。
设置包含 Key Vault 资源的订阅:
az account set --subscription $AKV_SUB_ID分配角色:
USER_ID=$(az ad signed-in-user show --query id -o tsv) az role assignment create --role "Key Vault Certificates Officer" --role "Key Vault Crypto User" --assignee $USER_ID --scope "/subscriptions/$AKV_SUB_ID/resourceGroups/$AKV_RG/providers/Microsoft.KeyVault/vaults/$AKV_NAME"
在 Key Vault 中分配访问策略(旧版)
标识需要以下权限:
-
Create权限,用于创建证书 -
Get权限,用于读取现有证书 -
拥有
Sign权限,可执行签名操作
若要详细了解如何将策略分配给主体,请参阅“分配 Key Vault 访问策略”(旧版)。
设置包含 Key Vault 资源的订阅:
az account set --subscription $AKV_SUB_ID在 Key Vault 中设置访问策略:
USER_ID=$(az ad signed-in-user show --query id -o tsv) az keyvault set-policy -n $AKV_NAME --certificate-permissions create get --key-permissions sign --object-id $USER_ID
重要说明
此示例显示了创建证书和对容器映像进行签名所需的最低权限。 根据要求,可能需要授予更多权限。
在 Key Vault 中创建自签名证书(Azure CLI)
以下步骤演示如何创建自签名证书以进行测试:
创建证书策略文件。
通过以下代码执行证书策略文件后,它会创建与 Key Vault 中的 公证项目证书要求 兼容的有效证书。
ekus的值用于代码签名,但对于 Notation 签名项目来说不是必须的。 在验证期间,该主体稍后用作可信身份。cat <<EOF > ./my_policy.json { "issuerParameters": { "certificateTransparency": null, "name": "Self" }, "keyProperties": { "exportable": false, "keySize": 2048, "keyType": "RSA", "reuseKey": true }, "secretProperties": { "contentType": "application/x-pem-file" }, "x509CertificateProperties": { "ekus": [ "1.3.6.1.5.5.7.3.3" ], "keyUsage": [ "digitalSignature" ], "subject": "$CERT_SUBJECT", "validityInMonths": 12 } } EOF创建证书:
az keyvault certificate create -n $CERT_NAME --vault-name $AKV_NAME -p @my_policy.json
使用 Notation CLI 和 Key Vault 插件对容器镜像进行签名
使用单个 Azure 标识向容器注册表进行身份验证:
az acr login --name $ACR_NAME重要说明
如果在系统上安装了 Docker,并且使用
az acr login或docker login对容器注册表进行了身份验证,则您的凭据已存储并可供 Notation 使用。 在这种情况下,无需再次运行notation login,才能向容器注册表进行身份验证。 若要详细了解 Notation 的身份验证选项,请参阅 在符合 OCI 的注册表中进行身份验证。使用 Azure 容器注册表任务生成和推送新映像。 始终使用摘要值来标识用于签名的映像,因为标记是可变的,可以覆盖。
DIGEST=$(az acr build -r $ACR_NAME -t $REGISTRY/${REPO}:$TAG $IMAGE_SOURCE --no-logs --query "outputImages[0].digest" -o tsv) IMAGE=$REGISTRY/${REPO}@$DIGEST在本文中,如果映像已生成并存储在注册表中,则标记将用作该映像的标识符,以便于:
IMAGE=$REGISTRY/${REPO}:$TAG获取签名密钥的 ID。 Key Vault 中的证书可以有多个版本。 以下命令获取最新版本的密钥 ID:
KEY_ID=$(az keyvault certificate show -n $CERT_NAME --vault-name $AKV_NAME --query 'kid' -o tsv)使用签名密钥 ID,以CBOR 对象签名和加密(COSE)的签名格式对容器映像进行签名。 若要使用自签名证书进行签名,需要设置插件配置值
self_signed=true。notation sign --signature-format cose --id $KEY_ID --plugin azure-kv --plugin-config self_signed=true $IMAGE若要使用 Key Vault 进行身份验证,默认情况下,会按顺序尝试以下凭据类型(如果已启用):
如果要指定凭据类型,请使用名为
credential_type的其他插件配置。 例如,可以显式地将credential_type设置为azurecli以使用 Azure CLI 凭据,如以下示例所示:notation sign --signature-format cose --id $KEY_ID --plugin azure-kv --plugin-config self_signed=true --plugin-config credential_type=azurecli $IMAGE下表显示了各种凭据类型的
credential_type值。凭据类型 credential_type的值环境凭据 environment工作负载标识凭据 workloadid托管标识凭据 managedidAzure CLI 凭据 azurecli注意
由于表示法 v1.2.0,表示法默认使用 OCI 引用器标记架构 将签名存储在容器注册表中。 如有必要,还可以使用标志启用
--force-referrers-tag false。 容器注册表功能支持 OCI 引荐者 API,但使用客户管理的密钥 (CMK) 加密的注册表除外。查看已签名图像及其关联签名的图表。
notation ls $IMAGE
使用 Notation CLI 验证容器镜像
若要验证容器映像,请将将叶证书签名的根证书添加到信任存储,并创建用于验证的信任策略。 对于本文使用的自签名证书,根证书本身是自签名证书。
下载公共证书:
az keyvault certificate download --name $CERT_NAME --vault-name $AKV_NAME --file $CERT_PATH将下载的公共证书添加到命名信任存储进行签名验证:
STORE_TYPE="ca" STORE_NAME="wabbit-networks.io" notation cert add --type $STORE_TYPE --store $STORE_NAME $CERT_PATH列出要确认的证书:
notation cert ls在验证之前配置信任策略。
信任策略使用户能够指定微调的验证策略。 以下示例配置名为
wabbit-networks-images的信任策略。 此策略适用于$REGISTRY/$REPO中的所有工件,并使用类型为$STORE_TYPE的命名信任库$STORE_NAME。 它还假定用户信任具有 X.509 使用者$CERT_SUBJECT的特定标识。 有关详细信息,请参阅 信任存储和信任策略规范。cat <<EOF > ./trustpolicy.json { "version": "1.0", "trustPolicies": [ { "name": "wabbit-networks-images", "registryScopes": [ "$REGISTRY/$REPO" ], "signatureVerification": { "level" : "strict" }, "trustStores": [ "$STORE_TYPE:$STORE_NAME" ], "trustedIdentities": [ "x509.subject: $CERT_SUBJECT" ] } ] } EOF使用
notation policy从之前创建的 JSON 文件中导入信任策略配置。notation policy import ./trustpolicy.json notation policy show用于
notation verify验证容器映像在生成后未更改:notation verify $IMAGE通过信任策略成功验证映像后,验证图像的 SHA256 摘要会在成功的输出消息中返回。
使用时间戳
自 Notation v1.2.0 版本以来,Notation 支持符合 RFC 3161 的时间戳。 此项增强通过信任时间戳颁发机构 (TSA),扩展了在证书有效期内创建的签名的信任范围。 即使证书过期,此信任也能成功进行签名验证。
作为映像签名者,应确保使用受信任的 TSA 生成的时间戳对容器映像进行签名。 映像验证者应确保信任映像签名者和关联的 TSA,并通过信任存储和信任策略来建立信任。
时间戳消除了由于证书过期而定期重新签署映像的需要,从而降低了成本。 使用生存期较短的证书时,此功能尤其重要。 有关如何使用时间戳对图像进行签名和验证的详细说明,请参阅 公证项目时间戳指南。
相关内容
表示法在 Azure Pipelines 和 GitHub Actions 上提供 CI/CD 解决方案:
- 若要在 Azure DevOps 管道中对容器映像进行签名和验证,请参阅 在 Azure 管道中使用表示法对容器映像进行签名和验证。
- 若要使用 GitHub Actions 对容器映像进行签名,请参阅 在 GitHub Actions 中使用表示法对容器映像进行签名。
- 若要使用 GitHub Actions 验证容器映像,请参阅使用 GitHub Actions 中的表示法验证容器映像。
为了确保仅在 Azure Kubernetes 服务(AKS)上部署受信任的容器映像:
- 使用 Azure Policy 映像完整性(预览版),按照指南使用映像完整性功能在将签名的映像部署到 Azure Kubernetes 服务群集(预览版)之前进行验证。
- 使用Ratify和 Azure Policy,按照指南使用 Ratify 和 Azure Policy 验证容器映像签名进行操作。