你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

适用于 Windows 的 Azure Key Vault 虚拟机扩展

Azure Key Vault 虚拟机 (VM) 扩展可自动刷新 Azure Key Vault 中存储的证书。 该扩展会监视 Key Vault 中存储的已观察到的证书列表。 检测到更改后,该扩展会检索并安装相应的证书。 本文介绍适用于 Windows 的 Key Vault VM 扩展支持的平台、配置和部署选项。

操作系统

Key Vault VM 扩展支持以下版本的 Windows:

  • Windows Server 2022
  • Windows Server 2019
  • Windows Server 2016
  • Windows Server 2012

自定义本地 VM 也支持 Key Vault VM 扩展。 VM 应上传并转换为专用映像,以便通过使用 Windows Server 2019 核心安装来在 Azure 中使用。

支持的证书

Key Vault VM 扩展支持以下证书内容类型:

  • PKCS #12
  • PEM

注意

Key Vault VM 扩展将所有证书下载到 Windows 证书存储或 VM 扩展设置中 certificateStoreLocation 属性指定的位置。

版本 3.0+ 中的更新

适用于 Windows 的 Key Vault VM 扩展 3.0 版本增加了对以下功能的支持:

  • 增加对下载的证书的 ACL 权限
  • 每个证书都启用证书存储配置
  • 导出私钥
  • IIS 证书重新绑定支持

先决条件

查看使用适用于 Windows 的 Key Vault VM 扩展的以下先决条件:

  • 具有证书的 Azure Key Vault 实例。 有关详细信息,请参阅使用 Azure 门户创建密钥保管库

  • 具有分配的托管标识的 VM。

  • 对于 VM 和 Azure 虚拟机规模集托管标识,必须在 Key Vault 范围级别分配“Key Vault 机密用户”角色。 此角色可检索证书的机密部分。 有关详细信息,请参阅以下文章:

  • 虚拟机规模集应具有以下 identity 配置:

    "identity": {
       "type": "UserAssigned",
       "userAssignedIdentities": {
          "[parameters('userAssignedIdentityResourceId')]": {}
       }
    }
    
  • Key Vault VM 扩展应具有以下 authenticationSettings 配置:

    "authenticationSettings": {
        "msiEndpoint": "[parameters('userAssignedIdentityEndpoint')]",
        "msiClientId": "[reference(parameters('userAssignedIdentityResourceId'), variables('msiApiVersion')).clientId]"
    }
    

注意

旧的访问策略权限模型还可用于访问 VM 和虚拟机规模集。 此方法需要对机密具有“get”和“list”权限的策略。 有关详细信息,请参阅分配 Key Vault 访问策略

扩展架构

以下 JSON 显示 Key Vault VM 代理扩展的架构。 在考虑架构实现选项之前,请查看以下重要说明。

  • 扩展不需要受保护的设置。 所有设置均视为公共信息。

  • 观察到的证书 URL 应采用 https://myVaultName.vault.azure.net/secrets/myCertName 格式。

    首选此格式是因为 /secrets 路径会返回完整证书(包括私钥),但 /certificates 路径不会。 有关证书的详细信息,请参阅 Azure Key Vault 密钥、机密和证书概述

  • 对于具有任何“用户分配的标识”的 VM,authenticationSettings 属性为“必需”属性。

    此属性指定用于对 Key Vault 进行身份验证的标识。 使用系统分配的标识定义此属性,以免出现一个 VM 扩展具有多个标识的问题。

{
   "type": "Microsoft.Compute/virtualMachines/extensions",
   "name": "KVVMExtensionForWindows",
   "apiVersion": "2022-08-01",
   "location": "<location>",
   "dependsOn": [
      "[concat('Microsoft.Compute/virtualMachines/', <vmName>)]"
   ],
   "properties": {
      "publisher": "Microsoft.Azure.KeyVault",
      "type": "KeyVaultForWindows",
      "typeHandlerVersion": "3.0",
      "autoUpgradeMinorVersion": true,
      "settings": {
         "secretsManagementSettings": {
             "pollingIntervalInS": <A string that specifies the polling interval in seconds. Example: "3600">,
             "linkOnRenewal": <Windows only. Ensures s-channel binding when the certificate renews without necessitating redeployment. Example: true>,
             "requireInitialSync": <Initial synchronization of certificates. Example: true>,
             "observedCertificates": <An array of KeyVault URIs that represent monitored certificates, including certificate store location and ACL permission to certificate private key. Example: 
             [
                {
                    "url": <A Key Vault URI to the secret portion of the certificate. Example: "https://myvault.vault.azure.net/secrets/mycertificate1">,
                    "certificateStoreName": <The certificate store name. Example: "MY">,
                    "certificateStoreLocation": <The certificate store location, which currently works locally only. Example: "LocalMachine">,
                    "accounts": <Optional. An array of preferred accounts with read access to certificate private keys. Administrators and SYSTEM get Full Control by default. Example: ["Network Service", "Local Service"]>
                },
                {
                    "url": <Example: "https://myvault.vault.azure.net/secrets/mycertificate2">,
                    "certificateStoreName": <Example: "MY">,
                    "certificateStoreLocation": <Example: "CurrentUser">,
                    "keyExportable": <Optional. Lets the private key be exportable. Example: "false">,
                    "accounts": <Example: ["Local Service"]>
                }
             ]>
         },
         "authenticationSettings": {
             "msiEndpoint":  <Required when the msiClientId property is used. Specifies the MSI endpoint. Example for most Azure VMs: "http://169.254.169.254/metadata/identity/oauth2/token">,
             "msiClientId":  <Required when the VM has any user assigned identities. Specifies the MSI identity. Example:  "c7373ae5-91c2-4165-8ab6-7381d6e75619">
         }
      }
   }
}

属性值

JSON 架构包括以下属性。

名称 值/示例 数据类型
apiVersion 2022 年 8 月 1 日 date
publisher Microsoft.Azure.KeyVault 字符串
type KeyVaultForWindows string
typeHandlerVersion "3.0" string
pollingIntervalInS "3600" string
linkOnRenewal(可选) boolean
requireInitialSync(可选) false boolean
observedCertificates [{...}, {...}] 字符串数组
observedCertificates/url "https://myvault.vault.azure.net/secrets/mycertificate" 字符串
observedCertificates/certificateStoreName MY string
observedCertificates/certificateStoreLocation LocalMachine 或 CurrentUser(区分大小写) string
observedCertificates/keyExportable(可选) false boolean
observedCertificates/accounts(可选) ["Network Service", "Local Service"] 字符串数组
msiEndpoint "http://169.254.169.254/metadata/identity/oauth2/token" 字符串
msiClientId c7373ae5-91c2-4165-8ab6-7381d6e75619 string

模板部署

可使用 Azure 资源管理器 (ARM) 模板部署 Azure VM 扩展。 部署需要部署后刷新证书的一个或多个虚拟机时,模板是理想选择。 可将该扩展部署到单个 VM 或虚拟机规模集实例。 架构和配置对于这两种模板类型通用。

密钥保管库扩展的 JSON 配置嵌套在 VM 或虚拟机规模集模板中。 对于 VM 资源扩展,该配置嵌套在 "resources": [] 虚拟机对象下。 对于虚拟机规模集实例扩展,该配置嵌套在 "virtualMachineProfile":"extensionProfile":{"extensions" :[] 对象下。

以下 JSON 代码片段为 Key Vault VM 扩展的 ARM 模板部署提供了示例设置。

{
   "type": "Microsoft.Compute/virtualMachines/extensions",
   "name": "KeyVaultForWindows",
   "apiVersion": "2022-08-01",
   "location": "<location>",
   "dependsOn": [
      "[concat('Microsoft.Compute/virtualMachines/', <vmName>)]"
   ],
   "properties": {
      "publisher": "Microsoft.Azure.KeyVault",
      "type": "KeyVaultForWindows",
      "typeHandlerVersion": "3.0",
      "autoUpgradeMinorVersion": true,
      "settings": {
         "secretsManagementSettings": {
             "pollingIntervalInS": <A string that specifies the polling interval in seconds. Example: "3600">,
             "linkOnRenewal": <Windows only. Ensures s-channel binding when the certificate renews without necessitating redeployment. Example: true>,
             "observedCertificates": <An array of KeyVault URIs that represent monitored certificates, including certificate store location and ACL permission to certificate private key. Example:
             [
                {
                    "url": <A Key Vault URI to the secret portion of the certificate. Example: "https://myvault.vault.azure.net/secrets/mycertificate1">,
                    "certificateStoreName": <The certificate store name. Example: "MY">,
                    "certificateStoreLocation": <The certificate store location, which currently works locally only. Example: "LocalMachine">,
                    "accounts": <Optional. An array of preferred accounts with read access to certificate private keys. Administrators and SYSTEM get Full Control by default. Example: ["Network Service", "Local Service"]>
                },
                {
                    "url": <Example: "https://myvault.vault.azure.net/secrets/mycertificate2">,
                    "certificateStoreName": <Example: "MY">,
                    "certificateStoreLocation": <Example: "CurrentUser">,
                    "keyExportable": <Optional. Lets the private key be exportable. Example: "false">,
                    "accounts": <Example: ["Local Service"]>
                },
                {
                    "url": <Example: "https://myvault.vault.azure.net/secrets/mycertificate3">,
                    "certificateStoreName": <Example: "TrustedPeople">,
                    "certificateStoreLocation": <Example: "LocalMachine">
                }
             ]>           
         },
         "authenticationSettings": {
            "msiEndpoint":  <Required when the msiClientId property is used. Specifies the MSI endpoint. Example for most Azure VMs: "http://169.254.169.254/metadata/identity/oauth2/token">,
            "msiClientId":  <Required when the VM has any user assigned identities. Specifies the MSI identity. Example: "c7373ae5-91c2-4165-8ab6-7381d6e75619">
         }
      }
   }
}

扩展依赖项排序

可以启用 Key Vault VM 扩展以支持扩展依赖项排序。 默认情况下,Key Vault VM 扩展在轮询开始后立即报告启动成功。 但是,可以将扩展配置为仅在其下载并安装所有证书后再报告启动成功。

如果使用其他需要在启动之前安装所有证书的扩展,则可以在 Key Vault VM 扩展中启用扩展依赖项排序。 此功能允许其他扩展声明 Key Vault VM 扩展的依赖项。

可以使用此功能阻止其他扩展在安装所有相关证书之前启动。 启用该功能后,Key Vault VM 扩展会无限期地重试下载和安装证书,并保持“正在转换”状态,直到所有证书均成功安装。 所有证书都就位后,Key Vault VM 扩展将报告启动成功。

若要在 Key Vault VM 扩展中启用扩展依赖项排序功能,请设置 secretsManagementSettings 属性:

"secretsManagementSettings": {
   "requireInitialSync": true,
   ...
}

有关如何在扩展之间设置依赖项的详细信息,请参阅虚拟机规模集中的序列扩展预配

重要

扩展依赖项排序功能与 ARM 模板不兼容(该模板会创建系统分配的标识并使用该标识更新 Key Vault 访问策略)。 如果尝试在此方案中使用该功能,则会发生死锁,因为 Key Vault 访问策略只有在所有扩展都启动后才会更新。 改为在部署之前使用单个用户分配的 MSI 标识,并使用该标识对你的密钥保管库进行预 ACL 操作。

Azure PowerShell 部署

可以使用 Azure PowerShell 部署 Azure Key Vault VM 扩展。 将 Key Vault VM 扩展设置保存到 JSON 文件 (settings.json)。

以下 JSON 代码片段提供了使用 PowerShell 部署 Key Vault VM 扩展的示例设置。

{   
   "secretsManagementSettings": {
   "pollingIntervalInS": "3600",
   "linkOnRenewal": true,
   "observedCertificates":
   [
      {
          "url": "https://<examplekv>.vault.azure.net/secrets/certificate1",
          "certificateStoreName": "MY",
          "certificateStoreLocation": "LocalMachine",
          "accounts": [
             "Network Service"
          ]
      },
      {
          "url": "https://<examplekv>.vault.azure.net/secrets/certificate2",
          "certificateStoreName": "MY",
          "certificateStoreLocation": "LocalMachine",
          "keyExportable": true,
          "accounts": [
             "Network Service",
             "Local Service"
          ]
      }
   ]},
   "authenticationSettings": {
      "msiEndpoint":  "http://169.254.169.254/metadata/identity/oauth2/token",
      "msiClientId":  "c7373ae5-91c2-4165-8ab6-7381d6e75619"
   }      
}

在 VM 上部署

# Build settings
$settings = (get-content -raw ".\settings.json")
$extName =  "KeyVaultForWindows"
$extPublisher = "Microsoft.Azure.KeyVault"
$extType = "KeyVaultForWindows"
 
# Start the deployment
Set-AzVmExtension -TypeHandlerVersion "3.0" -ResourceGroupName <ResourceGroupName> -Location <Location> -VMName <VMName> -Name $extName -Publisher $extPublisher -Type $extType -SettingString $settings

在虚拟机规模集实例上部署

# Build settings
$settings = ".\settings.json"
$extName = "KeyVaultForWindows"
$extPublisher = "Microsoft.Azure.KeyVault"
$extType = "KeyVaultForWindows"
  
# Add extension to Virtual Machine Scale Sets
$vmss = Get-AzVmss -ResourceGroupName <ResourceGroupName> -VMScaleSetName <VmssName>
Add-AzVmssExtension -VirtualMachineScaleSet $vmss  -Name $extName -Publisher $extPublisher -Type $extType -TypeHandlerVersion "3.0" -Setting $settings

# Start the deployment
Update-AzVmss -ResourceGroupName <ResourceGroupName> -VMScaleSetName <VmssName> -VirtualMachineScaleSet $vmss 

Azure CLI 部署

可以使用 Azure CLI 部署 Azure Key Vault VM 扩展。 将 Key Vault VM 扩展设置保存到 JSON 文件 (settings.json)。

以下 JSON 代码片段提供了使用 Azure CLI 部署 Key Vault VM 扩展的示例设置。

   {   
        "secretsManagementSettings": {
          "pollingIntervalInS": "3600",
          "linkOnRenewal": true,
          "observedCertificates": [
            {
                "url": "https://<examplekv>.vault.azure.net/secrets/certificate1",
                "certificateStoreName": "MY",
                "certificateStoreLocation": "LocalMachine",
                "accounts": [
                    "Network Service"
                ]
            },
            {
                "url": "https://<examplekv>.vault.azure.net/secrets/certificate2",
                "certificateStoreName": "MY",
                "certificateStoreLocation": "LocalMachine",                
                "keyExportable": true,
                "accounts": [
                    "Network Service",
                    "Local Service"
                ]
            }
        ]
        },
          "authenticationSettings": {
          "msiEndpoint":  "http://169.254.169.254/metadata/identity/oauth2/token",
          "msiClientId":  "c7373ae5-91c2-4165-8ab6-7381d6e75619"
        }      
     }

在 VM 上部署

# Start the deployment
az vm extension set --name "KeyVaultForWindows" `
 --publisher Microsoft.Azure.KeyVault `
 --resource-group "<resourcegroup>" `
 --vm-name "<vmName>" `
 --settings "@settings.json"

在虚拟机规模集实例上部署

# Start the deployment
az vmss extension set --name "KeyVaultForWindows" `
 --publisher Microsoft.Azure.KeyVault `
 --resource-group "<resourcegroup>" `
 --vmss-name "<vmssName>" `
 --settings "@settings.json"

排查问题

下面是有关如何排查部署问题的一些建议。

检查常见问题解答

观察到的证书数量有限制吗?

不是。 没有,Key Vault VM 扩展对观察到的证书 (observedCertificates) 数量没有限制。

未指定帐户时的默认权限是什么?

默认情况下,管理员和 SYSTEM 将获得完全控制。

如何确定证书密钥是 CAPI1 还是 CNG?

扩展依赖于 PFXImportCertStore API 的默认行为。 默认情况下,如果证书具有的“提供程序名称”属性与 CAPI1 匹配,则会使用 CAPI1 API 导入证书。 否则,将使用 CNG API 导入证书。

该扩展是否支持证书自动重新绑定?

是的,Azure Key Vault VM 扩展支持证书自动重新绑定。 当 linkOnRenewal 属性设置为 true 时,Key Vault VM 扩展在证书续订时支持 S 通道绑定。

对于 IIS,可以通过在 IIS 中启用证书续订的自动重新绑定来配置自动重新绑定。 安装了具有匹配的 SAN 的证书时,Azure Key Vault VM 扩展会生成证书生命周期通知。 IIS 使用此事件自动重新绑定证书。 有关详细信息,请参阅 IIS 中的证书重新绑定

查看扩展状态

在 Azure 门户中通过使用 PowerShell 或 Azure CLI 来检查扩展部署的状态。

若要查看给定 VM 的扩展部署状态,请运行以下命令。

  • Azure PowerShell:

    Get-AzVMExtension -ResourceGroupName <myResourceGroup> -VMName <myVM> -Name <myExtensionName>
    
  • Azure CLI:

    az vm get-instance-view --resource-group <myResourceGroup> --name <myVM> --query "instanceView.extensions"
    

查看日志和配置

Key Vault VM 扩展日志仅存在于本地 VM 上。 查看日志详细信息以帮助进行故障排除。

日志文件 说明
C:\WindowsAzure\Logs\WaAppAgent.log` 显示进行扩展更新的时间。
C:\WindowsAzure\Logs\Plugins\Microsoft.Azure.KeyVault.KeyVaultForWindows<最新版本>\ 显示证书下载的状态。 下载位置始终为 Windows 计算机的 MY 存储位置 (certlm.msc)。
C:\Packages\Plugins\Microsoft.Azure.KeyVault.KeyVaultForWindows<最新版本>\RuntimeSettings\ Key Vault VM 扩展服务日志显示 akvvm_service 服务的状态。
C:\Packages\Plugins\Microsoft.Azure.KeyVault.KeyVaultForWindows<最新版本>\Status\ Key Vault VM 扩展服务的配置和二进制文件。

获取支持

下面是一些其他选项,可帮助你解决部署问题: