システム割り当てマネージド ID を使用して Azure Cosmos DB データにアクセスする

適用対象: NoSQL

この記事では、マネージド ID データ プレーン ロールベースのアクセス制御 を使用して Azure Cosmos DB キーにアクセスするための 堅牢でキーローテーションに依存しないソリューションを設定します。 この記事の例では Azure Functions を使用しますが、マネージド ID をサポートする任意のサービスを使用できます。

ここでは、Azure Cosmos DB キーをコピーしなくても Azure Cosmos DB データにアクセスできる関数アプリを作成する方法について説明します。 関数アプリは、HTTP 要求が行われたときにトリガーされ、既存のデータベースをすべて一覧表示します。

前提条件

  • アクティブなサブスクリプションが含まれる Azure アカウント。 無料でアカウントを作成できます

  • 既存の Azure Cosmos DB API for NoSQL アカウント。 Azure Cosmos DB API for NoSQL アカウントを作成する

  • 既存の Azure Functions 関数アプリ。 Azure portal で初めての関数を作成する

  • 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 を使用して、関数アプリのシステム割り当てマネージド ID のプロパティを表示します。

      az webapp identity show \
          --resource-group $resourceGroupName \
          --name $functionName
      
    4. az cosmosdb show を使用して Azure Cosmos DB アカウントのプロパティを表示します。

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

Azure Cosmos DB NoSQL 用 API データベースを作成する

この手順では、2 つのデータベースを作成します。

  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
    

Azure Cosmos DB NoSQL 用 API エンドポイントを取得する

この手順では、NoSQL 用 API アカウントのドキュメント エンドポイントに対してクエリを実行します。

  1. クエリ パラメーターを documentEndpoint に設定して az cosmosdb show を使用します。 結果を記録します。 この値は、後の手順で使用します。

    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 アカウントへのアクセスを許可する

このステップでは、関数アプリのシステム割り当てマネージド ID にロールを割り当てます。 Azure Cosmos DB には、コントローン プレーンにアクセスするためにマネージド ID に割り当てられる複数の組み込みロールがあります。 データ プレーンにアクセスする場合は、メタデータを読み取るためのアクセスを使用して新しいカスタム ロールを作成します。

ヒント

最小特権アクセスの重要性についての詳細は、「特権アカウントの公開時間を短縮する」の記事を参照してください。

  1. クエリ パラメーターを id に設定して az cosmosdb show を使用します。 結果を scope という名前のシェル変数に保存します。

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

    注意

    この変数は、後の手順で再利用されます。

  2. クエリ パラメーターを principalId に設定して az webapp identity show を使用します。 結果を 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"
            ]
        }]
    }
    

    ヒント

    Azure Cloud Shell で、touch <filename> または組み込みエディター (code .) を使用して、ファイルを作成できます。 詳しくは、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
    

    Note

    この例では、ロール定義は definition.json という名前のファイルに定義されています。

  5. az role assignment create を使用して、Read Azure Cosmos DB Metadata のロールをシステム割り当てマネージド ID に割り当てます。

    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 キーにアクセスする

これで、カスタム ロールを使用したシステム割り当てマネージド ID を持つ関数アプリが作成されました。 次の関数アプリは、Azure Cosmos DB アカウントにデータベースの一覧を照会します。

  1. csmsfunc という名前のフォルダーに --dotnet パラメーターを持つローカル関数プロジェクトを作成します。 シェルのディレクトリを変更する

    func init csmsfunc --dotnet
    
    cd csmsfunc
    
  2. テンプレート パラメーターを httptrigger に設定し、名前readdatabases に設定して、新しい関数を作成します。

    func new --template httptrigger --name readdatabases
    
  3. .NET プロジェクトに Azure.IdentityMicrosoft.Azure.Cosmos NuGet パッケージを追加します。 dotnet build を使用してプロジェクトをビルドします。

    dotnet add package Azure.Identity
    
    dotnet add package Microsoft.Azure.Cosmos
    
    dotnet build
    
  4. 統合開発者環境 (IDE) で関数コードを開きます。

    ヒント

    Azure CLI をローカルまたは Azure Cloud Shell で使用している場合は、Visual Studio Code を開くことができます。

    code .
    
  5. readdatabases.cs ファイル内のコードを、このサンプル関数k実装に置き換えます。 更新したファイルを保存します。

    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 クラスはさまざまなローカル資格情報を使用して現在の ID を決定します。 ローカルでの実行はハウツーには必要ありませんが、独自の ID またはサービス プリンシパルを使用してローカルで開発できます。

  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 クラスは環境からの資格情報またはマネージド ID を使用します。 このガイドでは、システム割り当てマネージド ID を、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 portal で関数をテストします