Ошибка при получении токена доступа к управляемой идентификации из функции Azure - PullRequest
0 голосов
/ 18 июня 2020

У меня проблема с получением Azure токена доступа к управляемой идентификации из моего приложения-функции. Функция получает токен, а затем обращается к базе данных Mysql, используя этот токен в качестве пароля.

Я получаю ответ от функции:

9103 (HY000): An error occurred while validating the access token. Please acquire a new token and retry.

Код :

import logging
import mysql.connector
import requests
import azure.functions as func


def main(req: func.HttpRequest) -> func.HttpResponse:
    
    def get_access_token():

        URL = "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fossrdbms-aad.database.windows.net&client_id=<client_id>"
        headers = {"Metadata":"true"}

        try:
            req = requests.get(URL, headers=headers)
        except Exception as e:
            print(str(e))
            return str(e)
        else:
            password = req.json()["access_token"]

        return password

    def get_mysql_connection(password):
        """
        Get a Mysql Connection.
        """
        try:
            con = mysql.connector.connect(

            host='<host>.mysql.database.azure.com', 
            user='<user>@<db>',
            password=password,
            database = 'materials_db',
            auth_plugin='mysql_clear_password'
            )
        except Exception as e:

            print(str(e))
            return str(e)

        else:
            return "Connected to DB!"

    password = get_access_token()

    return func.HttpResponse(get_mysql_connection(password))

Запуск измененной версии этого кода на виртуальной машине с моим управляемым удостоверением работает. Кажется, что приложение-функция не может получить токен доступа. Любая помощь будет принята с благодарностью.

Примечание. Я ранее входил в базу данных как AzureAD Manager и создал этого пользователя со всеми привилегиями для этой базы данных.

Изменить : Больше не вызывает конечную точку для виртуальных машин.

def get_access_token():

    identity_endpoint = os.environ["IDENTITY_ENDPOINT"] # Env var provided by Azure. Local to service doing the requesting.
    identity_header = os.environ["IDENTITY_HEADER"] # Env var provided by Azure. Local to service doing the requesting.
    api_version = "2019-08-01" # "2018-02-01" #"2019-03-01" #"2019-08-01"
    CLIENT_ID = "<client_id>"
    resource_requested = "https%3A%2F%2Fossrdbms-aad.database.windows.net"
    # resource_requested = "https://ossrdbms-aad.database.windows.net"


    URL = f"{identity_endpoint}?api-version={api_version}&resource={resource_requested}&client_id={CLIENT_ID}"
    headers = {"X-IDENTITY-HEADER":identity_header}

    try:
        req = requests.get(URL, headers=headers)
    except Exception as e:
        print(str(e))
        return str(e)
    else:
        try:
            password = req.json()["access_token"]
        except:
            password = str(req.text)

    return password

Но теперь я получаю эту ошибку:

{"error":{"code":"UnsupportedApiVersion","message":"The HTTP resource that matches the request URI 'http://localhost:8081/msi/token?api-version=2019-08-01&resource=https%3A%2F%2Fossrdbms-aad.database.windows.net&client_id=<client_idxxxxx>' does not support the API version '2019-08-01'.","innerError":null}}

При проверке это кажется общей ошибкой. Это сообщение об ошибке распространяется, даже если это не основная проблема. Несколько раз отмечалось в Github.

Моя конечная точка теперь верна?

Ответы [ 2 ]

1 голос
/ 19 июня 2020

Эта проблема была вызвана неправильной конечной точкой, которую вы запрашивали для токена доступа. Мы можем просто использовать конечную точку http://169.254.169.254/metadata/identity..... в azure VM, но если в функции azure мы не можем ее использовать.

В функции azure, нам нужно получить IDENTITY_ENDPOINT из environment.

identity_endpoint = os.environ["IDENTITY_ENDPOINT"]

Конечная точка выглядит так:

http://127.0.0.1:xxxxx/MSI/token/

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

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

token_auth_uri = f"{identity_endpoint}?resource={resource_uri}&api-version=2019-08-01&client_id={client_id}"

Обновление:

#r "Newtonsoft.Json"

using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;

public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
{
    string resource="https://ossrdbms-aad.database.windows.net";
    string clientId="xxxxxxxx";
    log.LogInformation("C# HTTP trigger function processed a request.");
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(String.Format("{0}/?resource={1}&api-version=2019-08-01&client_id={2}", Environment.GetEnvironmentVariable("IDENTITY_ENDPOINT"), resource,clientId));
    request.Headers["X-IDENTITY-HEADER"] = Environment.GetEnvironmentVariable("IDENTITY_HEADER");
    request.Method = "GET";

    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
    StreamReader streamResponse = new StreamReader(response.GetResponseStream());
    string stringResponse = streamResponse.ReadToEnd();
    log.LogInformation("test:"+stringResponse);

    string name = req.Query["name"];

    string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    dynamic data = JsonConvert.DeserializeObject(requestBody);
    name = name ?? data?.name;

    return name != null
        ? (ActionResult)new OkObjectResult($"Hello, {name}")
        : new BadRequestObjectResult("Please pass a name on the query string or in the request body");
}
0 голосов
/ 13 июля 2020

Что касается вашей последней проблемы, когда вы видите UnsupportedApiVersion, вероятно, это проблема: https://github.com/MicrosoftDocs/azure-docs/issues/53726

Вот несколько вариантов, которые у меня сработали:

Я предполагаю, что вы размещаете приложение Function на Linux. Я заметил, что ApiVersion 2017-09-01 работает, но вам нужно внести дополнительные изменения (вместо «X-IDENTITY-HEADER» используйте «секретный» заголовок). А также используйте назначенное системой управляемое удостоверение для вашего приложения-функции, а не удостоверение, назначенное пользователем.

Когда я размещал приложение-функцию на Windows, у меня не было таких проблем. Поэтому, если вы хотите использовать управляемое удостоверение, назначенное пользователем, вы можете попробовать этот вариант. (с api-version = 2019-08-01 и X-IDENTITY-HEADER.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...