Dela via


Så här använder du hanterade identiteter för Azure-resurser på en virtuell Azure-dator för att hämta en åtkomsttoken

Hanterade identiteter för Azure-resurser är en funktion i Microsoft Entra-ID. Alla Azure-tjänster som stöder hanterade identiteter för Azure-resurser har sin egen tidslinje. Var noga med att kontrollera tillgänglighetsstatus för hanterade identiteter för din resurs och kända problem innan du börjar.

Hanterade identiteter för Azure-resurser ger Azure-tjänster en automatiskt hanterad identitet i Microsoft Entra ID. Du kan använda den här identiteten för att autentisera mot alla tjänster som har stöd för Microsoft Entra-autentisering, utan att behöva ha några autentiseringsuppgifter i koden.

Den här artikeln innehåller olika kod- och skriptexempel för tokenförvärv. Den innehåller också vägledning om hur du hanterar tokens förfallotid och HTTP-fel.

Förutsättningar

Om du planerar att använda Azure PowerShell-exemplen i den här artikeln måste du installera den senaste versionen av Azure PowerShell.

Viktigt!

Viktigt!

  • Säkerhetsgränsen för hanterade identiteter för Azure-resurser är den resurs där identiteten används. Alla kod/skript som körs på en virtuell dator kan begära och hämta token för alla hanterade identiteter som är tillgängliga på den.

Översikt

Ett klientprogram kan begära en åtkomsttoken för endast hanterad identitetsapp för åtkomst till en viss resurs. Token baseras på hanterade identiteter för Tjänstens huvudnamn för Azure-resurser. Därför behöver klienten inte hämta en åtkomsttoken under sitt eget huvudnamn för tjänsten. Token är lämplig för användning som en ägartoken i tjänst-till-tjänst-anrop som kräver klientautentiseringsuppgifter.

Länk beskrivning
Hämta en token med HTTP Protokollinformation för hanterade identiteter för Azure-resurstokenslutpunkt
Hämta en token med hjälp av Azure.Identity Hämta en token med hjälp av Azure.Identity-biblioteket
Hämta en token med hjälp av biblioteket Microsoft.Azure.Services.AppAuthentication för .NET Exempel på hur du använder biblioteket Microsoft.Azure.Services.AppAuthentication från en .NET-klient
Hämta en token med C# Exempel på hur du använder hanterade identiteter för Azure-resursers REST-slutpunkt från en C#-klient
Hämta en token med Java Exempel på hur du använder hanterade identiteter för Azure-resursers REST-slutpunkt från en Java-klient
Hämta en token med Go Exempel på hur du använder hanterade identiteter för Azure-resursers REST-slutpunkt från en Go-klient
Hämta en token med PowerShell Exempel på hur du använder hanterade identiteter för Azure-resursers REST-slutpunkt från en PowerShell-klient
Hämta en token med CURL Exempel på hur du använder hanterade identiteter för Azure-resursers REST-slutpunkt från en Bash/CURL-klient
Hantera cachelagring av token Vägledning för hantering av utgångna åtkomsttoken
Felhantering Vägledning för hantering av HTTP-fel som returneras från de hanterade identiteterna för Azure-resursers tokenslutpunkt
Resurs-ID:t för Azure-tjänster Var du kan hämta resurs-ID:t för Azure-tjänster som stöds

Hämta en token med HTTP

Det grundläggande gränssnittet för att hämta en åtkomsttoken baseras på REST, vilket gör det tillgängligt för alla klientprogram som körs på den virtuella datorn som kan göra HTTP REST-anrop. Den här metoden liknar Microsoft Entra-programmeringsmodellen, förutom att klienten använder en slutpunkt på den virtuella datorn (jämfört med en Microsoft Entra-slutpunkt).

Exempelbegäran med hjälp av IMDS-slutpunkten (Azure Instance Metadata Service) (rekommenderas):

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
Element Description
GET HTTP-verbet som anger att du vill hämta data från slutpunkten. I det här fallet en OAuth-åtkomsttoken.
http://169.254.169.254/metadata/identity/oauth2/token De hanterade identiteterna för Azure-resursers slutpunkt för instansmetadatatjänsten.
api-version En frågesträngsparameter som anger API-versionen för IMDS-slutpunkten. Använd API-version 2018-02-01 eller senare.
resource En frågesträngsparameter som anger målresursens app-ID-URI. Det visas också i anspråket (målgruppen aud ) för den utfärdade token. I det här exemplet begärs en token för åtkomst till Azure Resource Manager, som har en app-ID-URI för https://management.azure.com/.
Metadata Ett http-begärandehuvudfält som krävs av hanterade identiteter. Den här informationen används som en åtgärd mot SSRF-attacker (Server Side Request Forgery). Det här värdet måste anges till "true", i alla gemener.
object_id (Valfritt) En frågesträngsparameter som anger object_id för den hanterade identitet som du vill ha token för. Krävs om den virtuella datorn har flera användartilldelade hanterade identiteter.
client_id (Valfritt) En frågesträngsparameter som anger client_id för den hanterade identitet som du vill ha token för. Krävs om den virtuella datorn har flera användartilldelade hanterade identiteter.
msi_res_id (Valfritt) En frågesträngsparameter som anger msi_res_id (Azure-resurs-ID) för den hanterade identitet som du vill ha token för. Krävs om den virtuella datorn har flera användartilldelade hanterade identiteter.

Exempelsvar:

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"
}
Element Description
access_token Den begärda åtkomsttoken. När du anropar ett skyddat REST API bäddas token in i Authorization fältet för begärandehuvud som en "ägartoken", vilket gör att API:et kan autentisera anroparen.
refresh_token Används inte av hanterade identiteter för Azure-resurser.
expires_in Antalet sekunder som åtkomsttoken fortsätter att vara giltig, innan den upphör att gälla, från tidpunkten för utfärdandet. Tidpunkten för utfärdandet finns i tokens iat anspråk.
expires_on Tidsintervallet när åtkomsttoken upphör att gälla. Datumet representeras som antalet sekunder från "1970-01-01T0:0:0Z UTC" (motsvarar tokens exp anspråk).
not_before Tidsintervallet när åtkomsttoken börjar gälla och kan accepteras. Datumet representeras som antalet sekunder från "1970-01-01T0:0:0Z UTC" (motsvarar tokens nbf anspråk).
resource Resursen som åtkomsttoken begärdes för, som matchar frågesträngsparametern resource för begäran.
token_type Typen av token, som är en "Bearer"-åtkomsttoken, vilket innebär att resursen kan ge åtkomst till ägarnamnet för denna token.

Hämta en token med azure-identitetsklientbiblioteket

Att använda Azure identity-klientbiblioteket är det rekommenderade sättet att använda hanterade identiteter. Alla Azure SDK:er är integrerade med Azure.Identity biblioteket som ger stöd för DefaultAzureCredential. Den här klassen gör det enkelt att använda hanterade identiteter med Azure SDK:er.Lära sig mer

  1. Installera Azure.Identity-paketet och andra nödvändiga Azure SDK-bibliotekspaket, till exempel Azure.Security.KeyVault.Secrets.

  2. Använd exempelkoden nedan. Du behöver inte oroa dig för att få token. Du kan använda Azure SDK-klienterna direkt. Koden är till för att visa hur du hämtar token, om du behöver det.

    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);
    

Hämta en token med hjälp av biblioteket Microsoft.Azure.Services.AppAuthentication för .NET

För .NET-program och -funktioner är det enklaste sättet att arbeta med hanterade identiteter för Azure-resurser via paketet Microsoft.Azure.Services.AppAuthentication. Med det här biblioteket kan du också testa koden lokalt på utvecklingsdatorn. Du kan testa koden med ditt användarkonto från Visual Studio, Azure CLI eller Active Directory Integrated Authentication. Mer information om lokala utvecklingsalternativ med det här biblioteket finns i referensen Microsoft.Azure.Services.AppAuthentication. Det här avsnittet visar hur du kommer igång med biblioteket i koden.

  1. Lägg till referenser till NuGet-paketen Microsoft.Azure.Services.AppAuthentication och Microsoft.Azure.KeyVault i ditt program.

  2. Lägg till följande kod i programmet:

    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));
    

Mer information om Microsoft.Azure.Services.AppAuthentication och de åtgärder som exponeras finns i microsoft.Azure.Services.AppAuthentication-referensen och App Service och KeyVault med hanterade identiteter för Azure-resurser .NET-exempel.

Hämta en token med 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");
}

Hämta en token med Java

Använd det här JSON-biblioteket för att hämta en token med 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.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;
                }
            }
        }
    }
}

Hämta en token med 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)
}

Hämta en token med PowerShell

I följande exempel visas hur du använder de hanterade identiteterna för REST-slutpunkten för Azure-resurser från en PowerShell-klient till:

  1. Hämta en åtkomsttoken.
  2. Använd åtkomsttoken för att anropa ett Rest-API för Azure Resource Manager och få information om den virtuella datorn. Se till att ersätta ditt prenumerations-ID, resursgruppsnamn och namn på den virtuella datorn med <SUBSCRIPTION-ID>, <RESOURCE-GROUP>respektive <VM-NAME>.
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"}

Exempel på hur du parsar åtkomsttoken från svaret:

# 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

Hämta en token med 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

Exempel på hur du parsar åtkomsttoken från svaret:

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

Cachelagring av token

Undersystemet för hanterade identiteter cachelagrar token, men vi rekommenderar ändå att du implementerar cachelagring av token i koden. Du bör förbereda dig för scenarier där resursen anger att token har upphört att gälla.

On-the-wire-anrop till Microsoft Entra ID-resultat endast när:

  • Cachemissen inträffar på grund av att det inte finns någon token i de hanterade identiteterna för Undersystemcache för Azure-resurser.
  • Den cachelagrade token har upphört att gälla.

Felhantering

Slutpunkten för hanterade identiteter signalerar fel via statuskodfältet i HTTP-svarsmeddelanderubriken, som antingen 4xx- eller 5xx-fel:

Statuskod Felorsak Hantera
404 Hittades inte. IMDS-slutpunkten uppdateras. Försök igen med exponentiell backoff. Se vägledningen nedan.
410 IMDS genomgår uppdateringar IMDS kommer att vara tillgängligt inom 70 sekunder
429 För många förfrågningar. GRÄNSEN för IMDS-begränsning har nåtts. Försök igen med exponentiell backoff. Se vägledningen nedan.
4xx Fel i begäran. En eller flera av begärandeparametrarna var felaktiga. Försök inte igen. Mer information finns i felinformationen. 4xx-fel är designtidsfel.
5xx Tillfälligt fel från tjänsten. De hanterade identiteterna för Azure-resursers undersystem eller Microsoft Entra-ID returnerade ett tillfälligt fel. Det är säkert att försöka igen efter att ha väntat i minst 1 sekund. Om du försöker igen för snabbt eller för ofta kan IMDS och/eller Microsoft Entra-ID returnera ett hastighetsbegränsningsfel (429).
timeout IMDS-slutpunkten uppdateras. Försök igen med exponentiell backoff. Se vägledningen nedan.

Om ett fel inträffar innehåller motsvarande HTTP-svarstext JSON med felinformationen:

Element Description
fel Felidentifierare.
error_description Utförlig beskrivning av felet. Felbeskrivningar kan ändras när som helst. Skriv inte kod som förgrenar baserat på värden i felbeskrivningen.

HTTP-svarsreferens

I det här avsnittet beskrivs möjliga felsvar. Statusen "200 OK" är ett lyckat svar och åtkomsttoken finns i svarstexten JSON i access_token-elementet.

Statuskod Fel Felbeskrivning Lösning
400 – Felaktig begäran invalid_resource AADSTS50001: Programmet med namnet <URI> hittades inte i klientorganisationen med namnet <TENANT-ID.> Det här meddelandet visar om klientadministratören inte har installerat programmet eller om ingen klientanvändare har samtyckt till det. Du kan ha skickat din autentiseringsbegäran till fel klient.\ (Endast Linux)
400 – Felaktig begäran bad_request_102 Obligatoriskt metadatahuvud har inte angetts Metadata Antingen saknas fältet för begäranderubriken i din begäran eller så formateras det felaktigt. Värdet måste anges som true, i alla gemener. Se "Exempelbegäran" i föregående REST-avsnitt för ett exempel.
401 – Ej behörig unknown_source Okänd käll-URI <> Kontrollera att din HTTP GET-begärande-URI är korrekt formaterad. Delen scheme:host/resource-path måste anges som http://localhost:50342/oauth2/token. Se "Exempelbegäran" i föregående REST-avsnitt för ett exempel.
invalid_request Begäran saknar en obligatorisk parameter, innehåller ett ogiltigt parametervärde, innehåller en parameter mer än en gång eller på annat sätt är felaktigt.
unauthorized_client Klienten har inte behörighet att begära en åtkomsttoken med den här metoden. Orsakas av en begäran på en virtuell dator som inte har hanterade identiteter för Azure-resurser korrekt konfigurerade. Se Konfigurera hanterade identiteter för Azure-resurser på en virtuell dator med hjälp av Azure-portalen om du behöver hjälp med VM-konfiguration.
access_denied Resursägaren eller auktoriseringsservern nekade begäran.
unsupported_response_type Auktoriseringsservern stöder inte hämtning av en åtkomsttoken med den här metoden.
invalid_scope Det begärda omfånget är ogiltigt, okänt eller felaktigt.
500 Internt serverfel okänt Det gick inte att hämta token från Active Directory. Mer information finns i loggar i <filsökvägen> Kontrollera att den virtuella datorn har hanterade identiteter för Azure-resurser aktiverade. Se Konfigurera hanterade identiteter för Azure-resurser på en virtuell dator med hjälp av Azure-portalen om du behöver hjälp med VM-konfiguration.

Kontrollera också att din HTTP GET-begärande-URI är korrekt formaterad, särskilt resurs-URI:n som anges i frågesträngen. Se "Exempelbegäran" i föregående REST-avsnitt för ett exempel eller Azure-tjänster som stöder Microsoft Entra-autentisering för en lista över tjänster och deras respektive resurs-ID: n.

Viktigt!

  • IMDS är inte avsett att användas bakom en proxy och det stöds inte. Exempel på hur du kringgår proxyservrar finns i Exempel på Azure-instansmetadata.

Vägledning för återförsök

Vi rekommenderar att du försöker igen om du får felkoden 404, 429 eller 5xx (se Felhantering ovan). Om du får ett 410-fel anger det att IMDS genomgår uppdateringar och kommer att vara tillgängligt om högst 70 sekunder.

Begränsningsgränser gäller för antalet anrop som görs till IMDS-slutpunkten. När tröskelvärdet för begränsning överskrids begränsar IMDS-slutpunkten eventuella ytterligare begäranden medan begränsningen är i kraft. Under den här perioden returnerar IMDS-slutpunkten HTTP-statuskoden 429 ("För många begäranden") och begäranden misslyckas.

För att försöka igen rekommenderar vi följande strategi:

Återförsöksstrategi Inställningar Värden Hur det fungerar
ExponentialBackoff Antal nya försök
Min. backoff
Max. backoff
Deltabackoff
Första snabba återförsöket
5
0 sek.
60 sek.
2 sek.
falskt
Försök 1 – 0 sek. fördröjning
Försök 2 – ~2 sek. fördröjning
Försök 3 – ~6 sek. fördröjning
Försök 4 – ~14 sek. fördröjning
Försök 5 – ~30 sek. fördröjning

Resurs-ID:t för Azure-tjänster

Se Azure Services med stöd för hanterade identiteter för en lista över resurser som stöder hanterade identiteter för Azure-resurser.

Nästa steg