This commit is contained in:
jiasli 2024-11-20 12:03:18 +08:00
Родитель 1d062eebac
Коммит 9292267c86
5 изменённых файлов: 30 добавлений и 22 удалений

Просмотреть файл

@ -867,11 +867,16 @@ def check_connectivity(url='https://azure.microsoft.com', max_retries=5, timeout
def send_raw_request(cli_ctx, method, url, headers=None, uri_parameters=None, # pylint: disable=too-many-locals,too-many-branches,too-many-statements
body=None, skip_authorization_header=False, resource=None, output_file=None,
body=None, skip_authorization_header=False, resource=None, scopes=None, output_file=None,
generated_client_request_id_name='x-ms-client-request-id'):
import uuid
from requests import Session, Request
from requests.structures import CaseInsensitiveDict
from .auth.util import resource_to_scopes
# Prefer MSAL-styled scopes over ADAL-styled resource
if resource and not scopes:
scopes = resource_to_scopes(resource)
result = CaseInsensitiveDict()
for s in headers or []:
@ -952,13 +957,13 @@ def send_raw_request(cli_ctx, method, url, headers=None, uri_parameters=None, #
# Prepare the Bearer token for `Authorization` header
if not skip_authorization_header and url.lower().startswith('https://'):
# Prepare `resource` for `get_raw_token`
if not resource:
# Prepare `scopes` for `get_raw_token`
if not scopes:
# If url starts with ARM endpoint, like `https://management.azure.com/`,
# use `active_directory_resource_id` for resource, like `https://management.core.windows.net/`.
# use `active_directory_resource_id` for scopes, like `https://management.core.windows.net//.default`.
# This follows the same behavior as `azure.cli.core.commands.client_factory._get_mgmt_service_client`
if url.lower().startswith(endpoints.resource_manager.rstrip('/')):
resource = endpoints.active_directory_resource_id
scopes = resource_to_scopes(endpoints.active_directory_resource_id)
else:
from azure.cli.core.cloud import CloudEndpointNotSetException
for p in [x for x in dir(endpoints) if not x.startswith('_')]:
@ -967,9 +972,9 @@ def send_raw_request(cli_ctx, method, url, headers=None, uri_parameters=None, #
except CloudEndpointNotSetException:
continue
if isinstance(value, str) and url.lower().startswith(value.lower()):
resource = value
scopes = resource_to_scopes(value)
break
if resource:
if scopes:
# Prepare `subscription` for `get_raw_token`
# If this is an ARM request, try to extract subscription ID from the URL.
# But there are APIs which don't require subscription ID, like /subscriptions, /tenants
@ -979,17 +984,17 @@ def send_raw_request(cli_ctx, method, url, headers=None, uri_parameters=None, #
if url.lower().startswith(endpoints.resource_manager.rstrip('/')):
token_subscription = _extract_subscription_id(url)
if token_subscription:
logger.debug('Retrieving token for resource %s, subscription %s', resource, token_subscription)
token_info, _, _ = profile.get_raw_token(resource, subscription=token_subscription)
logger.debug('Retrieving token for scopes %s, subscription %s', scopes, token_subscription)
token_info, _, _ = profile.get_raw_token(scopes=scopes, subscription=token_subscription)
else:
logger.debug('Retrieving token for resource %s', resource)
token_info, _, _ = profile.get_raw_token(resource)
logger.debug('Retrieving token for scopes %s', scopes)
token_info, _, _ = profile.get_raw_token(scopes=scopes)
token_type, token, _ = token_info
headers = headers or {}
headers['Authorization'] = '{} {}'.format(token_type, token)
else:
logger.warning("Can't derive appropriate Azure AD resource from --url to acquire an access token. "
"If access token is required, use --resource to specify the resource")
logger.warning("Can't derive appropriate Microsoft Entra ID scopes from --url to acquire an access token. "
"If access token is required, use --scope to specify the scopes")
# https://requests.readthedocs.io/en/latest/user/advanced/#prepared-requests
s = Session()

Просмотреть файл

@ -33,11 +33,10 @@ class GraphClient:
def __init__(self, cli_ctx):
self._cli_ctx = cli_ctx
self._scopes = resource_to_scopes(cli_ctx.cloud.endpoints.microsoft_graph_resource_id)
# https://graph.microsoft.com/ (AzureCloud)
# https://microsoftgraph.chinacloudapi.cn (AzureChinaCloud)
self._resource = cli_ctx.cloud.endpoints.microsoft_graph_resource_id
# https://graph.microsoft.com//.default (AzureCloud)
# https://microsoftgraph.chinacloudapi.cn/.default (AzureChinaCloud)
self._scopes = resource_to_scopes(cli_ctx.cloud.endpoints.microsoft_graph_resource_id)
# https://graph.microsoft.com
# https://microsoftgraph.chinacloudapi.cn
@ -54,7 +53,7 @@ class GraphClient:
while True:
try:
r = send_raw_request(self._cli_ctx, method, url, resource=self._resource, uri_parameters=param,
r = send_raw_request(self._cli_ctx, method, url, scopes=self._scopes, uri_parameters=param,
body=body)
except HTTPError as ex:
raise GraphError(ex.response.json()['error']['message'], ex.response) from ex

Просмотреть файл

@ -30,7 +30,10 @@ def load_arguments(self, _):
'see https://github.com/Azure/azure-cli/blob/dev/doc/use_cli_effectively.md#quoting-issues')
c.argument('output_file', help='save response payload to a file')
c.argument('resource',
help='Resource url for which CLI should acquire a token from AAD in order to access '
help='Resource url for which CLI should acquire a token from Microsoft Entra ID in order to access '
'the service. Using --scope is preferred.')
c.argument('scopes', options_list=['--scope'], nargs='+',
help='Scopes for which CLI should acquire a token from Microsoft Entra ID in order to access '
'the service. The token will be placed in the Authorization header. By default, '
'CLI can figure this out based on --url argument, unless you use ones not in the list '
'of "az cloud show --query endpoints"')

Просмотреть файл

@ -15,14 +15,15 @@ SECRET_STORE_DEMO = "secret_store_demo"
def rest_call(cmd, url, method=None, headers=None, uri_parameters=None,
body=None, skip_authorization_header=False, resource=None, output_file=None):
body=None, skip_authorization_header=False, resource=None, scopes=None, output_file=None):
from azure.cli.core.commands.transform import unregister_global_transforms
# No transform should be performed on `az rest`.
unregister_global_transforms(cmd.cli_ctx)
from azure.cli.core.util import send_raw_request
r = send_raw_request(cmd.cli_ctx, method, url, headers, uri_parameters, body,
skip_authorization_header, resource, output_file)
r = send_raw_request(cmd.cli_ctx, method, url, headers=headers, uri_parameters=uri_parameters, body=body,
skip_authorization_header=skip_authorization_header, resource=resource, scopes=scopes,
output_file=output_file)
if not output_file and r.content:
try:
return r.json()