API .NetCore 2.2 не удается получить токен из AAD при использовании назначенного пользователем удостоверения - PullRequest
0 голосов
/ 17 января 2019

Мы не можем запросить базу данных sql в Azure из службы приложений Azure при использовании назначенного пользователем управляемого идентификатора (он работает нормально, если мы используем назначенный системой управляемый идентификатор)

Приложение является приложением .net core 2.2 web api.

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

Это удостоверение было настроено как администратор ad sql с помощью следующей команды:

az sql сервер ad-admin создать --resource-группа iactests --server iactestsql --object-id -u iactestmanagedIdentity

Маркер генерируется так:

services.AddDbContext<SchoolContext>(options => options.UseSqlServer(new 
SqlConnection
        {
            ConnectionString = configuration.GetConnectionString("SchoolContext"),
            AccessToken = isDevelopmentEnvironment ? null : new AzureServiceTokenProvider().GetAccessTokenAsync("https://database.windows.net/").Result
        }), ServiceLifetime.Scoped);

Это ошибка, которую мы получаем:

    Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProviderException: Parameters: Connection String: [No connection string specified], Resource: https://database.windows.net/, Authority: . Exception Message: Tried the following 3 methods to get an access token, but none of them worked.
Parameters: Connection String: [No connection string specified], Resource: https://database.windows.net/, Authority: . Exception Message: Tried to get token using Managed Service Identity. Access token could not be acquired. MSI ResponseCode: BadRequest, Response: 
Parameters: Connection String: [No connection string specified], Resource: https://database.windows.net/, Authority: . Exception Message: Tried to get token using Visual Studio. Access token could not be acquired. Visual Studio Token provider file not found at "D:\local\LocalAppData\.IdentityService\AzureServiceAuth\tokenprovider.json"
Parameters: Connection String: [No connection string specified], Resource: https://database.windows.net/, Authority: . Exception Message: Tried to get token using Azure CLI. Access token could not be acquired. 'az' is not recognized as an internal or external command,
operable program or batch file.


at Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProvider.GetAuthResultAsyncImpl(String authority, String resource, String scope)
at Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProvider.GetAuthenticationResultAsync(String resource, String tenantId)
at Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProvider.GetAccessTokenAsync(String resource, String tenantId)
--- End of inner exception stack trace ---

Если мы используем системное назначение идентификатора и настраиваем имя администратора sql в качестве идентификатора, это работает нормально

Есть идеи?

Заранее спасибо

Ответы [ 2 ]

0 голосов
/ 08 апреля 2019

Библиотека AppAuthentication теперь поддерживает указание назначенных пользователем удостоверений для виртуальных машин Azure и служб приложений начиная с версии 1.2.0-preview2 .

Чтобы использовать назначенный пользователем идентификатор, вам нужно установить строку подключения AppAuthentication в формате:

RunAs=App;AppId={ClientId of user-assigned identity}

Строка подключения AppAuthentication может быть установлена ​​в качестве аргумента, передаваемого в конструктор AzureServiceTokenProvider, или указана в переменной среды AzureServicesAuthConnectionString . Для получения дополнительной информации о строках соединения AppAuthentication см. здесь .

0 голосов
/ 17 января 2019

Похоже, AzureServiceTokenProvider не поддерживает назначенные пользователем управляемые удостоверения, по крайней мере, на этом этапе. AzureServiceTokenProvder - это оболочка над локальной конечной точкой HTTP, которая предоставляет токены для приложения.

Я смотрел на это и, похоже, вы должны предоставить clientId конечной точки, назначенной пользователем, для получения токена. А у AzureServiceTokenProvider нет способа сделать это (по крайней мере, я мог бы это выяснить).

Назначенные пользователем управляемые удостоверения добавляют возможность иметь несколько Назначенных пользователем управляемых удостоверений для приложения. Таким образом, API для получения токена должен указывать, какой MSI вы хотите, назначенный системой MSI или один из назначенных пользователем MSI. Конечная точка HTTP делает это так, что она использует назначенный системой MSI, если вы не укажете clientId.

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

public async Task<String> GetToken(string resource, string clientId = null)
{
    var endpoint = System.Environment.GetEnvironmentVariable("MSI_ENDPOINT", EnvironmentVariableTarget.Process);
    var secret = System.Environment.GetEnvironmentVariable("MSI_SECRET", EnvironmentVariableTarget.Process);

    if (string.IsNullOrEmpty(endpoint))
    {
        throw new InvalidOperationException("MSI_ENDPOINT environment variable not set");
    }
    if (string.IsNullOrEmpty(secret))
    {
        throw new InvalidOperationException("MSI_SECRET environment variable not set");
    }

    Uri uri;
    if (clientId == null)
    {
        uri = new Uri($"{endpoint}?resource={resource}&api-version=2017-09-01");
    }
    else
    {
        uri = new Uri($"{endpoint}?resource={resource}&api-version=2017-09-01&clientid={clientId}");
    }

    // get token from MSI
    var tokenRequest = new HttpRequestMessage()
    {
        RequestUri = uri,
        Method = HttpMethod.Get
    };
    tokenRequest.Headers.Add("secret", secret);
    var httpClient = new HttpClient();

    var response = await httpClient.SendAsync(tokenRequest);

    var body = await response.Content.ReadAsStringAsync();
    var result = JObject.Parse(body);

    string token = result["access_token"].ToString();
    return token;

}
...