ローカル開発環境から Azure Key Vault にアクセスする

この記事は約8分で読めます。

Azure Key Vault 参照時に401 Unauthrized エラーが発生

ローカル開発環境で Azure Functions(HttpTrigger) を開発中に、Functions 内で Azure Key Vault のシークレットを参照しようとしたところ、401 Unauthrized エラーが発生しました。

"error": {
    "code": "Unauthorized",
    "message": "AKV10032: Invalid issuer. Expected one of https://sts.windows.net/wwwwwwww-wwww-wwww-wwww-wwwwwwwwwwww/, https://sts.windows.net/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/, https://sts.windows.net/yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy/, found https://sts.windows.net/zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz/."
}

サンプルコードはこちらです。

using System;
using System.Net;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
using Azure.Security.KeyVault.Secrets;
using Azure.Identity;

namespace Company.Function
{
    public class HttpTrigger
    {
        private readonly ILogger _logger;

        public HttpTrigger(ILoggerFactory loggerFactory)
        {
            _logger = loggerFactory.CreateLogger<HttpTrigger>();
        }

        [Function("HttpTrigger")]
        public HttpResponseData Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req)
        {
            var response = req.CreateResponse(HttpStatusCode.OK);
            response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
            try
            {
                Uri valutUrl = new Uri("https://samplekeyvault.vault.azure.net/");
                DefaultAzureCredential credential = new DefaultAzureCredential();
                SecretClient secretClient = new SecretClient(valutUrl, credential);
                response.WriteString(secretClient.GetSecret("TestSecret").Value.Value);
            }
            catch (Exception e)
            {
                response.WriteString(e.Message);
            }

            return response;
        }
    }
}

Azure Key Vault にアクセスできるユーザーで認証しているのに参照できない

Azure Key Vault にアクセスするために Azure の認証を行う必要があります。”Azure SDK for .NET を使用した認証“に従い、Azure.Identity ライブラリの DefaultAzureCredential クラスを使用しました。

DefaultAzureCredential クラスを使用した認証ですが、認証方法がいくつかあり、認証の順序が決まっています。

DefaultAzureCredential の認証順序(上から順に認証します)

1Environment 環境変数に登録したアカウント情報を使用して認証します。
2Managed IdentityアプリケーションがマネージドIDが有効となっているAzure ホストにデプロイされている場合、マネージドIDを使用して認証します。
3Visual Studio(Visual Studio Code)Visual Studioを使用して認証した場合、Visual Studioに設定したアカウントで認証します。
※Visual Studio Codeの場合はAzure Account pluginに設定したアカウント
4Azure CLIAzure CLI の az login コマンドで認証したアカウントを使用します。
5Azure PowerShellAzure PowerShellの Connect-AzAccountコマンドで認証したアカウントを使用します。
6Interactiveデフォルトブラウザを使用して対話的に認証します。
DefaultAzureCredential の認証方法と順序(上から順に認証します)

ローカル環境では、Visual Studio Code (Azure Account plugin) を使用して、Azure Key Vaultにアクセスできるユーザーで認証し、Azure Funcitonsの開発をしていました。

DefaultAzureCredetial の認証順序で Visual Studio Code とあるので、これでローカル環境からAzure Key Vault にアクセスできるだろうと思っていたのが誤りでした。

ローカル環境からAzure Key Vaultを参照するには動作環境にClientSecretCredentialが必要

Azure Key Vaultのドキュメントによると、Azure Key Vault を参照するには”Vault URL”とClientSecretCredential(“client id”、”client secret”、”tenant id”)が必要とのことです。しかも、ClientSecretCredentialを環境変数に登録する必要があるとのこと。

環境変数にClientSecretCredentialを設定する

ローカル環境からAzure Key Vault にアクセスする場合、開発環境の環境変数に”client id”、”client secret”、”tenant id”を登録する必要があります。

環境変数に登録したClientSecretCredential

環境変数にClientSecretCredentialを登録することで、上記ソースコードでAzure Key Vaultにアクセスすることができました。

Visual Studio Code は local.settings.json に ClientSecretCredential を設定できる

Visual Studio Code で開発している場合は、local.settings.jsonに記載してもアクセスすることができます。

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",
    "AZURE_CLIENT_ID": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "AZURE_CLIENT_SECRET": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "AZURE_TENANT_ID": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  }
}

Azure 上で動作させる場合はアプリケーション設定に ClientSecretCredential を設定

Azure Functions をAzure上で動作させる場合は、関数アプリの「設定」→「構成」からアプリケーション設定へClientSecretCredentialを設定します。

Azure Functionsがローカル環境でデバッグできない場合は

Azure Functions をローカルでデバッグできない場合は、こちらが原因かもしれません。

コメント