Uso de identidades administradas asignadas por el sistema para acceder a datos de Azure Cosmos DB

SE APLICA A: SQL API

En este artículo, configurará una solución sólida e independiente de la rotación de claves para acceder a las claves de Azure Cosmos DB mediante identidades administradas y control de acceso basado en roles del plano de datos. En el ejemplo de este artículo se usa Azure Functions, pero puede usar cualquier servicio que admita identidades administradas.

Aprenderá a crear una aplicación de funciones que puede acceder a datos de Azure Cosmos DB sin necesidad de copiar ninguna clave de Azure Cosmos DB. La aplicación de funciones se desencadenará cuando se haga una solicitud HTTP y, a continuación, enumerará todas las bases de datos existentes.

Requisitos previos

Comprobación de requisitos previos

  1. En una ventana de terminal o comando, almacene los nombres de la aplicación de funciones de Azure Functions, la cuenta de Azure Cosmos DB y el grupo de recursos como variables de shell denominadas functionName, cosmosName y resourceGroupName.

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

    Nota:

    Estas variables se volverán a usar en pasos posteriores. En este ejemplo se supone que el nombre de la cuenta de Azure Cosmos DB es msdocs-cosmos-app, el nombre de la aplicación de funciones es msdocs-function-app, y el nombre del grupo de recursos es msdocs-cosmos-functions-dotnet-identity.

  2. Vea las propiedades de la aplicación de funciones mediante el comando az functionapp show.

    az functionapp show \
        --resource-group $resourceGroupName \
        --name $functionName
    
  3. Vea las propiedades de la identidad administrada asignada por el sistema para la aplicación de funciones mediante az webapp identity show.

    az webapp identity show \
        --resource-group $resourceGroupName \
        --name $functionName
    
  4. Vea las propiedades de la cuenta de Cosmos DB mediante az cosmosdb show.

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

Creación de bases de datos de SQL API de Cosmos DB

En este paso, creará dos bases de datos.

  1. En una ventana de terminal o comando, cree una base de datos products con az cosmosdb sql database create.

    az cosmosdb sql database create \
        --resource-group $resourceGroupName \
        --name products \
        --account-name $cosmosName
    
  2. Cree una base de datos customers.

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

Obtención del punto de conexión de SQL API de Cosmos DB

En este paso, consultará el punto de conexión del documento para la cuenta de SQL API.

  1. Use az cosmosdb show con el parámetro query establecido en documentEndpoint. Registre el resultado. Usará este valor en un paso posterior.

    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:

    Esta variable se volverá a usar en un paso posterior.

Concesión de acceso a la cuenta de Azure Cosmos

En este paso, asignará un rol a la identidad administrada asignada por el sistema de la aplicación de funciones. Azure Cosmos DB tiene varios roles integrados que se pueden asignar a la identidad administrada. Para esta solución, usará el rol Lector de datos integrado de Cosmos DB.

Sugerencia

Al asignar roles, asigne solo el acceso necesario. Si el servicio solo requiere leer datos, asigne el rol Lector de datos integrado de Cosmos DB a la identidad administrada. Para más información sobre la importancia del acceso con privilegios mínimos, vea el artículo Menor exposición de las cuentas con privilegios.

  1. Use az cosmosdb show con el parámetro query establecido en id. Almacene el resultado en una variable de shell denominada scope.

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

    Nota:

    Esta variable se volverá a usar en un paso posterior.

  2. Use az webapp identity show con el parámetro query establecido en principalId. Almacene el resultado en una variable de shell denominada principal.

    principal=$(
        az webapp identity show \
            --resource-group $resourceGroupName \
            --name $functionName \
            --query principalId \
            --output tsv
    )
    
    echo $principal
    
  3. Cree un nuevo objeto JSON con la configuración del nuevo rol personalizado.

    {
        "RoleName": "Read Cosmos Metadata",
        "Type": "CustomRole",
        "AssignableScopes": ["/"],
        "Permissions": [{
            "DataActions": [
                "Microsoft.DocumentDB/databaseAccounts/readMetadata"
            ]
        }]
    }
    
  4. Use az cosmosdb sql role definition create para crear una nueva definición de rol denominada Read Cosmos Metadata mediante el objeto JSON personalizado.

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

    Nota

    En este ejemplo, la definición de roles se define en un archivo denominado definition.json.

  5. Use az role assignment create para asignar el rol Read Cosmos Metadata a la identidad administrada asignada por el sistema.

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

Acceso mediante programación a las claves de Azure Cosmos DB

Ahora tenemos una aplicación de funciones que tiene una identidad administrada asignada por el sistema con el rol Lector de datos integrado de Cosmos DB. La siguiente aplicación de funciones consultará la cuenta de Azure Cosmos DB para obtener una lista de bases de datos.

  1. Cree un proyecto de función local con el parámetro --dotnet en una carpeta denominada csmsfunc. Cambie el directorio del shell.

    func init csmsfunc --dotnet
    
    cd csmsfunc
    
  2. Cree una nueva función con el parámetro template establecido en httptrigger y name establecido en readdatabases.

    func new --template httptrigger --name readdatabases
    
  3. Agregue los paquetes NuGet Azure.Identity y Microsoft.Azure.Cosmosal proyecto de .NET. Compile el proyecto mediante dotnet build.

    dotnet add package Azure.Identity
    
    dotnet add package Microsoft.Azure.Cosmos
    
    dotnet build
    
  4. Abra el código de función en un entorno de desarrollador integrado (IDE).

    Sugerencia

    Si usa la CLI de Azure localmente o en Azure Cloud Shell, puede abrir Visual Studio Code.

    code .
    
  5. Reemplace el código del archivo readdatabases.cs por esta implementación de función de ejemplo. Guarde el archivo actualizado.

    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);
            }
        }
    }
    

(Opcional) Ejecución de la función localmente

En un entorno local, la clase DefaultAzureCredential usará varias credenciales locales para determinar la identidad actual. Aunque la ejecución local no es necesaria para el procedimiento, puede desarrollar localmente mediante su propia identidad o una entidad de servicio.

  1. En el archivo local.settings.json, agregue una nueva configuración denominada COSMOS_ENDPOINT en el objeto Values. El valor de la configuración debe ser el punto de conexión del documento, que registró anteriormente en esta guía paso a paso.

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

    Nota:

    Este objeto JSON se ha abreviado por motivos de concisión. Este objeto JSON también incluye un valor de ejemplo que supone que el nombre de la cuenta es msdocs-cosmos-app.

  2. Ejecución de la aplicación de funciones

    func start
    

Implementar en Azure

Una vez publicada, la clase DefaultAzureCredential usará credenciales del entorno o una identidad administrada. En esta guía, la identidad administrada asignada por el sistema se usará como credencial para el constructor CosmosClient.

  1. Establezca la configuración COSMOS_ENDPOINT en la aplicación de funciones ya implementada en Azure.

    az functionapp config appsettings set \
        --resource-group $resourceGroupName \
        --name $functionName \
        --settings "COSMOS_ENDPOINT=$cosmosEndpoint"
    
  2. Para implementar la aplicación de funciones en Azure, reutilice la variable functionName del shell:

    func azure functionapp publish $functionName
    
  3. Pruebe la función en Azure Portal.

Pasos siguientes