Azure VM 上で Azure リソースのマネージド ID を使用してアクセス トークンを取得する方法
Azure リソース用マネージド ID は、Microsoft Entra ID の機能です。 Azure リソースのマネージド ID をサポートする各 Azure サービスは、それぞれ固有のタイムラインの下で提供されます。 ご利用のリソースに対するマネージド ID の提供状態と既知の問題をあらかじめ確認しておいてください。
Azure リソースのマネージド ID は、Microsoft Entra ID で自動的に管理される ID を Azure サービスに提供します。 この ID を使用すると、コード内に資格情報を記述することなく、Microsoft Entra の認証をサポートする任意のサービスに対して認証を行うことができます。
この記事では、トークンの取得に使用する各種コードとスクリプトの例を提供します。 また、トークンの有効期限や HTTP エラーの処理についてのガイダンスも提供します。
前提条件
- Azure リソースのマネージド ID 機能に慣れていない場合は、こちらの概要を参照してください。 Azure アカウントをお持ちでない場合は、無料のアカウントにサインアップしてから先に進んでください。
この記事の Azure PowerShell の例を使用する場合は、Azure PowerShell の最新バージョンをインストールする必要があります。
重要
- この記事のすべてのサンプル コード/スクリプトは、Azure リソースのマネージド ID を使用する仮想マシン上でクライアントが実行されていることを前提としています。 お使いの VM にリモート接続するには、Azure portal で仮想マシンへの "接続" 機能を使用します。 VM で Azure リソースのマネージド ID を有効にする方法の詳細については、「Azure Portal を使用して VM 上に Azure リソースのマネージド ID を構成する」、または関連する記事 (PowerShell、CLI、テンプレート、または Azure SDK の使用) のいずれかを参照してください。
重要
- Azure リソース用マネージド ID のセキュリティ境界は、ID が使われているリソースです。 仮想マシン上で実行されるすべてのコード/スクリプトは、そこで使用できる任意のマネージド ID のトークンを要求して取得できます。
概要
クライアント アプリケーションは、特定のリソースにアクセスするために、マネージド ID のアプリ専用アクセス トークンを要求できます。 トークンは、Azure リソース サービス プリンシパルのマネージド ID に基づいています。 そのため、クライアントが、独自のサービス プリンシパルでアクセス トークンを取得する必要はありません。 トークンは、クライアント資格情報を必要とするサービス間の呼び出しのベアラー トークンとしての使用に適しています。
Link | 説明 |
---|---|
HTTP を使用してトークンを取得する | Azure リソース トークン エンドポイントのマネージド ID に関するプロトコルの詳細 |
Azure.Identity を使用してトークンを取得する | Azure.Identity ライブラリを使用してトークンを取得する |
.NET 用の Microsoft.Azure.Services.AppAuthentication ライブラリを使用してトークンを取得する | .NET クライアントからの Microsoft.Azure.Services.AppAuthentication ライブラリの使用例 |
C# を使用してトークンを取得する | C# クライアントから Azure リソース REST エンドポイントのマネージド ID を使用する例 |
Java を使用してトークンを取得する | Java クライアントから Azure リソース REST エンドポイントのマネージド ID を使用する例 |
Go を使用してトークンを取得する | Go クライアントから Azure リソース REST エンドポイントのマネージド ID を使用する例 |
PowerShell を使用してトークンを取得する | PowerShell クライアントから Azure リソース REST エンドポイントのマネージド ID を使用する例 |
CURL を使用してトークンを取得する | Bash/CURL クライアントから Azure リソース REST エンドポイントのマネージド ID を使用する例 |
トークンのキャッシュの処理 | 有効期限が切れたアクセス トークンの処理に関するガイダンス |
エラー処理 | Azure リソース トークン エンドポイントのマネージド ID から返される HTTP エラーを処理するためのガイダンス |
Azure サービスのリソース ID | サポートされている Azure サービスのリソース ID を取得する場所 |
HTTP を使用してトークンを取得する
アクセス トークンの取得に使用する基本的なインターフェイスは REST に基づいているため、HTTP REST の呼び出しを行える VM 上で実行されている、すべてのクライアント アプリケーションにアクセスできます。 この方法は、クライアントが仮想マシン上のエンドポイントを使用する点以外は、Microsoft Entra のプログラミング モデルと同じです (Microsoft Entra のプログラミング モデルでは、Microsoft Entra エンドポイントを使用)。
Azure Instance Metadata Service (IMDS) エンドポイントを使用するサンプル要求 (推奨) :
GET 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/' HTTP/1.1 Metadata: true
要素 | 説明 |
---|---|
GET |
HTTP 動詞。エンドポイントからデータを取得する必要があることを示します。 この例では、OAuth アクセス トークンです。 |
http://169.254.169.254/metadata/identity/oauth2/token |
Instance Metadata Service 用の Azure リソース エンドポイントのマネージド ID。 |
api-version |
クエリ文字列パラメーター。IMDS エンドポイントの API バージョンです。 API バージョン 2018-02-01 以上を使用してください。 |
resource |
クエリ文字列パラメーター。ターゲット リソースのアプリ ID URI です。 発行されたトークンの aud (audience) 要求にも表示されます。 この例では、アプリ ID URI が https://management.azure.com/ の Azure Resource Manager にアクセスするためのトークンを要求しています。 |
Metadata |
マネージド ID に必要な HTTP 要求ヘッダー フィールド。 この情報は、サーバー側のリクエスト フォージェリ (SSRF) 攻撃に対する軽減策として使用されます。 この値は、"true" に設定し、すべて小文字にする必要があります。 |
object_id |
(省略可能) クエリの文字列パラメーター。トークン用の管理対象 ID の object_id を示します。 VM に複数のユーザーが割り当てたマネージド ID がある場合は必須です。 |
client_id |
(省略可能) クエリの文字列パラメーター。トークン用の管理対象 ID の client_id を示します。 VM に複数のユーザーが割り当てたマネージド ID がある場合は必須です。 |
msi_res_id |
(省略可能) クエリの文字列パラメーター。トークン用の管理対象 ID の msi_res_id (Azure リソース ID) を示します。 VM に複数のユーザーが割り当てたマネージド ID がある場合は必須です。 |
応答のサンプル:
HTTP/1.1 200 OK
Content-Type: application/json
{
"access_token": "eyJ0eXAi...",
"refresh_token": "",
"expires_in": "3599",
"expires_on": "1506484173",
"not_before": "1506480273",
"resource": "https://management.azure.com/",
"token_type": "Bearer"
}
要素 | 説明 |
---|---|
access_token |
要求されたアクセス トークン。 セキュリティで保護された REST API を呼び出すとき、トークンは Authorization 要求ヘッダー フィールドに "ベアラー" トークンとして埋め込まれ、API が呼び出し元を認証できるようにします。 |
refresh_token |
Azure リソースのマネージド ID には使用されません。 |
expires_in |
アクセス トークンが発行されてから期限切れになるまでの有効継続時間 (秒単位)。 発行時刻はトークンの iat 要求で確認できます。 |
expires_on |
アクセス トークンが期限切れになるまでの期間。 日付は "1970-01-01T0:0:0Z UTC" からの秒数として表されます (トークンの exp 要求に対応)。 |
not_before |
アクセス トークンが有効になり、承認されるまでの期間。 日付は "1970-01-01T0:0:0Z UTC" からの秒数として表されます (トークンの nbf 要求に対応)。 |
resource |
アクセス トークンの要求対象リソース。要求の resource クエリ文字列パラメーターと一致します。 |
token_type |
トークンの種類。つまり "ベアラー" アクセス トークン。リソースが、このトークンのベアラーへのアクセスを提供できることを意味します。 |
Azure ID クライアント ライブラリを使用してトークンを取得する
マネージド ID を使用するには、Azure ID クライアント ライブラリを使用する方法をお勧めします。 すべての Azure SDK は、DefaultAzureCredential のサポートを提供する Azure.Identity
ライブラリと統合されています。 このクラスを使用すると、Azure SDK でマネージド ID を簡単に使用できます。詳細については、こちらを参照してください。
Azure.Identity パッケージと、Azure.Security.KeyVault.Secrets などの他の必要な Azure SDK ライブラリ パッケージをインストールします。
下のサンプル コードを使用します。 トークンの取得について心配する必要はありません。 Azure SDK クライアントを直接使用できます。 このコードは、必要に応じてトークンを取得する方法を示すものです。
using Azure.Core; using Azure.Identity; string userAssignedClientId = "<your managed identity client Id>"; var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions { ManagedIdentityClientId = userAssignedClientId }); var accessToken = credential.GetToken(new TokenRequestContext(new[] { "https://vault.azure.net" })); // To print the token, you can convert it to string String accessTokenString = accessToken.Token.ToString(); //You can use the credential object directly with Key Vault client. var client = new SecretClient(new Uri("https://myvault.vault.azure.net/"), credential);
.NET 用の Microsoft.Azure.Services.AppAuthentication ライブラリを使用してトークンを取得する
.NET アプリケーションと Functions の場合、Azure リソースのマネージド ID を使用する最も簡単な方法は、Microsoft.Azure.Services.AppAuthentication パッケージを利用することです。 このライブラリを使用すると、開発用コンピューターでコードをローカルでテストすることもできます。 Visual Studio、Azure CLI、または Active Directory 統合認証のユーザー アカウントを使って、自分のコードをテストすることができます。 このライブラリでのローカル開発オプションについて詳しくは、Microsoft.Azure.Services.AppAuthentication のリファレンスに関するページをご覧ください。 このセクションでは、コードでライブラリを使い始める方法を示します。
Microsoft.Azure.Services.AppAuthentication および Microsoft.Azure.KeyVault NuGet パッケージに対する参照をアプリケーションに追加します。
次のコードをアプリケーションに追加します。
using Microsoft.Azure.Services.AppAuthentication; using Microsoft.Azure.KeyVault; // ... var azureServiceTokenProvider = new AzureServiceTokenProvider(); string accessToken = await azureServiceTokenProvider.GetAccessTokenAsync("https://management.azure.com/"); // OR var kv = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
Microsoft.Azure.Services.AppAuthentication およびそれによって公開される操作の詳細については、Microsoft.Azure.Services.AppAuthentication リファレンスと Azure リソースのマネージド ID を使用する App Service および KeyVault の .NET サンプルを参照してください。
C# を使用してトークンを取得する
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Web.Script.Serialization;
// Build request to acquire managed identities for Azure resources token
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/");
request.Headers["Metadata"] = "true";
request.Method = "GET";
try
{
// Call /token endpoint
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
// Pipe response Stream to a StreamReader, and extract access token
StreamReader streamResponse = new StreamReader(response.GetResponseStream());
string stringResponse = streamResponse.ReadToEnd();
JavaScriptSerializer j = new JavaScriptSerializer();
Dictionary<string, string> list = (Dictionary<string, string>) j.Deserialize(stringResponse, typeof(Dictionary<string, string>));
string accessToken = list["access_token"];
}
catch (Exception e)
{
string errorText = String.Format("{0} \n\n{1}", e.Message, e.InnerException != null ? e.InnerException.Message : "Acquire token failed");
}
Java を使用してトークンを取得する
Java を使用してトークンを取得するには、この JSON ライブラリを使用します。
import java.io.*;
import java.net.*;
import com.fasterxml.jackson.core.*;
class GetMSIToken {
public static void main(String[] args) throws Exception {
URL msiEndpoint = new URL("http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/");
HttpURLConnection con = (HttpURLConnection) msiEndpoint.openConnection();
con.setRequestMethod("GET");
con.setRequestProperty("Metadata", "true");
if (con.getResponseCode()!=200) {
throw new Exception("Error calling managed identity token endpoint.");
}
InputStream responseStream = con.getInputStream();
JsonFactory factory = new JsonFactory();
JsonParser parser = factory.createParser(responseStream);
while(!parser.isClosed()){
JsonToken jsonToken = parser.nextToken();
if(JsonToken.FIELD_NAME.equals(jsonToken)){
String fieldName = parser.getCurrentName();
jsonToken = parser.nextToken();
if("access_token".equals(fieldName)){
String accesstoken = parser.getValueAsString();
System.out.println("Access Token: " + accesstoken.substring(0,5)+ "..." + accesstoken.substring(accesstoken.length()-5));
return;
}
}
}
}
}
Go を使用してトークンを取得する
package main
import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
"encoding/json"
)
type responseJson struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
ExpiresIn string `json:"expires_in"`
ExpiresOn string `json:"expires_on"`
NotBefore string `json:"not_before"`
Resource string `json:"resource"`
TokenType string `json:"token_type"`
}
func main() {
// Create HTTP request for a managed services for Azure resources token to access Azure Resource Manager
var msi_endpoint *url.URL
msi_endpoint, err := url.Parse("http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01")
if err != nil {
fmt.Println("Error creating URL: ", err)
return
}
msi_parameters := msi_endpoint.Query()
msi_parameters.Add("resource", "https://management.azure.com/")
msi_endpoint.RawQuery = msi_parameters.Encode()
req, err := http.NewRequest("GET", msi_endpoint.String(), nil)
if err != nil {
fmt.Println("Error creating HTTP request: ", err)
return
}
req.Header.Add("Metadata", "true")
// Call managed services for Azure resources token endpoint
client := &http.Client{}
resp, err := client.Do(req)
if err != nil{
fmt.Println("Error calling token endpoint: ", err)
return
}
// Pull out response body
responseBytes,err := ioutil.ReadAll(resp.Body)
defer resp.Body.Close()
if err != nil {
fmt.Println("Error reading response body : ", err)
return
}
// Unmarshall response body into struct
var r responseJson
err = json.Unmarshal(responseBytes, &r)
if err != nil {
fmt.Println("Error unmarshalling the response:", err)
return
}
// Print HTTP response and marshalled response body elements to console
fmt.Println("Response status:", resp.Status)
fmt.Println("access_token: ", r.AccessToken)
fmt.Println("refresh_token: ", r.RefreshToken)
fmt.Println("expires_in: ", r.ExpiresIn)
fmt.Println("expires_on: ", r.ExpiresOn)
fmt.Println("not_before: ", r.NotBefore)
fmt.Println("resource: ", r.Resource)
fmt.Println("token_type: ", r.TokenType)
}
PowerShell を使用してトークンを取得する
次の例では、PowerShell クライアントから Azure リソース REST エンドポイントのマネージド ID を使用して、以下を実行する方法を示します。
- アクセス トークンを取得します。
- アクセス トークンを使用して Azure Resource Manager の REST API を呼び出し、VM に関する情報を取得します。
<SUBSCRIPTION-ID>
、<RESOURCE-GROUP>
、および<VM-NAME>
の代わりに、ご自分のサブスクリプション ID、リソース グループ名、および仮想マシン名をそれぞれ使用する必要があります。
Invoke-WebRequest -Uri 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fmanagement.azure.com%2F' -Headers @{Metadata="true"}
応答からアクセス トークンを解析する方法の例を次に示します。
# Get an access token for managed identities for Azure resources
$response = Invoke-WebRequest -Uri 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fmanagement.azure.com%2F' `
-Headers @{Metadata="true"}
$content =$response.Content | ConvertFrom-Json
$access_token = $content.access_token
echo "The managed identities for Azure resources access token is $access_token"
# Use the access token to get resource information for the VM
$vmInfoRest = (Invoke-WebRequest -Uri 'https://management.azure.com/subscriptions/<SUBSCRIPTION-ID>/resourceGroups/<RESOURCE-GROUP>/providers/Microsoft.Compute/virtualMachines/<VM-NAME>?api-version=2017-12-01' -Method GET -ContentType "application/json" -Headers @{ Authorization ="Bearer $access_token"}).content
echo "JSON returned from call to get VM info:"
echo $vmInfoRest
CURL を使用してトークンを取得する
curl 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fmanagement.azure.com%2F' -H Metadata:true -s
応答からアクセス トークンを解析する方法の例を次に示します。
response=$(curl 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fmanagement.azure.com%2F' -H Metadata:true -s)
access_token=$(echo $response | python -c 'import sys, json; print (json.load(sys.stdin)["access_token"])')
echo The managed identities for Azure resources access token is $access_token
トークンのキャッシュ
マネージド ID サブシステムによってトークンがキャッシュされますが、コードにトークン キャッシュを実装することをお勧めします。 リソースによってトークンの有効期限切れが示されるシナリオに備える必要があります。
ネットワークを介した Microsoft Entra ID の呼び出しは、次の場合にのみ行われます。
- Azure リソース サブシステム キャッシュのマネージド ID にトークンがないためキャッシュ ミスが発生する。
- キャッシュのトークンの有効期限が切れている。
エラー処理
マネージド ID エンドポイントは、HTTP 応答メッセージのヘッダーに含まれる状態コード フィールドを通じて、4xx エラーまたは 5xx エラーのいずれかとして、エラーを通知します。
状態コード | エラーの理由 | 処理方法 |
---|---|---|
404 見つかりません。 | IMDS エンドポイントが更新されています。 | 指数バックオフを使用して再試行してください。 以下のガイダンスを参照してください。 |
410 | IMDS は更新プログラムを実行しています | IMDS は 70 秒以内に使用可能になります |
429 要求が多すぎます。 | IMDS スロットルの上限に達しました。 | 指数バックオフを使用して再試行してください。 以下のガイダンスを参照してください。 |
要求の 4xx エラーです。 | 1 つ以上の要求パラメーターが正しくありませんでした。 | 再試行しないでください。 詳しくは、エラーの詳細を確認します。 4xx エラーは、デザイン時のエラーです。 |
サービスからの 5xx の一時的なエラーです。 | Azure リソース サブシステムまたは Microsoft Entra ID のマネージド ID から一時的なエラーが返されました。 | 少なくとも 1 秒間待機した後に、安全に再試行できます。 再試行が早すぎる場合や再試行の回数が多すぎる場合は、IMDS および Microsoft Entra ID からレート制限エラー (429) が返されることがあります。 |
タイムアウト | IMDS エンドポイントが更新されています。 | 指数バックオフを使用して再試行してください。 以下のガイダンスを参照してください。 |
エラーが発生すると、対応する HTTP 応答本文に、JSON とエラーの詳細が含まれます。
要素 | 説明 |
---|---|
error | エラー識別子。 |
error_description | エラーの詳細な説明。 エラーの説明は、予告なく変更になる場合があります。 エラーの説明に含まれる値に基づいて分岐するコードを作成しないでください。 |
HTTP 応答リファレンス
このセクションでは、想定されるエラー応答について説明します。 "200 OK" の状態は成功応答であり、access_token 要素内の応答本文の JSON にアクセス トークンが含まれています。
status code | エラー | エラーの説明 | 解決策 |
---|---|---|---|
400 Bad Request | invalid_resource | AADSTS50001: <URI> という名前のアプリケーションが <TENANT-ID> という名前のテナントに見つかりませんでした。 このメッセージは、テナント管理者がアプリケーションをインストールしていない場合、またはテナント ユーザーが同意していない場合に表示されます。 間違ったテナントに認証要求を送信した可能性があります。\ | (Linux のみ) |
400 Bad Request | bad_request_102 | 必要なメタデータ ヘッダーが指定されていません | 要求で Metadata 要求ヘッダー フィールドが見つからないか、形式が正しくありません。 値は true として指定し、すべて小文字にする必要があります。 例については、上記の「REST」セクションの「要求のサンプル」を参照してください。 |
401 権限がありません | unknown_source | 不明なソース <URI> | HTTP GET 要求の URI の形式が正しいことを確認します。 scheme:host/resource-path 部分は、http://localhost:50342/oauth2/token として指定する必要があります。 例については、上記の「REST」セクションの「要求のサンプル」を参照してください。 |
invalid_request | 要求に必要なパラメーターが含まれていないか、要求に無効なパラメーター値が含まれているか、要求に複数回パラメーターが含まれているか、要求の形式が正しくないかのいずれかです。 | ||
unauthorized_client | クライアントには、このメソッドを使用してアクセス トークンを要求する権限がありません。 | Azure リソースのマネージド ID が正しく構成されていない VM での要求が原因です。 VM の構成についてサポートが必要な場合は、「Azure portal を使用して VM 上に Azure リソースのマネージド ID を構成する」を参照してください。 | |
access_denied | リソース所有者または承認サーバーによって、要求が拒否されました。 | ||
unsupported_response_type | このメソッドを使用したアクセス トークンの取得は、承認サーバーによってサポートされていません。 | ||
invalid_scope | 要求されたスコープが無効、不明、または形式が正しくありません。 | ||
500 内部サーバー エラー | unknown | Active Directory からのトークンの取得に失敗しました。 詳細については、<file path> のログを参照してください | VM で、Azure リソースのマネージド ID が有効になっていることを確認します。 VM の構成についてサポートが必要な場合は、「Azure portal を使用して VM 上に Azure リソースのマネージド ID を構成する」を参照してください。 また、HTTP GET 要求の URI、特にクエリ文字列で指定されたリソース URI の形式が正しいかどうかを確認します。 例については、上記の「REST」セクションの「要求のサンプル」を参照してください。または、「Microsoft Entra 認証をサポートする Azure サービス」で、サービスの一覧と、そのリソース ID を参照してください。 |
重要
- IMDS をプロキシの背後で使用することは想定されておらず、サポートされていません。 プロキシをバイパスする方法の例については、「Azure Instance Metadata Samples (Azure インスタンス メタデータ サンプル)」をご覧ください。
再試行のガイダンス
404、429、または 5xx のエラー コードが表示される場合、再試行することをお勧めします (前の 「エラー処理」を参照)。 410 エラーが表示された場合は、IMDS が更新中であり、最大 70 秒で使用可能になることを示しています。
スロットル制限は、IMDS エンドポイントに対して行われる呼び出し回数に適用されます。 スロットルのしきい値を超えた場合、IMDS エンドポイントは、スロットルが有効な状態にあっても、それ以降の要求を制限します。 この期間中、IMDS エンドポイントは HTTP 状態コード 429 ("要求が多すぎます") を返し、要求は失敗します。
再試行については、次の方法をお勧めします。
再試行戦略 | 設定 | 値 | 動作のしくみ |
---|---|---|---|
ExponentialBackoff | 再試行回数 最小バックオフ 最大バックオフ 差分バックオフ 最初の高速再試行 |
5 0 秒 60 秒 2 秒 false |
試行 1 - 0 秒の遅延 試行 2 - 最大 2 秒の遅延 試行 3 - 最大 6 秒の遅延 試行 4 - 最大 14 秒の遅延 試行 5 - 最大 30 秒の遅延 |
Azure サービスのリソース ID
Azure リソースのマネージド ID をサポートするリソースの一覧については、マネージド ID がサポートされている Azure サービスに関するページを参照してください。
次のステップ
- Azure VM 上で Azure リソースのマネージド ID を有効にするには、「Configure managed identities for Azure resources on a VM using the Azure portal」 (Azure portal を使用して VM 上で Azure リソースのマネージド ID を構成する) を参照してください。