diff --git a/src/azure-cli-core/azure/cli/core/_profile.py b/src/azure-cli-core/azure/cli/core/_profile.py index eac084eb703..5f4e7ec328b 100644 --- a/src/azure-cli-core/azure/cli/core/_profile.py +++ b/src/azure-cli-core/azure/cli/core/_profile.py @@ -328,18 +328,14 @@ def logout_all(self): identity.logout_all_users() identity.logout_all_service_principal() - def get_login_credentials(self, resource=None, client_id=None, subscription_id=None, aux_subscriptions=None, - aux_tenants=None): + def get_login_credentials(self, client_id=None, subscription_id=None, aux_subscriptions=None, aux_tenants=None): """Get a CredentialAdaptor instance to be used with both Track 1 and Track 2 SDKs. - :param resource: The resource ID to acquire an access token. Only provide it for Track 1 SDKs. :param client_id: :param subscription_id: :param aux_subscriptions: :param aux_tenants: """ - resource = resource or self.cli_ctx.cloud.endpoints.active_directory_resource_id - if aux_tenants and aux_subscriptions: raise CLIError("Please specify only one of aux_subscriptions and aux_tenants, not both") @@ -368,11 +364,10 @@ def get_login_credentials(self, resource=None, client_id=None, subscription_id=N for external_tenant in external_tenants: external_credentials.append(self._create_credential(account, external_tenant, client_id=client_id)) from azure.cli.core.auth.credential_adaptor import CredentialAdaptor - cred = CredentialAdaptor(credential, - auxiliary_credentials=external_credentials, - resource=resource) + cred = CredentialAdaptor(credential, auxiliary_credentials=external_credentials) else: # managed identity + # TODO: Migrate MSIAuthentication to MSAL cred = MsiAccountTypes.msi_auth_factory(managed_identity_type, managed_identity_id, resource) return (cred, str(account[_SUBSCRIPTION_ID]), diff --git a/src/azure-cli-core/azure/cli/core/auth/credential_adaptor.py b/src/azure-cli-core/azure/cli/core/auth/credential_adaptor.py index dc97b48e6b2..10240c79056 100644 --- a/src/azure-cli-core/azure/cli/core/auth/credential_adaptor.py +++ b/src/azure-cli-core/azure/cli/core/auth/credential_adaptor.py @@ -3,24 +3,21 @@ # Licensed under the MIT License. See License.txt in the project root for license information. # -------------------------------------------------------------------------------------------- -import requests from knack.log import get_logger -from knack.util import CLIError -from .util import resource_to_scopes, _normalize_scopes +from .util import _normalize_scopes logger = get_logger(__name__) class CredentialAdaptor: - def __init__(self, credential, resource=None, auxiliary_credentials=None): + def __init__(self, credential, auxiliary_credentials=None): """ - Adaptor to both - - Track 1: msrest.authentication.Authentication, which exposes signed_session - - Track 2: azure.core.credentials.TokenCredential, which exposes get_token + Cross-tenant credential adaptor. It takes a main credential and auxiliary credentials. + + It implements Track 2 SDK's azure.core.credentials.TokenCredential by exposing get_token. :param credential: Main credential from .msal_authentication - :param resource: AAD resource for Track 1 only :param auxiliary_credentials: Credentials from .msal_authentication for cross tenant authentication. Details about cross tenant authentication: https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/authenticate-multi-tenant @@ -28,33 +25,9 @@ def __init__(self, credential, resource=None, auxiliary_credentials=None): self._credential = credential self._auxiliary_credentials = auxiliary_credentials - self._resource = resource - - def _get_token(self, scopes=None, **kwargs): - external_tenant_tokens = [] - # If scopes is not provided, use CLI-managed resource - scopes = scopes or resource_to_scopes(self._resource) - try: - token = self._credential.get_token(*scopes, **kwargs) - if self._auxiliary_credentials: - external_tenant_tokens = [cred.get_token(*scopes) for cred in self._auxiliary_credentials] - return token, external_tenant_tokens - except requests.exceptions.SSLError as err: - from azure.cli.core.util import SSLERROR_TEMPLATE - raise CLIError(SSLERROR_TEMPLATE.format(str(err))) - - def signed_session(self, session=None): - logger.debug("CredentialAdaptor.signed_session") - session = session or requests.Session() - token, external_tenant_tokens = self._get_token() - header = "{} {}".format('Bearer', token.token) - session.headers['Authorization'] = header - if external_tenant_tokens: - aux_tokens = ';'.join(['{} {}'.format('Bearer', tokens2.token) for tokens2 in external_tenant_tokens]) - session.headers['x-ms-authorization-auxiliary'] = aux_tokens - return session def get_token(self, *scopes, **kwargs): + """Get an access token from the main credential.""" logger.debug("CredentialAdaptor.get_token: scopes=%r, kwargs=%r", scopes, kwargs) # SDK azure-keyvault-keys 4.5.0b5 passes tenant_id as kwargs, but we don't support tenant_id for now, @@ -62,10 +35,10 @@ def get_token(self, *scopes, **kwargs): kwargs.pop('tenant_id', None) scopes = _normalize_scopes(scopes) - token, _ = self._get_token(scopes, **kwargs) - return token + return self._credential.get_token(*scopes, **kwargs) def get_auxiliary_tokens(self, *scopes, **kwargs): + """Get access tokens from auxiliary credentials.""" # To test cross-tenant authentication, see https://github.com/Azure/azure-cli/issues/16691 if self._auxiliary_credentials: return [cred.get_token(*scopes, **kwargs) for cred in self._auxiliary_credentials] diff --git a/src/azure-cli-core/azure/cli/core/auth/tests/test_credential_adaptor.py b/src/azure-cli-core/azure/cli/core/auth/tests/test_credential_adaptor.py deleted file mode 100644 index e955f492cd2..00000000000 --- a/src/azure-cli-core/azure/cli/core/auth/tests/test_credential_adaptor.py +++ /dev/null @@ -1,18 +0,0 @@ -# -------------------------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# -------------------------------------------------------------------------------------------- - -# pylint: disable=protected-access -import os -import json -import unittest -from unittest import mock - - -class TestIdentity(unittest.TestCase): - pass - - -if __name__ == '__main__': - unittest.main() diff --git a/src/azure-cli-core/azure/cli/core/auth/util.py b/src/azure-cli-core/azure/cli/core/auth/util.py index 61e91b27ca1..1e392eb444f 100644 --- a/src/azure-cli-core/azure/cli/core/auth/util.py +++ b/src/azure-cli-core/azure/cli/core/auth/util.py @@ -97,6 +97,7 @@ def scopes_to_resource(scopes): def _normalize_scopes(scopes): + # TODO: Drop this function """Normalize scopes to workaround some SDK issues.""" # Track 2 SDKs generated before https://github.com/Azure/autorest.python/pull/239 don't maintain diff --git a/src/azure-cli-core/azure/cli/core/commands/client_factory.py b/src/azure-cli-core/azure/cli/core/commands/client_factory.py index b0c17978758..b7fa59cf929 100644 --- a/src/azure-cli-core/azure/cli/core/commands/client_factory.py +++ b/src/azure-cli-core/azure/cli/core/commands/client_factory.py @@ -213,7 +213,6 @@ def _get_mgmt_service_client(cli_ctx, subscription_id=None, api_version=None, base_url_bound=True, - resource=None, sdk_profile=None, aux_subscriptions=None, aux_tenants=None, @@ -222,10 +221,6 @@ def _get_mgmt_service_client(cli_ctx, from azure.cli.core._profile import Profile logger.debug('Getting management service client client_type=%s', client_type.__name__) - # Track 1 SDK doesn't maintain the `resource`. The `resource` of the token is the one passed to - # get_login_credentials. - resource = resource or cli_ctx.cloud.endpoints.active_directory_resource_id - if credential: # Use a custom credential if not subscription_id: @@ -234,8 +229,7 @@ def _get_mgmt_service_client(cli_ctx, # Get a credential for the current `az login` context profile = Profile(cli_ctx=cli_ctx) credential, subscription_id, _ = profile.get_login_credentials( - subscription_id=subscription_id, resource=resource, - aux_subscriptions=aux_subscriptions, aux_tenants=aux_tenants) + subscription_id=subscription_id, aux_subscriptions=aux_subscriptions, aux_tenants=aux_tenants) client_kwargs = {} if base_url_bound: