Как использовать управляемые удостоверения для ресурсов Azure на виртуальной машине Azure для получения маркера доступа
Управляемые удостоверения для ресурсов Azure — это функция идентификатора Microsoft Entra. Каждая служба Azure, которая поддерживает управляемые удостоверения для ресурсов Azure, используется в соответствии с собственной временной шкалой. Прежде чем начать работу, обязательно проверьте состояние доступности управляемых удостоверений для своего ресурса и ознакомьтесь с известными проблемами.
Управляемые удостоверения для ресурсов Azure предоставляют службам Azure автоматически управляемое удостоверение, которое хранится в Microsoft Entra ID. Это удостоверение можно использовать для проверки подлинности в любой службе, которая поддерживает аутентификацию Microsoft Entra, без использования учетных данных в коде.
В этой статье приведены различные примеры кода и сценариев для получения маркера. Она также содержит рекомендации по обработке ошибок, связанных с истечением срока действия маркера и HTTP.
Необходимые компоненты
- См. дополнительные сведения об управляемых удостоверениях для ресурсов Azure. Если у вас нет учетной записи Azure, зарегистрируйтесь для получения бесплатной учетной записи, прежде чем продолжить.
Если вы планируете использовать примеры Azure PowerShell в этой статье, убедитесь, что установлена последняя версия Azure PowerShell.
Важно!
- Во всех примерах кода или сценариев в этой статье предполагается, что клиент выполняется на виртуальной машине, на которой включены управляемые удостоверения для ресурсов Azure. Используйте функцию подключения виртуальной машины на портале Azure для удаленного подключения к своей виртуальной машине. Дополнительные сведения о включении управляемых удостоверений для ресурсов Azure на виртуальной машине см. в статье Настройка управляемых удостоверений для ресурсов Azure на виртуальной машине Azure с помощью Azure CLI или в одном из вариантов статьи (с использованием PowerShell, интерфейса командной строки, шаблона или пакета SDK для Azure).
Важно!
- Граница безопасности управляемых удостоверений для ресурсов Azure — это ресурс, в котором используется удостоверение. Все примеры кода и сценариев, выполняемые на виртуальной машине, могут запрашивать и получать маркеры для любого управляемого удостоверения, доступного на ней.
Обзор
Клиентское приложение может запрашивать маркер доступа к приложению для управляемого удостоверения, чтобы получить доступ к заданному ресурсу. Этот маркер создан с помощью субъекта-службы управляемых удостоверений для ресурсов Azure. Таким образом, клиенту не нужно получать маркер доступа для собственного субъекта-службы. Маркер подходит для использования в качестве маркера носителя при выполнении вызовов между службами, требующих учетных данных клиента.
Ссылка | Description |
---|---|
Получение маркера с использованием HTTP | Сведения о протоколе для конечной точки маркера управляемых удостоверений для ресурсов Azure |
Получение токена с помощью Azure.Identity | Получение токена с помощью библиотеки Azure.Identity |
Получение токена с помощью библиотеки Microsoft.Azure.Services.AppAuthentication для .NET | Пример использования библиотеки Microsoft.Azure.Services.AppAuthentication из клиента .NET |
Получение маркера с использованием C# | Пример использования конечной точки REST управляемых удостоверений для ресурсов Azure из клиента C# |
Получение маркера с использованием Java | Пример использования конечной точки REST управляемых удостоверений для ресурсов Azure из клиента Java. |
Получение маркера с использованием Go | Пример использования конечной точки REST управляемых удостоверений для ресурсов Azure из клиента Go |
Получение маркера с помощью PowerShell | Пример использования конечной точки REST управляемых удостоверений для ресурсов Azure из клиента PowerShell |
Получение маркера с использованием CURL | Пример использования конечной точки REST управляемых удостоверений для ресурсов Azure из клиента Bash или CURL |
Обработка кэширования маркеров | Рекомендации по обработке срока действия маркера доступа |
Обработка ошибок | Рекомендации по обработке ошибок HTTP, возвращаемых из конечной точки маркера управляемых удостоверений для ресурсов Azure |
Идентификаторы ресурсов для служб Azure | Сведения о том, где можно получить идентификаторы ресурсов для поддерживаемых служб Azure |
Получение маркера с использованием HTTP
Основной интерфейс для получения маркера доступа создан на основе REST, что делает его доступным для любого клиентского приложения, выполняющегося на виртуальной машине,которая может выполнять вызовы HTTP REST. Такой подход аналогичен модели программирования Microsoft Entra, за исключением того, что клиент использует конечную точку на виртуальной машине (и конечную точку Microsoft Entra).
Пример запроса с использованием конечной точки службы метаданных экземпляров (IMDS) Azure (рекомендуется).
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
Элемент | Description |
---|---|
GET |
HTTP-команда, указывающая, что необходимо извлечь данные из конечной точки. В этом случае используется маркер доступа OAuth. |
http://169.254.169.254/metadata/identity/oauth2/token |
Конечная точка управляемых удостоверений для ресурсов Azure для Службы метаданных экземпляров. |
api-version |
Параметр строки запроса, указывающий версию API для конечной точки IMDS. Используйте версию API 2018-02-01 или более новую. |
resource |
Параметр строки запроса, указывающий URI идентификатора приложения целевого ресурса. Он также отображается в утверждении (аудитории) aud выданного маркера. В этом примере запрашивается маркер для доступа к Azure Resource Manager, который имеет универсальный код ресурса (URI) идентификатора приложения https://management.azure.com/ . |
Metadata |
Поле заголовка HTTP-запроса, необходимое для управляемых удостоверений. Эти сведения используются в качестве решения проблем с атаками подделки запросов на стороне сервера (SSRF). Должно быть присвоено значение true (все в нижнем регистре). |
object_id |
(Необязательно.) Параметр строки запроса, указывающий object_id управляемого удостоверения, для которого требуется токен. Требуется, если виртуальная машина имеет несколько управляемых удостоверений, назначаемых пользователем. |
client_id |
(Необязательно.) Параметр строки запроса, указывающий client_id управляемого удостоверения, для которого требуется токен. Требуется, если виртуальная машина имеет несколько управляемых удостоверений, назначаемых пользователем. |
msi_res_id |
(Необязательно) Параметр строки запроса, указывающий msi_res_id (идентификатор ресурса Azure) управляемого удостоверения, для которой требуется маркер. Требуется, если виртуальная машина имеет несколько управляемых удостоверений, назначаемых пользователем. |
Пример ответа:
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"
}
Элемент | Description |
---|---|
access_token |
Запрашиваемый маркер доступа. При вызове защищенного REST API маркер внедряется в поле заголовка запроса Authorization в качестве маркера носителя, позволяя API выполнить проверку подлинности вызывающего объекта. |
refresh_token |
Не используется управляемыми удостоверениями для ресурсов Azure. |
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
Клиентская библиотека удостоверений Azure является рекомендуемым способом использования управляемых удостоверений. Все пакеты средств разработки Azure интегрированы с библиотекой Azure.Identity
, обеспечивающей поддержку DefaultAzureCredential. Этот класс упрощает использование управляемых удостоверений с помощью пакетов SDK для Azure.Дополнительные сведения
Установите пакет Azure.Identity и другие необходимые пакеты библиотеки пакетов SDK Azure, например Azure.Security.KeyVault.Secrets.
Используйте пример кода ниже. Не следует беспокоиться о получении маркеров. Можно напрямую использовать клиенты пакета средств разработки для Azure. Код предназначен для демонстрации способа получения маркера при необходимости.
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);
Получение токена с помощью библиотеки Microsoft.Azure.Services.AppAuthentication для .NET
Самый простой способ для приложений и функций .NET работать с управляемыми удостоверениями для ресурсов Azure заключается в использовании пакета Microsoft.Azure.Services.AppAuthentication. Эта библиотека также позволит протестировать код локально на компьютере, на котором ведется разработка. Можете протестировать код, используя учетную запись пользователя, из Visual Studio, интерфейса командной строки Azureили встроенной проверки подлинности Active Directory. Дополнительные сведения о параметрах локальной разработки с помощью этой библиотеки см. в справочнике Microsoft.Azure.Services.AppAuthentication. В этом разделе показано, как начать работу с библиотекой в коде.
Добавьте ссылки на пакеты NuGet Microsoft.Azure.Services.AppAuthentication и Microsoft.Azure.KeyVault в приложение.
Добавьте в приложение следующий код:
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 и примере .NET, использующем службу приложений и хранилище ключей с управляемыми удостоверениями для ресурсов Azure.
Получение маркера с использованием 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
Используйте эту библиотеку JSON для получения маркера с помощью 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;
}
}
}
}
}
Получение маркера с использованием 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
В следующем примере демонстрируется использование конечной точки REST управляемых удостоверений для ресурсов Azure из клиента PowerShell для выполнения следующих задач.
- Получение маркера доступа.
- Использование маркера доступа для вызова REST API Azure Resource Manager и получения информации о виртуальной машине. Не забудьте указать свой идентификатор подписки, имя группы ресурсов и имя виртуальной машины для
<SUBSCRIPTION-ID>
,<RESOURCE-GROUP>
и<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"}
Пример анализа маркера доступа, полученного из ответа:
# 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
кэшировании маркеров
Подсистема управляемых удостоверений кэширует токены, однако по-прежнему рекомендуется реализовать кэширование маркеров в коде. Поэтому следует подготовиться к сценариям, когда ресурс указывает, что срок действия маркера истек.
По проводным вызовам идентификатора Microsoft Entra id результат только в следующих случаях:
- произошел промах кэша из-за отсутствия маркера в кэше подсистемы управляемых удостоверений для ресурсов Azure;
- истек срок действия маркера в кэше.
Обработка ошибок
Конечная точка управляемых удостоверений службы сообщает об ошибках в поле кода состояния заголовка ответного сообщения HTTP в виде ошибок 4xx или 5xx.
Код состояния | Причина ошибки | Способ устранения |
---|---|---|
404. Не найдено. | Конечная точка IMDS обновляется. | Повторите попытку с экспоненциальным увеличением задержки. См. инструкции ниже. |
410 | IMDS проходит через обновления | IMDS будет доступен в течение 70 секунд |
429 — слишком много запросов | Достигнут предел регулирования IMDS. | Повторите попытку с экспоненциальным увеличением задержки. См. инструкции ниже. |
Ошибка 4xx в запросе. | Один или несколько параметров запроса неверные. | Не повторять попытку. Для получения дополнительной информации просмотрите сведения об ошибке. Ошибки 4xx — это ошибки времени разработки. |
Временная ошибка 5xx службы. | Управляемые удостоверения подсистемы ресурсов Azure или идентификатор Microsoft Entra возвращают временную ошибку. | По прошествии 1 секунды можно безопасно повторить попытку. Если вы слишком быстро или слишком часто повторите попытку, IMDS и /или идентификатор Microsoft Entra может вернуть ошибку ограничения скорости (429). |
timeout | Конечная точка IMDS обновляется. | Повторите попытку с экспоненциальным увеличением задержки. См. инструкции ниже. |
Если возникает ошибка, в соответствующем тексте ответа HTTP содержится код JSON с подробностями об ошибке:
Элемент | Description |
---|---|
error | Идентификатор ошибки. |
error_description | Подробное описание ошибки. Описания ошибок могут в любое время измениться. Не записывайте код, который создает ветвь на основе значений в описании ошибки. |
Ссылка ответа HTTP
В этом разделе описываются возможные сообщения об ошибках. Состояние "200 ОК" — это успешный ответ, а маркер доступа содержится в коде JSON текста ответа в элементе access_token.
Код состояния | Ошибка | Описание ошибки | Решение |
---|---|---|---|
400 Bad Request (Неверный запрос) | invalid_resource | AADSTS50001: приложение с именем <URI> не найдено в клиенте с именем <TENANT-ID>. Это сообщение появляется, если администратор клиента не установил приложение или ни один пользователь клиента не дал на него согласия. Возможно, вы отправили запрос на проверку подлинности не тому клиенту. | (только для Linux) |
400 Bad Request (Неверный запрос) | bad_request_102 | Необходимый заголовок метаданных не указан | Поле заголовка запроса Metadata отсутствует или имеет неправильный формат. Должно быть указано значение true в нижнем регистре. В качестве примера см. "Пример запроса" в предыдущем разделе для REST. |
401 Unauthorized (Не авторизовано) | unknown_source | Неизвестный <URI> источника | Убедитесь, что универсальный код ресурса (URI) запроса HTTP GET имеет правильный формат. Часть scheme:host/resource-path должна быть указана как http://localhost:50342/oauth2/token . В качестве примера см. "Пример запроса" в предыдущем разделе для REST. |
invalid_request | В запросе отсутствует требуемый параметр, он включает недопустимое значение параметра, параметр указан несколько раз или как-то искажен. | ||
unauthorized_client | Клиент не авторизован для запроса маркера доступа с помощью этого метода. | Возникает из-за того, что в запросе на виртуальной машине неправильно настроены управляемые удостоверения для ресурсов Azure. Если вам нужна помощь с конфигурацией виртуальной машины, ознакомьтесь с разделом Настройка управляемых удостоверений для ресурсов Azure на виртуальной машине с помощью портала Azure. | |
access_denied | Владелец ресурса или сервер авторизации отклонил запрос. | ||
unsupported_response_type | Сервер авторизации не поддерживает получение маркера доступа с помощью этого метода. | ||
invalid_scope | Запрошенная область недопустима, неизвестна или неверна. | ||
500 — внутренняя ошибка сервера | неизвестно | Не удалось извлечь маркер из Active Directory. Дополнительные сведения см. в журналах в <путь к файлу>. | Убедитесь, что на виртуальной машине включены управляемые удостоверения для ресурсов Azure. Если вам нужна помощь с конфигурацией виртуальной машины, ознакомьтесь с разделом Настройка управляемых удостоверений для ресурсов Azure на виртуальной машине с помощью портала Azure. Кроме того, убедитесь, что универсальный код ресурса (URI) запроса HTTP GET отформатирован правильно, в частности универсальный код ресурса (URI), указанный в строке запроса. Пример запроса см. в предыдущем разделе REST, например, или службы Azure, поддерживающие проверку подлинности Microsoft Entra, для списка служб и соответствующих идентификаторов ресурсов. |
Важно!
- Служба IMDS не предназначена для работы за прокси-сервером, и эта функция не поддерживается. Примеры обхода прокси-сервера см. здесь.
Рекомендации по использованию механизма повторов
Если вы получите код с ошибкой 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
Список ресурсов, поддерживающих управляемые удостоверения для ресурсов Azure, см. в статье Службы Azure с поддержкой управляемых удостоверений.
Следующие шаги
- Чтобы включить управляемые удостоверения для ресурсов Azure на виртуальной машине Azure, ознакомьтесь с разделом Настройка управляемых удостоверений для ресурсов Azure на виртуальной машине с помощью портала Azure.