Как получить токен для конкретного пользователя, назначенного удостоверением управляемой службы для Службы приложений 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;
        }

person Jitendra Singh Rathor    schedule 31.01.2019    source источник
comment
Поскольку вы используете MSI со службой приложений ... вам, вероятно, следует попробовать использовать переменную среды MSI_ENDPOINT. Посмотрите здесь пример кода C #, чтобы узнать, как создать URL - docs.microsoft.com/en-us/azure/app-service/ .. Что-то вроде String.Format("{0}/?resource={1}&api-version={2}&object_id={3}&client_id={4}", Environment.GetEnvironmentVariable("MSI_ENDPOINT"), resource, apiversion, objectId, clientId));   -  person Rohit Saigal    schedule 01.02.2019
comment
Я смотрел MSI-Endpoint. Значение: 127.0.0.1:41811/MSI/token. Поэтому я изменил URL-адрес на 127.0.0.1:41811/MSI/token? api-version = 2018-02-01 & resource = management.azure.com /› Теперь я получаю сообщение об ошибке Не удалось подключиться к удаленному серверу. Вероятно, конечная точка недоступна.   -  person Jitendra Singh Rathor    schedule 01.02.2019
comment
Хорошо, понятно .. Я думаю, что URL-адрес должен быть создан во время выполнения с использованием переменной, как в примере кода в ссылке, показано ... вместо того, чтобы вводить 127.0.0.1 Также попробуйте передать только clientid в параметрах строки запроса для URL-адреса, а не objectId .. Я думаю, это должно быть clientid = где у вас client_id =   -  person Rohit Saigal    schedule 01.02.2019
comment
Когда я создаю его во время выполнения. MSI_ENDPOINT не установлен. На консоли Kudu я вижу, что значение переменной среды MSI_ENDPOINT установлено, но когда при запуске службы приложения значение MSI_ENDPOINT не установлено.   -  person Jitendra Singh Rathor    schedule 01.02.2019
comment
Возможно, вам потребуется перезапустить приложение или повторно развернуть код. См. Это примечание в Microsoft Docs .. Environment variables are set up when the process first starts, so after enabling a managed identity for your application, you may need to restart your application, or redeploy its code, before MSI_ENDPOINT and MSI_SECRET are available to your code.   -  person Rohit Saigal    schedule 01.02.2019
comment
Я вижу и другие изменения, которые необходимы для вашего кода. Я соберу все вместе и отправлю в качестве ответа образец кода, ссылку, снимок экрана и т. Д.   -  person Rohit Saigal    schedule 01.02.2019


Ответы (1)


Во-первых, эта ссылка Как использовать управляемые удостоверения для Служба приложений и функции Azure предоставляет хорошую документацию, относящуюся к MSI для служб приложений.

Вот краткий пример кода ... чтобы получить токен для конкретного пользователя, назначенного идентификатором управляемой службы, как вы задали в своем вопросе.

  • resource - 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));
    }
    

    В целом я вижу несколько изменений, которые вы должны заметить в приведенном выше примере кода:

    1. Make use of MSI_ENDPOINT to construct URL at runtime
    2. параметр должен быть clientid, а не client_id
    3. параметр object_id не нужен
    4. Версия api должна быть «2017-09-01», поскольку документация в приведенной выше ссылке говорит, что это единственная поддерживаемая версия.
  • Что касается вашей проблемы, когда значение MSI_ENDPOINT не устанавливается при запуске службы приложения, ознакомьтесь с этим примечанием по той же ссылке в Microsoft Docs.

    введите описание изображения здесь

  • Скриншот из документации, актуальной для всех используемых параметров

    введите описание изображения здесь

person Rohit Saigal    schedule 01.02.2019