如何在 Azure VM 上使用 Azure 资源的托管标识获取访问令牌How to use managed identities for Azure resources on an Azure VM to acquire an access token

Azure 资源的托管标识是 Azure Active Directory 的一项功能。Managed identities for Azure resources is a feature of Azure Active Directory. 支持 Azure 资源的托管标识的每个 Azure 服务都受其自己的时间线限制。Each of the Azure services that support managed identities for Azure resources are subject to their own timeline. 在开始之前,请务必查看资源的托管标识的可用性状态以及已知问题Make sure you review the availability status of managed identities for your resource and known issues before you begin.

Azure 资源的托管标识在 Azure Active Directory 中为 Azure 服务提供了一个自动托管标识。Managed identities for Azure resources provides Azure services with an automatically managed identity in Azure Active Directory. 此标识可用于通过支持 Azure AD 身份验证的任何服务的身份验证,这样就无需在代码中插入凭据了。You can use this identity to authenticate to any service that supports Azure AD authentication, without having credentials in your code.

本文提供有关获取令牌的各种代码和脚本示例,以及有关处理令牌过期和 HTTP 错误等重要主题的指导。This article provides various code and script examples for token acquisition, as well as guidance on important topics such as handling token expiration and HTTP errors.

先决条件Prerequisites

  • 如果不熟悉 Azure 资源功能的托管标识,请参阅此概述If you're not familiar with the managed identities for Azure resources feature, see this overview.

如果打算使用本文中的 Azure PowerShell 示例,请务必安装最新版本的 Azure PowerShellIf you plan to use the Azure PowerShell examples in this article, be sure to install the latest version of Azure PowerShell.

重要

  • 本文中的所有示例代码/脚本假设客户端使用 Azure 资源的托管标识在虚拟机上运行。All sample code/script in this article assumes the client is running on a virtual machine with managed identities for Azure resources. 在 Azure 门户中使用虚拟机的“连接”功能远程连接到 VM。Use the virtual machine "Connect" feature in the Azure portal, to remotely connect to your VM. 有关在 VM 上启用 Azure 资源的托管标识的详细信息,请参阅使用 Azure 门户在 VM 上配置 Azure 资源的托管标识,或有关在不同工具(使用 PowerShell、CLI、模板或 Azure SDK)中执行此操作的文章之一。For details on enabling managed identities for Azure resources on a VM, see Configure managed identities for Azure resources on a VM using the Azure portal, or one of the variant articles (using PowerShell, CLI, a template, or an Azure SDK).

重要

  • Azure 资源的托管标识的安全边界是它所使用的资源。The security boundary of managed identities for Azure resources, is the resource it's being used on. 虚拟机上运行的所有代码/脚本都可以请求和检索虚拟机上可用的任何托管标识的令牌。All code/scripts running on a virtual machine can request and retrieve tokens for any managed identities available on it.

概述Overview

客户端应用程序可以请求 Azure 资源的托管标识的仅限应用的访问令牌用于访问给定的资源。A client application can request managed identities for Azure resources app-only access token for accessing a given resource. 令牌基于 Azure 资源的托管标识服务主体The token is based on the managed identities for Azure resources service principal. 因此,客户端无需注册自身即可使用自己的服务主体获取访问令牌。As such, there is no need for the client to register itself to obtain an access token under its own service principal. 该令牌适合在需要客户端凭据的服务到服务调用中用作持有者令牌。The token is suitable for use as a bearer token in service-to-service calls requiring client credentials.

使用 HTTP 获取令牌Get a token using HTTP Azure 资源的托管标识令牌终结点的协议详细信息Protocol details for managed identities for Azure resources token endpoint
使用用于 .NET 的 Microsoft.Azure.Services.AppAuthentication 库获取令牌Get a token using the Microsoft.Azure.Services.AppAuthentication library for .NET 从 .NET 客户端使用 Microsoft.Azure.Services.AppAuthentication 库的示例Example of using the Microsoft.Azure.Services.AppAuthentication library from a .NET client
使用 C# 获取令牌Get a token using C# 使用来自 C# 客户端的 Azure 资源的托管标识 REST 终结点示例Example of using managed identities for Azure resources REST endpoint from a C# client
使用 Java 获取令牌Get a token using Java 使用来自 Java 客户端的 Azure 资源的托管标识 REST 终结点的的示例Example of using managed identities for Azure resources REST endpoint from a Java client
使用 Go 获取令牌Get a token using Go 使用来自 Go 客户端的 Azure 资源的托管标识 REST 终结点的的示例Example of using managed identities for Azure resources REST endpoint from a Go client
使用 Azure PowerShell 获取令牌Get a token using Azure PowerShell 使用来自 PowerShell 客户端的 Azure 资源的托管标识 REST 终结点示例Example of using managed identities for Azure resources REST endpoint from a PowerShell client
使用 CURL 获取令牌Get a token using CURL 使用来自 Bash/CURL 客户端的 Azure 资源的托管标识 REST 终结点示例Example of using managed identities for Azure resources REST endpoint from a Bash/CURL client
处理令牌缓存Handling token caching 有关处理过期访问令牌的指导Guidance for handling expired access tokens
错误处理Error handling 处理从 Azure 资源的托管标识令牌终结点返回的 HTTP 错误的指南Guidance for handling HTTP errors returned from the managed identities for Azure resources token endpoint
Azure 服务的资源 IDResource IDs for Azure services 在何处获取受支持 Azure 服务的资源 IDWhere to get resource IDs for supported Azure services

使用 HTTP 获取令牌Get a token using HTTP

用于获取访问令牌的基本接口基于 REST,因此,在 VM 上运行的、可发出 HTTP REST 调用的任何客户端应用程序都可以访问该接口。The fundamental interface for acquiring an access token is based on REST, making it accessible to any client application running on the VM that can make HTTP REST calls. 此接口类似于 Azure AD 编程模型,不同的是,客户端使用虚拟机上的终结点(而不是使用 Azure AD 终结点)。This is similar to the Azure AD programming model, except the client uses an endpoint on the virtual machine (vs an Azure AD endpoint).

使用 Azure 实例元数据服务 (IMDS) 终结点(推荐使用)的示例请求:Sample request using the Azure Instance Metadata Service (IMDS) endpoint (recommended):

GET 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.chinacloudapi.cn/' HTTP/1.1 Metadata: true
元素Element 说明Description
GET HTTP 谓词,指示想要从终结点检索数据。The HTTP verb, indicating you want to retrieve data from the endpoint. 在本例中,该数据为 OAuth 访问令牌。In this case, an OAuth access token.
http://169.254.169.254/metadata/identity/oauth2/token 实例元数据服务的 Azure 资源的托管标识终结点。The managed identities for Azure resources endpoint for the Instance Metadata Service.
api-version 查询字符串参数,指示 IMDS 终结点的 API 版本。A query string parameter, indicating the API version for the IMDS endpoint. 请使用 API 2018-02-01 或更高版本。Please use API version 2018-02-01 or greater.
resource 一个查询字符串参数,表示目标资源的应用 ID URI。A query string parameter, indicating the App ID URI of the target resource. 它也会显示在所颁发令牌的 aud(受众)声明中。It also appears in the aud (audience) claim of the issued token. 本示例请求一个用于访问 Azure 资源管理器的、应用 ID URI 为 https://management.chinacloudapi.cn/ 的令牌。This example requests a token to access Azure Resource Manager, which has an App ID URI of https://management.chinacloudapi.cn/.
Metadata 一个 HTTP 请求标头字段,Azure 资源的托管标识需要使用该元素来缓解服务器端请求伪造 (SSRF) 攻击。An HTTP request header field, required by managed identities for Azure resources as a mitigation against Server Side Request Forgery (SSRF) attack. 必须将此值设置为“true”(全小写)。This value must be set to "true", in all lower case.
object_id (可选)一个查询字符串参数,指示要将此令牌用于的托管标识的 object_id。(Optional) A query string parameter, indicating the object_id of the managed identity you would like the token for. 如果 VM 有用户分配的多个托管标识,则为必需的。Required, if your VM has multiple user-assigned managed identities.
client_id (可选)一个查询字符串参数,指示要将此令牌用于的托管标识的 client_id。(Optional) A query string parameter, indicating the client_id of the managed identity you would like the token for. 如果 VM 有用户分配的多个托管标识,则为必需的。Required, if your VM has multiple user-assigned managed identities.
mi_res_id (可选)一个查询字符串参数,指示要将此令牌用于的托管标识的 mi_res_id(Azure 资源 ID)。(Optional) A query string parameter, indicating the mi_res_id (Azure Resource ID) of the managed identity you would like the token for. 如果 VM 有用户分配的多个托管标识,则为必需的。Required, if your VM has multiple user-assigned managed identities.

使用 Azure 资源托管标识 VM 扩展终结点(计划于 2019 年 1 月弃用)的示例请求:Sample request using the managed identities for Azure resources VM Extension Endpoint (planned for deprecation in January 2019):

GET http://localhost:50342/oauth2/token?resource=https%3A%2F%2Fmanagement.chinacloudapi.cn%2F HTTP/1.1
Metadata: true
元素Element 说明Description
GET HTTP 谓词,指示想要从终结点检索数据。The HTTP verb, indicating you want to retrieve data from the endpoint. 在本例中,该数据为 OAuth 访问令牌。In this case, an OAuth access token.
http://localhost:50342/oauth2/token Azure 资源的托管标识终结点,其中 50342 是可配置的默认端口。The managed identities for Azure resources endpoint, where 50342 is the default port and is configurable.
resource 一个查询字符串参数,表示目标资源的应用 ID URI。A query string parameter, indicating the App ID URI of the target resource. 它也会显示在所颁发令牌的 aud(受众)声明中。It also appears in the aud (audience) claim of the issued token. 本示例请求一个用于访问 Azure 资源管理器的、应用 ID URI 为 https://management.chinacloudapi.cn/ 的令牌。This example requests a token to access Azure Resource Manager, which has an App ID URI of https://management.chinacloudapi.cn/.
Metadata 一个 HTTP 请求标头字段,Azure 资源的托管标识需要使用该元素来缓解服务器端请求伪造 (SSRF) 攻击。An HTTP request header field, required by managed identities for Azure resources as a mitigation against Server Side Request Forgery (SSRF) attack. 必须将此值设置为“true”(全小写)。This value must be set to "true", in all lower case.
object_id (可选)一个查询字符串参数,指示要将此令牌用于的托管标识的 object_id。(Optional) A query string parameter, indicating the object_id of the managed identity you would like the token for. 如果 VM 有用户分配的多个托管标识,则为必需的。Required, if your VM has multiple user-assigned managed identities.
client_id (可选)一个查询字符串参数,指示要将此令牌用于的托管标识的 client_id。(Optional) A query string parameter, indicating the client_id of the managed identity you would like the token for. 如果 VM 有用户分配的多个托管标识,则为必需的。Required, if your VM has multiple user-assigned managed identities.

示例响应:Sample response:

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.chinacloudapi.cn/",
  "token_type": "Bearer"
}
元素Element 说明Description
access_token 请求的访问令牌。The requested access token. 调用受保护 REST API 时,该令牌将作为“持有者”令牌嵌入在 Authorization 请求标头字段中,使 API 能够对调用方进行身份验证。When calling a secured REST API, the token is embedded in the Authorization request header field as a "bearer" token, allowing the API to authenticate the caller.
refresh_token 未由 Azure 资源的托管标识使用。Not used by managed identities for Azure resources.
expires_in 访问令牌在过期之前保持有效的秒数,从颁发时间开始算起。The number of seconds the access token continues to be valid, before expiring, from time of issuance. 可在令牌的 iat 声明中找到颁发时间。Time of issuance can be found in the token's iat claim.
expires_on 访问令牌过期的时间范围。The timespan when the access token expires. 该日期表示为自“1970-01-01T0:0:0Z UTC”开始的秒数(对应于令牌的 exp 声明)。The date is represented as the number of seconds from "1970-01-01T0:0:0Z UTC" (corresponds to the token's exp claim).
not_before 访问令牌生效且可被接受的时间范围。The timespan when the access token takes effect, and can be accepted. 该日期表示为自“1970-01-01T0:0:0Z UTC”开始的秒数(对应于令牌的 nbf 声明)。The date is represented as the number of seconds from "1970-01-01T0:0:0Z UTC" (corresponds to the token's nbf claim).
resource 请求访问令牌时所针对的资源,与请求的 resource 查询字符串参数匹配。The resource the access token was requested for, which matches the resource query string parameter of the request.
token_type 令牌的类型,这是一个“持有者”访问令牌,意味着资源可向此令牌的持有者授予访问权限。The type of token, which is a "Bearer" access token, which means the resource can give access to the bearer of this token.

使用用于 .NET 的 Microsoft.Azure.Services.AppAuthentication 库获取令牌Get a token using the Microsoft.Azure.Services.AppAuthentication library for .NET

对于 .NET 应用程序和函数,使用 Azure 资源的托管标识的最简单的方法是通过 Microsoft.Azure.Services.AppAuthentication 包。For .NET applications and functions, the simplest way to work with managed identities for Azure resources is through the Microsoft.Azure.Services.AppAuthentication package. 此库还允许通过 Visual Studio、Azure CLI 或 Active Directory 集成身份验证使用用户帐户,在开发计算机上对代码进行本地测试。This library will also allow you to test your code locally on your development machine, using your user account from Visual Studio, the Azure CLI, or Active Directory Integrated Authentication. 有关此库的本地开发选项的详细信息,请参阅 Microsoft.Azure.Services.AppAuthentication 参考For more on local development options with this library, see the Microsoft.Azure.Services.AppAuthentication reference. 本部分演示如何开始在代码中使用此库。This section shows you how to get started with the library in your code.

  1. 向应用程序添加对 Microsoft.Azure.Services.AppAuthenticationMicrosoft.Azure.KeyVault NuGet 包的引用。Add references to the Microsoft.Azure.Services.AppAuthentication and Microsoft.Azure.KeyVault NuGet packages to your application.

  2. 将以下代码添加到应用程序:Add the following code to your application:

    using Microsoft.Azure.Services.AppAuthentication;
    using Microsoft.Azure.KeyVault;
    // ...
    var azureServiceTokenProvider = new AzureServiceTokenProvider();
    string accessToken = await azureServiceTokenProvider.GetAccessTokenAsync("https://management.chinacloudapi.cn/");
    // OR
    var kv = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
    

若要了解有关 Microsoft.Azure.Services.AppAuthentication 及其公开的操作的详细信息,请参阅 Microsoft.Azure.Services.AppAuthentication 参考以及将应用服务和 KeyVault 与 Azure 资源的托管标识配合使用的 .NET 示例To learn more about Microsoft.Azure.Services.AppAuthentication and the operations it exposes, see the Microsoft.Azure.Services.AppAuthentication reference and the App Service and KeyVault with managed identities for Azure resources .NET sample.

使用 C# 获取令牌Get a token using 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.chinacloudapi.cn/");
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 获取令牌Get a token using Java

通过 Java 使用此 JSON 库检索令牌。Use this JSON library to retrieve a token using Java.

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.chinacloudapi.cn/");
        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 获取令牌Get a token using 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 := url.Values{}
    msi_parameters.Add("resource", "https://management.chinacloudapi.cn/")
    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)
}

使用 Azure PowerShell 获取令牌Get a token using Azure PowerShell

以下示例演示如何从 PowerShell 客户端使用 Azure 资源的托管标识 REST 终结点来执行以下操作:The following example demonstrates how to use the managed identities for Azure resources REST endpoint from a PowerShell client to:

  1. 获取访问令牌。Acquire an access token.
  2. 使用该访问令牌调用 Azure 资源管理器 REST API 并获取有关 VM 的信息。Use the access token to call an Azure Resource Manager REST API and get information about the VM. 请务必将 <SUBSCRIPTION-ID><RESOURCE-GROUP><VM-NAME> 分别替换为自己的订阅 ID、资源组名称和虚拟机名称。Be sure to substitute your subscription ID, resource group name, and virtual machine name for <SUBSCRIPTION-ID>, <RESOURCE-GROUP>, and <VM-NAME>, respectively.
Invoke-WebRequest -Uri 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fmanagement.chinacloudapi.cn%2F' -Headers @{Metadata="true"}

有关如何分析响应中的访问令牌的示例:Example on how to parse the access token from the response:

# 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.chinacloudapi.cn%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.chinacloudapi.cn/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 获取令牌Get a token using CURL

curl 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fmanagement.chinacloudapi.cn%2F' -H Metadata:true -s

有关如何分析响应中的访问令牌的示例:Example on how to parse the access token from the response:

response=$(curl 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fmanagement.chinacloudapi.cn%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

令牌缓存Token caching

正在使用的 Azure 资源的托管标识子系统(IMDS/Azure 资源 VM 扩展的托管标识)缓存令牌时,我们还建议在代码中实现令牌缓存。While the managed identities for Azure resources subsystem being used (IMDS/managed identities for Azure resources VM Extension) does cache tokens, we also recommend to implement token caching in your code. 因此,应准备资源指示令牌已过期的方案。As a result, you should prepare for scenarios where the resource indicates that the token is expired.

仅在下列情况下会对 Azure AD 结果进行在线调用:On-the-wire calls to Azure AD result only when:

  • 由于 Azure 资源子系统缓存的托管标识中没有令牌,因此将发生缓存失误cache miss occurs due to no token in the managed identities for Azure resources subsystem cache
  • 缓存令牌已过期the cached token is expired

错误处理。Error handling

Azure 资源的托管标识终结点通过 HTTP 响应消息标头的状态代码字段,以 4xx 或 5xx 错误的形式指示错误:The managed identities for Azure resources endpoint signals errors via the status code field of the HTTP response message header, as either 4xx or 5xx errors:

状态代码Status Code 错误原因Error Reason 处理方式How To Handle
404 未找到。404 Not found. 正在更新 IMDS 终结点。IMDS endpoint is updating. 使用指数补偿重试。Retry with Exponential Backoff. 请参阅下面的指南。See guidance below.
429 请求过多429 Too many requests. 达到 IMDS 节流限制。IMDS Throttle limit reached. 使用指数补偿重试。Retry with Exponential Backoff. 请参阅下面的指南。See guidance below.
请求中出现 4xx 错误。4xx Error in request. 一个或多个请求参数不正确。One or more of the request parameters was incorrect. 请勿重试。Do not retry. 查看错误详细信息了解更多信息。Examine the error details for more information. 4xx 错误属于设计时错误。4xx errors are design-time errors.
服务出现 5xx 暂时性错误。5xx Transient error from service. Azure 资源的托管标识子系统或 Azure Active Directory 返回了暂时性错误。The managed identities for Azure resources sub-system or Azure Active Directory returned a transient error. 至少等待 1 秒后可以安全重试。It is safe to retry after waiting for at least 1 second. 如果重试过快或过于频繁,IMDS 和/或 Azure AD 可能会返回速率限制错误 (429)。If you retry too quickly or too often, IMDS and/or Azure AD may return a rate limit error (429).
timeouttimeout 正在更新 IMDS 终结点。IMDS endpoint is updating. 使用指数补偿重试。Retry with Exponential Backoff. 请参阅下面的指南。See guidance below.

如果发生错误,相应的 HTTP 响应正文将包含 JSON 和错误详细信息:If an error occurs, the corresponding HTTP response body contains JSON with the error details:

元素Element 说明Description
errorerror 错误标识符。Error identifier.
error_descriptionerror_description 错误的详细说明。Verbose description of error. 错误说明随时可能更改。请不要编写会根据错误说明中的值生成分支片段的代码。Error descriptions can change at any time. Do not write code that branches based on values in the error description.

HTTP 响应参考HTTP response reference

本部分介绍可能的错误响应。This section documents the possible error responses. “200 OK”状态表示成功的响应,访问令牌包含在响应正文 JSON 的 access_token 元素中。A "200 OK" status is a successful response, and the access token is contained in the response body JSON, in the access_token element.

状态代码Status code 错误Error 错误说明Error Description 解决方案Solution
400 错误的请求400 Bad Request invalid_resourceinvalid_resource AADSTS50001:在名为 <TENANT-ID> 的租户中找不到名为 <URI> 的应用程序 。AADSTS50001: The application named <URI> was not found in the tenant named <TENANT-ID>. 如果应用程序尚未由租户管理员安装,或者尚未获得租户中的任何用户同意,则可能会发生这种情况。This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. 可能将身份验证请求发送给了错误的租户。You might have sent your authentication request to the wrong tenant.\ (仅限 Linux)(Linux only)
400 错误的请求400 Bad Request bad_request_102bad_request_102 未指定必需的元数据标头Required metadata header not specified 请求中缺少 Metadata 请求标头字段,或者该字段的格式不正确。Either the Metadata request header field is missing from your request, or is formatted incorrectly. 必须将该值指定为 true(全小写)。The value must be specified as true, in all lower case. 有关示例,请参阅前面 REST 部分中的“示例请求”。See the "Sample request" in the preceding REST section for an example.
401 未授权401 Unauthorized unknown_sourceunknown_source 未知源 <URI>Unknown Source <URI> 检查是否已正确设置 HTTP GET 请求 URI 的格式。Verify that your HTTP GET request URI is formatted correctly. 必须将 scheme:host/resource-path 部分指定为 http://localhost:50342/oauth2/tokenThe scheme:host/resource-path portion must be specified as http://localhost:50342/oauth2/token. 有关示例,请参阅前面 REST 部分中的“示例请求”。See the "Sample request" in the preceding REST section for an example.
invalid_requestinvalid_request 请求中缺少必需的参数、包含无效的参数值、多次包含某个参数,或格式不正确。The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed.
unauthorized_clientunauthorized_client 客户端无权使用此方法请求访问令牌。The client is not authorized to request an access token using this method. 此错误是由于某个请求未使用本地环回来调用扩展导致的,或者是由于发出请求的 VM 没有为 Azure 资源正确配置托管标识导致的。Caused by a request that didn't use local loopback to call the extension, or on a VM that doesn't have managed identities for Azure resources configured correctly. 如需 VM 配置方面的帮助,请参阅使用 Azure 门户在 VM 上配置 Azure 资源的托管标识See Configure managed identities for Azure resources on a VM using the Azure portal if you need assistance with VM configuration.
access_deniedaccess_denied 资源所有者或授权服务器拒绝了请求。The resource owner or authorization server denied the request.
unsupported_response_typeunsupported_response_type 授权服务器不支持使用此方法获取访问令牌。The authorization server does not support obtaining an access token using this method.
invalid_scopeinvalid_scope 请求的范围无效、未知或格式不正确。The requested scope is invalid, unknown, or malformed.
500 内部服务器错误500 Internal server error 未知unknown 无法从 Active Directory 检索令牌。Failed to retrieve token from the Active directory. 有关详细信息,请参阅 <file path> 中的日志For details see logs in <file path> 验证是否在 VM 上启用了 Azure 资源的托管标识。Verify that managed identities for Azure resources has been enabled on the VM. 如需 VM 配置方面的帮助,请参阅使用 Azure 门户在 VM 上配置 Azure 资源的托管标识See Configure managed identities for Azure resources on a VM using the Azure portal if you need assistance with VM configuration.

另请检查是否已正确设置 HTTP GET 请求 URI 的格式,尤其是查询字符串中指定的资源 URI。Also verify that your HTTP GET request URI is formatted correctly, particularly the resource URI specified in the query string. 有关示例,请参阅前面 REST 部分中的“示例请求”;有关服务的列表及其相应资源 ID,请参阅支持 Azure AD 身份验证的 Azure 服务See the "Sample request" in the preceding REST section for an example, or Azure services that support Azure AD authentication for a list of services and their respective resource IDs.

重试指南Retry guidance

建议在收到 404、429 或 5xx 错误代码后重试(请参阅上述错误处理)。It is recommended to retry if you receive a 404, 429, or 5xx error code (see Error handling above).

限制适用于对 IMDS 终结点所做的调用次数。Throttling limits apply to the number of calls made to the IMDS endpoint. 当超出限制阈值时,IMDS 终结点在限制有效时限制任何后续请求。When the throttling threshold is exceeded, IMDS endpoint limits any further requests while the throttle is in effect. 在此期间,IMDS 终结点将返回 HTTP 状态码 429(“请求过多”),并且请求失败。During this period, the IMDS endpoint will return the HTTP status code 429 ("Too many requests"), and the requests fail.

若要重试,建议使用以下策略:For retry, we recommend the following strategy:

重试策略Retry strategy 设置Settings Values 工作原理How it works
ExponentialBackoffExponentialBackoff 重试计数Retry count
最小回退Min back-off
最大回退Max back-off
增量回退Delta back-off
首次快速重试First fast retry
55
0 秒0 sec
60 秒60 sec
2 秒2 sec
falsefalse
第 1 次尝试 - 延迟 0 秒Attempt 1 - delay 0 sec
第 2 次尝试 - 约延迟 2 秒Attempt 2 - delay ~2 sec
第 3 次尝试 - 约延迟 6 秒Attempt 3 - delay ~6 sec
第 4 次尝试 - 约延迟 14 秒Attempt 4 - delay ~14 sec
第 5 次尝试 - 约延迟 30 秒Attempt 5 - delay ~30 sec

Azure 服务的资源 IDResource IDs for Azure services

有关支持 Azure AD 且已使用 Azure 资源的托管标识进行测试的资源列表及其相应资源 ID,请参阅支持 Azure AD 身份验证的 Azure 服务See Azure services that support Azure AD authentication for a list of resources that support Azure AD and have been tested with managed identities for Azure resources, and their respective resource IDs.

后续步骤Next steps