Как получить токен для определенного назначенного пользователем удостоверения управляемой службы для службы приложений Azure?
Я пытаюсь получить MSI-токен для определенной пользовательской личности. Наш сервис приложений имеет 2 пользовательских идентификатора, и я хочу токен от имени одного из назначенных пользователем идентификаторов.
Вот код:
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(
"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/&object_id=<ObjectId>&client_id=<clientId>");
req.Headers["Metadata"] = "true";
req.Method = "GET";
try
{
// Call /token endpoint
HttpWebResponse response = (HttpWebResponse)req.GetResponse();
// Pipe response Stream to a StreamReader, and extract access token
StreamReader streamResponse = new StreamReader(response.GetResponseStream());
string stringResponse = streamResponse.ReadToEnd();
Dictionary<string, string> list =
JsonConvert.DeserializeObject<Dictionary<string, string>>(stringResponse);
string accessToken = list["access_token"];
System.IO.File.WriteAllText(@".\Log.txt", accessToken);
}
catch (Exception e)
{
string errorText = String.Format("{0} \n\n{1}", e.Message, e.InnerException != null ? e.InnerException.Message : "Acquire token failed");
System.IO.File.WriteAllText(@".\Log.txt", errorText);
throw;
}
Он развернут в службе приложений Azure. Когда я попадаю в этот раздел, я вижу эту ошибку: была сделана попытка получить доступ к сокету способом, запрещенным его правами доступа
Я попытался подключиться к http://169.254.169.254/ чтобы получить токен с помощью консоли kudu. Но эта конечная точка, кажется, не доступна там.
Я пытался использовать AzureServiceTokenProvider из Microsoft.Azure.Services.AppAuthentication для генерации токена MSI, но не смог найти никакой документации о том, как использовать его для нескольких назначенных пользователем удостоверений.
Редактировать:
Обновление 1:
Я попытался использовать конечную точку из переменной среды MSI_ENDPOINT вместо 169.254.169.254. Но похоже, что значение MSI_ENDPOINT не установлено, когда я запускаю службу приложения. Вот код, который я пробовал:
var endpoint = Environment.GetEnvironmentVariable("MSI_ENDPOINT");
string apiVersion = "2018-02-01";
string resource = "https://management.azure.com/";
string objectId = "<objectid>";
string clientId = "<clientId>";
// Build request to acquire managed identities for Azure resources token
//HttpWebRequest req = (HttpWebRequest)WebRequest.Create(
// "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/&object_id=4aef1720-b3b1-4935-8d68-e330508907fa&client_id=558ecc75-8697-4419-bab9-aa2c87043cfd");
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(
String.Format(
"{0}?resource={1}&api-version={2}&object_id={3}&client_id={4}",
endpoint,
resource,
apiVersion,
objectId,
clientId));
req.Headers["Metadata"] = "true";
req.Method = "GET";
try
{
// Call /token endpoint
HttpWebResponse response = (HttpWebResponse)req.GetResponse();
// Pipe response Stream to a StreamReader, and extract access token
StreamReader streamResponse = new StreamReader(response.GetResponseStream());
string stringResponse = streamResponse.ReadToEnd();
Dictionary<string, string> list =
JsonConvert.DeserializeObject<Dictionary<string, string>>(stringResponse);
string accessToken = list["access_token"];
System.IO.File.WriteAllText(@".\Log.txt", accessToken);
}
catch (Exception e)
{
string errorText = String.Format("{0} \n\n{1}", e.Message, e.InnerException != null ? e.InnerException.Message : "Acquire token failed");
string log = "MSI_ENDPOINT : " + endpoint + "\n";
log += ("ErrorText : " + errorText + "\n");
System.IO.File.WriteAllText(@".\Log.txt", errorText);
throw;
}
1 ответ
Во-первых, эта ссылка Как использовать управляемые удостоверения для функций приложений и служб Azure содержит хорошую документацию, относящуюся к MSI для служб приложений.
Вот быстрый пример кода... для получения токена для конкретного пользователя, которому назначен идентификатор управляемой службы, как вы задали в своем вопросе.
- ресурс - URI ресурса AAD ресурса, для которого должен быть получен токен.
- apiversion - версия API токена, которая будет использоваться. "2017-09-01" в настоящее время является единственной поддерживаемой версией.
clientId - идентификатор назначенного пользователем идентификатора, который будет использоваться. Если опущено, используется назначенный системой идентификатор.
public static async Task<HttpResponseMessage> GetToken(string resource, string apiversion, string clientId) { HttpClient client = new HttpClient(); client.DefaultRequestHeaders.Add("Secret", Environment.GetEnvironmentVariable("MSI_SECRET")); return await client.GetAsync(String.Format("{0}/?resource={1}&api-version={2}&clientid={3}", Environment.GetEnvironmentVariable("MSI_ENDPOINT"), resource, apiversion,clientId)); }
В целом я вижу несколько изменений, которые вы должны заметить в приведенном выше примере кода:
- Используйте MSI_ENDPOINT для создания URL во время выполнения
- параметр должен быть клиентским, а не client_id
- параметр object_id не нужен
- Версия API должна быть "2017-09-01", так как в приведенной выше ссылке указано, что поддерживается только одна версия.
Если вы не указали значение MSI_ENDPOINT при запуске службы приложения, просмотрите эту заметку по той же ссылке в Microsoft Docs.
Снимок экрана из документации, относящейся ко всем используемым параметрам