使用系統指派的受控識別來存取 Azure Cosmos DB 數據

適用於:NoSQL

在本文中,您會使用受控識別,和資料平面角色型存取控制,設定強固、無從驗證的金鑰輪替解決方案,存取 Azure Cosmos DB 金鑰。 此文章中的範例使用 Azure Functions,但您可以使用任何支援受控識別的服務。

您將瞭解如何建立可存取 Azure Cosmos DB 資料的函數應用程式,而不需複製任何 Azure Cosmos DB 金鑰。 提出 HTTP 要求後,會觸發函數應用程式,然後列出目前所有的資料庫。

必要條件

  • 具有有效訂用帳戶的 Azure 帳戶。 免費建立帳戶

  • 現有的 Azure Cosmos DB API for NoSQL 帳戶。 建立 Azure Cosmos DB API for NoSQL 帳戶

  • 現有的 Azure Functions 函數應用程式。 在 Azure 入口網站建立您的第一個函式

  • Azure Functions Core Tools

  • 若要執行本文中的步驟,請安裝 Azure CLI,並登入 Azure

    先決條件檢查

    1. 在終端或命令視窗中,將 Azure Functions 函數應用程式的名稱、Azure Cosmos DB 帳戶和資源群組儲存為名為 functionNamecosmosNameresourceGroupName 的殼層變數。

      # 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"
      

      注意

      在後續步驟中會重複使用這些變數。 此範例假設您的 Azure Cosmos DB 帳戶名稱為 msdocs-cosmos-app,函數應用程式名稱為 msdocs-function-app,而資源群組名稱為 msdocs-cosmos-functions-dotnet-identity

    2. 使用 az functionapp show 命令,檢視函數應用程式的屬性。

      az functionapp show \
          --resource-group $resourceGroupName \
          --name $functionName
      
    3. 使用 az webapp identity show 檢視函數應用程式的系統指派受控識別屬性。

      az webapp identity show \
          --resource-group $resourceGroupName \
          --name $functionName
      
    4. 使用 az cosmosdb show 檢視 Azure Cosmos DB 帳戶的屬性。

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

建立適用於 NoSQL 資料庫的 Azure Cosmos DB API

在此步驟中,您會建立兩個資料庫。

  1. 在終端或命令視窗中,使用 az cosmosdb sql database create 建立新的 products 資料庫。

    az cosmosdb sql database create \
        --resource-group $resourceGroupName \
        --name products \
        --account-name $cosmosName
    
  2. 建立新的 customers 資料庫。

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

取得適用於 NoSQL 端點的 Azure Cosmos DB API

在此步驟中,您會查詢 API for NoSQL 帳戶的文件端點。

  1. 使用 az cosmosdb show,並將查詢參數設為 documentEndpoint。 記錄結果。 稍後的步驟中需要用到此值。

    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
    

    注意

    在後續步驟中會重複使用這個變數。

授與 Azure Cosmos DB 帳戶的存取權

在此步驟中,您會將角色指派給函數應用程式之系統指派的受控識別。 Azure Cosmos DB 具有多個內建角色,可供您指派給控制平面存取的受控識別。 就資料平面存取而言,您將建立一個具有讀取中繼資料權限的新自訂角色。

提示

如需最低權限存取權的重要性詳細資訊,請參閱降低特殊權限帳戶的暴露風險一文。

  1. 使用 az cosmosdb show,並將查詢參數設為 id。 將結果儲存在名為 scope 的殼層變數中。

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

    注意

    在後續步驟中會重複使用這個變數。

  2. 使用 az webapp identity show,並將查詢參數設為 principalId。 將結果儲存在名為 principal 的殼層變數中。

    principal=$(
        az webapp identity show \
            --resource-group $resourceGroupName \
            --name $functionName \
            --query principalId \
            --output tsv
    )
    
    echo $principal
    
  3. 使用新的自訂角色設定來建立新的 JSON 檔案。

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

    提示

    您可使用 touch <filename> 或是內建編輯器 (code .),在 Azure Cloud Shell 中建立檔案。 如需詳細資訊,請參閱 Azure Cloud Shell 編輯器

  4. 使用 az cosmosdb sql role definition create 來使用自訂 JSON 物件建立名為 Read Azure Cosmos DB Metadata 的新角色定義。

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

    注意

    在此範例中,角色定義是在名為 definition.json 的檔案中加以定義。

  5. 使用 az role assignment create 指派 Read Azure Cosmos DB Metadata 角色給系統指派的受控識別。

    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
    

以程式設計方式存取 Azure Cosmos DB 金鑰

我們目前的函數應用程式擁有具備自訂角色的系統指派受控識別。 以下函數應用程式會查詢 Azure Cosmos DB 帳戶的資料庫清單。

  1. 在名為 csmsfunc 的資料夾中,建立包含 --dotnet 參數的本機函數專案。 變更殼層的目錄

    func init csmsfunc --dotnet
    
    cd csmsfunc
    
  2. 建立新的函式,並將範本參數設為 httptrigger名稱設為 readdatabases

    func new --template httptrigger --name readdatabases
    
  3. Azure.IdentityMicrosoft.Azure.Cosmos NuGet 封裝新增至 .NET 專案。 使用 dotnet build 組建專案。

    dotnet add package Azure.Identity
    
    dotnet add package Microsoft.Azure.Cosmos
    
    dotnet build
    
  4. 在整合式開發人員環境 (IDE) 中開啟函數程式碼。

    提示

    如果您在本機或在 Azure Cloud Shell 中使用 Azure CLI,即可開啟 Visual Studio Code。

    code .
    
  5. 以此範例函數實作取代 readdatabases.cs 檔案中的程式碼。 儲存更新的檔案。

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

(選擇性)在本機執行函式

在本機環境中,DefaultAzureCredential 類別會使用各種本機認證,判斷目前的身分識別。 在本機執行不需要操作指南,但您可以使用自己的身分識別或服務主體在本機進行開發。

  1. local.settings.json 檔案的 Values 物件中,新增名為 COSMOS_ENDPOINT 的新設定。 設定的值應該是您稍早在本操作指南中記錄的文件端點。

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

    注意

    為求簡潔明瞭,此 JSON 物件已縮短。 此 JSON 物件也包含範例值,並假設您的帳戶名稱為 msdocs-cosmos-app

  2. 執行函式應用程式

    func start
    

部署至 Azure

發佈後,DefaultAzureCredential 類別會使用環境或受控識別的認證。 針對本指南,系統指派的受控識別會作為 CosmosClient 認證的建構函式。

  1. 在 Azure 中部署的函數應用程式上,設定 COSMOS_ENDPOINT 設定。

    az functionapp config appsettings set \
        --resource-group $resourceGroupName \
        --name $functionName \
        --settings "COSMOS_ENDPOINT=$cosmosEndpoint"
    
  2. 重複使用 functionName 殼層變數,將您的函數應用程式部署至 Azure:

    func azure functionapp publish $functionName
    
  3. 測試 Azure 入口網站中的函數