From 56123d6c7c8d5fe86ca7104c4c241d39fa28ec34 Mon Sep 17 00:00:00 2001 From: jiasli <4003950+jiasli@users.noreply.github.com> Date: Thu, 3 Apr 2025 17:30:40 +0800 Subject: [PATCH] assignee_object_id --- .../azure/cli/command_modules/role/_help.py | 14 +- .../azure/cli/command_modules/role/_params.py | 11 +- .../azure/cli/command_modules/role/custom.py | 48 +++-- .../test_role_assignment_no_graph.yaml | 176 ++++++++++++++++-- .../role/tests/latest/test_role.py | 18 +- 5 files changed, 221 insertions(+), 46 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/role/_help.py b/src/azure-cli/azure/cli/command_modules/role/_help.py index 42915529882..f44d6807d80 100644 --- a/src/azure-cli/azure/cli/command_modules/role/_help.py +++ b/src/azure-cli/azure/cli/command_modules/role/_help.py @@ -781,6 +781,8 @@ text: az role assignment delete --role Reader --scope /subscriptions/00000000-0000-0000-0000-000000000000 - name: Delete all role assignments of an assignee at the subscription scope. text: az role assignment delete --assignee 00000000-0000-0000-0000-000000000000 --scope /subscriptions/00000000-0000-0000-0000-000000000000 + - name: Delete all role assignments of an assignee (with its object ID) at the subscription scope. + text: az role assignment delete --assignee-object-id 00000000-0000-0000-0000-000000000000 --scope /subscriptions/00000000-0000-0000-0000-000000000000 """ helps['role assignment list'] = """ @@ -796,12 +798,16 @@ Delete classic administrators who no longer need access or assign an Azure RBAC role for fine-grained access control. Learn more: https://go.microsoft.com/fwlink/?linkid=2238474 examples: - - name: List all role assignments with "Reader" role at the subscription scope. + - name: List role assignments at the subscription scope. + text: az role assignment list --scope /subscriptions/00000000-0000-0000-0000-000000000000 + - name: List role assignments at the subscription scope, without filling roleDefinitionName property. + text: az role assignment list --scope /subscriptions/00000000-0000-0000-0000-000000000000 --fill-role-definition-name false + - name: List role assignments with "Reader" role at the subscription scope. text: az role assignment list --role Reader --scope /subscriptions/00000000-0000-0000-0000-000000000000 - - name: List all role assignments of an assignee at the subscription scope. + - name: List role assignments of an assignee at the subscription scope. text: az role assignment list --assignee 00000000-0000-0000-0000-000000000000 --scope /subscriptions/00000000-0000-0000-0000-000000000000 - - name: List all role assignments with "Reader" role at the subscription scope, without filling principalName property - text: az role assignment list --role Reader --scope /subscriptions/00000000-0000-0000-0000-000000000000 --fill-principal-name false + - name: List role assignments of an assignee (with its object ID) at the subscription scope, without filling principalName property. This command does not query Microsoft Graph. + text: az role assignment list --assignee-object-id 00000000-0000-0000-0000-000000000000 --scope /subscriptions/00000000-0000-0000-0000-000000000000 --fill-principal-name false """ helps['role assignment list-changelogs'] = """ diff --git a/src/azure-cli/azure/cli/command_modules/role/_params.py b/src/azure-cli/azure/cli/command_modules/role/_params.py index c0df58dd540..102bc42d846 100644 --- a/src/azure-cli/azure/cli/command_modules/role/_params.py +++ b/src/azure-cli/azure/cli/command_modules/role/_params.py @@ -327,10 +327,11 @@ def load_arguments(self, _): c.argument('include_inherited', action='store_true', help='include assignments applied on parent scopes') c.argument('can_delegate', action='store_true', help='when set, the assignee will be able to create further role assignments to the same role') c.argument('assignee', help='represent a user, group, or service principal. supported format: object id, user sign-in name, or service principal name') - c.argument('assignee_object_id', help="Use this parameter instead of '--assignee' to bypass Graph API invocation in case of insufficient privileges. " - "This parameter only works with object ids for users, groups, service principals, and " - "managed identities. For managed identities use the principal id. For service principals, " - "use the object id and not the app id.") + c.argument('assignee_object_id', + help="The assignee's object ID (also known as principal ID). " + "Use this argument instead of '--assignee' to bypass Microsoft Graph query in case " + "the logged-in account has no permission or the machine has no network access to query " + "Microsoft Graph.") c.argument('ids', nargs='+', help='space-separated role assignment ids') c.argument('include_classic_administrators', arg_type=get_three_state_flag(), help='list default role assignments for subscription classic administrators, aka co-admins') @@ -350,6 +351,8 @@ def load_arguments(self, _): c.argument('fill_role_definition_name', arg_type=get_three_state_flag(), help="Fill roleDefinitionName property in addition to roleDefinitionId. This operation is " "expensive. If you encounter performance issue, set this flag to false.") + c.argument('include_groups', action='store_true', + help='Include extra assignments to the groups of which the user is a member (transitively).') 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 {}' with self.argument_context('role assignment list-changelogs') as c: diff --git a/src/azure-cli/azure/cli/command_modules/role/custom.py b/src/azure-cli/azure/cli/command_modules/role/custom.py index 616b31177dc..0017b1a7f39 100644 --- a/src/azure-cli/azure/cli/command_modules/role/custom.py +++ b/src/azure-cli/azure/cli/command_modules/role/custom.py @@ -209,7 +209,7 @@ def create_role_assignment(cmd, role, scope, assignment_name=assignment_name) except Exception as ex: # pylint: disable=broad-except if _error_caused_by_role_assignment_exists(ex): # for idempotent - return list_role_assignments(cmd, assignee=assignee, role=role, scope=scope)[0] + return list_role_assignments(cmd, assignee_object_id=object_id, role=role, scope=scope)[0] raise @@ -232,14 +232,19 @@ def _create_role_assignment(cli_ctx, role, assignee, resource_group_name=None, s condition=condition, condition_version=condition_version) -def list_role_assignments(cmd, assignee=None, role=None, resource_group_name=None, # pylint: disable=too-many-locals - scope=None, include_inherited=False, +def list_role_assignments(cmd, # pylint: disable=too-many-locals, too-many-branches + assignee=None, assignee_object_id=None, + role=None, + resource_group_name=None, scope=None, + include_inherited=False, show_all=False, include_groups=False, include_classic_administrators=False, fill_role_definition_name=True, fill_principal_name=True): - ''' - :param include_groups: include extra assignments to the groups of which the user is a - member(transitively). - ''' + if assignee and assignee_object_id: + raise CLIError('Usage error: Provide only one of --assignee or --assignee-object-id.') + if assignee_object_id and include_classic_administrators: + raise CLIError('Usage error: --assignee-object-id cannot be used with --include-classic-administrators. ' + 'Use --assignee instead.') + if include_classic_administrators: logger.warning(CLASSIC_ADMINISTRATOR_WARNING) @@ -256,8 +261,10 @@ def list_role_assignments(cmd, assignee=None, role=None, resource_group_name=Non scope = _build_role_scope(resource_group_name, scope, definitions_client._config.subscription_id) + if assignee and not assignee_object_id: + assignee_object_id = _resolve_object_id(cmd.cli_ctx, assignee, fallback_to_object_id=True) assignments = _search_role_assignments(cmd.cli_ctx, assignments_client, definitions_client, - scope, assignee, role, + scope, assignee_object_id, role, include_inherited, include_groups) results = todict(assignments) if assignments else [] @@ -522,13 +529,19 @@ def _get_displayable_name(graph_object): return graph_object['displayName'] or '' -def delete_role_assignments(cmd, ids=None, assignee=None, role=None, resource_group_name=None, - scope=None, include_inherited=False, +def delete_role_assignments(cmd, ids=None, + assignee=None, assignee_object_id=None, + role=None, + resource_group_name=None, scope=None, + include_inherited=False, yes=None): # pylint: disable=unused-argument # yes is currently a no-op - if not any((ids, assignee, role, resource_group_name, scope)): + if not any((ids, assignee, assignee_object_id, role, resource_group_name, scope)): raise ArgumentUsageError('Please provide at least one of these arguments: ' - '--ids, --assignee, --role, --resource-group, --scope') + '--ids, --assignee, --assignee-object-id, --role, --resource-group, --scope') + + if assignee and assignee_object_id: + raise CLIError('Usage error: Provide only one of --assignee or --assignee-object-id.') factory = _auth_client_factory(cmd.cli_ctx, scope) assignments_client = factory.role_assignments @@ -559,8 +572,11 @@ def delete_role_assignments(cmd, ids=None, assignee=None, role=None, resource_gr scope = _build_role_scope(resource_group_name, scope, assignments_client._config.subscription_id) + # Delay resolving object ID, because if ids are provided, no need to resolve + if assignee and not assignee_object_id: + assignee_object_id = _resolve_object_id(cmd.cli_ctx, assignee, fallback_to_object_id=True) assignments = _search_role_assignments(cmd.cli_ctx, assignments_client, definitions_client, - scope, assignee, role, include_inherited, + scope, assignee_object_id, role, include_inherited, include_groups=False) if assignments: @@ -571,11 +587,7 @@ def delete_role_assignments(cmd, ids=None, assignee=None, role=None, resource_gr def _search_role_assignments(cli_ctx, assignments_client, definitions_client, - scope, assignee, role, include_inherited, include_groups): - assignee_object_id = None - if assignee: - assignee_object_id = _resolve_object_id(cli_ctx, assignee, fallback_to_object_id=True) - + scope, assignee_object_id, role, include_inherited, include_groups): # https://learn.microsoft.com/en-us/azure/role-based-access-control/role-assignments-list-rest # "atScope()" and "principalId eq '{value}'" query cannot be used together (API limitation). # always use "scope" if provided, so we can get assignments beyond subscription e.g. management groups diff --git a/src/azure-cli/azure/cli/command_modules/role/tests/latest/recordings/test_role_assignment_no_graph.yaml b/src/azure-cli/azure/cli/command_modules/role/tests/latest/recordings/test_role_assignment_no_graph.yaml index 68bd270e92d..0a473136741 100644 --- a/src/azure-cli/azure/cli/command_modules/role/tests/latest/recordings/test_role_assignment_no_graph.yaml +++ b/src/azure-cli/azure/cli/command_modules/role/tests/latest/recordings/test_role_assignment_no_graph.yaml @@ -22,7 +22,7 @@ interactions: uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_role_assign000001/providers/Microsoft.ManagedIdentity/userAssignedIdentities/clitest000002?api-version=2023-01-31 response: body: - string: '{"location":"westus","tags":{},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/cli_role_assign000001/providers/Microsoft.ManagedIdentity/userAssignedIdentities/clitest000002","name":"clitest000002","type":"Microsoft.ManagedIdentity/userAssignedIdentities","properties":{"tenantId":"54826b22-38d6-4fb2-bad9-b7b93a3e9c5a","principalId":"69ea8350-eba7-4f5f-8c0f-311dba248670","clientId":"aa88cf35-a04a-4a38-a3fe-a75bd3915491"}}' + string: '{"location":"westus","tags":{},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/cli_role_assign000001/providers/Microsoft.ManagedIdentity/userAssignedIdentities/clitest000002","name":"clitest000002","type":"Microsoft.ManagedIdentity/userAssignedIdentities","properties":{"tenantId":"54826b22-38d6-4fb2-bad9-b7b93a3e9c5a","principalId":"b14ee29e-54cd-4425-a067-e35854a5d532","clientId":"b72bbf02-ee61-46e0-9b44-d2cd1dca5d2a"}}' headers: cache-control: - no-cache @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 31 Mar 2025 09:33:43 GMT + - Thu, 03 Apr 2025 09:30:09 GMT expires: - '-1' location: @@ -45,19 +45,19 @@ interactions: x-content-type-options: - nosniff x-ms-operation-identifier: - - tenantId=54826b22-38d6-4fb2-bad9-b7b93a3e9c5a,objectId=0d504196-1423-4569-9a6e-15149656f0ee/southeastasia/326402af-31e3-4875-9f0c-723b2851cb50 + - tenantId=54826b22-38d6-4fb2-bad9-b7b93a3e9c5a,objectId=0d504196-1423-4569-9a6e-15149656f0ee/southeastasia/3914cd69-385d-4733-ab27-31f325bf754f x-ms-ratelimit-remaining-subscription-global-writes: - '2999' x-ms-ratelimit-remaining-subscription-writes: - '199' x-msedge-ref: - - 'Ref A: 6BB79AF23F374B3096C52FC67B1C98D1 Ref B: MAA201060513019 Ref C: 2025-03-31T09:33:38Z' + - 'Ref A: C4F14B6EB6D84D40A1247020DB308838 Ref B: MAA201060516011 Ref C: 2025-04-03T09:30:04Z' status: code: 201 message: Created - request: body: '{"properties": {"roleDefinitionId": "/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7", - "principalId": "69ea8350-eba7-4f5f-8c0f-311dba248670", "principalType": "ServicePrincipal"}}' + "principalId": "b14ee29e-54cd-4425-a067-e35854a5d532", "principalType": "ServicePrincipal"}}' headers: Accept: - application/json @@ -79,7 +79,7 @@ interactions: uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_role_assign000001/providers/Microsoft.Authorization/roleAssignments/88888888-0000-0000-0000-000000000001?api-version=2022-04-01 response: body: - string: '{"properties":{"roleDefinitionId":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7","principalId":"69ea8350-eba7-4f5f-8c0f-311dba248670","principalType":"ServicePrincipal","scope":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_role_assign000001","condition":null,"conditionVersion":null,"createdOn":"2025-03-31T09:33:44.6569301Z","updatedOn":"2025-03-31T09:33:45.5819477Z","createdBy":null,"updatedBy":"0d504196-1423-4569-9a6e-15149656f0ee","delegatedManagedIdentityResourceId":null,"description":null},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_role_assign000001/providers/Microsoft.Authorization/roleAssignments/88888888-0000-0000-0000-000000000001","type":"Microsoft.Authorization/roleAssignments","name":"88888888-0000-0000-0000-000000000001"}' + string: '{"properties":{"roleDefinitionId":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7","principalId":"b14ee29e-54cd-4425-a067-e35854a5d532","principalType":"ServicePrincipal","scope":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_role_assign000001","condition":null,"conditionVersion":null,"createdOn":"2025-04-03T09:30:10.7797806Z","updatedOn":"2025-04-03T09:30:11.5905444Z","createdBy":null,"updatedBy":"0d504196-1423-4569-9a6e-15149656f0ee","delegatedManagedIdentityResourceId":null,"description":null},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_role_assign000001/providers/Microsoft.Authorization/roleAssignments/88888888-0000-0000-0000-000000000001","type":"Microsoft.Authorization/roleAssignments","name":"88888888-0000-0000-0000-000000000001"}' headers: cache-control: - no-cache @@ -88,7 +88,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 31 Mar 2025 09:33:48 GMT + - Thu, 03 Apr 2025 09:30:15 GMT expires: - '-1' pragma: @@ -100,13 +100,13 @@ interactions: x-content-type-options: - nosniff x-ms-operation-identifier: - - tenantId=54826b22-38d6-4fb2-bad9-b7b93a3e9c5a,objectId=0d504196-1423-4569-9a6e-15149656f0ee/southeastasia/6131290b-a33f-4c9b-9d39-541cfe3f718f + - tenantId=54826b22-38d6-4fb2-bad9-b7b93a3e9c5a,objectId=0d504196-1423-4569-9a6e-15149656f0ee/southeastasia/498913c7-dfb8-44d3-86a0-aca898bb6bcf x-ms-ratelimit-remaining-subscription-global-writes: - '2999' x-ms-ratelimit-remaining-subscription-writes: - '199' x-msedge-ref: - - 'Ref A: E2058AC52F4E4EC5AF6C58AE9CF4AB8B Ref B: MAA201060515019 Ref C: 2025-03-31T09:33:44Z' + - 'Ref A: 1AE3B5DD7CA0499F968B2AB7D00413D4 Ref B: MAA201060514033 Ref C: 2025-04-03T09:30:10Z' status: code: 201 message: Created @@ -122,7 +122,55 @@ interactions: Connection: - keep-alive ParameterSetName: - - --scope --fill-principal-name --fill-role-definition-name + - --all --assignee-object-id --fill-role-definition-name --fill-principal-name + User-Agent: + - AZURECLI/2.71.0 azsdk-python-core/1.31.0 Python/3.12.9 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleAssignments?api-version=2022-04-01&$filter=principalId%20eq%20'b14ee29e-54cd-4425-a067-e35854a5d532' + response: + body: + string: '{"value":[{"properties":{"roleDefinitionId":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7","principalId":"b14ee29e-54cd-4425-a067-e35854a5d532","principalType":"ServicePrincipal","scope":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_role_assign000001","condition":null,"conditionVersion":null,"createdOn":"2025-04-03T09:30:11.5905444Z","updatedOn":"2025-04-03T09:30:11.5905444Z","createdBy":"0d504196-1423-4569-9a6e-15149656f0ee","updatedBy":"0d504196-1423-4569-9a6e-15149656f0ee","delegatedManagedIdentityResourceId":null,"description":null},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_role_assign000001/providers/Microsoft.Authorization/roleAssignments/88888888-0000-0000-0000-000000000001","type":"Microsoft.Authorization/roleAssignments","name":"88888888-0000-0000-0000-000000000001"}]}' + headers: + cache-control: + - no-cache + content-length: + - '943' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 03 Apr 2025 09:30:15 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=54826b22-38d6-4fb2-bad9-b7b93a3e9c5a,objectId=0d504196-1423-4569-9a6e-15149656f0ee/southeastasia/edd2ef04-c74b-4375-a690-5862af7a3775 + x-ms-ratelimit-remaining-subscription-global-reads: + - '3749' + x-msedge-ref: + - 'Ref A: 947C4C42E5044259A89203DF3A0A5020 Ref B: MAA201060513047 Ref C: 2025-04-03T09:30:16Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - role assignment delete + Connection: + - keep-alive + ParameterSetName: + - --scope --assignee-object-id User-Agent: - AZURECLI/2.71.0 azsdk-python-core/1.31.0 Python/3.12.9 (Windows-11-10.0.26100-SP0) method: GET @@ -298,7 +346,7 @@ interactions: f58310d9-a9f6-439a-9e8d-f62e7b41a168})) AND ((!(ActionMatches{''Microsoft.Authorization/roleAssignments/delete''})) OR (@Resource[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAllValues:GuidNotEquals {8e3af657-a8ff-443c-a75c-2fe8c4bcb635, 18d7d88d-d35e-4fb5-a5c3-7773c20a72d9, - f58310d9-a9f6-439a-9e8d-f62e7b41a168}))","conditionVersion":"2.0","createdOn":"2025-03-06T03:56:03.6228304Z","updatedOn":"2025-03-06T03:56:03.6228304Z","createdBy":"794f8d45-6eb3-4e1e-bc62-c01317eaeac1","updatedBy":"794f8d45-6eb3-4e1e-bc62-c01317eaeac1","delegatedManagedIdentityResourceId":null,"description":null},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleAssignments/1d43f516-15af-4822-a1a1-efd803d46bba","type":"Microsoft.Authorization/roleAssignments","name":"1d43f516-15af-4822-a1a1-efd803d46bba"},{"properties":{"roleDefinitionId":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleDefinitions/18500a29-7fe2-46b2-a342-b16a415e101d","principalId":"4603767a-0e74-4b03-a80f-7bebfddc052f","principalType":"User","scope":"/subscriptions/00000000-0000-0000-0000-000000000000","condition":null,"conditionVersion":null,"createdOn":"2025-03-07T04:50:24.9603373Z","updatedOn":"2025-03-07T04:50:24.9603373Z","createdBy":"4603767a-0e74-4b03-a80f-7bebfddc052f","updatedBy":"4603767a-0e74-4b03-a80f-7bebfddc052f","delegatedManagedIdentityResourceId":null,"description":null},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleAssignments/5c4eb356-2ae5-47b9-90b1-5e5cd2208a4e","type":"Microsoft.Authorization/roleAssignments","name":"5c4eb356-2ae5-47b9-90b1-5e5cd2208a4e"},{"properties":{"roleDefinitionId":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleDefinitions/0e5f05e5-9ab9-446b-b98d-1e2157c94125","principalId":"30716a40-adee-4985-86bd-37216988befe","principalType":"User","scope":"/subscriptions/00000000-0000-0000-0000-000000000000","condition":null,"conditionVersion":null,"createdOn":"2025-03-11T06:00:05.4514643Z","updatedOn":"2025-03-11T06:00:05.4514643Z","createdBy":"30716a40-adee-4985-86bd-37216988befe","updatedBy":"30716a40-adee-4985-86bd-37216988befe","delegatedManagedIdentityResourceId":null,"description":null},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleAssignments/b76287e1-2027-4750-b818-aec4692ff0b0","type":"Microsoft.Authorization/roleAssignments","name":"b76287e1-2027-4750-b818-aec4692ff0b0"},{"properties":{"roleDefinitionId":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleDefinitions/0e5f05e5-9ab9-446b-b98d-1e2157c94125","principalId":"69a25840-8928-4ea0-a8a5-e44d0fdaee5f","principalType":"ServicePrincipal","scope":"/subscriptions/00000000-0000-0000-0000-000000000000","condition":null,"conditionVersion":null,"createdOn":"2025-03-11T06:00:08.1563237Z","updatedOn":"2025-03-11T06:00:08.1563237Z","createdBy":"30716a40-adee-4985-86bd-37216988befe","updatedBy":"30716a40-adee-4985-86bd-37216988befe","delegatedManagedIdentityResourceId":null,"description":null},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleAssignments/446b4259-4e74-4cb2-be0f-4013b3f733e0","type":"Microsoft.Authorization/roleAssignments","name":"446b4259-4e74-4cb2-be0f-4013b3f733e0"},{"properties":{"roleDefinitionId":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7","principalId":"487c6b3f-b3ae-4a77-b145-6790ccd0473d","principalType":"User","scope":"/subscriptions/00000000-0000-0000-0000-000000000000","condition":null,"conditionVersion":null,"createdOn":"2025-03-12T01:04:36.7387446Z","updatedOn":"2025-03-12T01:04:36.7387446Z","createdBy":"0d504196-1423-4569-9a6e-15149656f0ee","updatedBy":"0d504196-1423-4569-9a6e-15149656f0ee","delegatedManagedIdentityResourceId":null,"description":null},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleAssignments/2f59a8c0-da83-4035-8731-c53d70cabfd6","type":"Microsoft.Authorization/roleAssignments","name":"2f59a8c0-da83-4035-8731-c53d70cabfd6"},{"properties":{"roleDefinitionId":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7","principalId":"a7003d8c-e50f-4371-91a6-ef37bba4ab23","principalType":"ServicePrincipal","scope":"/subscriptions/00000000-0000-0000-0000-000000000000","condition":null,"conditionVersion":null,"createdOn":"2025-03-28T09:31:57.9355411Z","updatedOn":"2025-03-28T09:31:57.9355411Z","createdBy":"0d504196-1423-4569-9a6e-15149656f0ee","updatedBy":"0d504196-1423-4569-9a6e-15149656f0ee","delegatedManagedIdentityResourceId":null,"description":null},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleAssignments/be58443a-2eea-4e2d-abd9-2d259271431e","type":"Microsoft.Authorization/roleAssignments","name":"be58443a-2eea-4e2d-abd9-2d259271431e"},{"properties":{"roleDefinitionId":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7","principalId":"7fe989f6-5c63-416a-94ca-46e5fe1297c5","principalType":"ServicePrincipal","scope":"/subscriptions/00000000-0000-0000-0000-000000000000","condition":null,"conditionVersion":null,"createdOn":"2025-03-28T10:12:47.4154575Z","updatedOn":"2025-03-28T10:12:47.4154575Z","createdBy":"0d504196-1423-4569-9a6e-15149656f0ee","updatedBy":"0d504196-1423-4569-9a6e-15149656f0ee","delegatedManagedIdentityResourceId":null,"description":null},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleAssignments/d511b881-d136-48fe-9656-191d8562b126","type":"Microsoft.Authorization/roleAssignments","name":"d511b881-d136-48fe-9656-191d8562b126"},{"properties":{"roleDefinitionId":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7","principalId":"69ea8350-eba7-4f5f-8c0f-311dba248670","principalType":"ServicePrincipal","scope":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_role_assign000001","condition":null,"conditionVersion":null,"createdOn":"2025-03-31T09:33:45.5819477Z","updatedOn":"2025-03-31T09:33:45.5819477Z","createdBy":"0d504196-1423-4569-9a6e-15149656f0ee","updatedBy":"0d504196-1423-4569-9a6e-15149656f0ee","delegatedManagedIdentityResourceId":null,"description":null},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_role_assign000001/providers/Microsoft.Authorization/roleAssignments/88888888-0000-0000-0000-000000000001","type":"Microsoft.Authorization/roleAssignments","name":"88888888-0000-0000-0000-000000000001"},{"properties":{"roleDefinitionId":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7","principalId":"7fe989f6-5c63-416a-94ca-46e5fe1297c5","principalType":"ServicePrincipal","scope":"/providers/Microsoft.Management/managementGroups/admintest","condition":null,"conditionVersion":null,"createdOn":"2025-02-18T08:44:40.9777560Z","updatedOn":"2025-02-18T08:44:40.9777560Z","createdBy":"0d504196-1423-4569-9a6e-15149656f0ee","updatedBy":"0d504196-1423-4569-9a6e-15149656f0ee","delegatedManagedIdentityResourceId":null,"description":null},"id":"/providers/Microsoft.Management/managementGroups/admintest/providers/Microsoft.Authorization/roleAssignments/43f1843d-1137-4009-bdb6-f730e7d50e53","type":"Microsoft.Authorization/roleAssignments","name":"43f1843d-1137-4009-bdb6-f730e7d50e53"}]}' + f58310d9-a9f6-439a-9e8d-f62e7b41a168}))","conditionVersion":"2.0","createdOn":"2025-03-06T03:56:03.6228304Z","updatedOn":"2025-03-06T03:56:03.6228304Z","createdBy":"794f8d45-6eb3-4e1e-bc62-c01317eaeac1","updatedBy":"794f8d45-6eb3-4e1e-bc62-c01317eaeac1","delegatedManagedIdentityResourceId":null,"description":null},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleAssignments/1d43f516-15af-4822-a1a1-efd803d46bba","type":"Microsoft.Authorization/roleAssignments","name":"1d43f516-15af-4822-a1a1-efd803d46bba"},{"properties":{"roleDefinitionId":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleDefinitions/18500a29-7fe2-46b2-a342-b16a415e101d","principalId":"4603767a-0e74-4b03-a80f-7bebfddc052f","principalType":"User","scope":"/subscriptions/00000000-0000-0000-0000-000000000000","condition":null,"conditionVersion":null,"createdOn":"2025-03-07T04:50:24.9603373Z","updatedOn":"2025-03-07T04:50:24.9603373Z","createdBy":"4603767a-0e74-4b03-a80f-7bebfddc052f","updatedBy":"4603767a-0e74-4b03-a80f-7bebfddc052f","delegatedManagedIdentityResourceId":null,"description":null},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleAssignments/5c4eb356-2ae5-47b9-90b1-5e5cd2208a4e","type":"Microsoft.Authorization/roleAssignments","name":"5c4eb356-2ae5-47b9-90b1-5e5cd2208a4e"},{"properties":{"roleDefinitionId":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleDefinitions/0e5f05e5-9ab9-446b-b98d-1e2157c94125","principalId":"30716a40-adee-4985-86bd-37216988befe","principalType":"User","scope":"/subscriptions/00000000-0000-0000-0000-000000000000","condition":null,"conditionVersion":null,"createdOn":"2025-03-11T06:00:05.4514643Z","updatedOn":"2025-03-11T06:00:05.4514643Z","createdBy":"30716a40-adee-4985-86bd-37216988befe","updatedBy":"30716a40-adee-4985-86bd-37216988befe","delegatedManagedIdentityResourceId":null,"description":null},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleAssignments/b76287e1-2027-4750-b818-aec4692ff0b0","type":"Microsoft.Authorization/roleAssignments","name":"b76287e1-2027-4750-b818-aec4692ff0b0"},{"properties":{"roleDefinitionId":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleDefinitions/0e5f05e5-9ab9-446b-b98d-1e2157c94125","principalId":"69a25840-8928-4ea0-a8a5-e44d0fdaee5f","principalType":"ServicePrincipal","scope":"/subscriptions/00000000-0000-0000-0000-000000000000","condition":null,"conditionVersion":null,"createdOn":"2025-03-11T06:00:08.1563237Z","updatedOn":"2025-03-11T06:00:08.1563237Z","createdBy":"30716a40-adee-4985-86bd-37216988befe","updatedBy":"30716a40-adee-4985-86bd-37216988befe","delegatedManagedIdentityResourceId":null,"description":null},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleAssignments/446b4259-4e74-4cb2-be0f-4013b3f733e0","type":"Microsoft.Authorization/roleAssignments","name":"446b4259-4e74-4cb2-be0f-4013b3f733e0"},{"properties":{"roleDefinitionId":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7","principalId":"487c6b3f-b3ae-4a77-b145-6790ccd0473d","principalType":"User","scope":"/subscriptions/00000000-0000-0000-0000-000000000000","condition":null,"conditionVersion":null,"createdOn":"2025-03-12T01:04:36.7387446Z","updatedOn":"2025-03-12T01:04:36.7387446Z","createdBy":"0d504196-1423-4569-9a6e-15149656f0ee","updatedBy":"0d504196-1423-4569-9a6e-15149656f0ee","delegatedManagedIdentityResourceId":null,"description":null},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleAssignments/2f59a8c0-da83-4035-8731-c53d70cabfd6","type":"Microsoft.Authorization/roleAssignments","name":"2f59a8c0-da83-4035-8731-c53d70cabfd6"},{"properties":{"roleDefinitionId":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7","principalId":"a7003d8c-e50f-4371-91a6-ef37bba4ab23","principalType":"ServicePrincipal","scope":"/subscriptions/00000000-0000-0000-0000-000000000000","condition":null,"conditionVersion":null,"createdOn":"2025-03-28T09:31:57.9355411Z","updatedOn":"2025-03-28T09:31:57.9355411Z","createdBy":"0d504196-1423-4569-9a6e-15149656f0ee","updatedBy":"0d504196-1423-4569-9a6e-15149656f0ee","delegatedManagedIdentityResourceId":null,"description":null},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleAssignments/be58443a-2eea-4e2d-abd9-2d259271431e","type":"Microsoft.Authorization/roleAssignments","name":"be58443a-2eea-4e2d-abd9-2d259271431e"},{"properties":{"roleDefinitionId":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7","principalId":"7fe989f6-5c63-416a-94ca-46e5fe1297c5","principalType":"ServicePrincipal","scope":"/subscriptions/00000000-0000-0000-0000-000000000000","condition":null,"conditionVersion":null,"createdOn":"2025-03-28T10:12:47.4154575Z","updatedOn":"2025-03-28T10:12:47.4154575Z","createdBy":"0d504196-1423-4569-9a6e-15149656f0ee","updatedBy":"0d504196-1423-4569-9a6e-15149656f0ee","delegatedManagedIdentityResourceId":null,"description":null},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleAssignments/d511b881-d136-48fe-9656-191d8562b126","type":"Microsoft.Authorization/roleAssignments","name":"d511b881-d136-48fe-9656-191d8562b126"},{"properties":{"roleDefinitionId":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7","principalId":"b14ee29e-54cd-4425-a067-e35854a5d532","principalType":"ServicePrincipal","scope":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_role_assign000001","condition":null,"conditionVersion":null,"createdOn":"2025-04-03T09:30:11.5905444Z","updatedOn":"2025-04-03T09:30:11.5905444Z","createdBy":"0d504196-1423-4569-9a6e-15149656f0ee","updatedBy":"0d504196-1423-4569-9a6e-15149656f0ee","delegatedManagedIdentityResourceId":null,"description":null},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_role_assign000001/providers/Microsoft.Authorization/roleAssignments/88888888-0000-0000-0000-000000000001","type":"Microsoft.Authorization/roleAssignments","name":"88888888-0000-0000-0000-000000000001"},{"properties":{"roleDefinitionId":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7","principalId":"7fe989f6-5c63-416a-94ca-46e5fe1297c5","principalType":"ServicePrincipal","scope":"/providers/Microsoft.Management/managementGroups/admintest","condition":null,"conditionVersion":null,"createdOn":"2025-02-18T08:44:40.9777560Z","updatedOn":"2025-02-18T08:44:40.9777560Z","createdBy":"0d504196-1423-4569-9a6e-15149656f0ee","updatedBy":"0d504196-1423-4569-9a6e-15149656f0ee","delegatedManagedIdentityResourceId":null,"description":null},"id":"/providers/Microsoft.Management/managementGroups/admintest/providers/Microsoft.Authorization/roleAssignments/43f1843d-1137-4009-bdb6-f730e7d50e53","type":"Microsoft.Authorization/roleAssignments","name":"43f1843d-1137-4009-bdb6-f730e7d50e53"}]}' headers: cache-control: - no-cache @@ -307,7 +355,107 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 31 Mar 2025 09:33:49 GMT + - Thu, 03 Apr 2025 09:30:16 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=54826b22-38d6-4fb2-bad9-b7b93a3e9c5a,objectId=0d504196-1423-4569-9a6e-15149656f0ee/southeastasia/3047a091-9cfa-4ac1-9fc6-2b5366a77a0a + x-ms-ratelimit-remaining-subscription-global-reads: + - '3749' + x-msedge-ref: + - 'Ref A: 26CB4832C44E40AEA3470A8D4A438B1F Ref B: MAA201060514049 Ref C: 2025-04-03T09:30:16Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - role assignment delete + Connection: + - keep-alive + Content-Length: + - '0' + ParameterSetName: + - --scope --assignee-object-id + User-Agent: + - AZURECLI/2.71.0 azsdk-python-core/1.31.0 Python/3.12.9 (Windows-11-10.0.26100-SP0) + method: DELETE + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_role_assign000001/providers/Microsoft.Authorization/roleAssignments/88888888-0000-0000-0000-000000000001?api-version=2022-04-01 + response: + body: + string: '{"properties":{"roleDefinitionId":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7","principalId":"b14ee29e-54cd-4425-a067-e35854a5d532","principalType":"ServicePrincipal","scope":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_role_assign000001","condition":null,"conditionVersion":null,"createdOn":"2025-04-03T09:30:11.5905444Z","updatedOn":"2025-04-03T09:30:18.1521739Z","createdBy":"0d504196-1423-4569-9a6e-15149656f0ee","updatedBy":"0d504196-1423-4569-9a6e-15149656f0ee","delegatedManagedIdentityResourceId":null,"description":null},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_role_assign000001/providers/Microsoft.Authorization/roleAssignments/88888888-0000-0000-0000-000000000001","type":"Microsoft.Authorization/roleAssignments","name":"88888888-0000-0000-0000-000000000001"}' + headers: + cache-control: + - no-cache + content-length: + - '931' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 03 Apr 2025 09:30:25 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=54826b22-38d6-4fb2-bad9-b7b93a3e9c5a,objectId=0d504196-1423-4569-9a6e-15149656f0ee/southeastasia/1a1b9f4b-4222-4734-92c0-9476b80956e6 + x-ms-ratelimit-remaining-subscription-deletes: + - '199' + x-ms-ratelimit-remaining-subscription-global-deletes: + - '2999' + x-msedge-ref: + - 'Ref A: 7C8C1FF4F2424782BCF3C03D885AE7AB Ref B: MAA201060514049 Ref C: 2025-04-03T09:30:17Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - role assignment list + Connection: + - keep-alive + ParameterSetName: + - --all --assignee-object-id + User-Agent: + - AZURECLI/2.71.0 azsdk-python-core/1.31.0 Python/3.12.9 (Windows-11-10.0.26100-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleAssignments?api-version=2022-04-01&$filter=principalId%20eq%20'b14ee29e-54cd-4425-a067-e35854a5d532' + response: + body: + string: '{"value":[]}' + headers: + cache-control: + - no-cache + content-length: + - '12' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 03 Apr 2025 09:30:25 GMT expires: - '-1' pragma: @@ -319,11 +467,11 @@ interactions: x-content-type-options: - nosniff x-ms-operation-identifier: - - tenantId=54826b22-38d6-4fb2-bad9-b7b93a3e9c5a,objectId=0d504196-1423-4569-9a6e-15149656f0ee/southeastasia/cd18f7e7-9e92-49c1-bbec-642cb0278c52 + - tenantId=54826b22-38d6-4fb2-bad9-b7b93a3e9c5a,objectId=0d504196-1423-4569-9a6e-15149656f0ee/southeastasia/48b2bf18-01d5-429d-a73b-36ce15c1851e x-ms-ratelimit-remaining-subscription-global-reads: - '3749' x-msedge-ref: - - 'Ref A: 24F1FF4BACB84B10B232200B4931E383 Ref B: MAA201060515029 Ref C: 2025-03-31T09:33:49Z' + - 'Ref A: 100B379925454E83AADAB2621AFB0DB2 Ref B: SIN221080719049 Ref C: 2025-04-03T09:30:26Z' status: code: 200 message: OK diff --git a/src/azure-cli/azure/cli/command_modules/role/tests/latest/test_role.py b/src/azure-cli/azure/cli/command_modules/role/tests/latest/test_role.py index 10d73d960f1..41bfd9dcce0 100644 --- a/src/azure-cli/azure/cli/command_modules/role/tests/latest/test_role.py +++ b/src/azure-cli/azure/cli/command_modules/role/tests/latest/test_role.py @@ -706,6 +706,8 @@ def check_changelogs(): @ResourceGroupPreparer(name_prefix='cli_role_assign') @AllowLargeResponse() def test_role_assignment_no_graph(self, resource_group): + # After live testing, manually verify the recording file that no HTTP request to + # https://graph.microsoft.com is made with mock.patch('azure.cli.command_modules.role.custom._gen_guid', side_effect=self.create_guid): self.kwargs.update({ 'uami': self.create_random_name('clitest', 15), # user-assigned managed identity @@ -720,15 +722,19 @@ def test_role_assignment_no_graph(self, resource_group): self.cmd('role assignment create ' '--assignee-object-id {uami_object_id} --assignee-principal-type ServicePrincipal ' '--role {role_reader_guid} --scope {rg_id}') - # Verify '--fill-principal-name false' skips the Graph query for filling principalName. - self.cmd('role assignment list --scope {rg_id} --fill-principal-name false ' - '--fill-role-definition-name false', + # --assignee-object-id bypasses Graph query for resolving assignee object ID + # '--fill-role-definition-name false' bypasses role definitions query for filling roleDefinitionName + # '--fill-principal-name false' bypasses Graph query for filling principalName + self.cmd('role assignment list --all --assignee-object-id {uami_object_id} ' + '--fill-role-definition-name false --fill-principal-name false', checks=[ self.check("length([])", 1), - self.not_exists("[0].principalName"), - self.not_exists("[0].roleDefinitionName") + self.not_exists("[0].roleDefinitionName"), + self.not_exists("[0].principalName") ]) - # Manually verify the recording file that no HTTP request to https://graph.microsoft.com is made + self.cmd('role assignment delete --scope {rg_id} --assignee-object-id {uami_object_id}') + self.cmd('role assignment list --all --assignee-object-id {uami_object_id}', + checks=self.check("length([])", 0)) class RoleAssignmentWithConfigScenarioTest(RoleScenarioTestBase):