Токен аутентификации не имеет доступа на уровне регистрации

Фон

Я делаю спокойный вызов API к конечной точке потребления Microsoft Azure, как описано ниже.

https://docs.microsoft.com/en-gb/rest/api/consumment/reservationrecommendations/list

Однако я всегда получаю следующую ошибку.

Маркер аутентификации не имеет доступа на уровне регистрации.

{
  "error": {
    "code": "401",
    "message": "Authentication token doesn't have enrollment level access. 
  }
}

Токен действителен и может использоваться для доступа к другим конечным точкам в API потребления. Тестовая ссылка «Попробуйте» на странице Azure фактически возвращает 200, однако, когда я делаю вызов, я получаю 401.

Вопрос

Может ли кто-нибудь пролить свет на это сообщение об ошибке? Я нигде не могу найти помощь по этой ошибке.

Код

Аутентификация

https://docs.microsoft.com/en-gb/azure/active-directory/develop/v1-oauth2-client-creds-grant-flow#first-case-access-token-request-with-a-shared-secret

 private static string GetAccessToken(string clientId, string clientSecret, string tenantId)
    {

        HttpClient client = new HttpClient();
        client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json;");

        string hostname = $"https://login.microsoftonline.com/{tenantId}/oauth2/token";

        var content = new FormUrlEncodedContent(new[]
        {
            new KeyValuePair<string, string>("grant_type", "client_credentials"),
            new KeyValuePair<string, string>("client_id", clientId),
            new KeyValuePair<string, string>("client_secret", clientSecret),
            new KeyValuePair<string, string>("resource", "https://management.azure.com/")
        });

        HttpResponseMessage httpResponse = client.PostAsync(hostname, content).Result;
        var responseString = httpResponse.Content.ReadAsStringAsync();

        if (httpResponse.StatusCode == HttpStatusCode.OK)
        {
            dynamic tokenObject = JsonConvert.DeserializeObject(responseString.Result);

            return tokenObject.access_token;
        }
        else
        {
            return null;
        }
    }

Вызов API

 public static dynamic GetReservationRecommendations(Params parameters)
 {
   var token = GetAccessToken(parameters.ClientId, parameters.ClientSecret, parameters.TenantId);

     HttpClient client = new HttpClient();
     client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", token);
     client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json;");

     string hostname = $"https://management.azure.com/subscriptions/{parameters.SubscriptionId}/providers/Microsoft.Consumption/reservationRecommendations?api-version=2018-10-01";

     HttpResponseMessage httpResponse = client.GetAsync(hostname).Result;
     var responseString = httpResponse.Content.ReadAsStringAsync();

     if (httpResponse.StatusCode == HttpStatusCode.OK)
     {
         return responseString.Result;
     }
     else
     {
         return null;
     }
 }

person Dan Cundy    schedule 29.11.2018    source источник
comment
Работает ли это с Try it в ссылке, которую вы упомянули?   -  person Joy Wang    schedule 30.11.2018
comment
Не могли бы вы показать более подробный код о том, как сгенерировать токен?   -  person Joey Cai    schedule 30.11.2018
comment
@JoyWang да, это так.   -  person Dan Cundy    schedule 03.12.2018
comment
@JoeyCai добавил фрагмент кода.   -  person Dan Cundy    schedule 03.12.2018
comment
Похоже, что пользователи, аутентифицирующиеся с помощью этого токена, не имеют правильных разрешений для выполнения этого действия.   -  person Luc    schedule 03.12.2018
comment
@DanCundy В прошлом я наблюдал странное поведение, когда показатели потребления были доступны только нашему первоначальному пользователю, который зарегистрировал нашу подписку Azure, несмотря на то, что они якобы имели те же разрешения, что и другие наши администраторы. Это было для внешнего интерфейса портала Enterprise Access, поэтому оно может не применяться, но похоже, что есть некоторый дополнительный уровень доступа, помимо того, что в управлении пользователями Azure.   -  person UpQuark    schedule 05.12.2018
comment
@UpQuark Да, это очень странное поведение. На данный момент я решил использовать Billing API с учетными данными EA, но предпочел бы использовать API потребления для всех.   -  person Dan Cundy    schedule 05.12.2018


Ответы (1)


Обоснование ошибки

Идентификатор приложения, который вы используете для получения токена, не имеет достаточных разрешений для API потребления — список рекомендаций по резервированию

Попробуйте, тестовая ссылка работает, но код не работает

AFAIK Попробуйте ссылку, которая попросит вас сначала войти в систему с учетной записью в браузере. Таким образом, он использует идентификатор пользователя, а не идентификатор приложения. Таким образом, возможно, что пользователь, с которым вы тестируете, имеет достаточно высокие разрешения/роль, но код, конечно, использует clientId и clientSecret, поэтому он все равно может дать сбой, если приложение не получит все необходимые разрешения.

Необходимые разрешения

  1. Этот API использует разрешения ARM, поэтому вашему субъекту-службе приложения необходимо предоставить разрешения. Минимум роль «Читатель управления затратами». (Возможно, вы сделали это, поскольку упомянули, что некоторые другие конечные точки работают на вас)

    На портале Azure выберите Подписки > Ваша подписка > IAM.

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

    Затем добавьте назначение роли для субъекта-службы вашего приложения.

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

  2. Глядя на сообщение об ошибке «Токен аутентификации не имеет доступа на уровне регистрации», я думаю, что ваша подписка Azure находится в рамках EA (т. е. Соглашение Enterprise). Я говорю это, потому что смог воспроизвести точно такое же сообщение об ошибке только в подписке EA, а не в другой обычной подписке с оплатой по мере использования, когда субъект-служба уже имел роль «Читатель управления затратами». Если ваша подписка находится под подпиской EA, выполните следующие действия.

    Поэтому необходимо предоставить разрешения на портале Azure и корпоративном портале (портал EA). Подробности см. в этой документации Microsoft. Назначить доступ к данным Управления затратами< /а>

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

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

    Пожалуйста, следуйте этой документации для действий, связанных с порталом EA. Включить доступ к расходам на портале EA введите здесь описание изображения

person Rohit Saigal    schedule 06.12.2018
comment
Я не уверен, что именно в этом проблема, так как у меня включены оба выделенных раздела на портале EA. мой субъект-служба приложения также является считывателем биллинга и имеет доступ к API управления. Я изучаю возможность предоставления субъекту-службе приложения владельца с соответствующими привилегиями, но пока не удосужился протестировать эту идею. - person Dan Cundy; 10.12.2018