Condividi tramite


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, le app del servizio app appena create possono generare un nome host predefinito univoco che utilizza la convenzione di denominazione <app-name>-<random-hash>.<region>.azurewebsites.net. Ad esempio: myapp-ds27dh7271aah175.westus-01.azurewebsites.net. I nomi delle app esistenti rimangono invariati.

Per altre informazioni, vedere il post di blog sulla creazione un’app Web con un nome host predefinito univoco.

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 di Funzioni di Azure.

Key Vault è un servizio che fornisce una 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 a Key Vault, il codice dell'applicazione può usarlo come qualsiasi altra impostazione o stringa di connessione dell'app. In questo modo, è possibile mantenere segreti separati dalla configurazione dell'app. Le impostazioni dell'app vengono crittografate in modo sicuro a riposo, ma se sono necessarie funzionalità per la gestione dei segreti, devono essere inserite in un Key Vault.

Concedi all'app l'accesso a un Key Vault

Per leggere i segreti da un archivio di chiavi, è prima necessario creare un archivio 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 al Key Vault usano l'identità assegnata automaticamente 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. 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. Invece, il vault dovrebbe essere configurato per accettare il traffico da una rete virtuale utilizzata dall'app.

  1. Assicurarsi che l'applicazione disponga di funzionalità di rete in uscita configurate, come descritto in Funzionalità di rete dell'App Service e Opzioni di rete per Azure Functions.

    Attualmente, le applicazioni Linux che si connettono a endpoint privati devono essere configurate in modo esplicito per instradare tutto il traffico attraverso la rete virtuale. 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. Assicurati che la configurazione del vault consenta alla rete o alla subnet utilizzata dalla tua app di accedervi.

Notare che anche se l'insieme di credenziali è stato configurato correttamente in modo da accettare il traffico dalla rete virtuale, i log di controllo dell'insieme di credenziali potrebbero comunque mostrare un evento SecretGet non riuscito (403 - Accesso negato) dall'indirizzo IP pubblico in uscita dell'app. Questo sarà seguito da un evento SecretGet riuscito proveniente dall'indirizzo IP privato dell'app, come previsto dal design.

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 concederle 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 del Key Vault 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 a Key Vault per l'app.

Informazioni sulla 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 viene aggiornata automaticamente e inizia 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 a Key Vault 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.

Informazioni sulle impostazioni dell'app di origine da Key Vault

Per usare un riferimento a Key Vault, 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 dell'app che usano riferimenti a Key Vault deve essere contrassegnata come impostazioni slot, poiché è necessario disporre di insiemi di credenziali diversi per ogni ambiente.

Un riferimento a Key Vault è 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 valore VaultName è obbligatorio ed è il nome dell'insieme di credenziali. Il valore SecretName è obbligatorio e rappresenta il nome del segreto. Il SecretVersion valore è 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 la configurazione dell'applicazione WEBSITE_CONTENTAZUREFILECONNECTIONSTRING per montare Azure Files 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 verifica se la condivisione di contenuto esiste. Se la condivisione di contenuto non esiste, la piattaforma prova a crearla. Se la piattaforma non riesce a individuare o creare la condivisione contenuto, blocca la richiesta.

Quando si usano riferimenti a Key Vault in questa impostazione, il controllo di convalida ha esito negativo per impostazione predefinita, perché il segreto 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 ignorare tutti i controlli e non crea automaticamente la condivisione contenuto. Assicurarsi che la condivisione contenuto venga creata in anticipo.

Attenzione

Se si ignora la convalida e la stringa di connessione o la condivisione di contenuto non è valida, l'app non verrà avviata correttamente e gestirà errori HTTP 500.

Durante la creazione dell'app, il tentativo di montare la condivisione dei contenuti potrebbe non riuscire perché le autorizzazioni relative all'identità gestita non vengono 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 soddisfare questo comportamento. Per altre informazioni, vedere Distribuzione di Azure Resource Manager più avanti in questo articolo. In questo caso, App Service di Azure utilizza un file system predefinito fino all'impostazione di Azure Files, 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 sono considerati segreti, pertanto è possibile configurarli direttamente anziché usare riferimenti a Key Vault.

Distribuzione Azure Resource Manager

Quando si automatizzano le distribuzioni di risorse tramite i modelli di Azure Resource Manager, potrebbe essere necessario sequenziare le dipendenze in un determinato ordine per rendere questa funzionalità funzionante. Assicurarsi di definire le impostazioni dell'app come risorsa propria, anziché usare una proprietà siteConfig nella definizione dell'app. L'app deve essere definita prima in modo che l'identità assegnata dal sistema venga creata con essa 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. Questa dipendenza è in genere un comportamento non sicuro, perché l'aggiornamento delle impostazioni dell'app si comporta in modo asincrono. Tuttavia, poiché è stata inclusa l'impostazione dell'applicazione WEBSITE_ENABLE_SYNC_UPDATE_SITE , l'aggiornamento è sincrono. 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.

Risolvere i problemi relativi ai riferimenti a Key Vault

Se un riferimento non viene risolto correttamente, viene usata la stringa di riferimento (ad esempio @Microsoft.KeyVault(...)). Questa situazione potrebbe causare errori dell'applicazione, 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, il motivo potrebbe anche essere che un segreto non esiste più o il riferimento contiene un errore di sintassi.

Se la sintassi è corretta, è possibile visualizzare altre cause di errore controllando lo stato di risoluzione corrente nel portale. Passare 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 a Key Vault.

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

Per usare il rilevatore per il servizio app:

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

Per usare il rilevatore per Funzioni di Azure:

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