Use as referências do Key Vault para o Serviço de Aplicativo e o Azure Functions

Este tópico mostra como trabalhar com segredos do Cofre de Chaves do Azure no seu aplicativo Serviço de Aplicativo ou no Aplicativo de Funções do Azure sem exigir alterações de código. 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.

Concedendo o seu acesso ao aplicativo para o Google Key Vault

Para ler os segredos do Key Vault, você precisa criar um vault e conceder permissão ao aplicativo para acessá-lo.

  1. Crie um cofre de chaves seguindo o início rápido do Key Vault .

  2. Crie uma Identidade gerenciada para seu aplicativo.

    Referências ao Key Vault usarão a identidade atribuída pelo sistema do aplicativo por padrão, mas você pode especificar uma identidade atribuída pelo usuário.

  3. Crie uma política de acesso no Key Vault para a identidade do aplicativo que você criou anteriormente. Ative a permissão secreta "Obter" nesta política. Não defina o "aplicativo autorizado" ou as configurações applicationId, pois isso não é compatível com uma identidade gerenciada.

Acessar cofres restritos à rede

Se o cofre estiver configurado com restrições de rede, você também precisará garantir que o aplicativo tenha acesso à rede.

  1. Verifique se o aplicativo tem os 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 tentam usar pontos de extremidade privados também exigem que o aplicativo seja configurado explicitamente para que todo o tráfego seja roteado pela rede virtual. Esse requisito será removido em uma atualização futura. Para definir isso, use o seguinte comando da CLI:

    az webapp config set --subscription <sub> -g <rg> -n <appname> --generic-configurations '{"vnetRouteAllEnabled": true}'
    
  2. Verifique as contas de configuração do cofre para a rede ou sub-rede por meio da qual seu aplicativo vai acessá-lo.

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

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

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

  1. Atribua a identidade ao seu aplicativo, caso ainda não tenha feito isso.

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

    userAssignedIdentityResourceId=$(az identity show -g MyResourceGroupName -n MyUserAssignedIdentityName --query id -o tsv)
    appResourceId=$(az webapp show -g MyResourceGroupName -n MyAppName --query id -o tsv)
    az rest --method PATCH --uri "${appResourceId}?api-version=2021-01-01" --body "{'properties':{'keyVaultReferenceIdentity':'${userAssignedIdentityResourceId}'}}"
    

Essa configuração se aplicará a todas as referências ao aplicativo.

Sintaxe de referência

Uma referência do Key Vault é da forma @Microsoft.KeyVault({referenceString}), em que {referenceString} é substituído por uma das seguintes opções:

Cadeia de caracteres de referência Descrição
SecretUri = secretUri O SecretUri deve ser o URI do plano de dados completo de um segredo no Key Vault, opcionalmente incluindo uma versão, por exemplo, https://myvault.vault.azure.net/secrets/mysecret/ ou https://myvault.vault.azure.net/secrets/mysecret/ec96f02080254f109c51a1f14cdb1931
VaultName = vaultName; SecretName = secretName; SecretVersion = secretVersion O VaultName é exigido e deve ser o nome do seu recurso Key Vault. O SecretName é exigido e deve ser o nome do segredo de destino. O SecretVersion é opcional, mas, se presente, indica a versão do segredo a ser usada.

Por exemplo, uma referência completa seria semelhante ao seguinte:

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

Como alternativa:

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

Rotação

Se uma versão não for especificada na referência, o aplicativo usará a versão mais recente no Key Vault. Quando versões mais recentes estiverem disponíveis, como com um evento de rotação, o aplicativo será atualizado automaticamente e começará a usar a versão mais recente dentro de um dia. As alterações de configuração feitas no aplicativo causarão uma atualização imediata para as versões mais recentes de todos os segredos referenciados.

Configurações de aplicativos de origem do cofre de chaves

AS referências do Key Vault podem ser usadas como valores para Configurações do Aplicativo, permitindo que você mantenha os segredos no Key Vault, em vez da configuração do site. As configurações do aplicativo são criptografadas com segurança inativa, mas se você precisar de recursos de gerenciamento secreto, elas deverão entrar no Key Vault.

Para usar uma referência do Key Vault para uma configuração de aplicativo, defina a referência como o valor da configuração. Seu aplicativo pode fazer referência ao segredo por meio de sua chave normalmente. Nenhuma alteração de código é necessária.

Dica

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

Considerações sobre montagem de Arquivos do Azure

Os aplicativos podem usar a configuração de aplicativo WEBSITE_CONTENTAZUREFILECONNECTIONSTRING para montar Arquivos do Azure como o sistema de arquivos. Essa configuração tem verificações de validação adicionais 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 um seja especificado por meio da configuração WEBSITE_CONTENTSHARE. Para todas as solicitações que modificam essas configurações, a plataforma tentará validar se esse compartilhamento de conteúdo existe e tentará criar se não existir. Se ela não puder localizar ou criar o compartilhamento de conteúdo, a solicitação será bloqueada.

Ao usar referências do Key Vault para essa configuração, essa verificação de validação falhará por padrão, pois 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". Isso ignorará todas as verificações, e o compartilhamento de conteúdo não será criado para você. Você deve garantir que ele seja criado com antecedência.

Cuidado

Se você ignorar a validação e a cadeia de conexão ou o compartilhamento de conteúdo for inválido, o aplicativo não poderá iniciar corretamente e só atenderá a erros HTTP 500.

Como parte da criação do site, também é possível que a tentativa de montagem do compartilhamento de conteúdo falhe devido às permissões de identidade gerenciada não serem propagadas ou a integração de rede virtual não estar configurada. Você pode adiar a configuração de Arquivos do Azure até mais tarde no modelo de implantação para acomodar isso. Confira Modos de implantação do Azure Resource Manager para saber mais. O Serviço de Aplicativo usará um sistema de arquivos padrão até que Arquivos do Azure seja configurado e os arquivos não sejam copiados, portanto, você precisará garantir que nenhuma tentativa de implantação ocorra durante o período provisório antes que Arquivos do Azure seja montado.

Implantação do Azure Resource Manager

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

Um exemplo de pseudomodelo para um aplicativo de função pode ser semelhante ao seguinte:

{
    //...
    "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('storageConnectionStringResourceId')).secretUriWithVersion, ')')]",
                        "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('storageConnectionStringResourceId')).secretUriWithVersion, ')')]",
                        "APPINSIGHTS_INSTRUMENTATIONKEY": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('appInsightsKeyResourceId')).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]"
                    }
                }
            ]
        }
    ]
}

Observação

Neste exemplo, a implantação do controle de origem depende das configurações do aplicativo. Esse comportamento normalmente é inseguro, pois a atualização da configuração do aplicativo se comporta de maneira assíncrona. No entanto, como incluímos a configuração do aplicativo WEBSITE_ENABLE_SYNC_UPDATE_SITE, a atualização é síncrona. Isso significa que a implantação do controle de origem só será iniciada quando as configurações do aplicativo tiverem sido totalmente atualizadas. Para obter mais configurações de aplicativo, confira Variáveis de ambiente e configurações de aplicativo no Serviço de Aplicativo do Azure.

Solucionar problemas de referências do Key Vault

Se uma referência não for resolvida corretamente, o valor de referência será usado em seu lugar. Isso significa que, para as configurações do aplicativo, uma variável de ambiente seria criada cujo valor tem a sintaxe @Microsoft.KeyVault(...). Isso pode fazer com que o aplicativo gere erros, pois estava esperando um segredo de uma determinada estrutura.

Normalmente, isso se deve a uma configuração incorreta da política de acesso do Key Vault. No entanto, também pode ser devido a um segredo não mais existente ou a um erro de sintaxe na própria referência.

Se a sintaxe estiver correta, você poderá ver 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. Abaixo da definição de configuração, você deve ver informações de status, incluindo todos os erros. A ausência deles implica que a sintaxe de referência é inválida.

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

Como usar o detector para o Serviço de Aplicativo

  1. No portal, navegue até seu aplicativo.
  2. Selecione Diagnosticar e solucionar problemas.
  3. Escolha Disponibilidade e Desempenho e selecione aplicativo Web inativo.
  4. Encontre Diagnóstico de Configurações de Aplicativos do Key Vault e clique em Mais informações.

Como usar o detector para Azure Functions

  1. No portal, navegue até seu aplicativo.
  2. Navegue até Recursos da plataforma.
  3. Selecione Diagnosticar e solucionar problemas.
  4. Escolha Disponibilidade e Desempenho e selecione Aplicativo de funções inativo ou relatando erros.
  5. Clique em Diagnóstico de Configurações de Aplicativo do Key Vault.