Partilhar via


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

Em vez de colocar um valor seguro (como uma senha) diretamente em seu arquivo de modelo ou parâmetro, você pode recuperar o valor de um Cofre de Chaves do Azure durante uma implantação. Você recupera o valor fazendo referência ao cofre de chaves e ao segredo em seu arquivo de parâmetros. O valor nunca é exposto porque você só faz referência ao ID do cofre da chave.

Importante

Este artigo se concentra em como passar um valor confidencial como um parâmetro de modelo. Quando o segredo é passado como um parâmetro, o cofre de chaves pode existir em uma assinatura diferente do grupo de recursos no qual você está implantando.

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, consulte Instalar um certificado do Cofre de Chaves do Azure em uma máquina virtual.

Implantar cofres de chaves e segredos

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

Se você já tiver um cofre de chaves, verifique se ele permite implantações de modelos.

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

Para criar um novo 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ê automaticamente tem acesso para criar segredos. Se você 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 sã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, consulte:

Conceder acesso de implantação aos segredos

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

As funções Proprietário e Colaborador concedem esse acesso. Se você criou o cofre de chaves, você é o proprietário e tem a permissão.

Para outros usuários, conceda a Microsoft.KeyVault/vaults/deploy/action permissão. O procedimento a seguir mostra como criar uma função com a permissão mínima e atribuí-la a 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/00000000-0000-0000-0000-000000000000"
      ]
    }
    

    Substitua "00000000-0000-0000-0000-0000000000000" pelo 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
    

    Os exemplos atribuem a função personalizada ao usuário no nível do grupo de recursos.

Ao usar um cofre de chaves com o modelo para um Aplicativo Gerenciado, você deve conceder acesso à entidade de serviço do Provedor de Recursos do Aparelho . Para obter mais informações, consulte Segredo do Cofre da Chave de Acesso ao implantar Aplicativos Gerenciados do Azure.

Segredos de referência com ID estático

Com essa abordagem, você faz referência ao cofre de chaves no arquivo de parâmetros, não ao modelo. A imagem a seguir mostra como o arquivo de parâmetro faz referência ao segredo e passa esse valor para o modelo.

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

Tutorial: Integrar o Azure Key Vault no Resource Manager A implantação do modelo usa esse método.

O modelo a seguir implanta um servidor SQL que inclui uma senha de administrador. O parâmetro password é definido como uma cadeia de caracteres segura. Mas 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, faça referência ao segredo do cofre de chaves. Você faz referência ao segredo passando o identificador de recurso do cofre de chaves e o nome do segredo:

No arquivo de parâmetros 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>"
    }
  }
}

Se você precisar usar uma versão do segredo diferente da versão atual, inclua a secretVersion propriedade.

"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>

Segredos de referência com ID dinâmico

A seção anterior mostrou como passar um ID de 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 do cofre de chaves que varia com base na implantação atual. Ou talvez você queira passar valores de parâmetro para o modelo em vez de criar um parâmetro de referência no arquivo de parâmetro. A solução é gerar dinamicamente o ID do recurso para um segredo do cofre de chaves usando um modelo vinculado.

Não é possível gerar dinamicamente o 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, você adiciona o modelo aninhado e passa um parâmetro que contém a ID do recurso gerado 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 para o segredo do cofre de chaves.

O modelo a seguir cria dinamicamente o ID do cofre de chaves e o 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óximos passos