Compartilhar via


Usar o Azure Key Vault para passar um valor de parâmetro seguro durante a implantação

Em vez de colocar um valor seguro (como uma senha) diretamente no seu modelo ou arquivo de parâmetro, você pode recuperar o valor de um Azure Key Vault durante a implantação. Você recupera o valor fazendo referência ao cofre de chaves e ao segredo no arquivo de parâmetros. O valor nunca é exposto porque você apenas fazer referência à sua ID de cofre de chaves.

Importante

O foco deste artigo é mostrar como aprovar um valor confidencial como um parâmetro do modelo. Quando o segredo é passado como um parâmetro, o cofre de chaves pode existir em uma assinatura que não seja a do grupo de recursos de destino da implantação.

Este artigo não aborda como definir uma propriedade de máquina virtual para a URL de um certificado em um cofre de chaves. Para obter um modelo de início rápido desse cenário, confira Instalar um certificado do Azure Key Vault em uma máquina virtual.

Implantar Key Vaults e segredos

Para acessar um cofre de chaves durante a implantação do modelo, defina enabledForTemplateDeployment no cofre de chaves como true.

Caso já tenha um cofre de chaves, verifique se ele permite executar implantações de modelos.

az keyvault update  --name ExampleVault --enabled-for-template-deployment true

Para criar um cofre de chaves e adicionar um segredo, use:

az group create --name ExampleGroup --location centralus
az keyvault create \
  --name ExampleVault \
  --resource-group ExampleGroup \
  --location centralus \
  --enabled-for-template-deployment true
az keyvault secret set --vault-name ExampleVault --name "ExamplePassword" --value "hVFkk965BuUv"

Como proprietário do cofre de chaves, você tem acesso de modo automático para criar segredos. Se precisar permitir que outro usuário crie segredos, use:

az keyvault set-policy \
  --upn <user-principal-name> \
  --name ExampleVault \
  --secret-permissions set delete get list

As políticas de acesso não serão necessárias se o usuário estiver implantando um modelo que recupera um segredo. Adicione um usuário às políticas de acesso somente se o usuário precisar trabalhar diretamente com os segredos. As permissões de implantação são definidas na próxima seção.

Para obter mais informações sobre como criar cofres de chaves e adicionar segredos, confira:

Conceder acesso de implantação aos segredos

O usuário que implanta o modelo deve ter a permissão Microsoft.KeyVault/vaults/deploy/action para o escopo do grupo de recursos e cofre de chaves. Ao verificar esse acesso, Azure Resource Manager impede que um usuário não aprovado acesse o segredo passando na ID de recurso para o cofre de chaves. Você pode conceder acesso de implantação aos usuários sem conceder acesso de gravação aos segredos.

Ambas as funções Proprietário e Colaborador concedem esse acesso. Caso tenha criado o cofre de chaves, você é o proprietário e tem a permissão.

Para outros usuários, conceda a permissão Microsoft.KeyVault/vaults/deploy/action. O procedimento a seguir mostra como criar uma função com permissão mínima e atribui-la um usuário.

  1. Crie um arquivo JSON de definição de função personalizada:

    {
      "Name": "Key Vault resource manager template deployment operator",
      "IsCustom": true,
      "Description": "Lets you deploy a resource manager template with the access to the secrets in the Key Vault.",
      "Actions": [
        "Microsoft.KeyVault/vaults/deploy/action"
      ],
      "NotActions": [],
      "DataActions": [],
      "NotDataActions": [],
      "AssignableScopes": [
        "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e"
      ]
    }
    

    Substitua "00000000-0000-0000-0000-000000000000" por sua ID da assinatura.

  2. Crie a nova função usando o arquivo JSON:

    az role definition create --role-definition "<path-to-role-file>"
    az role assignment create \
      --role "Key Vault resource manager template deployment operator" \
      --scope /subscriptions/<Subscription-id>/resourceGroups/<resource-group-name> \
      --assignee <user-principal-name> \
      --resource-group ExampleGroup
    

    As amostras designam a função personalizada para o usuário no nível do grupo de recursos.

Ao usar um cofre de chaves com o modelo para um Aplicativo Gerenciado, você precisa conceder acesso à entidade de serviço Provedor de Recursos do Dispositivo. Para obter mais informações, confira Segredo do Azure Key Vault durante a implantação de Aplicativos Gerenciados do Azure.

Fazer referência segredos com ID estática

Com esta abordagem, você faz referência ao Key Vault no arquivo de parâmetro, não no modelo. A imagem a seguir mostra como o arquivo de parâmetro faz referência ao segredo e passa o valor para o modelo.

Diagrama mostrando a integração do cofre de chaves do Resource Manager com o Static ID.

O Tutorial: integrar o Azure Key Vault à Implantação de modelo do Resource Manager usa este método.

O modelo a seguir implanta um servidor SQL que inclui uma senha de administrador. O parâmetro de senha é definido como uma cadeia de caracteres segura. No entanto, o modelo não especifica de onde vem esse valor.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "sqlServerName": {
      "type": "string"
    },
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]"
    },
    "adminLogin": {
      "type": "string"
    },
    "adminPassword": {
      "type": "securestring"
    }
  },
  "resources": [
    {
      "type": "Microsoft.Sql/servers",
      "apiVersion": "2021-11-01",
      "name": "[parameters('sqlServerName')]",
      "location": "[parameters('location')]",
      "properties": {
        "administratorLogin": "[parameters('adminLogin')]",
        "administratorLoginPassword": "[parameters('adminPassword')]",
        "version": "12.0"
      }
    }
  ]
}

Agora, crie um arquivo de parâmetro para o modelo anterior. No arquivo de parâmetro, especifique um parâmetro que corresponda ao nome do parâmetro no modelo. Para o valor do parâmetro, referenciar o segredo do cofre de chave. Você faz referência ao segredo transmitindo o identificador de recurso do cofre de chaves e o nome do segredo:

No arquivo de parâmetro a seguir, o segredo do cofre de chaves já deve existir e você fornece um valor estático para sua ID de recurso.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "adminLogin": {
      "value": "exampleadmin"
    },
    "adminPassword": {
      "reference": {
        "keyVault": {
          "id": "/subscriptions/<subscription-id>/resourceGroups/<rg-name>/providers/Microsoft.KeyVault/vaults/<vault-name>"
        },
        "secretName": "ExamplePassword"
      }
    },
    "sqlServerName": {
      "value": "<your-server-name>"
    }
  }
}

Caso precise usar uma versão do segredo diferente da versão atual, inclua a propriedade secretVersion.

"secretName": "ExamplePassword",
"secretVersion": "cd91b2b7e10e492ebb870a6ee0591b68"

Implante o modelo e passe o arquivo de parâmetro:

az group create --name SqlGroup --location westus2
az deployment group create \
  --resource-group SqlGroup \
  --template-uri <template-file-URI> \
  --parameters <parameter-file>

Fazer referência a segredos com ID dinâmica

A seção anterior mostrou como passar uma ID do recurso estático para o segredo do cofre de chaves do parâmetro. Em alguns cenários, você precisa fazer referência a um segredo de cofre da chave que varia com base na implantação atual. Ou você pode passar valores de parâmetros para o modelo em vez de criar um parâmetro de referência no arquivo de parâmetros. A solução é gerar dinamicamente a ID do recurso para um segredo do cofre de chaves usando um modelo vinculado.

Não é possível gerar dinamicamente a ID do recurso no arquivo de parâmetros porque as expressões de modelo não são permitidas no arquivo de parâmetros.

No modelo pai, adicione o modelo aninhado e passe um parâmetro que contém a ID de recurso gerada dinamicamente. A imagem a seguir mostra como um parâmetro no modelo vinculado faz referência ao segredo.

Diagrama ilustrando a geração de ID dinâmica do segredo do Key Vault.

O seguinte modelo cria dinamicamente a ID do cofre de chaves e a passa como um parâmetro.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
      "location": {
        "type": "string",
        "defaultValue": "[resourceGroup().location]",
        "metadata": {
          "description": "The location where the resources will be deployed."
        }
      },
      "vaultName": {
        "type": "string",
        "metadata": {
          "description": "The name of the keyvault that contains the secret."
        }
      },
      "secretName": {
        "type": "string",
        "metadata": {
          "description": "The name of the secret."
        }
      },
      "vaultResourceGroupName": {
        "type": "string",
        "metadata": {
          "description": "The name of the resource group that contains the keyvault."
        }
      },
      "vaultSubscription": {
        "type": "string",
        "defaultValue": "[subscription().subscriptionId]",
        "metadata": {
          "description": "The name of the subscription that contains the keyvault."
        }
      }
  },
  "resources": [
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2020-10-01",
      "name": "dynamicSecret",
      "properties": {
        "mode": "Incremental",
        "expressionEvaluationOptions": {
          "scope": "inner"
        },
        "template": {
          "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
          "contentVersion": "1.0.0.0",
          "parameters": {
            "adminLogin": {
              "type": "string"
            },
            "adminPassword": {
              "type": "securestring"
            },
            "location": {
              "type": "string"
            }
          },
          "variables": {
            "sqlServerName": "[concat('sql-', uniqueString(resourceGroup().id, 'sql'))]"
          },
          "resources": [
            {
              "type": "Microsoft.Sql/servers",
              "apiVersion": "2021-11-01",
              "name": "[variables('sqlServerName')]",
              "location": "[parameters('location')]",
              "properties": {
                "administratorLogin": "[parameters('adminLogin')]",
                "administratorLoginPassword": "[parameters('adminPassword')]"
              }
            }
          ],
          "outputs": {
            "sqlFQDN": {
              "type": "string",
              "value": "[reference(variables('sqlServerName')).fullyQualifiedDomainName]"
            }
          }
        },
        "parameters": {
          "location": {
            "value": "[parameters('location')]"
          },
          "adminLogin": {
            "value": "ghuser"
          },
          "adminPassword": {
            "reference": {
              "keyVault": {
                "id": "[resourceId(parameters('vaultSubscription'), parameters('vaultResourceGroupName'), 'Microsoft.KeyVault/vaults', parameters('vaultName'))]"
              },
              "secretName": "[parameters('secretName')]"
            }
          }
        }
      }
    }
  ]
}

Próximas etapas