オンプレや他クラウド上の Windows サーバーを Azure Arc で管理しつつ、IIS アプリから Azure Key Vault のシークレットを安全に取得したい──そのときにつまずきやすい「CLI では取れるのに IIS からは取れない」問題を、仕組みから具体的な解決手順まで詳しく解説します。
Azure Arc + Windows サーバー + IIS + Azure Key Vault でよくあるハマりどころ
Azure Arc 対応サーバー(Azure Arc enabled server)上で動いている Windows サーバーに対して、運用担当者が Azure CLI を使って az keyvault secret show などを実行すると、Azure Key Vault から問題なくシークレットを取得できるケースは多くあります。
ところが、同じサーバー上で稼働している IIS アプリケーションから、Azure SDK for .NET(C#) を使って同じ Key Vault のシークレットを取得しようとすると、認証エラーやタイムアウトで取得できない、という事象が少なくありません。
このとき多くの管理者が疑問に思うのが次の点です。
- Azure Arc でオンボードしたサーバーでは、Azure 仮想マシン(Azure VM)と違う特別な設定が必要なのか?
- IIS のアプリケーション プールだけが Key Vault にアクセスできないのはなぜか?
- マネージド ID 自体は有効なはずなのに、アプリからだけ失敗する理由は?
結論から言えば、Azure Arc サーバーでも Azure VM と同様にマネージド ID が利用可能であり、問題の正体は「どのローカル アカウントが Arc エージェントの ID エンドポイントを叩けるか」にあります。この記事では、その仕組みと具体的な対処方法を分かりやすく整理します。
Azure Arc サーバーとマネージド ID の仕組み
まずは Azure Arc 対応サーバーのマネージド ID 周りの仕組みを確認します。ここを押さえておくと、IIS から Key Vault にアクセスできない理由が自然と見えてきます。
Azure Arc サーバーにもシステム割当てマネージド ID が付与される
Azure Arc でオンボードした Windows サーバーは、Azure 上では 「接続マシン(connected machine)」リソースとして扱われます。このリソースに対して、通常の Azure VM と同じように システム割当てマネージド ID(System-assigned Managed Identity) を有効化できます。
システム割当てマネージド ID が有効な Arc サーバーでは、Arc エージェントが次のような動きをします。
http://localhost:40342に IMDS 互換のローカル エンドポイントを公開する- プロセスから参照できるように、以下のような環境変数を設定する
IDENTITY_ENDPOINTIDENTITY_HEADERIDENTITY_SERVER_THUMBPRINTなど
- アプリからのトークン要求を受け取り、Azure AD からアクセストークンを取得して返す
.NET アプリで DefaultAzureCredential を利用している場合、このローカル エンドポイントに自動的にアクセスし、Key Vault などの Azure リソースにアクセスするためのトークンを取得します。
Azure VM と Azure Arc サーバーの違い
システム割当てマネージド ID が利用できる、という意味では Azure VM と Azure Arc サーバーはよく似ています。ただし、エンドポイントの実装や許可されるローカル アカウント周りで細かな違いがあります。
| 項目 | Azure VM | Azure Arc 対応サーバー |
|---|---|---|
| リソース種別 | Virtual Machine | Connected Machine(Arc enabled server) |
| マネージド ID 対応 | システム/ユーザー割当て | 主にシステム割当て |
| ローカル エンドポイント | http://169.254.169.254/metadata/identity/… | http://localhost:40342/metadata/identity/… |
| トークン要求の制御 | 主にネットワークと VM 内のコンテキストで制御 | ローカル グループ(後述)でアクセス可能アカウントを制御 |
| 運用イメージ | Azure 上の VM | オンプレ/他クラウド上のサーバーを Azure から管理 |
このように、Azure Arc でもマネージド ID による Key Vault への安全なアクセスは可能です。ただし「どのローカル アカウントからトークン要求を行えるか」という点は Azure VM よりも意識する必要があります。
なぜ Azure CLI では取れるのに IIS からは取れないのか
今回の問題の核心は、Azure CLI を実行しているユーザーと、IIS アプリを実行しているアカウントが違うという点にあります。
Azure CLI が成功する理由
Arc サーバーにログオンしている管理者が Azure CLI で次のようなコマンドを実行した場合を考えます。
az login
az keyvault secret show `
--vault-name <vault-name> `
--name MySecret
このとき、CLI が利用している認証は次のようなパターンになります。
- 管理者本人の Azure AD ユーザーでログインしている
- その Azure AD ユーザーに Key Vault へのアクセス権限(RBAC またはアクセスポリシー)が付与されている
- 結果として、Key Vault のシークレットを問題なく取得できる
つまり、CLI の成功は「Arc サーバーのマネージド ID が正しく動いている」ことを示しているとは限らず、単に人間のユーザーに十分な権限があるというだけの場合も多いのです。
IIS アプリケーション プールが失敗する理由
一方、IIS アプリケーションから以下のような C# コードで Key Vault にアクセスするケースを考えます。
var client = new SecretClient(
new Uri("https://<vault-name>.vault.azure.net/"),
new DefaultAzureCredential());
KeyVaultSecret secret = await client.GetSecretAsync("MySecret");
string value = secret.Value;
このコードは DefaultAzureCredential を使っているため、Arc サーバー環境であれば通常、マネージド ID を利用した認証が試みられます。ここで重要になるのが、どの Windows アカウントでこのコードが実行されているかです。
IIS では、アプリケーション プールごとに「ID(Identity)」が設定されており、既定では次のような構成になっています。
| 項目 | 例 |
|---|---|
| アプリケーション プール名 | MyAppPool |
| アプリケーション プール ID | ApplicationPoolIdentity または専用のドメイン アカウント(例: CONTOSO\svc-iis-app) |
| 実際のログオン アカウント | 上記の ID に対応する OS 上のユーザー |
問題となるのは、このアプリケーション プールの ID が、後述する「Hybrid agent extension applications」ローカル グループのメンバーになっていない点です。
トークン取得を許可されるローカル グループが鍵
Azure Arc エージェントは、誰でもローカル エンドポイントにアクセスしてトークンを取得できるようには設計されていません。セキュリティの観点から、次のいずれかの条件を満たしたアカウントだけが、ID エンドポイントへの認証チャレンジを完了できるようになっています。
- ローカル Administrators グループのメンバー
- Hybrid agent extension applications ローカル グループのメンバー
つまり、Arc エージェントの ID エンドポイントに対してトークン要求を行い、Key Vault 用のアクセストークンを取得できるのは、上記のグループに属するアカウントのみです。
| アカウント種別 | 典型的な例 | デフォルトの状態 | トークン取得可否 |
|---|---|---|---|
| ローカル管理者 | SERVER01\Administrator | Administrators グループに所属 | 取得可能 |
| ドメイン管理者 | CONTOSO\AdminUser | Administrators に追加されていれば可 | 多くの環境で取得可能 |
| IIS アプリ プール専用アカウント | CONTOSO\svc-iis-app | 通常はどのローカル グループにも属さない | デフォルトでは取得不可 |
| 仮想アカウント | IIS APPPOOL\MyAppPool | 最小権限で実行 | 取得不可 |
このため、IIS アプリケーション プールの ID が Hybrid agent extension applications グループに所属していなければ、マネージド ID 用のトークン取得に失敗し、その結果として Key Vault へのアクセスも失敗します。
解決策の全体像
以上を踏まえると、Azure Arc でオンボードした Windows サーバー上の IIS アプリから Azure Key Vault のシークレットを取得するために必要な対処は、以下の 4 ステップに整理できます。
| ステップ | 目的 | ポイント |
|---|---|---|
| 1. Arc マシンのマネージド ID を確認 | Arc リソース側の ID 設定を確認 | システム割当て ID が有効かどうかを確認 |
| 2. Key Vault への権限を付与 | マネージド ID に適切な RBAC/アクセス許可を付与 | 原則として Azure RBAC(Key Vault Secrets User)を推奨 |
| 3. IIS アプリ プール ID を Hybrid agent extension applications に追加 | IIS アプリの実行アカウントからトークンを取得できるようにする | サービス アカウントのみを最小限追加する |
| 4. アプリ側で Azure SDK を適切に利用 | DefaultAzureCredential などでマネージド ID を利用 | Azure.Identity の最新バージョンを利用 |
以下、各ステップを具体的なコマンドやコード例とともに詳しく見ていきます。
ステップ 1:Arc マシンのマネージド ID を確認する
まず、対象となる Azure Arc 対応サーバーのマネージド ID の状態を Azure CLI で確認します。
az connectedmachine show `
--name <マシン名> `
--resource-group <リソースグループ名> `
--query identity
出力例イメージ:
{
"principalId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"tenantId": "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy",
"type": "SystemAssigned"
}
typeがSystemAssignedになっていることを確認します。principalIdは、この Arc マシンのマネージド ID に対応するサービス プリンシパルの ID です。
ここで ID が無効になっている場合は、ポータルまたは CLI からシステム割当てマネージド ID を有効化してください。
ステップ 2:Key Vault に対して Arc マシンの ID に権限を付与する
次に、Arc サーバーのマネージド ID が Azure Key Vault のシークレットにアクセスできるように権限を付与します。
推奨:Azure RBAC(Key Vault Secrets User ロール)を利用
現在のベストプラクティスとしては、Key Vault へのアクセス制御もAzure RBAC を利用する方法が推奨されています。Key Vault リソース、または必要に応じてリソース グループ/サブスクリプション単位で、次のロールを割り当てます。
- ロール名:Key Vault Secrets User
- 割り当て先:Arc マシンのマネージド ID(
principalIdを持つサービス プリンシパル)
これにより、その Arc サーバー上で動作するマネージド ID 対応アプリケーションは、Key Vault のシークレットを取得できるようになります。
旧方式:Key Vault のアクセスポリシーを利用する場合
レガシーな構成や特定要件により、Key Vault のアクセスポリシーを利用している場合は、Arc マシンのマネージド ID に対して少なくとも以下の権限を付与します。
- Secrets の
get - 必要に応じて
list
ただし、新規構成や再設計のタイミングでは Azure RBAC への移行を検討することをおすすめします。
ステップ 3:IIS アプリケーション プール ID を Hybrid agent extension applications に追加
ここが今回の問題の「本丸」です。IIS アプリケーション プールの実行アカウントを、Arc エージェントの ID エンドポイントにアクセス可能なローカル グループに所属させる必要があります。
現在のアプリケーション プール ID を確認する
IIS マネージャーから GUI で確認することもできますが、PowerShell や appcmd.exe を使って確認するとスクリプト化しやすくなります。
Import-Module WebAdministration
# アプリケーション プールの ID を確認
Get-ItemProperty "IIS:\AppPools\MyAppPool" -Name processModel.identityType, processModel.userName
出力イメージ:
processModel.identityType : SpecificUser
processModel.userName : CONTOSO\svc-iis-app
ここで、実行アカウント(例:CONTOSO\svc-iis-app)を控えておきます。もし ApplicationPoolIdentity になっている場合は、Arc エージェントとの連携を考えると専用のドメイン アカウントやマネージド サービスアカウントを設定する方が管理しやすいケースが多いでしょう。
Hybrid agent extension applications ローカル グループに追加する
次に、控えておいたサービス アカウントを Arc エージェント用のローカル グループに追加します。管理者権限の PowerShell で以下を実行します。
Add-LocalGroupMember `
-Group "Hybrid agent extension applications" `
-Member "CONTOSO\svc-iis-app"
グループ名は環境によってはローカライズされている場合がありますが、一般的には上記の英語名になっています。グループ名が不明な場合は次のようにしてローカル グループを一覧表示し、名前を確認します。
Get-LocalGroup | Where-Object Name -like "*Hybrid*"
グループへの追加が完了したら、次のいずれかを行います。
- 対象アプリケーション プールのみを再起動する
Restart-WebAppPool -Name "MyAppPool" - 環境によっては IIS 全体を再起動する
iisreset
これで、IIS アプリケーション プールの実行アカウントが Arc エージェントの ID エンドポイントにアクセスできるようになり、マネージド ID を用いたトークン取得が可能になります。
最小権限の考え方
セキュリティ上、Hybrid agent extension applications グループに追加するアカウントは本当に必要なサービス アカウントだけに絞ることが重要です。
| アカウント | グループ追加の是非 | 理由 |
|---|---|---|
| ドメイン管理者アカウント | 追加すべきではない | そもそも管理者として十分な権限を持っており、ID エンドポイントアクセスのために追加する必要はない |
| 特定の IIS アプリ プール用サービス アカウント | 必要に応じて追加 | Key Vault へアクセスするアプリのみを厳選して追加する |
| 一般ユーザー アカウント | 追加しない | ID エンドポイントへの不必要なアクセスリスクを増やすだけになる |
ステップ 4:アプリ側で Azure SDK を適切に利用する
最後に、IIS 上のアプリケーション側の実装です。基本的には Azure SDK for .NET の DefaultAzureCredential を素直に利用すれば問題ありませんが、いくつか注意点があります。
C# コード例(.NET 6 以降/.NET Framework 4.8 など)
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
// Key Vault の URL
var vaultUri = new Uri("https://<vault-name>.vault.azure.net/");
// DefaultAzureCredential は Arc 環境ではマネージド ID を自動的に利用
var credential = new DefaultAzureCredential();
var client = new SecretClient(vaultUri, credential);
// 非同期でシークレット取得
KeyVaultSecret secret = await client.GetSecretAsync("MySecret");
string secretValue = secret.Value;
ポイントは以下の通りです。
Azure.Identityパッケージを最新の安定版にしておくDefaultAzureCredentialをそのまま利用し、個別のManagedIdentityCredentialなどをカスタマイズしない(基本は不要)- Key Vault の URL(
https://<vault-name>.vault.azure.net/)を間違えない
構成ファイルでの設定例(接続先 Key Vault を変更しやすくする)
アプリケーション設定ファイル(appsettings.json など)で Key Vault 名を持たせておくと、ステージング/本番などの環境ごとに切り替えやすくなります。
{
"KeyVault": {
"Name": "<vault-name>"
}
}
コード側:
var keyVaultName = configuration["KeyVault:Name"];
var vaultUri = new Uri($"https://{keyVaultName}.vault.azure.net/");
var client = new SecretClient(vaultUri, new DefaultAzureCredential());
トラブルシューティング:それでも取得できないときに確認するポイント
上記の構成を行っても Key Vault からシークレットを取得できない場合、次のポイントを順番に確認していくと原因を切り分けやすくなります。
1. ID エンドポイントに直接アクセスしてみる
IIS アプリと同じアカウント(サービス アカウントなど)で PowerShell を実行し、Arc エージェントの ID エンドポイントに直接アクセスしてみます。疑似的にトークン取得を試すことで、ネットワークレベルの問題か、権限の問題かを切り分けられます。
$env:IDENTITY_ENDPOINT
$env:IDENTITY_HEADER
# リソースとして Key Vault を指定してトークン要求
$tokenResponse = Invoke-WebRequest `
-Uri "$env:IDENTITY_ENDPOINT?resource=https://vault.azure.net" `
-Headers @{ "X-IDENTITY-HEADER" = $env:IDENTITY_HEADER } `
-Method GET
$tokenResponse.StatusCode
$tokenResponse.Content
- HTTP 200 が返り、JSON にアクセストークンが含まれていればトークン取得は成功しています。
- 401 や 403 などが返る場合は、Hybrid agent extension applications へのグループ追加や、環境変数の有効範囲を再確認します。
2. Key Vault 側のログを確認する
Key Vault に対して診断ログを有効化している場合は、アクセス拒否や認証失敗のイベントを確認します。
- どのプリンシパル(マネージド ID)がアクセスしようとしているか
- どの操作(シークレットの
get/listなど)が拒否されているか
これにより、Arc マシンのマネージド ID そのものに Key Vault への権限が不足しているのか、あるいは別の問題なのかを切り分けることができます。
3. Azure AD 監査ログでマネージド ID の動きを確認する
マネージド ID による認証は Azure AD の監査ログにも記録されます。Key Vault へのアクセスが発生しているかを確認することで、少なくとも Azure AD までトークン要求が届いているかどうかを判断できます。
4. アプリ側の例外メッセージを丁寧に読む
Azure SDK が返す例外メッセージには、原因を特定するヒントが含まれていることが多くあります。例えば、次のようなパターンです。
| メッセージの傾向 | 想定される原因 |
|---|---|
| 「Managed Identity endpoint is not available」系 | ID エンドポイントに到達できていない/環境変数が設定されていない |
| 「Authentication failed」系 | マネージド ID に Key Vault への権限がない、もしくは Hybrid agent extension applications グループに所属していない |
| 「A connection attempt failed because…」系 | ローカルファイアウォールやプロキシ設定、Arc エージェント自体の不具合 |
実際の解決事例の流れ
最後に、冒頭のケースと同様の状況で実際に行った解決手順を、時系列で整理しておきます。
- Arc 対応サーバー上で管理者が Azure CLI から Key Vault シークレットを取得したところ、問題なく取得可能だった。
- IIS 上の C# アプリからは、同じシークレット名を指定しても 401/403 エラーで取得に失敗した。
- Azure CLI が利用しているのは管理者本人の Azure AD ユーザーであることを確認し、これはマネージド ID とは異なることを再認識した。
- Arc リソースの
identityを確認し、システム割当てマネージド ID が有効であることを確認した。 - Key Vault に対して、Arc マシンのマネージド ID に「Key Vault Secrets User」ロールを割り当てた。
- IIS のアプリケーション プールの ID が
CONTOSO\svc-iis-appという専用アカウントであることを確認。 - そのアカウントを、PowerShell から
Hybrid agent extension applicationsローカル グループに追加。 - アプリケーション プールを再起動し、再度アプリから Key Vault へのアクセスを実行したところ、シークレット取得に成功。
このように、IIS アプリ プールのサービス アカウントを Hybrid agent extension applications グループに追加することで、Arc サーバー上の IIS アプリからも Azure Key Vault のシークレットを正常に取得できるようになりました。
セキュリティと運用のベストプラクティス
最後に、Azure Arc + IIS + Key Vault 構成を運用するうえで意識しておきたいポイントをまとめます。
1. マネージド ID の利用を徹底する
- アプリケーションにクライアントシークレットや証明書のパスワードを埋め込まない
- Key Vault へのアクセスは可能な限りマネージド ID 経由とし、ID 設定は Azure 側で管理する
2. 最小権限の原則を守る
- Key Vault のロール割り当ては必要な Scope(Key Vault 単体など)に絞る
- Hybrid agent extension applications グループには、Key Vault にアクセスするサービス アカウントのみを追加する
3. ログと監査を有効にしておく
- Key Vault の診断ログを有効にし、アクセス状況を定期的に確認する
- Azure AD 監査ログでマネージド ID の利用状況をチェックする
4. ドキュメント化とナレッジ共有
- Arc サーバー固有のポイント(Hybrid agent extension applications グループなど)をチーム内でドキュメント化して共有する
- 新規に IIS アプリを配置する際のチェックリストに「サービス アカウントのグループ追加」を含めておく
まとめ:Azure Arc サーバーから IIS アプリで Key Vault を使いこなす
Azure Arc でオンボードした Windows サーバーから Azure Key Vault のシークレットを IIS アプリケーションで取得できない問題は、一見すると「Arc 特有の複雑な制限」に見えるかもしれません。しかし、仕組みを分解してみると実態は次の 3 点に集約されます。
- Arc サーバーにもシステム割当てマネージド ID が付与され、ローカルの ID エンドポイントからトークン取得ができる。
- トークン取得を行えるのは、Administrators または Hybrid agent extension applications ローカル グループに属するアカウントだけである。
- IIS アプリケーション プールのサービス アカウントは、既定ではこのグループに属していないため、マネージド ID を利用できない。
したがって、IIS アプリ プールのサービス アカウントを Hybrid agent extension applications グループへ追加し、Arc マシンのマネージド ID に Key Vault の権限を割り当てることで、Azure Arc サーバー上でも Azure VM と同じように、セキュアかつシンプルに Key Vault のシークレットを取得できるようになります。
オンプレ/他クラウドの Windows サーバーを Azure Arc で一元管理している環境では、このパターンを標準化しておくことで、新しい IIS アプリケーションの展開や既存アプリのクラウド連携をスムーズに進めることができるでしょう。

コメント