Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/azure-cli-core/azure/cli/core/_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -879,7 +879,13 @@ def _find_using_common_tenant(self, access_token, resource):
# because user creds went through the 'common' tenant, the error here must be
# tenant specific, like the account was disabled. For such errors, we will continue
# with other tenants.
logger.warning("Failed to authenticate '%s' due to error '%s'", t, ex)
msg = (getattr(ex, 'error_response', None) or {}).get('error_description') or ''
if 'AADSTS50076' in msg:
logger.warning("Tenant %s requires Multi-Factor Authentication (MFA). "
"To access this tenant, use 'az login --tenant' to explicitly "
"login to this tenant.", tenant_id)
else:
logger.warning("Failed to authenticate '%s' due to error '%s'", t, ex)
continue
subscriptions = self._find_using_specific_tenant(
tenant_id,
Expand Down
42 changes: 42 additions & 0 deletions src/azure-cli-core/azure/cli/core/tests/test_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -1847,6 +1847,48 @@ def test_find_using_common_tenant(self, _get_authorization_code_mock, mock_auth_
self.assertEqual(len(all_subscriptions), 1)
self.assertEqual(all_subscriptions[0].tenant_id, self.tenant_id)

@mock.patch('adal.AuthenticationContext', autospec=True)
@mock.patch('azure.cli.core._profile._get_authorization_code', autospec=True)
def test_find_using_common_tenant_mfa_warning(self, _get_authorization_code_mock, mock_auth_context):
# Assume 2 tenants. Home tenant tenant1 doesn't require MFA, but tenant2 does
import adal
cli = DummyCli()
mock_arm_client = mock.MagicMock()
tenant2_mfa_id = 'tenant2-0000-0000-0000-000000000000'
mock_arm_client.tenants.list.return_value = [TenantStub(self.tenant_id), TenantStub(tenant2_mfa_id)]
mock_arm_client.subscriptions.list.return_value = [deepcopy(self.subscription1_raw)]
token_cache = adal.TokenCache()
finder = SubscriptionFinder(cli, lambda _, _1, _2: mock_auth_context, token_cache, lambda _: mock_arm_client)

adal_error_mfa = adal.AdalError(error_msg="", error_response={
'error': 'interaction_required',
'error_description': "AADSTS50076: Due to a configuration change made by your administrator, "
"or because you moved to a new location, you must use multi-factor "
"authentication to access '797f4846-ba00-4fd7-ba43-dac1f8f63013'.\n"
"Trace ID: 00000000-0000-0000-0000-000000000000\n"
"Correlation ID: 00000000-0000-0000-0000-000000000000\n"
"Timestamp: 2020-03-10 04:42:59Z",
'error_codes': [50076],
'timestamp': '2020-03-10 04:42:59Z',
'trace_id': '00000000-0000-0000-0000-000000000000',
'correlation_id': '00000000-0000-0000-0000-000000000000',
'error_uri': 'https://login.microsoftonline.com/error?code=50076',
'suberror': 'basic_action'})

# adal_error_mfa are raised on the second call
mock_auth_context.acquire_token.side_effect = [self.token_entry1, adal_error_mfa]

# action
all_subscriptions = finder._find_using_common_tenant(access_token="token1",
resource='https://management.core.windows.net/')

# assert
# subscriptions are correctly returned
self.assertEqual(all_subscriptions, [self.subscription1])
self.assertEqual(mock_auth_context.acquire_token.call_count, 2)

# With pytest, use -o log_cli=True to manually check the log

@mock.patch('adal.AuthenticationContext', autospec=True)
@mock.patch('azure.cli.core._profile._get_authorization_code', autospec=True)
def test_find_using_specific_tenant(self, _get_authorization_code_mock, mock_auth_context):
Expand Down