Usar referências do Cofre da Chave como configurações de aplicativo no Serviço de Aplicativo do Azure e no Azure Functions

Nota

A partir de 1º de junho de 2024, todos os aplicativos do Serviço de Aplicativo recém-criados terão a opção de gerar um nome de host padrão exclusivo usando a convenção <app-name>-<random-hash>.<region>.azurewebsites.netde nomenclatura. Os nomes de aplicativos existentes permanecerão inalterados.

Exemplo: myapp-ds27dh7271aah175.westus-01.azurewebsites.net

Para obter mais detalhes, consulte Nome de host padrão exclusivo para recurso do Serviço de Aplicativo.

Este artigo mostra como usar segredos do Cofre da Chave do Azure como valores de configurações de aplicativo ou cadeias de conexão em seus aplicativos do Serviço de Aplicativo ou do Azure Functions.

O Azure Key Vault é um serviço que fornece gerenciamento centralizado de segredos, com controle total sobre políticas de acesso e histórico de auditoria. Quando uma configuração de aplicativo ou cadeia de conexão é uma referência de cofre de chaves, o código do aplicativo pode usá-la como qualquer outra configuração de aplicativo ou cadeia de conexão. Dessa forma, você pode manter segredos além da configuração do seu aplicativo. As configurações do aplicativo são criptografadas com segurança em repouso, mas se você precisar de recursos de gerenciamento secretos, eles devem ir para um cofre de chaves.

Conceda ao seu aplicativo acesso a um cofre de chaves

Para ler segredos de um cofre de chaves, você precisa ter um cofre criado e dar permissão ao seu aplicativo para acessá-lo.

  1. Crie um cofre de chaves seguindo o início rápido do Cofre da Chave.

  2. Crie uma identidade gerenciada para seu aplicativo.

    As referências do cofre de chaves usam a identidade atribuída pelo sistema do aplicativo por padrão, mas você pode especificar uma identidade atribuída pelo usuário.

  3. Autorize o acesso de leitura a segredos em seu cofre de chaves para a identidade gerenciada que você criou anteriormente. A forma como o faz depende do modelo de permissões do seu cofre de chaves:

Acessar cofres restritos à rede

Se o cofre estiver configurado com restrições de rede, verifique se o aplicativo tem acesso à rede. Os cofres não devem depender dos IPs de saída públicos do aplicativo porque o IP de origem da solicitação secreta pode ser diferente. Em vez disso, o cofre deve ser configurado para aceitar tráfego de uma rede virtual usada pelo aplicativo.

  1. Verifique se o aplicativo tem recursos de rede de saída configurados, conforme descrito em Recursos de rede do Serviço de Aplicativo e Opções de rede do Azure Functions.

    Os aplicativos Linux que se conectam a pontos de extremidade privados devem ser explicitamente configurados para rotear todo o tráfego através da rede virtual. Este requisito será removido numa próxima atualização. Para definir essa configuração, execute o seguinte comando:

    az webapp config set --subscription <sub> -g <group-name> -n <app-name> --generic-configurations '{"vnetRouteAllEnabled": true}'
    
  2. Certifique-se de que a configuração do cofre permite que a rede ou sub-rede que seu aplicativo usa para acessá-lo.

Acessar cofres com uma identidade atribuída pelo usuário

Alguns aplicativos precisam fazer referência a segredos no momento da criação, quando uma identidade atribuída ao sistema ainda não está disponível. Nesses casos, uma identidade atribuída pelo usuário pode ser criada e ter acesso ao cofre com antecedência.

Depois de conceder permissões para a identidade atribuída pelo usuário, siga estas etapas:

  1. Atribua a identidade ao seu aplicativo, se ainda não o fez.

  2. Configure o aplicativo para usar essa identidade para operações de referência do cofre de chaves definindo a keyVaultReferenceIdentity propriedade como a ID do recurso da identidade atribuída pelo usuário.

    identityResourceId=$(az identity show --resource-group <group-name> --name <identity-name> --query id -o tsv)
    az webapp update --resource-group <group-name> --name <app-name> --set keyVaultReferenceIdentity=${identityResourceId}
    

Essa configuração se aplica a todas as referências do cofre de chaves do aplicativo.

Rotação

Se a versão secreta não estiver especificada na referência, o aplicativo usará a versão mais recente existente no cofre de chaves. Quando versões mais recentes ficam disponíveis, como com um evento de rotação, o aplicativo é atualizado automaticamente e começa a usar a versão mais recente em 24 horas. O atraso deve-se ao facto de o Serviço de Aplicações colocar em cache os valores das referências do cofre de chaves e voltar a obtê-los a cada 24 horas. Qualquer alteração de configuração no aplicativo causa uma reinicialização do aplicativo e uma rebusca imediata de todos os segredos referenciados.

Configurações do aplicativo de origem do cofre da chave

Para usar uma referência do cofre de chaves, defina a referência como o valor da configuração. Seu aplicativo pode referenciar o segredo por meio de sua chave normalmente. Não são necessárias alterações de código.

Gorjeta

A maioria das configurações de aplicativos que usam referências de cofre de chaves deve ser marcada como configurações de slot, pois você deve ter cofres separados para cada ambiente.

Uma referência de cofre de chave é do formato @Microsoft.KeyVault({referenceString}), onde {referenceString} está em um dos seguintes formatos:

Cadeia de referência Description
SecretUri=secretUri O SecretUri deve ser o URI completo do plano de dados de um segredo no cofre, por exemplo https://myvault.vault.azure.net/secrets/mysecret. Opcionalmente, inclua uma versão, como https://myvault.vault.azure.net/secrets/mysecret/ec96f02080254f109c51a1f14cdb1931.
VaultName=vaultName; SecretName=secretName; SecretVersion=secretVersion O VaultName é necessário e é o nome do cofre. O SecretName é obrigatório e é o nome secreto. O SecretVersion é opcional, mas se presente indica a versão do segredo a ser usada.

Por exemplo, uma referência completa sem uma versão específica seria semelhante à seguinte cadeia de caracteres:

@Microsoft.KeyVault(SecretUri=https://myvault.vault.azure.net/secrets/mysecret)

Em alternativa:

@Microsoft.KeyVault(VaultName=myvault;SecretName=mysecret)

Considerações para a montagem de arquivos do Azure

Os aplicativos podem usar a configuração do WEBSITE_CONTENTAZUREFILECONNECTIONSTRING aplicativo para montar Arquivos do Azure como o sistema de arquivos. Essa configuração tem verificações de validação para garantir que o aplicativo possa ser iniciado corretamente. A plataforma depende de ter um compartilhamento de conteúdo nos Arquivos do Azure e assume um nome padrão, a menos que seja especificado por meio da WEBSITE_CONTENTSHARE configuração. Para quaisquer solicitações que modifiquem essas configurações, a plataforma valida se esse compartilhamento de conteúdo existe e tenta criá-lo se não. Se não conseguir localizar ou criar o compartilhamento de conteúdo, ele bloqueará a solicitação.

Quando você usa referências de cofre de chaves nessa configuração, a verificação de validação falha por padrão, porque o segredo em si não pode ser resolvido durante o processamento da solicitação de entrada. Para evitar esse problema, você pode ignorar a validação definindo WEBSITE_SKIP_CONTENTSHARE_VALIDATION como "1". Essa configuração diz ao Serviço de Aplicativo para ignorar todas as verificações e não cria o compartilhamento de conteúdo para você. Você deve garantir que ele seja criado com antecedência.

Atenção

Se você pular a validação e a cadeia de conexão ou o compartilhamento de conteúdo forem inválidos, o aplicativo não poderá ser iniciado corretamente e só servirá erros HTTP 500.

Como parte da criação do aplicativo, a tentativa de montagem do compartilhamento de conteúdo pode falhar devido às permissões de identidade gerenciadas não serem propagadas ou à integração de rede virtual não estar configurada. Você pode adiar a configuração dos Arquivos do Azure até mais tarde no modelo de implantação para acomodar isso. Consulte Implantação do Azure Resource Manager para saber mais. Nesse caso, o Serviço de Aplicativo usa um sistema de arquivos padrão até que os Arquivos do Azure sejam configurados e os arquivos não sejam copiados. Você deve garantir que nenhuma tentativa de implantação ocorra durante o período provisório antes que os Arquivos do Azure sejam montados.

Considerações sobre a instrumentação do Application Insights

Os aplicativos podem usar as configurações do APPINSIGHTS_INSTRUMENTATIONKEY aplicativo para APPLICATIONINSIGHTS_CONNECTION_STRING se integrar ao Application Insights. As experiências de portal para o Serviço de Aplicativo e o Azure Functions também usam essas configurações para exibir dados de telemetria do recurso. Se esses valores forem referenciados no Cofre de Chaves, essas experiências não estarão disponíveis e, em vez disso, você precisará trabalhar diretamente com o recurso do Application Insights para exibir a telemetria. No entanto, esses valores não são considerados segredos, portanto, você pode, alternativamente, considerar configurá-los diretamente em vez de usar referências do cofre de chaves.

Implementação do Azure Resource Manager

Ao automatizar implantações de recursos por meio de modelos do Azure Resource Manager, talvez seja necessário sequenciar suas dependências em uma ordem específica para fazer esse recurso funcionar. Certifique-se de definir as configurações do aplicativo como seu próprio recurso, em vez de usar uma siteConfig propriedade na definição do aplicativo. Isso ocorre porque o aplicativo precisa ser definido primeiro para que a identidade atribuída ao sistema seja criada com ele e possa ser usada na política de acesso.

O pseudomodelo a seguir é um exemplo de como um aplicativo de função pode parecer:

{
    //...
    "resources": [
        {
            "type": "Microsoft.Storage/storageAccounts",
            "name": "[variables('storageAccountName')]",
            //...
        },
        {
            "type": "Microsoft.Insights/components",
            "name": "[variables('appInsightsName')]",
            //...
        },
        {
            "type": "Microsoft.Web/sites",
            "name": "[variables('functionAppName')]",
            "identity": {
                "type": "SystemAssigned"
            },
            //...
            "resources": [
                {
                    "type": "config",
                    "name": "appsettings",
                    //...
                    "dependsOn": [
                        "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
                        "[resourceId('Microsoft.KeyVault/vaults/', variables('keyVaultName'))]",
                        "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), variables('storageConnectionStringName'))]",
                        "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), variables('appInsightsKeyName'))]"
                    ],
                    "properties": {
                        "AzureWebJobsStorage": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('storageConnectionStringName')).secretUriWithVersion, ')')]",
                        "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('storageConnectionStringName')).secretUriWithVersion, ')')]",
                        "APPINSIGHTS_INSTRUMENTATIONKEY": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('appInsightsKeyName')).secretUriWithVersion, ')')]",
                        "WEBSITE_ENABLE_SYNC_UPDATE_SITE": "true"
                        //...
                    }
                },
                {
                    "type": "sourcecontrols",
                    "name": "web",
                    //...
                    "dependsOn": [
                        "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
                        "[resourceId('Microsoft.Web/sites/config', variables('functionAppName'), 'appsettings')]"
                    ],
                }
            ]
        },
        {
            "type": "Microsoft.KeyVault/vaults",
            "name": "[variables('keyVaultName')]",
            //...
            "dependsOn": [
                "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]"
            ],
            "properties": {
                //...
                "accessPolicies": [
                    {
                        "tenantId": "[reference(resourceId('Microsoft.Web/sites/', variables('functionAppName')), '2020-12-01', 'Full').identity.tenantId]",
                        "objectId": "[reference(resourceId('Microsoft.Web/sites/', variables('functionAppName')), '2020-12-01', 'Full').identity.principalId]",
                        "permissions": {
                            "secrets": [ "get" ]
                        }
                    }
                ]
            },
            "resources": [
                {
                    "type": "secrets",
                    "name": "[variables('storageConnectionStringName')]",
                    //...
                    "dependsOn": [
                        "[resourceId('Microsoft.KeyVault/vaults/', variables('keyVaultName'))]",
                        "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
                    ],
                    "properties": {
                        "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountResourceId'),'2019-09-01').key1)]"
                    }
                },
                {
                    "type": "secrets",
                    "name": "[variables('appInsightsKeyName')]",
                    //...
                    "dependsOn": [
                        "[resourceId('Microsoft.KeyVault/vaults/', variables('keyVaultName'))]",
                        "[resourceId('Microsoft.Insights/components', variables('appInsightsName'))]"
                    ],
                    "properties": {
                        "value": "[reference(resourceId('microsoft.insights/components/', variables('appInsightsName')), '2019-09-01').InstrumentationKey]"
                    }
                }
            ]
        }
    ]
}

Nota

Neste exemplo, a implantação do controle do código-fonte depende das configurações do aplicativo. Normalmente, esse é um comportamento inseguro, pois a atualização da configuração do aplicativo se comporta de forma assíncrona. No entanto, como incluímos a configuração do WEBSITE_ENABLE_SYNC_UPDATE_SITE aplicativo, a atualização é síncrona. Isso significa que a implantação do controle do código-fonte só começará depois que as configurações do aplicativo tiverem sido totalmente atualizadas. Para obter mais configurações de aplicativo, consulte Variáveis de ambiente e configurações de aplicativo no Serviço de Aplicativo do Azure.

Solução de problemas de referências do cofre de chaves

Se uma referência não for resolvida corretamente, a cadeia de caracteres de referência será usada em vez disso (por exemplo, @Microsoft.KeyVault(...)). Isso pode fazer com que o aplicativo lance erros, porque ele está esperando um segredo de um valor diferente.

A falha na resolução é geralmente devido a uma configuração incorreta da política de acesso do Cofre da Chave. No entanto, também pode ser devido a um segredo que já não existe ou a um erro de sintaxe na própria referência.

Se a sintaxe estiver correta, você poderá visualizar outras causas de erro verificando o status atual da resolução no portal. Navegue até Configurações do aplicativo e selecione "Editar" para a referência em questão. A caixa de diálogo de edição mostra informações de status, incluindo erros. Se você não vir a mensagem de status, isso significa que a sintaxe é inválida e não é reconhecida como uma referência do cofre de chaves.

Você também pode usar um dos detetores embutidos para obter informações adicionais.

Usando o detetor para o Serviço de Aplicativo

  1. No portal, navegue até seu aplicativo.
  2. Selecione Diagnosticar e resolver problemas.
  3. Escolha Disponibilidade e Desempenho e selecione Aplicativo Web para baixo.
  4. Na caixa de pesquisa, procure e selecione Key Vault Application Settings Diagnostics.

Usando o detetor para o Azure Functions

  1. No portal, navegue até seu aplicativo.
  2. Navegue até Recursos da plataforma.
  3. Selecione Diagnosticar e resolver problemas.
  4. Escolha Disponibilidade e Desempenho e selecione Aplicativo de função para baixo ou Relatar erros.
  5. Selecione Key Vault Application Settings Diagnostics.