Skip to content

Commit 919923c

Browse files
authored
[Role] az role assignment list: Add --fill-principal-name to allow omitting principalName property (#30693)
1 parent 28ce46f commit 919923c

File tree

5 files changed

+2055
-16
lines changed

5 files changed

+2055
-16
lines changed

src/azure-cli/azure/cli/command_modules/role/_help.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,8 @@
800800
text: az role assignment list --role Reader --scope /subscriptions/00000000-0000-0000-0000-000000000000
801801
- name: List all role assignments of an assignee at the subscription scope.
802802
text: az role assignment list --assignee 00000000-0000-0000-0000-000000000000 --scope /subscriptions/00000000-0000-0000-0000-000000000000
803+
- name: List all role assignments with "Reader" role at the subscription scope, without filling principalName property
804+
text: az role assignment list --role Reader --scope /subscriptions/00000000-0000-0000-0000-000000000000 --fill-principal-name false
803805
"""
804806

805807
helps['role assignment list-changelogs'] = """

src/azure-cli/azure/cli/command_modules/role/_params.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,14 @@ def load_arguments(self, _):
340340
c.argument('assignment_name', name_arg_type,
341341
help='A GUID for the role assignment. It must be unique and different for each role assignment. If omitted, a new GUID is generated.')
342342

343+
with self.argument_context('role assignment list') as c:
344+
c.argument('fill_principal_name', arg_type=get_three_state_flag(),
345+
help="Query Microsoft Graph to get the assignee's userPrincipalName (for user), "
346+
"servicePrincipalNames (for service principal) or displayName (for group), then fill "
347+
"principalName property with it. "
348+
"If the logged-in account has no permission or the machine has no network access to query "
349+
"Microsoft Graph, set this flag to false to avoid warning or error.")
350+
343351
time_help = 'The {} of the query in the format of %Y-%m-%dT%H:%M:%SZ, e.g. 2000-12-31T12:59:59Z. Defaults to {}'
344352
with self.argument_context('role assignment list-changelogs') as c:
345353
c.argument('start_time', help=time_help.format('start time', '1 Hour prior to the current time'))

src/azure-cli/azure/cli/command_modules/role/custom.py

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,8 @@ def _create_role_assignment(cli_ctx, role, assignee, resource_group_name=None, s
234234

235235
def list_role_assignments(cmd, assignee=None, role=None, resource_group_name=None,
236236
scope=None, include_inherited=False,
237-
show_all=False, include_groups=False, include_classic_administrators=False):
237+
show_all=False, include_groups=False, include_classic_administrators=False,
238+
fill_principal_name=True):
238239
'''
239240
:param include_groups: include extra assignments to the groups of which the user is a
240241
member(transitively).
@@ -282,22 +283,23 @@ def list_role_assignments(cmd, assignee=None, role=None, resource_group_name=Non
282283
i['roleDefinitionName'] = None # the role definition might have been deleted
283284

284285
# fill in principal names
285-
principal_ids = set(worker.get_role_property(i, 'principalId')
286-
for i in results if worker.get_role_property(i, 'principalId'))
286+
if fill_principal_name:
287+
principal_ids = set(worker.get_role_property(i, 'principalId')
288+
for i in results if worker.get_role_property(i, 'principalId'))
287289

288-
if principal_ids:
289-
try:
290-
principals = _get_object_stubs(graph_client, principal_ids)
291-
principal_dics = {i[ID]: _get_displayable_name(i) for i in principals}
292-
293-
for i in [r for r in results if not r.get('principalName')]:
294-
i['principalName'] = ''
295-
if principal_dics.get(worker.get_role_property(i, 'principalId')):
296-
worker.set_role_property(i, 'principalName',
297-
principal_dics[worker.get_role_property(i, 'principalId')])
298-
except (HttpResponseError, GraphError) as ex:
299-
# failure on resolving principal due to graph permission should not fail the whole thing
300-
logger.info("Failed to resolve graph object information per error '%s'", ex)
290+
if principal_ids:
291+
try:
292+
principals = _get_object_stubs(graph_client, principal_ids)
293+
principal_dics = {i[ID]: _get_displayable_name(i) for i in principals}
294+
295+
for i in [r for r in results if not r.get('principalName')]:
296+
i['principalName'] = ''
297+
if principal_dics.get(worker.get_role_property(i, 'principalId')):
298+
worker.set_role_property(i, 'principalName',
299+
principal_dics[worker.get_role_property(i, 'principalId')])
300+
except (HttpResponseError, GraphError) as ex:
301+
# failure on resolving principal due to graph permission should not fail the whole thing
302+
logger.info("Failed to resolve graph object information per error '%s'", ex)
301303

302304
for r in results:
303305
if not r.get('additionalProperties'): # remove the useless "additionalProperties"

src/azure-cli/azure/cli/command_modules/role/tests/latest/recordings/test_role_assignment_no_graph.yaml

Lines changed: 2002 additions & 0 deletions
Large diffs are not rendered by default.

src/azure-cli/azure/cli/command_modules/role/tests/latest/test_role.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,31 @@ def check_changelogs():
689689
finally:
690690
self.cmd('ad user delete --id {upn}')
691691

692+
@ResourceGroupPreparer(name_prefix='cli_role_assign')
693+
@AllowLargeResponse()
694+
def test_role_assignment_no_graph(self, resource_group):
695+
with mock.patch('azure.cli.command_modules.role.custom._gen_guid', side_effect=self.create_guid):
696+
self.kwargs.update({
697+
'uami': self.create_random_name('clitest', 15), # user-assigned managed identity
698+
# https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles
699+
'role_reader_guid': 'acdd72a7-3385-48ef-bd42-f606fba81ae7'
700+
})
701+
self._prepare_scope_kwargs()
702+
703+
uami = self.cmd('identity create -g {rg} -n {uami} --location westus').get_output_in_json()
704+
self.kwargs['uami_object_id'] = uami['principalId']
705+
706+
self.cmd('role assignment create '
707+
'--assignee-object-id {uami_object_id} --assignee-principal-type ServicePrincipal '
708+
'--role {role_reader_guid} --scope {rg_id}')
709+
# Verify '--fill-principal-name false' skips the Graph query for filling principalName.
710+
self.cmd('role assignment list --scope {rg_id} --fill-principal-name false',
711+
checks=[
712+
self.check("length([])", 1),
713+
self.not_exists("[0].principalName")
714+
])
715+
# Manually verify the recording file that no HTTP request to https://graph.microsoft.com is made
716+
692717

693718
class RoleAssignmentWithConfigScenarioTest(RoleScenarioTestBase):
694719

0 commit comments

Comments
 (0)