Получите маркер обновления Azure Active Directory для ACR

#python #azure #azure-active-directory #access-token #azure-sdk

Вопрос:

Я пытался использовать поток интерактивной аутентификации AAD для перечисления изображений в данном экземпляре реестра контейнеров Azure (как описано здесь), для которого требуется как токен доступа AAD, так и токен обновления AAD, чтобы получить токены обновления/доступа самого ресурса.

Я предположил, что требуемый токен доступа AAD-это простой токен доступа к ‘management.azure.com’, который я получаю со следующим кодом:

 from azure.identity import DefaultAzureCredential, InteractiveBrowserCredential
credentials = InteractiveBrowserCredential()
aad_access_token = credentials.get_token('https://management.azure.com/.default')
 

Который возвращает обычный токен доступа (например, «eyJ0eX…»). Однако я не смог найти никаких ссылок на получение токена обновления программно; Похоже, что все SDK Azure заботятся об этом в фоновом режиме. Есть ли какой-либо способ получить этот токен, поскольку для потока аутентификации самого ресурса (ACR) требуются оба токена?

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

Также важно отметить — я работаю в среде, где Azure CLI не функционирует, поэтому я должен использовать SDK python или аналогичные инструменты и не рассчитывать на системные команды, такие как «вход в систему az» или «получение учетных данных az».

Ответ №1:

Поэтому у меня возникло несколько недоразумений относительно функциональности токенов обновления и доступа с ресурсами AAD и Azure. Немного проб и ошибок, я обнаружил, что следующий код работает просто отлично:

 import requests
from azure.identity import InteractiveBrowserCredential
from pprint import pprint

CATALOG_SCOPE = "registry:catalog:*"
AZURE_MANAGEMENT_SCOPE_URL = 'https://management.azure.com/.default'
ACR_URL = "YOUR_REPO.azurecr.io"


def get_aad_access_token():
    cred = InteractiveBrowserCredential()
    aad_access_token = cred.get_token(AZURE_MANAGEMENT_SCOPE_URL)
    return aad_access_token.token


def get_acr_refresh_token(acr_url, aad_access_token):
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded',
    }

    data = {
        'grant_type': 'access_token',
        'service': acr_url,
        'access_token': aad_access_token
    }

    response = requests.post(f'https://{acr_url}/oauth2/exchange', headers=headers, data=data)
    acr_refresh_token = json.loads(response.content)
    # pprint(response.__dict__)
    return acr_refresh_token['refresh_token']


def get_acr_access_token(acr_refresh_token, acr_url, scope):
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded',
    }

    data = {
        'grant_type': 'refresh_token',
        'service': acr_url,
        'scope': scope,
        'refresh_token': acr_refresh_token
    }

    response = requests.post(f'https://{acr_url}/oauth2/token', headers=headers, data=data)
    # pprint(response.__dict__)
    acr_access_token = json.loads(response.content)
    return acr_access_token['access_token']


def list_acr_images(acr_url):
    operation = "/v2/_catalog/"
    aad_access_token = get_aad_access_token()
    acr_refresh_token = get_acr_refresh_token(acr_url, aad_access_token)
    acr_access_token = get_acr_access_token(acr_refresh_token, acr_url, CATALOG_SCOPE)

    headers = {
        'Authorization': f"Bearer {acr_access_token}",
    }

    response = requests.post(f'https://{acr_url}{operation}', headers=headers)
    return json.loads(response.content)


if __name__ == '__main__':
    pprint(list_acr_images(ACR_URL))