简体   繁体   English

Azure Keyvault 通过 ARM 添加功能 MSI

[英]Azure Keyvault add Function MSI via ARM

I think Managed Service Identity is a great concept and I love keyvault.我认为托管服务身份是一个很棒的概念,我喜欢密钥保管库。 However:然而:

When I use the script using an incremental resource group deployment:当我使用增量资源组部署使用脚本时:

Sample is modified for brevity为简洁起见修改了示例

{
      "type": "Microsoft.KeyVault/vaults",
      "name": "[parameters('keyvaultName')]",
      "apiVersion": "2015-06-01",
      "properties": {            
        "accessPolicies": [
          {
            "objectId": "[reference(parameters('functionAppName'), '2016-08-01', 'Full').identity.principalId]",
            "permissions": {
              "keys": [],
              "secrets": [
                "Get"
              ]
            }
          }
        ]
      },
      "dependsOn": [
        "[resourceId('Microsoft.Web/sites', parameters('functionAppName'))]"
      ]
    },
    {
      "apiVersion": "2016-08-01",
      "type": "Microsoft.Web/sites",
      "name": "[parameters('functionAppName')]",
      "kind": "functionapp",
      "identity": {
        "type": "SystemAssigned"
      },
    }

It deploys successfully and adds the MSI to keyvault, but --它部署成功并将MSI添加到keyvault,但是——

It blows away the already assigned access policies.它取消了已经分配的访问策略。 Is it possible for arm to preserve accessPolicies and only add/update policies that match? arm 是否可以保留 accessPolicies 并仅添加/更新匹配的策略?

Without this it's impossible to fully script a deployment with a MSI and also assign the principal to keyvault..如果没有这个,就不可能使用 MSI 完全编写部署脚本并将主体分配给 keyvault..

Am I missing something?我错过了什么吗?

As the author of the blog post , I'll post the details per the mods:作为博文的作者,我将发布每个模组的详细信息:

When you deploy a resource of type Microsoft.KeyVault/vaults/accessPolicies with the name “add”, it will merge in your changes.当您使用名称“添加”部署 Microsoft.KeyVault/vaults/accessPolicies 类型的资源时,它将合并到您的更改中。 This special child resource type was created to allow Managed Service Identity scenarios where you don't know the identity of a VM until the VM is deployed and you want to give that identity access to the vault during deployment.创建这种特殊的子资源类型是为了允许托管服务身份方案,在这种情况下,您在部署 VM 之前不知道 VM 的身份,并且您希望在部署期间授予该身份访问 Vault 的权限。

An incremental deployment can be used along with this json to achieve the objective:增量部署可与此 json 一起使用以实现目标:

 { "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "vaultName": { "type": "string" } }, "resources": [ { "type": "Microsoft.KeyVault/vaults/accessPolicies", "name": "[concat(parameters('vaultName'), '/add')]", "apiVersion": "2016-10-01", "properties": { "accessPolicies": [ { "tenantId": "dfe47ca8-acfc-4539-9519-7d195a9e79e4", "objectId": "5abe9358-10ae-4195-ba23-d34111430329", "permissions": { "keys": ["all"], "secrets": ["all"], "certificates": ["all"], "storage": ["all"] } } ] } } ], "outputs": { } }

The issue with the highest-voted answer is that it removes the key vault from the ARM template altogether, meaning that the key vault's creation becomes a manual process on new environments.最高投票答案的问题是它完全从 ARM 模板中删除了密钥保管库,这意味着密钥保管库的创建成为新环境中的手动过程。

ARM does not allow a key vault to be redeployed without clearing its existing access policies. ARM 不允许在不清除其现有访问策略的情况下重新部署密钥保管库。 The accessPolicies property is required (except when recovering a deleted vault), so omitting it will cause an error. accessPolicies属性是必需的(恢复已删除的保管库时除外),因此省略它会导致错误。 Setting it to [] will clear all existing policies.将其设置为[]将清除所有现有策略。 There has been a Microsoft Feedback request to fix this since 2018, currently with 152 votes.自 2018 年以来,一直有Microsoft 反馈要求解决此问题,目前已获得 152 票。

The best way I've found of working around this is to make the key vault deployed conditionally only if it does not already exist, and define the access policies through a separate add child resource.我找到的解决此问题的最佳方法是仅在 Key Vault 不存在时有条件地部署它,通过单独的add子资源定义访问策略。 This causes the specified policies to get added or updated, whilst preserving any other existing policies.这会导致添加或更新指定的策略,同时保留任何其他现有策略。 I check whether the key vault already exists by passing in the list of existing resource names to the ARM template.我通过将现有资源名称列表传递给 ARM 模板来检查密钥保管库是否已存在。

In the Azure pipeline:在 Azure 管道中:

- task: AzurePowerShell@5
  displayName: 'Get existing resource names'
  inputs:
    azureSubscription: '$(armServiceConnection)'
    azurePowerShellVersion: 'LatestVersion'
    ScriptType: 'InlineScript'
    Inline: |      
      $resourceNames = (Get-AzResource -ResourceGroupName $(resourceGroupName)).Name | ConvertTo-Json -Compress
      Write-Output "##vso[task.setvariable variable=existingResourceNames]$resourceNames"
    azurePowerShellVersion: 'LatestVersion'

- task: AzureResourceManagerTemplateDeployment@3
  name: DeployResourcesTemplate
  displayName: 'Deploy resources through ARM template
  inputs:
    deploymentScope: 'Resource Group'
    action: 'Create Or Update Resource Group'
    # ...
    overrideParameters: >-
      -existingResourceNames $(existingResourceNames)
      # ...
    deploymentMode: 'Incremental'

In the ARM template:在 ARM 模板中:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",

  "parameters": {
    "keyVaultName": {
      "type": "string"
    },
    "existingResourceNames": {
      "type": "array",
      "defaultValue": []
    }
  },

  "resources": [
    {
      "type": "Microsoft.KeyVault/vaults",
      "apiVersion": "2016-10-01",
      "name": "[parameters('keyVaultName')]",
      "location": "[resourceGroup().location]",
      // Only deploy the key vault if it does not already exist.
      // Conditional deployment doesn't cascade to child resources, which can be deployed even when their parent isn't.
      "condition": "[not(contains(parameters('existingResourceNames'), parameters('keyVaultName')))]",
      "properties": {
        "sku": {
          "family": "A",
          "name": "Standard"
        },
        "tenantId": "[subscription().tenantId]",
        "enabledForDeployment": false,
        "enabledForDiskEncryption": false,
        "enabledForTemplateDeployment": true,
        "enableSoftDelete": true,
        "accessPolicies": []
      },
      "resources": [
        {
          "type": "accessPolicies",
          "apiVersion": "2016-10-01",
          "name": "add",
          "location": "[resourceGroup().location]",
          "dependsOn": [
            "[parameters('keyVaultName')]"
          ],
          "properties": {
            "accessPolicies": [
              // Specify your access policies here.
              // List does not need to be exhaustive; other existing access policies are preserved.
            ]
          }
        }
      ]
    }
  ]
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM