Usare le identità gestite assegnate dal sistema per accedere ai dati di Azure Cosmos DB

SI APPLICA A: NoSQL

In questo articolo si configurerà una soluzione affidabile e indipendente dalla rotazione delle chiavi per accedere alle chiavi di Azure Cosmos DB usando identità gestite e controllo degli accessi in base al ruolo del piano dati. L'esempio in questo articolo usa Funzioni di Azure, ma è possibile usare qualsiasi servizio che supporti le identità gestite.

Si apprenderà come creare un'app per le funzioni in grado di accedere ai dati di Azure Cosmos DB senza dover copiare chiavi di Azure Cosmos DB. L'app per le funzioni viene attivata quando viene effettuata una richiesta HTTP e quindi vengono elencati tutti i database esistenti.

Prerequisiti

  • Un account Azure con una sottoscrizione attiva. Creare un account gratuitamente.

  • Un'API di Azure Cosmos DB per l'account NoSQL. Creare un'API di Azure Cosmos DB per l'account NoSQL

  • Un'app per le funzioni Funzioni di Azure esistente. Creare la prima funzione nel portale di Azure

  • Azure Functions Core Tools

  • Per eseguire i passaggi illustrati in questo articolo, installare l'interfaccia della riga di comando di Azure e accedere ad Azure.

    Controllo dei prerequisiti

    1. In un terminale o in una finestra di comando archiviare i nomi dell'app per le funzioni Funzioni di Azure, l'account e il gruppo di risorse di Azure Cosmos DB come variabili della shell denominate functionName, cosmosNamee resourceGroupName.

      # Variable for function app name
      functionName="msdocs-function-app"
      
      # Variable for Azure Cosmos DB account name
      cosmosName="msdocs-cosmos-app"
      
      # Variable for resource group name
      resourceGroupName="msdocs-cosmos-functions-dotnet-identity"
      

      Nota

      Queste variabili verranno riutilizzate nei passaggi successivi. Questo esempio presuppone che il nome dell'account Azure Cosmos DB sia msdocs-cosmos-app, il nome dell'app per le funzioni è msdocs-function-app e il nome del gruppo di risorse è msdocs-cosmos-functions-dotnet-identity.

    2. Visualizzare le proprietà dell'app per le funzioni usando il az functionapp show comando .

      az functionapp show \
          --resource-group $resourceGroupName \
          --name $functionName
      
    3. Visualizzare le proprietà dell'identità gestita assegnata dal sistema per l'app per le funzioni usando az webapp identity show.

      az webapp identity show \
          --resource-group $resourceGroupName \
          --name $functionName
      
    4. Visualizzare le proprietà dell'account Azure Cosmos DB usando az cosmosdb show.

      az cosmosdb show \
          --resource-group $resourceGroupName \
          --name $cosmosName
      

Creare un'API di Azure Cosmos DB per database NoSQL

In questo passaggio verranno creati due database.

  1. In un terminale o in una finestra di comando creare un nuovo products database usando az cosmosdb sql database create.

    az cosmosdb sql database create \
        --resource-group $resourceGroupName \
        --name products \
        --account-name $cosmosName
    
  2. Creare un nuovo customers database.

    az cosmosdb sql database create \
        --resource-group $resourceGroupName \
        --name customers \
        --account-name $cosmosName
    

Ottenere l'API di Azure Cosmos DB per l'endpoint NoSQL

In questo passaggio si eseguirà una query sull'endpoint del documento per l'account API per NoSQL.

  1. Usare az cosmosdb show con il parametro di query impostato su documentEndpoint. Registrare il risultato. Questo valore verrà utilizzato in un passaggio successivo.

    az cosmosdb show \
        --resource-group $resourceGroupName \
        --name $cosmosName \
        --query documentEndpoint
    
    cosmosEndpoint=$(
        az cosmosdb show \
            --resource-group $resourceGroupName \
            --name $cosmosName \
            --query documentEndpoint \
            --output tsv
    )
    
    echo $cosmosEndpoint
    

    Nota

    Questa variabile verrà riutilizzata in un passaggio successivo.

Concedere l'accesso all'account Azure Cosmos DB

In questo passaggio si assegnerà un ruolo all'identità gestita assegnata dal sistema dell'app per le funzioni. Azure Cosmos DB include più ruoli predefiniti che è possibile assegnare all'identità gestita per l'accesso al piano di controllo. Per l'accesso al piano dati, si creerà un nuovo ruolo personalizzato con accesso ai metadati di lettura.

Suggerimento

Per altre informazioni sull'importanza dell'accesso con privilegi minimi, vedere l'articolo Ridurre l'esposizione degli account con privilegi.

  1. Usare az cosmosdb show con il parametro di query impostato su id. Archiviare il risultato in una variabile della shell denominata scope.

    scope=$(
        az cosmosdb show \
            --resource-group $resourceGroupName \
            --name $cosmosName \
            --query id \
            --output tsv
    )
    
    echo $scope
    

    Nota

    Questa variabile verrà riutilizzata in un passaggio successivo.

  2. Usare az webapp identity show con il parametro di query impostato su principalId. Archiviare il risultato in una variabile della shell denominata principal.

    principal=$(
        az webapp identity show \
            --resource-group $resourceGroupName \
            --name $functionName \
            --query principalId \
            --output tsv
    )
    
    echo $principal
    
  3. Creare un nuovo file JSON con la configurazione del nuovo ruolo personalizzato.

    {
        "RoleName": "Read Azure Cosmos DB Metadata",
        "Type": "CustomRole",
        "AssignableScopes": ["/"],
        "Permissions": [{
            "DataActions": [
                "Microsoft.DocumentDB/databaseAccounts/readMetadata"
            ]
        }]
    }
    

    Suggerimento

    È possibile creare un file in Azure Cloud Shell usando touch <filename> o l'editor predefinito (code .). Per altre informazioni, vedere Editor di Azure Cloud Shell

  4. Usare az cosmosdb sql role definition create per creare una nuova definizione di ruolo denominata Read Azure Cosmos DB Metadata usando l'oggetto JSON personalizzato.

    az cosmosdb sql role definition create \
        --resource-group $resourceGroupName \
        --account-name $cosmosName \
        --body @definition.json
    

    Nota

    In questo esempio la definizione del ruolo viene definita in un file denominato definition.json.

  5. Usare az role assignment create per assegnare il Read Azure Cosmos DB Metadata ruolo all'identità gestita assegnata dal sistema.

    az cosmosdb sql role assignment create \
        --resource-group $resourceGroupName \
        --account-name $cosmosName \
        --role-definition-name "Read Azure Cosmos DB Metadata" \
        --principal-id $principal \
        --scope $scope
    

Accedere alle chiavi di Azure Cosmos DB a livello di codice

È ora disponibile un'app per le funzioni con un'identità gestita assegnata dal sistema con il ruolo personalizzato. L'app per le funzioni seguente eseguirà una query sull'account Azure Cosmos DB per un elenco di database.

  1. Creare un progetto di funzione locale con il --dotnet parametro in una cartella denominata csmsfunc. Modificare la directory della shell

    func init csmsfunc --dotnet
    
    cd csmsfunc
    
  2. Creare una nuova funzione con il parametro modello impostato su httptrigger e il nome impostato su readdatabases.

    func new --template httptrigger --name readdatabases
    
  3. Aggiungere il Azure.Identity pacchetto e Microsoft.Azure.Cosmos NuGet al progetto .NET. Compilare il progetto usando dotnet build.

    dotnet add package Azure.Identity
    
    dotnet add package Microsoft.Azure.Cosmos
    
    dotnet build
    
  4. Aprire il codice della funzione in un ambiente di sviluppo integrato (IDE).

    Suggerimento

    Se si usa l'interfaccia della riga di comando di Azure in locale o in Azure Cloud Shell, è possibile aprire Visual Studio Code.

    code .
    
  5. Sostituire il codice nel file readdatabases.cs con questa implementazione della funzione di esempio. Salvare il file aggiornato.

    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using Azure.Identity;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Azure.Cosmos;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Extensions.Http;
    using Microsoft.AspNetCore.Http;
    using Microsoft.Extensions.Logging;
    
    namespace csmsfunc
    {
        public static class readdatabases
        {
            [FunctionName("readdatabases")]
            public static async Task<IActionResult> Run(
                [HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequest req,
                ILogger log)
            {
                log.LogTrace("Start function");
    
                CosmosClient client = new CosmosClient(
                    accountEndpoint: Environment.GetEnvironmentVariable("COSMOS_ENDPOINT", EnvironmentVariableTarget.Process),
                    new DefaultAzureCredential()
                );
    
                using FeedIterator<DatabaseProperties> iterator = client.GetDatabaseQueryIterator<DatabaseProperties>();
    
                List<(string name, string uri)> databases = new();
                while(iterator.HasMoreResults)
                {
                    foreach(DatabaseProperties database in await iterator.ReadNextAsync())
                    {
                        log.LogTrace($"[Database Found]\t{database.Id}");
                        databases.Add((database.Id, database.SelfLink));
                    }
                }
    
                return new OkObjectResult(databases);
            }
        }
    }
    

(Facoltativo) Eseguire la funzione in locale

In un ambiente locale, la DefaultAzureCredential classe userà varie credenziali locali per determinare l'identità corrente. Anche se l'esecuzione in locale non è necessaria per le procedure, è possibile sviluppare localmente usando la propria identità o un'entità servizio.

  1. Nel file local.settings.json aggiungere una nuova impostazione denominata COSMOS_ENDPOINT nell'oggetto Values. Il valore dell'impostazione deve essere l'endpoint del documento registrato in precedenza in questa guida pratica.

    ...
    "Values": {
        ...
        "COSMOS_ENDPOINT": "https://msdocs-cosmos-app.documents.azure.com:443/",
        ...
    }
    ...
    

    Nota

    Questo oggetto JSON è stato abbreviato per brevità. Questo oggetto JSON include anche un valore di esempio che presuppone che il nome dell'account sia msdocs-cosmos-app.

  2. Eseguire l'app per le funzioni

    func start
    

Distribuire in Azure

Dopo la pubblicazione, la DefaultAzureCredential classe userà le credenziali dell'ambiente o di un'identità gestita. Per questa guida, l'identità gestita assegnata dal sistema verrà usata come credenziale per il CosmosClient costruttore.

  1. Impostare l'impostazione COSMOS_ENDPOINT nell'app per le funzioni già distribuita in Azure.

    az functionapp config appsettings set \
        --resource-group $resourceGroupName \
        --name $functionName \
        --settings "COSMOS_ENDPOINT=$cosmosEndpoint"
    
  2. Distribuire l'app per le funzioni in Azure riutilizzando la variabile shell functionName :

    func azure functionapp publish $functionName
    
  3. Testare la funzione nel portale di Azure.