Skip to content
Open
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
18 changes: 18 additions & 0 deletions src/azure-cli/azure/cli/command_modules/role/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,15 @@
short-summary: Manage service principal owners.
"""

helps['ad sp owner add'] = """
type: command
short-summary: Add a service principal owner.
examples:
- name: Add a service principal owner. (autogenerated)
text: az ad sp owner add --id 00000000-0000-0000-0000-000000000000 --owner-object-id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
crafted: true
"""

helps['ad sp owner list'] = """
type: command
short-summary: List service principal owners.
Expand All @@ -630,6 +639,15 @@
crafted: true
"""

helps['ad sp owner remove'] = """
type: command
short-summary: Remove a service principal owner.
examples:
- name: Remove a service principal owner.
text: az ad sp owner remove --id 00000000-0000-0000-0000-000000000000 --owner-object-id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
crafted: true
"""

helps['ad sp show'] = """
type: command
short-summary: Get the details of a service principal.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,16 @@ def service_principal_owner_list(self, id):
result = self._send("GET", "/servicePrincipals/{id}/owners".format(id=id))
return result

def service_principal_owner_add(self, id, body):
# https://learn.microsoft.com/en-us/graph/api/serviceprincipal-post-owners
result = self._send("POST", "/servicePrincipals/{id}/owners/$ref".format(id=id), body=body)
return result

def service_principal_owner_remove(self, id, owner_id):
# https://learn.microsoft.com/en-us/graph/api/serviceprincipal-delete-owners
result = self._send("DELETE", "/servicePrincipals/{id}/owners/{owner_id}/$ref".format(id=id, owner_id=owner_id))
return result

def owned_objects_list(self):
# https://learn.microsoft.com/en-us/graph/api/user-list-ownedobjects
result = self._send("GET", "/me/ownedObjects")
Expand Down
2 changes: 1 addition & 1 deletion src/azure-cli/azure/cli/command_modules/role/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ def load_arguments(self, _):
arg_type=get_three_state_flag())

with self.argument_context('ad sp owner list') as c:
c.argument('identifier', options_list=['--id'], help='service principal name, or object id or the service principal')
c.argument('identifier', options_list=['--id'], help='service principal name, or object id of the service principal')

for item in ['ad app credential reset', 'ad sp credential reset', 'ad sp create-for-rbac']:
with self.argument_context(item) as c:
Expand Down
2 changes: 2 additions & 0 deletions src/azure-cli/azure/cli/command_modules/role/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ def load_command_table(self, _):

with self.command_group('ad sp owner', client_factory=get_graph_client, exception_handler=graph_err_handler) as g:
g.custom_command('list', 'list_service_principal_owners')
g.custom_command('add', 'add_service_principal_owner')
g.custom_command('remove', 'remove_service_principal_owner')

# RBAC related
with self.command_group('ad sp', client_factory=get_graph_client, exception_handler=graph_err_handler) as g:
Expand Down
16 changes: 16 additions & 0 deletions src/azure-cli/azure/cli/command_modules/role/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -1191,6 +1191,22 @@ def _get_app_object_id_from_sp_object_id(client, sp_object_id):
raise CLIError("Can't find associated application id from '{}'".format(sp_object_id))


def add_service_principal_owner(client, owner_object_id, identifier):
sp_object_id = _resolve_service_principal(client, identifier)
owners = client.service_principal_owner_list(sp_object_id)
# API not idempotent and fails with:
# One or more added object references already exist for the following modified properties: 'owners'
# We make it idempotent.
if not next((x for x in owners if x[ID] == owner_object_id), None):
body = _build_directory_object_json(client, owner_object_id)
client.service_principal_owner_add(sp_object_id, body)


def remove_service_principal_owner(client, owner_object_id, identifier):
sp_object_id = _resolve_service_principal(client, identifier)
return client.service_principal_owner_remove(sp_object_id, owner_object_id)


def list_service_principal_owners(client, identifier):
sp_object_id = _resolve_service_principal(client, identifier)
return client.service_principal_owner_list(sp_object_id)
Expand Down
Loading
Loading