启用客户管理的密钥

本文是由四部分构成的教程系列的第二部分。 第一部分概述了客户管理的密钥、其功能,以及在注册表中启用客户管理的密钥之前的注意事项。 本文将引导你完成使用 Azure CLI、Azure 门户或 Azure 资源管理器模板来启用客户管理的密钥的步骤。

先决条件

使用 Azure CLI 启用客户管理的密钥

创建资源组

运行 az group create 命令来创建一个资源组,用于保存密钥保管库、容器注册表和其他所需资源:

az group create --name <resource-group-name> --location <location>

创建用户分配的托管标识

为注册表配置用户分配的托管标识,以便可以访问密钥保管库:

  1. 运行 az identity create 命令创建托管标识:

    az identity create \
      --resource-group <resource-group-name> \
      --name <managed-identity-name>
    
  2. 在命令输出中,记下 idprincipalId 值以使用密钥保管库配置注册表访问:

    {
      "clientId": "xxxx2bac-xxxx-xxxx-xxxx-192cxxxx6273",
      "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/myresourcegroup/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myresourcegroup",
      "location": "chinaeast2",
      "name": "myidentityname",
      "principalId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "resourceGroup": "myresourcegroup",
      "tags": {},
      "tenantId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "type": "Microsoft.ManagedIdentity/userAssignedIdentities"
    }
    
  3. 为方便起见,请将 idprincipalId 值存储在环境变量中:

    identityID=$(az identity show --resource-group <resource-group-name> --name <managed-identity-name> --query 'id' --output tsv)
    
    identityPrincipalID=$(az identity show --resource-group <resource-group-name> --name <managed-identity-name> --query 'principalId' --output tsv)
    

创建 key vault

  1. 运行 az keyvault create 命令创建一个密钥保管库,可以在其中存储客户管理的用于加密注册表的密钥。

  2. 默认情况下,新的密钥保管库会自动启用软删除设置。 为防止意外删除密钥或密钥保管库导致的数据丢失,建议启用“清除保护”设置:

    az keyvault create --name <key-vault-name> \
      --resource-group <resource-group-name> \
      --enable-purge-protection
    
  3. 为方便起见,请记下密钥保管库资源 ID 并将值存储在环境变量中:

    keyvaultID=$(az keyvault show --resource-group <resource-group-name> --name <key-vault-name> --query 'id' --output tsv)
    

启用受信任的服务以访问密钥保管库

如果使用防火墙或虚拟网络(专用终结点)来保护密钥保管库,则必须启用网络设置,以允许受信任的 Azure 服务进行访问。 有关详细信息,请参阅配置 Azure Key Vault 网络设置

启用托管标识以访问密钥保管库

可通过两种方式启用托管标识以访问密钥保管库。

第一种是为密钥保管库配置访问策略并设置密钥权限以使用用户分配的托管标识进行访问:

  1. 运行 az keyvault set policy 命令。 传递先前创建并存储的环境变量值 principalID

  2. 将密钥权限设置为 getunwrapKeywrapKey

    az keyvault set-policy \
      --resource-group <resource-group-name> \
      --name <key-vault-name> \
      --object-id $identityPrincipalID \
      --key-permissions get unwrapKey wrapKey
    
    

第二种是使用 Azure 基于角色的访问控制 (RBAC) 将权限分配给用户分配的托管标识并访问密钥保管库。 运行 az role assignment create 命令并将 Key Vault Crypto Service Encryption User 角色分配给用户分配的托管标识:

az role assignment create --assignee $identityPrincipalID \
  --role "Key Vault Crypto Service Encryption User" \
  --scope $keyvaultID

创建密钥并获取密钥 ID

  1. 运行 az keyvault key create 命令以在密钥保管库中创建密钥:

    az keyvault key create \
      --name <key-name> \
      --vault-name <key-vault-name>
    
  2. 记下命令输出中的密钥 ID (kid):

    [...]
      "key": {
        "crv": null,
        "d": null,
        "dp": null,
        "dq": null,
        "e": "AQAB",
        "k": null,
        "keyOps": [
          "encrypt",
          "decrypt",
          "sign",
          "verify",
          "wrapKey",
          "unwrapKey"
        ],
        "kid": "https://mykeyvault.vault.azure.cn/keys/mykey/<version>",
        "kty": "RSA",
    [...]
    
  3. 为方便起见,请将为密钥 ID 选择的格式存储在 $keyID 环境变量中。 可以使用带版本或不带版本的密钥 ID。

密钥轮换

可以选择手动或自动密钥轮换。

使用带密钥版本的客户管理的密钥加密注册表,将只允许在 Azure 容器注册表中手动轮换密钥。 此示例存储密钥的 kid 属性:

keyID=$(az keyvault key show \
  --name <keyname> \
  --vault-name <key-vault-name> \
  --query 'key.kid' --output tsv)

如果通过省略密钥版本来使用客户管理的密钥加密注册表,将启用自动密钥轮换来检测 Azure 密钥保管库中的新密钥版本。 此示例删除密钥的 kid 属性中的版本:

keyID=$(az keyvault key show \
  --name <keyname> \
  --vault-name <key-vault-name> \
  --query 'key.kid' --output tsv)

keyID=$(echo $keyID | sed -e "s/\/[^/]*$//")

使用客户管理的密钥创建注册表

  1. 运行 az acr create 命令,以在“高级”服务层级创建注册表并启用客户管理的密钥。

  2. 传递在前面的步骤中存储在环境变量中的托管标识 ID (id) 和密钥 ID (kid) 值:

    az acr create \
      --resource-group <resource-group-name> \
      --name <container-registry-name> \
      --identity $identityID \
      --key-encryption-key $keyID \
      --sku Premium
    

显示加密状态

运行 az acr encryption show 命令以显示使用客户管理的密钥执行的注册表加密的状态:

az acr encryption show --name <container-registry-name>

输出类似于以下内容,具体取决于用于加密注册表的密钥:

{
  "keyVaultProperties": {
    "identity": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "keyIdentifier": "https://myvault.vault.azure.cn/keys/myresourcegroup/abcdefg123456789...",
    "keyRotationEnabled": true,
    "lastKeyRotationTimestamp": xxxxxxxx
    "versionedKeyIdentifier": "https://myvault.vault.azure.cn/keys/myresourcegroup/abcdefg123456789...",
  },
  "status": "enabled"
}

使用 Azure 门户启用客户管理的密钥

创建用户分配的托管标识

要在 Azure 门户中为 Azure 资源创建用户分配的托管标识

  1. 按照步骤创建用户分配的标识

  2. 保存标识名称以在之后的步骤中使用。

用于在 Azure 门户中创建用户分配标识的选项的屏幕截图。

创建 key vault

  1. 按照快速入门:使用 Azure 门户创建密钥保管库中的步骤操作。

  2. 为客户管理的密钥创建密钥保管库时,请在“基本信息”选项卡中启用“清除保护”设置。 此设置有助于防止因意外删除密钥或密钥保管库导致的数据丢失。

    用于在 Azure 门户中创建密钥保管库的选项的屏幕截图。

启用受信任的服务以访问密钥保管库

如果使用防火墙或虚拟网络(专用终结点)来保护密钥保管库,请启用网络设置,以允许受信任的 Azure 服务进行访问。 有关详细信息,请参阅配置 Azure Key Vault 网络设置

启用托管标识以访问密钥保管库

可通过两种方式启用托管标识以访问密钥保管库。

第一种是为密钥保管库配置访问策略并设置密钥权限以使用用户分配的托管标识进行访问:

  1. 转到密钥保管库。
  2. 选择“设置”>“访问策略”>“+添加访问策略”。
  3. 选择“密钥权限”,然后选择“获取”、“解包密钥”和“包装密钥”。
  4. 在“选择主体”中,选择你的用户分配的托管标识的资源名称。
  5. 依次选择“添加”、“保存”。

用于创建密钥保管库访问策略的选项的屏幕截图。

另一种是将 Key Vault Crypto Service Encryption User RBAC 角色分配给密钥保管库范围内的用户分配的托管标识。 有关详细步骤,请参阅使用 Azure 门户分配 Azure 角色

创建密钥

在密钥保管库中创建一个密钥并使用它来加密注册表。 如果要选择特定的密钥版本作为客户管理的密钥,请执行以下步骤。 如果密钥保管库访问仅限于专用终结点或选定网络,则创建注册表之前可能还需要创建密钥。

  1. 转到密钥保管库。
  2. 选择“设置”>“密钥”。
  3. 选择“+生成/导入”并输入密钥的唯一名称。
  4. 接受剩余的默认值,然后选择“创建”。
  5. 创建后,选择该密钥,然后选择当前版本。 复制密钥版本的密钥标识符。

创建容器注册表

  1. 选择“创建资源”>“容器”>“容器注册表”。
  2. 在“基本信息”选项卡中选择或创建一个资源组,然后输入注册表名称。 在“SKU”中选择“高级”。
  3. 在“加密”选项卡上的“客户管理的密钥”中,选择“已启用”。
  4. 对于“标识”,选择创建的托管标识。
  5. 对于“加密”,选择以下选项之一
    • 选择“从密钥保管库中选择”,然后选择现有的密钥保管库和密钥,或选择“新建”。 你选择的密钥不带版本,可启用自动密钥轮换。
    • 选择“输入密钥 URI”,并提供现有密钥的标识符。 可以提供带版本的密钥 URI(适用于必须手动轮换的密钥)或不带版本的密钥 URI(用于启用自动密钥轮换)。 有关创建密钥的步骤,请参阅上一部分。
  6. 选择“查看 + 创建”。
  7. 选择“创建”以部署注册表实例。

显示用于在 Azure 门户中创建加密注册表的选项的屏幕截图。

显示加密状态

要在门户中查看注册表的加密状态,请转到注册表。 在“设置”下,选择“加密”。

使用资源管理器模板启用客户管理的密钥

可以使用资源管理器模板来创建容器注册表,并使用客户管理的密钥启用加密:

  1. 将资源管理器模板的以下内容复制到新文件中并将其另存为 CMKtemplate.json:

    {
      "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
      "contentVersion": "1.0.0.0",
      "parameters": {
        "vault_name": {
          "defaultValue": "",
          "type": "String"
        },
        "registry_name": {
          "defaultValue": "",
          "type": "String"
        },
        "identity_name": {
          "defaultValue": "",
          "type": "String"
        },
        "kek_id": {
          "type": "String"
        }
      },
      "variables": {},
      "resources": [
        {
          "type": "Microsoft.ContainerRegistry/registries",
          "apiVersion": "2019-12-01-preview",
          "name": "[parameters('registry_name')]",
          "location": "[resourceGroup().location]",
          "sku": {
            "name": "Premium",
            "tier": "Premium"
          },
          "identity": {
            "type": "UserAssigned",
            "userAssignedIdentities": {
              "[resourceID('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('identity_name'))]": {}
            }
          },
          "dependsOn": [
            "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('identity_name'))]"
          ],
          "properties": {
            "adminUserEnabled": false,
            "encryption": {
              "status": "enabled",
              "keyVaultProperties": {
                "identity": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('identity_name')), '2018-11-30').clientId]",
                "KeyIdentifier": "[parameters('kek_id')]"
              }
            },
            "networkRuleSet": {
              "defaultAction": "Allow",
              "virtualNetworkRules": [],
              "ipRules": []
            },
            "policies": {
              "quarantinePolicy": {
                "status": "disabled"
              },
              "trustPolicy": {
                "type": "Notary",
                "status": "disabled"
              },
              "retentionPolicy": {
                "days": 7,
                "status": "disabled"
              }
            }
          }
        },
        {
          "type": "Microsoft.KeyVault/vaults/accessPolicies",
          "apiVersion": "2018-02-14",
          "name": "[concat(parameters('vault_name'), '/add')]",
          "dependsOn": [
            "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('identity_name'))]"
          ],
          "properties": {
            "accessPolicies": [
              {
                "tenantId": "[subscription().tenantId]",
                "objectId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('identity_name')), '2018-11-30').principalId]",
                "permissions": {
                  "keys": [
                    "get",
                    "unwrapKey",
                    "wrapKey"
                  ]
                }
              }
            ]
          }
        },
        {
          "type": "Microsoft.ManagedIdentity/userAssignedIdentities",
          "apiVersion": "2018-11-30",
          "name": "[parameters('identity_name')]",
          "location": "[resourceGroup().location]"
        }
      ]
    }
    
  2. 按照前面部分中的步骤创建以下资源:

    • 密钥保管库,按名称标识
    • 密钥保管库密钥,按密钥 ID 标识
  3. 运行 az deployment group create 命令,以使用前面的模板文件创建注册表。 如有指示,请提供新的注册表名称和用户分配的托管标识名称,以及创建的密钥保管库名称和密钥 ID。

    az deployment group create \
      --resource-group <resource-group-name> \
      --template-file CMKtemplate.json \
      --parameters \
        registry_name=<registry-name> \
        identity_name=<managed-identity> \
        vault_name=<key-vault-name> \
        key_id=<key-vault-key-id>
    
  4. 运行 az acr encryption show 命令显示注册表加密的状态:

    az acr encryption show --name <registry-name>
    

后续步骤

继续阅读下一篇文章,了解如何轮换客户管理的密钥、更新密钥版本和撤销客户管理的密钥。