适用于 Linux 的 Key Vault 虚拟机扩展

密钥保管库 VM 扩展可自动刷新 Azure 密钥保管库中存储的证书。 具体而言,该扩展会监视在密钥保管库中存储的观察到的证书列表。 扩展程序在检测到更改后会检索并安装相应的证书。 本文档详细介绍适用于 Linux 的 Key Vault VM 扩展支持的平台、配置和部署选项。

操作系统

Key Vault VM 扩展支持以下 Linux 发行版:

  • Ubuntu 20.04、22.04

注意

Key Vault VM 扩展会将证书下载到默认位置或 VM 扩展设置(版本 1/2)或单个证书设置(版本 3)中“certStoreLocation”属性所提供的位置。 Key Vault VM 扩展会将文件夹权限更新为 700 (drwx------),即仅允许对文件夹所有者的“读取”、“写入”和“执行”权限

支持的证书内容类型

  • PKCS #12
  • PEM

版本 3.0+ 中的更新

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

  • 为下载的证书添加 ACL 权限,为用户和组提供读取访问权限
  • 证书安装位置配置
  • 自定义符号名称支持
  • 通过 Fluentd 提供 VM 扩展日志记录集成支持

先决条件

  • 具有证书的 Key Vault 实例。 请参阅创建 Key Vault

  • 在 VM/VMSS 上分配的托管标识

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

  • VMSS 应具有以下标识设置:"identity": { "type": "UserAssigned", "userAssignedIdentities": { "[parameters('userAssignedIdentityResourceId')]": {} } }

  • AKV 扩展应具有此设置:"authenticationSettings": { "msiEndpoint": "[parameters('userAssignedIdentityEndpoint')]", "msiClientId": "[reference(parameters('userAssignedIdentityResourceId'), variables('msiApiVersion')).clientId]" }

Key Vault VM 扩展版本

  • 用户可以选择将现有的 Key Vault VM 扩展版本升级到较新版本。

  • 如果希望升级到较新的版本,则需先删除以前的版本,然后安装较新的版本。

  az vm extension delete --name KeyVaultForLinux --resource-group ${resourceGroup} --vm-name ${vmName}
  az vm extension set -n "KeyVaultForLinux" --publisher Microsoft.Azure.KeyVault --resource-group "${resourceGroup}" --vm-name "${vmName}" -settings .\akvvm.json -version 3.0

--version 3.0 标志是可选的,因为默认安装最新版本。

  • 如果 VM 有以前版本下载的证书,则删除 VM 扩展不会删除已下载的证书。 安装较新版本后,不会修改现有证书。 你需要删除证书文件或滚动更新证书,以获取 VM 上包含完整链的 PEM 文件。

扩展架构

以下 JSON 显示 Key Vault VM 代理扩展的架构。 该扩展不需要受保护的设置 - 其所有设置都被视为没有安全影响的信息。 该扩展需要受监视的密钥列表、轮询频率和目标证书存储。 具体而言:

    {
      "type": "Microsoft.Compute/virtualMachines/extensions",
      "name": "KVVMExtensionForLinux",
      "apiVersion": "2022-11-01",
      "location": "<location>",
      "dependsOn": [
          "[concat('Microsoft.Compute/virtualMachines/', <vmName>)]"
      ],
      "properties": {
      "publisher": "Microsoft.Azure.KeyVault",
      "type": "KeyVaultForLinux",
      "typeHandlerVersion": "3.0",
      "autoUpgradeMinorVersion": true,
      "enableAutomaticUpgrade": true,
      "settings": {
      "loggingSettings": <Optional logging settings, e.g.:
        {
              "logger": <Logger engine name. e.g.: "fluentd">,
              "endpoint": <Logger listening endpoint "tcp://localhost:24224">,
              "format": <Logging format. e.g.: "forward">,
              "servicename": <Service name used in logs. e.g.: "akvvm_service">
          }>,
        "secretsManagementSettings": {
          "pollingIntervalInS": <polling interval in seconds, e.g. "3600">,
          "linkOnRenewal": <Not available on Linux e.g.: false>,
          "requireInitialSync": <initial synchronization of certificates e..g: true>,
          "aclEnabled": <Enables ACLs for downloaded certificates, e.g.: true>,
          "observedCertificates": <An array of KeyVault URIs that represent monitored certificates, including certificate store location, ACL permission to certificate private key, and custom symbolic name. e.g.: 
             [
                {
                    "url": <A Key Vault URI to the secret portion of the certificate. e.g.: "https://myvault.vault.azure.cn/secrets/mycertificate1">,
                    "certificateStoreLocation": <disk path where certificate is stored, e.g.: "/var/lib/waagent/Microsoft.Azure.KeyVault/app1">,
                    "customSymbolicLinkName": <symbolic name for the certificate. e.g.: "app1Cert1">,
                    "acls": [
                        {
                            "user": "app1",
                            "group": "appGroup1"
                        },
                        {
                            "user": "service1"
                        }
                    ]
                },
                {
                    "url": <Example: "https://myvault.vault.azure.cn/secrets/mycertificate2">,
                    "certificateStoreLocation": <disk path where the certificate is stored, e.g.: "/var/lib/waagent/Microsoft.Azure.KeyVault/app2">,
                    "acls": [
                        {
                            "user": "app2",
                        }
                    ]
                }
             ]>
        },
        "authenticationSettings": <Optional msi settings, e.g.:
        {
          "msiEndpoint":  <Required when msiClientId is provided. MSI endpoint e.g. for most Azure VMs: "http://169.254.169.254/metadata/identity">,
          "msiClientId":  <Required when VM has any user assigned identities. MSI identity e.g.: "c7373ae5-91c2-4165-8ab6-7381d6e75619".>
        }>
       }
      }
    }

注意

观察到的证书 URL 的格式应为 https://myVaultName.vault.azure.cn/secrets/myCertName

这是因为 /secrets 路径会返回完整证书(包括私钥),但 /certificates 路径不会。 有关证书的详细信息可在此处找到:密钥保管库证书

重要

具有任何“用户分配的标识”的 VM 需要“authenticationSettings”属性。 即使你想使用系统分配的标识,这仍然是必需的;否则 VM 扩展将不知道使用哪个标识。 如果没有此部分,具有用户分配标识的 VM 将导致密钥保管库扩展失败并且无法下载证书。 将 msiClientId 设置为将对 Key Vault 进行身份验证的标识。

对于已启用 Azure Arc 的 VM,也是必需的。 将 msiEndpoint 设置为 http://localhost:40342/metadata/identity

属性值

名称 值/示例 数据类型
apiVersion 2022-07-01 date
publisher Microsoft.Azure.KeyVault string
type KeyVaultForLinux string
typeHandlerVersion 3.0 int
pollingIntervalInS 3600 string
certificateStoreName 它在 Linux 上被忽略 string
linkOnRenewal false boolean
requireInitialSync boolean
aclEnabled boolean
certificateStoreLocation /var/lib/waagent/Microsoft.Azure.KeyVault.Store string
observedCertificates [{...}, {...}] 字符串数组
observedCertificates/url "https://myvault.vault.azure.cn/secrets/mycertificate1" string
observedCertificates/certificateStoreLocation "/var/lib/waagent/Microsoft.Azure.KeyVault/app1" string
observedCertificates/customSymbolicLinkName(可选) "app1Cert1" string
observedCertificates/acls(可选) "{...}, {...}" 字符串数组
authenticationSettings(可选) {...} object
authenticationSettings/msiEndpoint http://169.254.169.254/metadata/identity string
authenticationSettings/msiClientId c7373ae5-91c2-4165-8ab6-7381d6e75619 string
loggingSettings(可选) {...} object
loggingSettings/logger "fluentd" string
loggingSettings/endpoint "tcp://localhost:24224" string
loggingSettings/format "forward" string
loggingSettings/servicename "akvvm_service" string

模板部署

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

必须将虚拟机扩展的 JSON 配置嵌套在该模板的虚拟机资源片段中,具体来说是嵌套在虚拟机模板的 "resources": [] 对象和 "virtualMachineProfile":"extensionProfile":{"extensions" :[] 对象下的虚拟机规模集。

注意

VM 扩展需要分配有系统或用户托管标识,才能向 Key Vault 进行身份验证。 请参阅如何向 Key Vault 进行身份验证和分配 Key Vault 访问策略。

   {
      "type": "Microsoft.Compute/virtualMachines/extensions",
      "name": "KeyVaultForLinux",
      "apiVersion": "2022-11-01",
      "location": "<location>",
      "dependsOn": [
          "[concat('Microsoft.Compute/virtualMachines/', <vmName>)]"
      ],
      "properties": {
      "publisher": "Microsoft.Azure.KeyVault",
      "type": "KeyVaultForLinux",
      "typeHandlerVersion": "3.0",
      "autoUpgradeMinorVersion": true,
      "enableAutomaticUpgrade": true,
      "settings": {
          "secretsManagementSettings": {
          "pollingIntervalInS": <polling interval in seconds, e.g. "3600">,
          "requireInitialSync": <initial synchronization of certificates e..g: false>,
          "aclEnabled": <enables/disables acls on defined certificates e.g.: 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.cn/secrets/mycertificate1">,
                    "certificateStoreLocation": <The certificate store location, which currently works locally only. Example: "/var/lib/waagent/Microsoft.Azure.KeyVault.Store">,
                    "acls": <Optional. An array of preferred acls with read access to certificate private keys. Example: 
                    [
                        {
                            "user": "app1",
                            "group": "appGroup1"
                        },
                        {
                            "user": "service1"
                        }
                    ]>
                },
                {
                    "url": <Example: "https://myvault.vault.azure.cn/secrets/mycertificate2">,
                    "certificateStoreName": <ignored on linux>,
                    "certificateStoreLocation": <The certificate store location, which currently works locally only. Example: "/var/lib/waagent/Microsoft.Azure.KeyVault.Store">,
                    "acls": <Optional. An array of preferred acls with read access to certificate private keys. Example: 
                    [
                        {
                            "user": "app2"
                        }
                    ]>
                }
               
             ]>   
          },
          "authenticationSettings": {
              "msiEndpoint":  <Required when msiClientId is provided. MSI endpoint e.g. for most Azure VMs: "http://169.254.169.254/metadata/identity">,
              "msiClientId":  <Required when VM has any user assigned identities. MSI identity e.g.: "c7373ae5-91c2-4165-8ab6-7381d6e75619">
          }
        } 
      }
    }

扩展依赖项排序

Key Vault VM 扩展支持扩展排序(如果已配置)。 默认情况下,扩展在轮询开始后立即报告启动成功。 但是,可以将其配置为等到成功下载证书的完整列表之后再报告成功启动。 如果其他扩展依赖于所安装的证书才能启动,则启用此设置将使那些扩展可以声明 Key Vault 扩展的依赖项。 这将阻止启动那些扩展,直到安装了其所依赖的所有证书为止。 扩展将一直重试初始下载,并保持 Transitioning 状态。

要启用扩展依赖项,请设置以下内容:

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

注意

使用此功能与 ARM 模板不兼容(该模板会创建系统分配的标识并使用该标识更新 Key Vault 访问策略)。 这样做将导致死锁,因为在所有扩展启动之前,无法更新保管库访问策略。 应改为在部署之前使用单个用户分配的 MSI 标识,并使用该标识对你的保管库进行预 ACL 操作。

Azure PowerShell 部署

警告

PowerShell 客户端通常会将 \ 添加到 settings.json 中的 ",这会导致 akvvm_service 失败,并出现错误:[CertificateManagementConfiguration] Failed to parse the configuration settings with:not an object.

可以使用 Azure PowerShell,将 Key Vault VM 扩展部署到现有虚拟机或虚拟机规模集。

  • 在 VM 上部署该扩展:

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

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

{
   "secretsManagementSettings": {
   "pollingIntervalInS": "3600",
   "linkOnRenewal": true,
   "aclEnabled": true,
   "observedCertificates":
   [
      {
          "url": "https://<examplekv>.vault.azure.cn/secrets/mycertificate1",
          "certificateStoreLocation":  "/var/lib/waagent/Microsoft.Azure.KeyVault.Store",
          "acls": 
          [
              {
                  "user": "app1",
                  "group": "appGroup1"
              },
              {
                  "user": "service1"
              }
          ]
      },
      {
          "url": "https://<examplekv>.vault.azure.cn/secrets/mycertificate2",
          "certificateStoreLocation": "/var/lib/waagent/Microsoft.Azure.KeyVault.Store",
          "acls": 
          [
              {
                  "user": "app2"
              }
          ]
      }
   ]},
   "authenticationSettings": {
      "msiEndpoint":  "http://169.254.169.254/metadata/identity/oauth2/token",
      "msiClientId":  "xxxxxx-xxxx-xxxx-xxxx-xxxxxxxx"
   }      
}
  • 在虚拟机上部署扩展:
# Build settings
$settings = (get-content -raw ".\settings.json")
$extName =  "KeyVaultForLinux"
$extPublisher = "Microsoft.Azure.KeyVault"
$extType = "KeyVaultForLinux"
 
# 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 = (get-content -raw ".\settings.json")
    $extName = "KeyVaultForLinux"
    $extPublisher = "Microsoft.Azure.KeyVault"
    $extType = "KeyVaultForLinux"
      
    # 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,将密钥保管库 VM 扩展部署到现有虚拟机或虚拟机规模集。

  • 在 VM 上部署该扩展:

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

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

{
   "secretsManagementSettings": {
   "pollingIntervalInS": "3600",
   "linkOnRenewal": true,
   "aclEnabled": true,
   "observedCertificates":
   [
      {
          "url": "https://<examplekv>.vault.azure.cn/secrets/mycertificate1",
          "certificateStoreLocation":  "/var/lib/waagent/Microsoft.Azure.KeyVault.Store",
          "acls": 
          [
              {
                  "user": "app1",
                  "group": "appGroup1"
              },
              {
                  "user": "service1"
              }
          ]
      },
      {
          "url": "https://<examplekv>.vault.azure.cn/secrets/mycertificate2",
          "certificateStoreLocation": "/var/lib/waagent/Microsoft.Azure.KeyVault.Store",
          "acls": 
          [
              {
                  "user": "app2"
              }
          ]
      }
   ]},
   "authenticationSettings": {
      "msiEndpoint":  "http://169.254.169.254/metadata/identity/oauth2/token",
      "msiClientId":  "xxxxxx-xxxx-xxxx-xxxx-xxxxxxxx"
   }      
}

  • 在虚拟机上部署扩展

    # Start the deployment
      az vm extension set -n "KeyVaultForLinux" `
      --publisher Microsoft.Azure.KeyVault `
      -g "<resourcegroup>" `
      --vm-name "<vmName>" `
      --version 3.0 `
      --enable-auto-upgrade true `
      --settings "@settings.json"

  • 若要在虚拟机规模集上部署扩展:
    # Start the deployment
    az vmss extension set -n "KeyVaultForLinux" `
    --publisher Microsoft.Azure.KeyVault `
    -g "<resourcegroup>" `
    --vmss-name "<vmssName>" `
    --version 3.0 `
    --enable-auto-upgrade true `
    --settings "@settings.json"

请注意以下限制/要求:

  • Key Vault 限制:
    • 必须在部署时存在
    • 必须将 Key Vault 机密用户角色分配给 VM 标识的 Key Vault

故障排除和支持

有关扩展部署状态的数据可以从 Azure 门户和使用 Azure PowerShell 进行检索。 若要查看给定 VM 的扩展部署状态,请使用 Azure PowerShell 运行以下命令。

Azure PowerShell

Get-AzVMExtension -VMName <vmName> -ResourceGroupname <resource group name>

Azure CLI

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

Azure CLI 可以在多个 shell 环境中运行,但格式略有变化。 如果 Azure CLI 命令出现意外结果,请参阅如何成功使用 Azure CLI

日志和配置

Key Vault VM 扩展日志存在于本地 VM 上,在进行故障排除时能提供最多信息。 可以使用可选的日志记录部分通过 fluentd 与日志记录提供程序集成

位置 说明
/var/log/waagent.log 显示进行扩展更新的时间。
/var/log/azure/Microsoft.Azure.KeyVault.KeyVaultForLinux/* 检查 Key Vault VM 扩展服务日志,以确定 akvvm_service 服务和证书下载的状态。 可以在包含一个名为“证书文件名”的条目的文件中找到 PEM 文件的下载位置。 如果未指定 certificateStoreLocation,它会默认设置为“/var/lib/waagent/Microsoft.Azure.KeyVault.Store/”
/var/lib/waagent/Microsoft.Azure.KeyVault.KeyVaultForLinux-<最新版本>/config/* Key Vault VM 扩展服务的配置和二进制文件。

符号链接是高级快捷方式。 若要避免监视文件夹和自动获取最新证书,可以使用此符号链接 ([VaultName].[CertificateName]) 获取 Linux 上最新版本的证书。

常见问题

  • 可配置的 observedCertificates 数是否有限制? 没有,Key Vault VM 扩展对 observedCertificates 数没有限制。

支持

如果对本文中的任何观点存在疑问,可以联系 Azure 支持上的 Azure 专家。 或者,你也可以提出 Azure 支持事件。 请转到 Azure 支持站点提交请求。 有关使用 Azure 支持的信息,请阅读 Azure 支持常见问题