Usare i riferimenti a Key Vault come impostazioni dell'app in Servizio app di Azure e Funzioni di Azure

Nota

A partire dal 1° giugno 2024, tutte le app del servizio app appena create avranno la possibilità di generare un nome host predefinito univoco usando la convenzione di denominazione <app-name>-<random-hash>.<region>.azurewebsites.net. I nomi delle app esistenti rimarranno invariati.

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

Per altri dettagli, vedere Nome host predefinito univoco per la risorsa del Servizio app di Azure.

Questo articolo illustra come usare i segreti di Azure Key Vault come valori delle impostazioni dell'app o delle stringhe di connessione nel Servizio app di Azure o nelle app Funzioni di Azure.

Azure Key Vault è un servizio che supporta la gestione centralizzata dei segreti con controllo completo sui criteri di accesso e sulla cronologia di controllo. Quando un'impostazione dell'app o una stringa di connessione è un riferimento all'insieme di credenziali delle chiavi, il codice dell'applicazione può usarlo come qualsiasi altra impostazione dell'app o stringa di connessione. In questo modo, è possibile mantenere segreti separati dalla configurazione dell'app. Le impostazioni dell'applicazione vengono crittografate in modo sicuro se statiche, ma se sono necessarie funzionalità di gestione dei segreti, è consigliabile archiviarle in un insieme di credenziali delle chiavi.

Concedere all'app l'accesso a un insieme di credenziali delle chiavi

Per leggere i segreti da un insieme di credenziali delle chiavi, è necessario avere creato un insieme di credenziali e concedere all'app l'autorizzazione per accedervi.

  1. Creare un insieme di credenziali seguendo l'avvio rapido per Key Vault.

  2. Creare un'identità gestita per l'applicazione.

    I riferimenti all'insieme di credenziali delle chiavi usano l'identità assegnata dal sistema dell'app per impostazione predefinita, ma è possibile specificare un'identità assegnata dall'utente.

  3. Autorizzare l'accesso in lettura ai segreti nell'insieme di credenziali delle chiavi per l'identità gestita creata in precedenza. La modalità di esecuzione dipende dal modello di autorizzazioni dell'insieme di credenziali delle chiavi:

Accedere a insiemi di credenziali con restrizioni di rete

Se l'insieme di credenziali è configurato con restrizioni di rete, assicurarsi che l'applicazione disponga dell'accesso alla rete. Gli insiemi di credenziali non devono dipendere dagli INDIRIZZI IP in uscita pubblici dell'app perché l'indirizzo IP di origine della richiesta privata potrebbe essere diverso. Al contrario, l'insieme di credenziali deve essere configurato per accettare il traffico da una rete virtuale usata dall'app.

  1. Assicurarsi che l'applicazione disponga di funzionalità di rete in uscita configurate, come descritto in Funzionalità di rete del Servizio app di Azure e Opzioni di rete di Funzioni di Azure.

    Le applicazioni Linux che si connettono a endpoint privati devono essere configurate in modo esplicito per instradare tutto il traffico attraverso la rete virtuale. Questo requisito verrà rimosso in un prossimo aggiornamento. Per configurare questa impostazione, eseguire il comando seguente:

    az webapp config set --subscription <sub> -g <group-name> -n <app-name> --generic-configurations '{"vnetRouteAllEnabled": true}'
    
  2. Assicurarsi che la configurazione dell'insieme di credenziali consenta alla rete o alla subnet usata dall'app di accedervi.

Accedere agli insiemi di credenziali con un'identità assegnata dall'utente

Alcune app devono fare riferimento ai segreti in fase di creazione, quando un'identità assegnata dal sistema non è ancora disponibile. In questi casi, è possibile creare un'identità assegnata dall'utente e fornire l'accesso all'insieme di credenziali in anticipo.

Dopo aver concesso le autorizzazioni all'identità assegnata dall'utente, seguire questa procedura:

  1. Assegnare l'identità all'applicazione, se non lo si ha già fatto.

  2. Configurare l'app per usare questa identità per le operazioni di riferimento dell'insieme di credenziali delle chiavi impostando la proprietà keyVaultReferenceIdentity sull'ID risorsa dell'identità assegnata dall'utente.

    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}
    

Questa impostazione si applica a tutti i riferimenti all'insieme di credenziali delle chiavi per l'app.

Rotazione

Se la versione del segreto non è specificata nel riferimento, l'app usa la versione più recente presente nell'insieme di credenziali delle chiavi. Quando le versioni più recenti diventano disponibili, ad esempio con un evento di rotazione, l'app è aggiornata automaticamente e inizierà a usare la versione più recente entro 24 ore. Il ritardo è dovuto al fatto che il Servizio app memorizza nella cache i valori dei riferimenti all'insieme di credenziali delle chiavi e li recupera ogni 24 ore. Qualsiasi modifica di configurazione all'app causa il riavvio di un'app e un refetch immediato di tutti i segreti a cui si fa riferimento.

Impostazioni dell'app di origine dall'insieme di credenziali delle chiavi

Per usare un riferimento all'insieme di credenziali delle chiavi, impostare il riferimento come valore dell'impostazione. L'app può fare riferimento al segreto tramite la relativa chiave come di consueto. Non sono necessarie modifiche al codice.

Suggerimento

La maggior parte delle impostazioni di applicazione che usano riferimenti all'incontro deve essere contrassegnata come impostazioni slot, perché è consigliabile usare insiemi di credenziali separati per ogni ambiente.

Un riferimento all'insieme di credenziali delle chiavi è nel formato @Microsoft.KeyVault({referenceString}), dove {referenceString} si trova in uno dei formati seguenti:

Stringa di riferimento Descrizione
SecretUri=secretUri SecretUri deve essere l'URI completo del piano dati di un segreto nell'insieme di credenziali, ad esempio https://myvault.vault.azure.net/secrets/mysecret. Facoltativamente, includere una versione, ad esempio https://myvault.vault.azure.net/secrets/mysecret/ec96f02080254f109c51a1f14cdb1931.
VaultName=vaultName;SecretName=secretName;SecretVersion=secretVersion Il VaultName è obbligatorio ed è il nome dell'insieme di credenziali. Il SecretName è obbligatorio ed è il nome del segreto. Il SecretVersion è facoltativo, ma se presente indica la versione del segreto da usare.

Ad esempio, un riferimento completo senza una versione specifica sarà simile alla stringa seguente:

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

In alternativa:

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

Considerazioni sul montaggio di File di Azure

Le app possono usare l'impostazione dell'applicazione WEBSITE_CONTENTAZUREFILECONNECTIONSTRING per montare File di Azure come file system. Questa impostazione include controlli di convalida per assicurarsi che l'app possa essere avviata correttamente. La piattaforma si basa sulla presenza di una condivisione di contenuto all'interno di File di Azure e presuppone un nome predefinito, a meno che non ne venga specificato uno tramite l'impostazione WEBSITE_CONTENTSHARE. Per eventuali richieste che modificano queste impostazioni, la piattaforma convalida se la condivisione di contenuto esiste e tenta di crearla in caso contrario. Se non riesce a individuare o creare la condivisione di contenuto, blocca la richiesta.

Quando si usano riferimenti all'insieme di credenziali delle chiavi in questa impostazione, il controllo di convalida ha esito negativo per impostazione predefinita, perché il segreto stesso non può essere risolto durante l'elaborazione della richiesta in ingresso. Per evitare questo problema, è possibile ignorare la convalida impostando WEBSITE_SKIP_CONTENTSHARE_VALIDATION su "1". Questa impostazione indica al Servizio app di Azure di ignorare tutti i controlli e non crea automaticamente la condivisione contenuto. Assicurarsi che venga creato in anticipo.

Attenzione

Se si ignora la convalida e la stringa di connessione o la condivisione contenuto non sono valide, l'app non sarà in grado di avviarsi correttamente e gestirà solo errori HTTP 500.

Durante la creazione dell'app, il tentativo di montaggio della condivisione contenuto potrebbe non riuscire a causa di autorizzazioni di identità gestite non propagate o l'integrazione della rete virtuale non è stata configurata. È possibile posticipare la configurazione di File di Azure fino a un secondo momento nel modello di distribuzione per supportarlo. Per altre informazioni, vedere Distribuzione di Azure Resource Manager. In questo caso, il Servizio app di Azure usa un file system predefinito fino alla configurazione di File di Azure e i file non vengono copiati. È necessario assicurarsi che non si verifichino tentativi di distribuzione durante il periodo provvisorio prima che File di Azure venga montato.

Considerazioni sulla strumentazione di Application Insights

Le app possono usare le impostazioni dell'applicazione APPINSIGHTS_INSTRUMENTATIONKEY o APPLICATIONINSIGHTS_CONNECTION_STRING per l'integrazione con Application Insights. Le esperienze del portale per Il Servizio app di Azure e Funzioni di Azure usano anche queste impostazioni per visualizzare i dati di telemetria dalla risorsa. Se si fa riferimento a questi valori da Key Vault, queste esperienze non sono disponibili ed è invece necessario lavorare direttamente con la risorsa di Application Insights per visualizzare i dati di telemetria. Tuttavia, questi valori non vengono considerati segreti, pertanto è possibile configurarli direttamente anziché usare riferimenti all'insieme di credenziali delle chiavi.

Distribuzione Azure Resource Manager

Durante l'automazione delle distribuzioni di risorse tramite modelli di Azure Resource Manager, potrebbe essere necessario disporre in sequenza le dipendenze in un determinato ordine per usufruire di questa funzionalità. Assicurarsi di definire le impostazioni dell'app come risorsa propria, anziché usare una proprietà siteConfig nella definizione dell'app. Questo avviene perché l'app deve essere definita per prima, in modo che l'identità assegnata dal sistema venga creata insieme al sito e possa essere usata nei criteri di accesso.

Lo pseudo-modello seguente è un esempio dell'aspetto di un'app per le funzioni:

{
    //...
    "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

In questo esempio, la distribuzione del controllo del codice sorgente dipende dalle impostazioni dell'applicazione. Si tratta in genere di un comportamento non sicuro, dato che l'aggiornamento delle impostazioni dell'applicazione ha un comportamento asincrono. Tuttavia, dato che è stata inclusa l'impostazione dell'applicazione WEBSITE_ENABLE_SYNC_UPDATE_SITE, l'aggiornamento è sincrono. Questo significa che la distribuzione del controllo del codice sorgente inizierà solo dopo l'aggiornamento completo delle impostazioni dell'applicazione. Per altre impostazioni delle ap, vedere Variabili di ambiente e impostazioni dell'app in Servizio app di Azure.

Risoluzione dei problemi relativi ai riferimenti all'insieme di credenziali delle chiavi

Se un riferimento non viene risolto correttamente, viene usata la stringa di riferimento (ad esempio @Microsoft.KeyVault(...)). L'applicazione potrebbe generare errori perché prevede un segreto di un valore diverso.

Il problema di risoluzione è in genere dovuto a una configurazione errata dei criteri di accesso a Key Vault. Tuttavia, potrebbe anche essere dovuto a un segreto non più esistente o a un errore di sintassi nel riferimento stesso.

Se la sintassi è corretta, è possibile visualizzare altre cause di errore controllando lo stato di risoluzione corrente nel portale. Andare a Impostazioni applicazione e selezionare "Modifica" per il riferimento in questione. La finestra di dialogo di modifica mostra informazioni sullo stato, inclusi eventuali errori. Se il messaggio di stato non viene visualizzato, significa che la sintassi non è valida e non è riconosciuta come riferimento all'insieme di credenziali delle chiavi.

È anche possibile usare uno dei rilevatori predefiniti per ottenere informazioni aggiuntive.

Uso del rilevatore per il servizio app

  1. Nel portale, andare all'app.
  2. Selezionare Diagnostica e risoluzione dei problemi.
  3. Scegliere Disponibilità e prestazioni e selezionare App Web guasta.
  4. Nella casella di ricerca cercare e selezionare Diagnostica delle impostazioni dell'applicazione Key Vault.

Uso del rilevatore per Funzioni di Azure

  1. Nel portale, andare all'app.
  2. Andare a Funzionalità della piattaforma.
  3. Selezionare Diagnostica e risoluzione dei problemi.
  4. Scegliere Disponibilità e prestazioni e selezionare App per le funzioni guasta o che segnala errori.
  5. Selezionare Diagnostica delle impostazioni dell'applicazione Key Vault.