使用自签名证书通过表示法和 Azure Key Vault 对容器映像进行签名

为容器映像签名是一个确保其真实性和完整性的过程。 这是通过将数字签名添加到容器映像来实现的,该签名可在部署期间进行验证。 签名有助于验证映像是否来自受信任的发布者,并且尚未修改。 表示法是由 Notary Project 开发的开放源代码供应链工具,它支持对容器映像及其他项目进行签名和验证。 Azure Key Vault (AKV) 用于存储证书,其签名密钥可供支持 Notation AKV 插件 (azure-kv) 的 Notation 用来对容器映像及其他项目进行签名和验证。 Azure 容器注册表 (ACR) 允许将签名附加到容器映像和其他项目,以及查看这些签名。

本教程的内容:

  • 安装 Notation CLI 和 AKV 插件
  • 在 AKV 中创建自签名证书
  • 使用 Azure 任务生成并推送容器映像
  • 使用 Notation CLI 和 AKV 插件为容器映像签名
  • 使用 Notation CLI 根据签名验证容器映像

先决条件

安装 Notation CLI 和 AKV 插件

  1. 在 Linux amd64 环境中安装 Notation v1.1.0。 按照 Notation 安装指南下载适用于其他环境的包。

    # Download, extract and install
    curl -Lo notation.tar.gz https://github.com/notaryproject/notation/releases/download/v1.1.0/notation_1.1.0_linux_amd64.tar.gz
    tar xvzf notation.tar.gz
    
    # Copy the Notation binary to the desired bin directory in your $PATH, for example
    cp ./notation /usr/local/bin
    
  2. 在 Linux amd64 环境中安装 Notation Azure Key Vault 插件 azure-kv v1.0.2。

    注意

    可以在插件的发布页上找到 Notation Azure Key Vault 插件的 URL 和 SHA256 校验和。

    notation plugin install --url https://github.com/Azure/notation-azure-kv/releases/download/v1.0.2/notation-azure-kv_1.0.2_linux_amd64.tar.gz --sha256sum f2b2e131a435b6a9742c202237b9aceda81859e6d4bd6242c2568ba556cee20e
    
  3. 列出可用的插件,并确认版本为 1.0.2azure-kv 插件是否已包含在列表中。

    notation plugin ls
    

配置环境变量

注意

为便于执行教程中的命令,请提供 Azure 资源的值来匹配现有的 ACR 和 AKV 资源。

  1. 配置 AKV 资源名。

    # Name of the existing AKV used to store the signing keys
    AKV_NAME=myakv
    # Name of the certificate created in AKV
    CERT_NAME=wabbit-networks-io
    CERT_SUBJECT="CN=wabbit-networks.io,O=Notation,L=Seattle,ST=WA,C=US"
    CERT_PATH=./${CERT_NAME}.pem
    
  2. 配置 ACR 和映像资源名。

    # Name of the existing registry example: myregistry.azurecr.cn
    ACR_NAME=myregistry
    # Existing full domain of the ACR
    REGISTRY=$ACR_NAME.azurecr.cn
    # Container name inside ACR where image will be stored
    REPO=net-monitor
    TAG=v1
    IMAGE=$REGISTRY/${REPO}:$TAG
    # Source code directory containing Dockerfile to build
    IMAGE_SOURCE=https://github.com/wabbit-networks/net-monitor.git#main
    

使用 Azure CLI 登录

az cloud set -n AzureChinaCloud
az login
# az cloud set -n AzureCloud   //means return to Public Azure.

若要详细了解 Azure CLI 及其登录方式,请参阅使用 Azure CLI 登录

在 AKV (Azure CLI) 中分配访问策略

需要具有正确访问策略权限的用户主体才能创建自签名证书和对项目进行签名。 此主体可以是用户主体、服务主体或托管标识。 此主体至少需要以下权限:

  • Create证书的权限
  • Get证书的权限
  • Sign密钥的权限

在本教程中,访问策略分配给已登录的 Azure 用户。 若要详细了解如何将策略分配给主体,请参阅分配访问策略

设置包含 AKV 资源的订阅

az account set --subscription <your_subscription_id>

在 AKV 中设置访问策略

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

重要

此示例显示了创建证书和对容器映像进行签名所需的最低权限。 根据要求,可能需要授予其他权限。

在 AKV (Azure CLI) 中创建自签名证书

以下步骤演示如何为测试创建自签名证书。

  1. 创建证书策略文件。

    如下所示,执行证书策略文件后,它会创建与 AKV 中的 Notary Project 证书要求兼容的有效证书。 ekus 的值用于代码签名,但表示法不需要使用它即可对项目进行签名。 主题稍后用作用户在验证期间信任的信任标识。

    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
    
  2. 创建证书。

    az keyvault certificate create -n $CERT_NAME --vault-name $AKV_NAME -p @my_policy.json
    

使用 Notation CLI 和 AKV 插件为容器映像签名

  1. 使用单个 Azure 标识向 ACR 进行身份验证。

    az acr login --name $ACR_NAME
    

重要

如果已在系统上安装 Docker 并使用 az acr logindocker login azure --cloud-name AzureChinaCloud 向 ACR 进行身份验证,则凭据已存储并可用于表示法。 在这种情况下,无需再次运行 notation login 即可向 ACR 进行身份验证。 若要详细了解表示法的身份验证选项,请参阅使用符合 OCI 的注册表进行身份验证

  1. 使用 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
    
  2. 获取签名密钥的密钥 ID。 AKV 中的证书可以有多个版本,以下命令获取最新版本的密钥 ID。

    KEY_ID=$(az keyvault certificate show -n $CERT_NAME --vault-name $AKV_NAME --query 'kid' -o tsv)
    
  3. 使用签名密钥,以 COSE 签名格式为容器映像签名。 若要使用自签名证书进行签名,需要设置插件配置值 self_signed=true

    notation sign --signature-format cose --id $KEY_ID --plugin azure-kv --plugin-config self_signed=true $IMAGE
    
  4. 查看已签名映像和关联签名的图。

    notation ls $IMAGE
    

使用 Notation CLI 为容器映像签名

若要验证容器映像,请将对叶证书进行签名的根证书添加到信任存储区,并创建用于验证的信任策略。 对于本教程中使用的自签名证书,根证书是自签名证书本身。

  1. 下载公共证书。

    az keyvault certificate download --name $CERT_NAME --vault-name $AKV_NAME --file $CERT_PATH
    
  2. 将下载的公共证书添加到命名信任存储,以便进行签名验证。

    STORE_TYPE="ca"
    STORE_NAME="wabbit-networks.io"
    notation cert add --type $STORE_TYPE --store $STORE_NAME $CERT_PATH
    
  3. 列出要确认的证书。

    notation cert ls
    
  4. 在验证之前先配置信任策略。

    信任策略允许用户指定经过微调的验证策略。 以下示例配置名为 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
    
  5. 使用 notation policy 从我们之前创建的 JSON 文件导入信任策略配置。

    notation policy import ./trustpolicy.json
    notation policy show
    
  6. 使用 notation verify 验证容器映像自生成时以来未发生更改。

    notation verify $IMAGE
    

    使用信任策略成功验证映像后,将在成功输出消息中返回已验证映像的 sha256 摘要。

后续步骤

请参阅 使用映像完整性在将已签名映像部署到 Azure Kubernetes 服务 (AKS) 群集之前对其进行验证(预览版)Azure 上的 Ratify,以在 AKS 上部署它们之前开始验证和审核已签名映像。