NEXTSCAPE blog

株式会社ネクストスケープの社員による会社公式ブログです。ネスケラボでは、社員が日頃どのようなことに興味をもっているのか、仕事を通してどのような面白いことに取り組んでいるのかなど、会社や技術に関する情報をマイペースに紹介しています。

MENU

Azure App Configuration: DefaultAzureCredentialを使ってローカル デバッグとAzure上での接続をワンコードにする

はじめに

エンタープライズ サービス部の乙黒です。 この投稿は NEXTSCAPE Advent Calendar 2022 の3日目の記事です。

この記事ではAzureのApp ServiceからApp Configurationへ接続する場合を例に、ローカルデバッグ時の認証とAzure上でのマネージドID認証をワンコードで書く方法について紹介します。

注意点

マネージドID接続のソースコード

learn.microsoft.com

この記事を参考にして、Program.csでの接続設定のコードは次のようになります。

var builder = WebApplication.CreateBuilder(args);

builder.Configuration.AddAzureAppConfiguration(options =>
{
    options.Connect(
        new Uri("https://{App Configurationのリソース名}.azconfig.io"),
        new ManagedIdentityCredential());
});

見ての通り、ソースコードで指定されているのはApp ConifgurationのエンドポイントURLのみです。ソースコードや設定ファイルに接続文字列、シークレット情報を記述する必要がなくなるため、管理が楽になります。

マネージドID接続を使うときの悩みどころ

App Configurationへの接続に限らず、マネージドIDを使ってAzureのリソース間を繋げるときに厄介なのが

  • マネージドIDはAzure上でしか動作しない

という点です。つまり、上に挙げたソースコードだと、ローカルデバッグ時に認証エラーが起きてしまいます。

シンプルにこれを解決しようとすると #if ディレクティブを利用して

  • デバッグ構成のときは接続文字列で認証
  • リリース構成のときはマネージドIDで認証

と分ける方法がパッと思いつきます。コードにするとこんな感じです。

var builder = WebApplication.CreateBuilder(args);

#if DEBUG
builder.Configuration.AddAzureAppConfiguration("{App Configurationへの接続文字列}");
#else
builder.Configuration.AddAzureAppConfiguration(options =>
{
    options.Connect(
        new Uri("https://{App Configurationのリソース名}.azconfig.io"),
        new ManagedIdentityCredential());
});
#endif

この例には

  • ローカル デバッグ中は リリース ビルド側にビルドエラーになるようなバグがあっても見落とされがちになる。
  • パッケージ化したい場合は使えない

等の問題があります。

DefaultAzureCredential を使おう

この問題を解決するのが DefaultAzureCredential です。DefaultAzureCredential を使えば、ローカルデバッグ時の認証とAzure上でのマネージドID認証をこんな風にワンコードで書くことができます。

var builder = WebApplication.CreateBuilder(args);

builder.Configuration.AddAzureAppConfiguration(options =>
{
    options.Connect(
        new Uri("https://{App Configurationのリソース名}.azconfig.io"),
        new DefaultAzureCredential());
});

DefaultAzureCredential は何をやっているのか

この記事を書いている時点で日本語翻訳されていないのですが、こちらに仕様が書かれています。

learn.microsoft.com

簡単に言うと、

  • 様々な認証方式を順に試して、成功したら処理を抜ける

ということをやっています。

認証を試行する順序の2番目のManagedIdentityCredentialがあり、Azure上にデプロイされたときはマネージドID認証が使われることになります。

また、Visual Studioでローカル デバッグしているときは4番目の VisualStudioCredentialを使って、Visual Studioにサインインしているアカウントで認証が行われます。

以下、実際にデバッグ実行してみたところ、上手くいかずにハマった点がいくつかあったため、紹介しておきます。

ハマったこと①:App Configurationのロール割り当て設定

  • Visual Studioからデバッグするユーザーには「App Configuration データ閲覧者」を割り当てる必要がある。

learn.microsoft.com

こちらの記事にも書いてありますが、「閲覧者」、「共同作成者」、「所有者」のいずれもApp Configurationデータの読み取り割アクセス権を持ちません。 データを読み取るには「App Configuration データ閲覧者」を割り当てる必要があります。

ハマったこと②:ゲストアカウントの場合はオプションにテナントIDを指定する必要がある

Visual Studioからデバッグするユーザーが異なるAADテナントから参加している場合、DefaultAzureCredentialOptionsでテナントIDを指定しないと認証が通りません。

var builder = WebApplication.CreateBuilder(args);

var credentialOptions = new DefaultAzureCredentialOptions()
{
    TenantId = "{テナントID}"
};

builder.Configuration.AddAzureAppConfiguration(options =>
{
    options.Connect(
        new Uri("https://{App Configurationのリソース名}.azconfig.io"),
        new DefaultAzureCredential(credentialOptions));
});

ハマったこと③:複数バージョンのVisual Studioがインストールされていると認証エラーが発生する

Visual Studio 2022 でデバッグしていたところ、どうしても認証が通らず、深みにハマりました。

認証エラーのメッセージを見てみると、Microsoft.Asal.TokenService.exeのパスが「2019」になっていました。

Process "C:\Program Files\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\CommonExtensions\Microsoft\Asal\TokenService\Microsoft.Asal.TokenService.exe" has failed with unexpected error: (以下省略)

私の環境ではVS 2019とVS 2022の2つのバージョンのVisual Studioがインストールされており、どういう訳かVS 2022でのデバッグ中もVS 2019のexeが実行されてしまい、一向にトークンが取得できない状況になっていました。 環境変数を修正すれば正常化する可能性もありますが、私の場合はVS 2019が既に不要だったため、アンインストールすることで正常化しました。

まとめ

ローカルデバッグ時の認証とAzure上でのマネージドID認証をワンコードで書く方法について紹介させていただきました。 Azure Functionsへの応用やKeyVaultとの接続についても、機会がありましたら書かせていただきたいと思います。