ごった煮

色々な事を書いてます

Visual Studio 2022 + Azure Functions + Azure App Configuration + Managed Service Identity の構成をローカル実行する方法について(2022年5月)

Managed Service Identity (MSI) を使用して、App Configuration と接続する構成をとる場合、ローカル環境でも DefaultAzureCredential を使用していれば、問題なく動くはずなのですが 不思議な挙動に悩まされたので、備忘録を残します。

環境及び構成

  • Visual Studio 2022 (v.17.1.3)
  • Azure Functions (v4、in-process)

前提条件

  • ローカルからの認証に使用する Azure のアカウントには、App Configuration Data Reader ロールを付与済み
  • Visual Studio には、対象の App Configuration Data Reader ロールが付与済のアカウントでログイン済み

実装したソースコード

builder.ConfigurationBuilder.AddAzureAppConfiguration(o =>
{
    var connectionString = defaultConfig["AppConfig:ConnectionString"];
    if (string.IsNullOrWhiteSpace(connectionString))
    {
        var endpoint = new Uri(defaultConfig["AppConfig:Endpoint"]);
        o.Connect(endpoint, new DefaultAzureCredential());
    }
    else
    {
        o.Connect(connectionString);
    }

    var context = builder.GetContext();
    o.Select("*");
});

当初期待していた挙動

  • Visual Studio の認証情報を使用して、App Configuration への接続が認証され、App Configuration から設定情報が取得できる

実際の挙動

  • 認証エラーが返却される(401)

対処方法

デフォルトのサブスクリプションを切り替える

自分のアカウントは、複数のサブスクリプションに所属している + 今回接続したかったサブスクリプションがデフォルトのサブスクリプションに設定されていませんでした。

なので、まずデフォルトのサブスクリプションを設定しました。

az account set --subscription {サブスクリプション Id}

これでデフォルトのサブスクリプションが切り替わります。 この状態で、Function App を実行してみます。

Function App の実行結果

  • 認証エラーが返却される(401)

最初と同じ挙動です。

DefaultAzureCredential が使用するテナント Id を指定する

次に、Function App 側で、認証に行くテナントを直接指定します。

2パターン設定方法がありますので、好きな方法で指定します。

パターン1

DefaultAzureCredential の引数として、オプションにテナント Id を指定する方法です。

builder.ConfigurationBuilder.AddAzureAppConfiguration(o =>
{
    var connectionString = defaultConfig["AppConfig:ConnectionString"];
    if (string.IsNullOrWhiteSpace(connectionString))
    {
        var endpoint = new Uri(defaultConfig["AppConfig:Endpoint"]);
        o.Connect(endpoint, new DefaultAzureCredential(new DefaultAzureCredentialOptions
        {
            VisualStudioTenantId = "{{テナント Id}}"
        }));
    }
    else
    {
        o.Connect(connectionString);
    }

    var context = builder.GetContext();
    o.Select("*");
});

パターン2

local.settings.jsonAZURE_TENANT_ID を設定する

{
    "IsEncrypted": false,
    "Values": {
        //--- Development
        "AppConfig:ConnectionString": "",
        "AppConfig:Endpoint": "",
        "AZURE_TENANT_ID": "テナント Id",
    }
}

Azure 上では、このテナント Id を指定する必要はないので、個人的には、ソースコードを変更せずに済むこちらを使用しました。

設定が終わったら、Function App を実行します。

Function App の実行結果

  • 接続成功

テナント Id を指定した状態で、Azure CLI のデフォルトサブスクリプションを他のものに切り替える

次に、テナント Id を Function App で指定した状態で、Azure CLI の設定を元に戻します。

設定は、先ほどの az account set ~ で関係のないサブスクリプション Id を指定してみます。

変更したら、Function App を実行します。

Function App の実行結果

  • 認証エラーが返却される(401)

この挙動を見るに、Visual Studio + Function App の構成で MSI をローカルで使用したい場合、Azure CLI の設定 + テナント Id の指定が必要なようです。

まとめ

これバグなのでは?