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
22 changes: 17 additions & 5 deletions src/azure-cli-core/azure/cli/core/tests/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -380,26 +380,38 @@ def test_send_raw_requests(self, send_mock, get_raw_token_mock):
def test_scopes_to_resource(self):
from azure.cli.core.util import scopes_to_resource
# scopes as a list
self.assertEqual(scopes_to_resource(['https://management.core.windows.net/.default']),
self.assertEqual(scopes_to_resource(['https://management.core.windows.net//.default']),
'https://management.core.windows.net/')
# scopes as a tuple
self.assertEqual(scopes_to_resource(('https://storage.azure.com/.default',)),
'https://storage.azure.com/')
'https://storage.azure.com')

# Double slashes are reduced
# resource with trailing slash
self.assertEqual(scopes_to_resource(('https://management.azure.com//.default',)),
'https://management.azure.com/')
self.assertEqual(scopes_to_resource(['https://datalake.azure.net//.default']),
'https://datalake.azure.net/')

# resource without trailing slash
self.assertEqual(scopes_to_resource(('https://managedhsm.azure.com/.default',)),
'https://managedhsm.azure.com')

def test_resource_to_scopes(self):
from azure.cli.core.util import resource_to_scopes
# resource converted to a scopes list
self.assertEqual(resource_to_scopes('https://management.core.windows.net/'),
['https://management.core.windows.net/.default'])
['https://management.core.windows.net//.default'])

# Use double slashes for certain services
# resource with trailing slash
self.assertEqual(resource_to_scopes('https://management.azure.com/'),
['https://management.azure.com//.default'])
self.assertEqual(resource_to_scopes('https://datalake.azure.net/'),
['https://datalake.azure.net//.default'])

# resource without trailing slash
self.assertEqual(resource_to_scopes('https://managedhsm.azure.com'),
['https://managedhsm.azure.com/.default'])


class TestBase64ToHex(unittest.TestCase):

Expand Down
26 changes: 13 additions & 13 deletions src/azure-cli-core/azure/cli/core/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -1169,32 +1169,32 @@ def handle_version_update():

def resource_to_scopes(resource):
"""Convert the ADAL resource ID to MSAL scopes by appending the /.default suffix and return a list.
For example: 'https://management.core.windows.net/' -> ['https://management.core.windows.net/.default']
For example:
'https://management.core.windows.net/' -> ['https://management.core.windows.net//.default']
'https://managedhsm.azure.com' -> ['https://managedhsm.azure.com/.default']

:param resource: The ADAL resource ID
:return: A list of scopes
"""
if 'datalake' in resource or 'batch' in resource or 'database' in resource:
# For datalake, batch and database, the slash must be doubled due to service issue, like
# https://datalake.azure.net//.default
# TODO: This should be fixed on the service side.
scope = resource + '/.default'
else:
scope = resource.rstrip('/') + '/.default'
# https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-permissions-and-consent#trailing-slash-and-default
# We should not trim the trailing slash, like in https://management.azure.com/
# In other word, the trailing slash should be preserved and scope should be https://management.azure.com//.default
scope = resource + '/.default'
return [scope]


def scopes_to_resource(scopes):
"""Convert MSAL scopes to ADAL resource by stripping the /.default suffix and return a str.
For example: ['https://management.core.windows.net/.default'] -> 'https://management.core.windows.net/'
For example:
['https://management.core.windows.net//.default'] -> 'https://management.core.windows.net/'
['https://managedhsm.azure.com/.default'] -> 'https://managedhsm.azure.com'

:param scopes: The MSAL scopes. It can be a list or tuple of string
:return: The ADAL resource
:rtype: str
"""
scope = scopes[0]
if scope.endswith(".default"):
scope = scope[:-len(".default")]
if scope.endswith("/.default"):
scope = scope[:-len("/.default")]

# Trim extra ending slashes. https://datalake.azure.net// -> https://datalake.azure.net/
scope = scope.rstrip('/') + '/'
return scope