オンプレミスでホストされている .NET アプリから Azure リソースに対して認証する

Azure の外部 (オンプレミスやサード パーティのデータ センターなど) でホストされているアプリは、Azure リソースにアクセスするときに、アプリケーション サービス プリンシパルを使用して Azure に対する認証を行う必要があります。 アプリケーション サービス プリンシパル オブジェクトは、Azure のアプリ登録プロセスを使用して作成されます。 アプリケーション サービス プリンシパルが作成されると、アプリのクライアント ID とクライアント シークレットが生成されます。 その後、クライアント ID、クライアント シークレット、テナント ID が環境変数に格納され、実行時にアプリを Azure に対して認証するために Azure Identity ライブラリで使用できるようになります。

アプリがホストされている環境ごとに異なるアプリ登録を作成する必要があります。 これにより、各サービス プリンシパルに対して環境固有のリソース アクセス許可が構成され、ある環境にデプロイされたアプリが、別の環境の一部である Azure リソースと通信しないようにすることができます。

1 - Azure にアプリケーションを登録する

アプリは、Azure portal または Azure CLI を使用して Azure に登録できます。

Azure portal にサインインして、次の手順を実行します。

手順 Screenshot
Azure portal で、次の操作を行います。
  1. Azure portal の上部にある検索バーに「アプリの登録」と入力します。
  2. 検索バーの下に表示されるメニューの [サービス] 見出しの下にある [アプリの登録] と書かれた項目を選択します。
Azure portal の上部の検索バーを使用して、[アプリの登録] ページを検索してそこに移動する方法を示すスクリーンショット。
[アプリの登録] ページで、[+ 新規登録] を選択します。 [アプリの登録] ページの [新規登録] ボタンの場所を示すスクリーンショット。
[アプリケーションの登録] ページで、次のようにフォームに入力します。
  1. 名前 → Azure でのアプリ登録の名前を入力します。 この名前には、アプリ登録の対象となるアプリ名と環境 (test、prod) を含めることをお勧めします。
  2. サポートされているアカウントの種類この組織のディレクトリ内のアカウントのみ
[登録] を選択してアプリを登録し、アプリケーション サービス プリンシパルを作成します。
アプリに名前を付け、サポートされているアカウントの種類をこの組織ディレクトリ内のアカウントとしてのみ指定することで、[アプリケーションの登録] ページに入力する方法を示すスクリーンショット。
お使いのアプリの [アプリの登録] ページで、次の操作を行います。
  1. アプリケーション (クライアント) ID → ローカル開発時にアプリが Azure にアクセスするために使用するアプリ ID です。 この値は、後の手順で必要になるので、テキスト エディターで一時的な場所にコピーします。
  2. ディレクトリ (テナント) ID → この値は、Azure に対して認証するときにもアプリで必要になります。 この値も後の手順で必要になるので、テキスト エディターで一時的な場所にコピーします。
  3. クライアント資格情報 → アプリが Azure に対して認証して Azure サービスを使用する前に、アプリのクライアント資格情報を設定する必要があります。 [証明書またはシークレットの追加] を選択して、アプリの資格情報を追加します。
アプリの登録が完了した後の [アプリの登録] ページのスクリーンショット。このスクリーンショットは、今後の手順で必要になるアプリケーション ID とテナント ID の場所を示しています。また、アプリのアプリケーション シークレットを追加するために使用するリンクの場所も示しています。
[証明書とシークレット] ページで、[+ 新しいクライアント シークレット] を選びます。 証明書とシークレット ページで新しいクライアント シークレットを作成するために使用するリンクの場所を示すスクリーンショット。
[クライアント シークレットの追加] ダイアログがページの右側から表示されます。 このダイアログで、次の操作を行います。
  1. 説明現在の値を入力します。
  2. 有効期限 → "24 か月"の値を選択します。
[追加] を選択してシークレットを追加します。

重要: シークレットの有効期限の前に予定表にアラームを設定します。 これにより、事前に新しいシークレットを追加し、このシークレットの有効期限が切れる前にアプリを更新して、アプリのサービスが中断しないようにできます。
アプリ登録プロセスによって作成されるアプリケーション サービス プリンシパル用に新しいクライアント シークレットが追加されるページを示すスクリーンショット。
[証明書とシークレット] ページにクライアント シークレットの値が表示されます。

この値は、後の手順で必要になるので、テキスト エディターの一時的な場所にコピーします。

重要: この値が表示されるのはこのタイミングだけです。 このページを終了または更新すると、この値を再度表示できなくなります。 このクライアント シークレットを無効にせずにクライアント シークレットを追加することもできますが、この値は再び表示されることはありません。
生成されたクライアント シークレットを含むページを示すスクリーンショット。

2 - アプリケーション サービス プリンシパルにロールを割り当てる

次に、アプリがどのリソースでどのロール (アクセス許可) を必要としているかを決定し、それらのロールをアプリに割り当てる必要があります。 ロールは、リソース、リソース グループ、またはサブスクリプション スコープで割り当てることができます。 ほとんどのアプリは、すべての Azure リソースを 1 つのリソース グループにグループ化するため、この例では、リソース グループ スコープでサービス プリンシパルのロールを割り当てる方法を示しています。

手順 Screenshot
Azure portal の上部にある検索ボックスを使用してリソース グループ名を検索し、アプリのリソース グループを見つけます。

ダイアログ ボックスの [リソース グループ] 見出しの下にあるリソース グループ名を選択して、リソース グループに移動します。
Azure portal の上部にある検索ボックスを使って、ロール (アクセス許可) の割り当て対象のリソース グループを検索してそこに移動する方法を示すスクリーンショット。
リソース グループのページで、左側のメニューから [アクセス制御 (IAM)] を選択します。 アクセス制御 (IAM) メニュー項目の場所を示すリソース グループ ページのスクリーンショット。
[アクセス制御 (IAM)] ページで、次の操作を行います。
  1. [ロールの割り当て] タブを選択します。
  2. 上部のメニューから [+ 追加] を選択し、次に結果のドロップダウン メニューから [ロールの割り当ての追加] を選択します。
[ロールの割り当て] タブへの移動方法と、ロールの割り当てをリソース グループに追加するボタンの場所を示すスクリーンショット。
[ロールの割り当ての追加] ページには、リソース グループで割り当てることができるすべてのロールが一覧表示されます。
  1. 検索ボックスを使用して、より管理しやすいサイズにリストをフィルター処理します。 この例では、Storage BLOB ロールをフィルター処理する方法を示します。
  2. 割り当てるロールを選択します。
[次へ] を選択して、次の画面に進みます。
リソース グループに追加するロールの割り当てを見つけるためにフィルター処理して選択する方法を示すスクリーンショット。
次の [ロールの割り当ての追加] ページでは、ロールを割り当てるユーザーを指定できます。
  1. [アクセスの割り当て先] で、[ユーザー、グループ、またはサービス プリンシパル] を選択します。
  2. [メンバー][+ メンバーの選択] を選択します。
Azure portal の右側にダイアログ ボックスが開きます。
Microsoft Entra グループにロールを割り当てる際に選択するラジオ ボタンと、ロールを割り当てるグループを選択する際に使用されるリンクを示すスクリーンショット。
[メンバーの選択] ダイアログで、次の操作を行います。
  1. [選択] テキスト ボックスを使用して、サブスクリプション内のユーザーとグループの一覧をフィルター処理できます。 必要に応じて、アプリ用に作成したサービス プリンシパルの最初の数文字を入力して、一覧をフィルター処理します。
  2. アプリケーションに関連付けられているサービス プリンシパルを選択します。
ダイアログの下部にある [選択] を選択して続行します。
「メンバーの選択」ダイアログ ボックスでアプリケーションの Microsoft Entra グループをフィルター処理し選択する方法を示すスクリーンショット。
[ロールの割り当ての追加] 画面で、サービス プリンシパルが選択済みとして表示されるようになりました。

[レビューと割り当て] を選択して最終ページに移動し、もう一度レビューと割り当てを行ってプロセスを完了します。
完了した [ロールの割り当ての追加] ページと、プロセスを完了するために使用する [レビューと割り当て] ボタンの場所を示すスクリーンショット。

3 - アプリケーションの環境変数を構成する

DefaultAzureCredential オブジェクトでは、実行時に一連の環境変数でサービス プリンシパルの資格情報が検索されます。 .NET を使用する場合、ツールと環境に応じて、複数の方法で環境変数を構成できます。

どの方法を選ぶかに関わらず、サービス プリンシパルを使う場合は、次の環境変数を構成します。

  • AZURE_CLIENT_ID → アプリ ID の値です。
  • AZURE_TENANT_ID → テナント ID の値です。
  • AZURE_CLIENT_SECRET →アプリ用に生成されたパスワード/資格情報。

アプリが IIS でホストされている場合は、アプリ プールごとに環境変数を設定し、アプリ間で設定を分離することをお勧めします。

appcmd.exe set config -section:system.applicationHost/applicationPools /+"[name='Contoso'].environmentVariables.[name='ASPNETCORE_ENVIRONMENT',value='Production']" /commit:apphost
appcmd.exe set config -section:system.applicationHost/applicationPools /+"[name='Contoso'].environmentVariables.[name='AZURE_CLIENT_ID',value='00000000-0000-0000-0000-000000000000']" /commit:apphost
appcmd.exe set config -section:system.applicationHost/applicationPools /+"[name='Contoso'].environmentVariables.[name='AZURE_TENANT_ID',value='11111111-1111-1111-1111-111111111111']" /commit:apphost
appcmd.exe set config -section:system.applicationHost/applicationPools /+"[name='Contoso'].environmentVariables.[name='AZURE_CLIENT_SECRET',value='=abcdefghijklmnopqrstuvwxyz']" /commit:apphost

これらの設定は、applicationHost.config ファイル内の applicationPools 要素を使って直接構成することもできます。

<applicationPools>
   <add name="CorePool" managedRuntimeVersion="v4.0" managedPipelineMode="Classic">
      <environmentVariables>
         <add name="ASPNETCORE_ENVIRONMENT" value="Development" />
         <add name="AZURE_CLIENT_ID" value="00000000-0000-0000-0000-000000000000" />
         <add name="AZURE_TENANT_ID" value="11111111-1111-1111-1111-111111111111" />
         <add name="AZURE_CLIENT_SECRET" value="=abcdefghijklmnopqrstuvwxyz" />
      </environmentVariables>
   </add>
</applicationPools>

4 - アプリケーションに DefaultAzureCredential を実装する

DefaultAzureCredential は、Microsoft Entra に対して認証を行うための、厳格かつ順序付けされたメカニズムのシーケンスです。 それぞれの認証メカニズムは、TokenCredential クラスから派生したクラスであり、credential と呼ばれます。 実行時に、DefaultAzureCredential は最初の資格情報を使用して認証を試みます。 その資格情報がアクセス トークンの取得に失敗した場合は、アクセス トークンが正常に取得されるまで、シーケンス内の次の資格情報が試行されます。 これにより、アプリは環境固有のコードを記述することなく、異なる環境で異なる資格情報を使用できます。

DefaultAzureCredential によって資格情報が検索される順序と場所は、DefaultAzureCredential にあります。

DefaultAzureCredential を使用するには、Azure.Identity と、必要に応じて Microsoft.Extensions.Azure パッケージをアプリケーションに追加します。

選択したターミナルで、アプリケーション プロジェクト ディレクトリに移動し、次のコマンドを実行します。

dotnet add package Azure.Identity
dotnet add package Microsoft.Extensions.Azure

Azure サービスには、さまざまな Azure SDK クライアント ライブラリの特殊なクライアント クラスを使用してアクセスします。 これらのクラスと独自のカスタム サービスは、アプリ全体で依存関係の挿入を介してアクセスできるように登録する必要があります。 Program.cs で、次の手順を実行してクライアント クラスと DefaultAzureCredential を登録します。

  1. using ディレクティブを介して Azure.IdentityMicrosoft.Extensions.Azure 名前空間を含めます。
  2. Add というプレフィックスが付いた、対応する拡張メソッドを使用して、Azure サービス クライアントを登録します。
  3. UseCredential メソッドに DefaultAzureCredential のインスタンスを渡します。

次に例を示します。

using Microsoft.Extensions.Azure;
using Azure.Identity;

builder.Services.AddAzureClients(clientBuilder =>
{
    clientBuilder.AddBlobServiceClient(
        new Uri("https://<account-name>.blob.core.windows.net"));
    clientBuilder.UseCredential(new DefaultAzureCredential());
});

UseCredential の代わりに、DefaultAzureCredential を直接インスタンス化します。

using Azure.Identity;

builder.Services.AddSingleton<BlobServiceClient>(_ =>
    new BlobServiceClient(
        new Uri("https://<account-name>.blob.core.windows.net"),
        new DefaultAzureCredential()));

上記のコードがローカル開発ワークステーションで実行されている場合、アプリケーション サービス プリンシパルの環境変数、または Visual Studio などのローカルにインストールされた開発者ツールで、開発者資格情報のセットが検索されます。 どちらの方法も、ローカル開発中に Azure リソースに対してアプリを認証するために使用できます。

Azure にデプロイすると、この同じコードで、アプリを他の Azure リソースに対して認証することもできます。 DefaultAzureCredential では、環境設定とマネージド ID 構成を取得し、他のサービスに対して自動的に認証することができます。