From 4445dc39b79179ef96ba57258ac9116c8284f481 Mon Sep 17 00:00:00 2001 From: shanepeckham Date: Thu, 9 Aug 2018 11:51:13 +0100 Subject: [PATCH 1/3] Rebase az ad app permissions list grant --- .../azure/cli/command_modules/role/_help.py | 14 +++++ .../azure/cli/command_modules/role/_params.py | 7 +++ .../cli/command_modules/role/commands.py | 2 + .../azure/cli/command_modules/role/custom.py | 55 ++++++++++++++++++- 4 files changed, 76 insertions(+), 2 deletions(-) diff --git a/src/command_modules/azure-cli-role/azure/cli/command_modules/role/_help.py b/src/command_modules/azure-cli-role/azure/cli/command_modules/role/_help.py index 850c2e4f48b..e1d9b6abc0b 100644 --- a/src/command_modules/azure-cli-role/azure/cli/command_modules/role/_help.py +++ b/src/command_modules/azure-cli-role/azure/cli/command_modules/role/_help.py @@ -151,6 +151,20 @@ az ad app update --id e042ec79-34cd-498f-9d9f-123456781234 --set groupMembershipClaims=All """ +helps['ad app permission grant'] = """ + type: command + short-summary: Grant an app OAuth2 permissions from another app + examples: + - name: Grant a native application with OAuth2 permissions from an existing AAD app with TTL of 2 years + text: az ad app permission grant --id e042ec79-34cd-498f-9d9f-1234234 --app-id a0322f79-57df-498f-9d9f-12678 --expires 2 +""" +helps['ad app permission list'] = """ + type: command + short-summary: List the app OAuth2 permissions + examples: + - name: List the OAuth2 permissions for an existing AAD app + text: az ad app permission list --id e042ec79-34cd-498f-9d9f-1234234 +""" helps['ad user list'] = """ type: command short-summary: List Azure Active Directory users. diff --git a/src/command_modules/azure-cli-role/azure/cli/command_modules/role/_params.py b/src/command_modules/azure-cli-role/azure/cli/command_modules/role/_params.py index ad60fc0506a..51c7007081b 100644 --- a/src/command_modules/azure-cli-role/azure/cli/command_modules/role/_params.py +++ b/src/command_modules/azure-cli-role/azure/cli/command_modules/role/_params.py @@ -42,6 +42,13 @@ def load_arguments(self, _): help="resource scopes and roles the application requires access to. Should be in manifest json format. See examples below for details") c.argument('native_app', arg_type=get_three_state_flag(), help="an application which can be installed on a user's device or computer") + with self.argument_context('ad app permission grant') as c: + c.argument('app_id', help='clientId of an existing app from which you want to grant permissions to your app') + c.argument('expires', help='Expiry date for the permissions in years, options include 1, 2 or never.') + + with self.argument_context('ad app permission list') as c: + c.argument('identifier', options_list=['--id'], help='identifier uri, application id, or object id of the associated application') + with self.argument_context('ad sp') as c: c.argument('identifier', options_list=['--id'], help='service principal name, or object id') diff --git a/src/command_modules/azure-cli-role/azure/cli/command_modules/role/commands.py b/src/command_modules/azure-cli-role/azure/cli/command_modules/role/commands.py index 5b538bddb52..030c2d83970 100644 --- a/src/command_modules/azure-cli-role/azure/cli/command_modules/role/commands.py +++ b/src/command_modules/azure-cli-role/azure/cli/command_modules/role/commands.py @@ -84,6 +84,8 @@ def load_command_table(self, _): g.custom_command('delete', 'delete_application') g.custom_command('list', 'list_apps') g.custom_show_command('show', 'show_application') + g.custom_command('permission grant', 'grant_application') + g.custom_command('permission list', 'list_granted_application') g.generic_update_command('update', setter_name='patch_application', setter_type=role_custom, getter_name='show_application', getter_type=role_custom, custom_func_name='update_application', custom_func_type=role_custom) diff --git a/src/command_modules/azure-cli-role/azure/cli/command_modules/role/custom.py b/src/command_modules/azure-cli-role/azure/cli/command_modules/role/custom.py index d68ca47a747..9521e5bc02d 100644 --- a/src/command_modules/azure-cli-role/azure/cli/command_modules/role/custom.py +++ b/src/command_modules/azure-cli-role/azure/cli/command_modules/role/custom.py @@ -667,6 +667,53 @@ def create_application(client, display_name, homepage=None, identifier_uris=None return result +def list_granted_application(cmd, identifier): + graph_client = _graph_client_factory(cmd.cli_ctx) + + # Get the Service Principal ObjectId for the client app + client_sp_object_id = _resolve_service_principal(graph_client.service_principals, appid=identifier) + + # Get the OAuth2 permissions client app + permissions = graph_client.oauth2.get( + filter="clientId eq '{}'".format(client_sp_object_id)) + + return permissions.additional_properties['value'] + + +def grant_application(cmd, identifier, app_id, expires='1'): + graph_client = _graph_client_factory(cmd.cli_ctx) + + # Get the Service Principal ObjectId for the client app + client_sp_object_id = _resolve_service_principal(graph_client.service_principals, appid=identifier) + + # Get the Service Principal ObjectId for associated app + associated_sp_object_id = _resolve_service_principal(graph_client.service_principals, appid=app_id) + + # Build payload + start_date = datetime.datetime.utcnow() + end_date = start_date + relativedelta(years=1) + + if expires == '2': + end_date = start_date + relativedelta(years=2) + elif expires.lower() == 'never': + end_date = start_date + relativedelta(years=1000) + + payload = { + "odata.type": "Microsoft.DirectoryServices.OAuth2PermissionGrant", + "clientId": client_sp_object_id, + "consentType": "AllPrincipals", + "resourceId": associated_sp_object_id, + "scope": "user_impersonation", + "startTime": start_date.isoformat(), + "expiryTime": end_date.isoformat() + } + + # Grant OAuth2 permissions + response = graph_client.oauth2.post(payload) + + return response + + def update_application(instance, display_name=None, homepage=None, # pylint: disable=unused-argument identifier_uris=None, password=None, reply_urls=None, key_value=None, key_type=None, key_usage=None, start_date=None, end_date=None, available_to_other_tenants=None, @@ -884,9 +931,13 @@ def delete_service_principal_credential(cmd, identifier, key_id, cert=False): key_id, identifier)) -def _resolve_service_principal(client, identifier): +def _resolve_service_principal(client, identifier=None, appid=None): # todo: confirm with graph team that a service principal name must be unique - result = list(client.list(filter="servicePrincipalNames/any(c:c eq '{}')".format(identifier))) + if identifier: + result = list(client.list(filter="servicePrincipalNames/any(c:c eq '{}')".format(identifier))) + elif appid: + result = list(client.list(filter="appId eq '{}'".format(appid))) + if result: return result[0].object_id if _is_guid(identifier): From 9b49a63fa5c1c06633075393ee146f77dbb11ed6 Mon Sep 17 00:00:00 2001 From: shanepeckham Date: Thu, 9 Aug 2018 18:10:17 +0100 Subject: [PATCH 2/3] Rebased az ad app permissions list grant --- .../azure/cli/command_modules/role/_help.py | 4 ++++ .../azure/cli/command_modules/role/custom.py | 18 +++++++----------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/command_modules/azure-cli-role/azure/cli/command_modules/role/_help.py b/src/command_modules/azure-cli-role/azure/cli/command_modules/role/_help.py index e1d9b6abc0b..f8cc8d0b6e9 100644 --- a/src/command_modules/azure-cli-role/azure/cli/command_modules/role/_help.py +++ b/src/command_modules/azure-cli-role/azure/cli/command_modules/role/_help.py @@ -151,6 +151,10 @@ az ad app update --id e042ec79-34cd-498f-9d9f-123456781234 --set groupMembershipClaims=All """ +helps['ad app permission'] = """ + type: group + short-summary: manage an application's OAuth2 permissions. +""" helps['ad app permission grant'] = """ type: command short-summary: Grant an app OAuth2 permissions from another app diff --git a/src/command_modules/azure-cli-role/azure/cli/command_modules/role/custom.py b/src/command_modules/azure-cli-role/azure/cli/command_modules/role/custom.py index 9521e5bc02d..50c875ce5aa 100644 --- a/src/command_modules/azure-cli-role/azure/cli/command_modules/role/custom.py +++ b/src/command_modules/azure-cli-role/azure/cli/command_modules/role/custom.py @@ -671,11 +671,11 @@ def list_granted_application(cmd, identifier): graph_client = _graph_client_factory(cmd.cli_ctx) # Get the Service Principal ObjectId for the client app - client_sp_object_id = _resolve_service_principal(graph_client.service_principals, appid=identifier) + client_sp_object_id = _resolve_service_principal(graph_client.service_principals, identifier) # Get the OAuth2 permissions client app permissions = graph_client.oauth2.get( - filter="clientId eq '{}'".format(client_sp_object_id)) + filter="clientId eq '{}'".format(client_sp_object_id)) # pylint: disable=no-member return permissions.additional_properties['value'] @@ -684,10 +684,10 @@ def grant_application(cmd, identifier, app_id, expires='1'): graph_client = _graph_client_factory(cmd.cli_ctx) # Get the Service Principal ObjectId for the client app - client_sp_object_id = _resolve_service_principal(graph_client.service_principals, appid=identifier) + client_sp_object_id = _resolve_service_principal(graph_client.service_principals, identifier) # Get the Service Principal ObjectId for associated app - associated_sp_object_id = _resolve_service_principal(graph_client.service_principals, appid=app_id) + associated_sp_object_id = _resolve_service_principal(graph_client.service_principals, app_id) # Build payload start_date = datetime.datetime.utcnow() @@ -709,7 +709,7 @@ def grant_application(cmd, identifier, app_id, expires='1'): } # Grant OAuth2 permissions - response = graph_client.oauth2.post(payload) + response = graph_client.oauth2.post(payload) # pylint: disable=no-member return response @@ -931,13 +931,9 @@ def delete_service_principal_credential(cmd, identifier, key_id, cert=False): key_id, identifier)) -def _resolve_service_principal(client, identifier=None, appid=None): +def _resolve_service_principal(client, identifier): # todo: confirm with graph team that a service principal name must be unique - if identifier: - result = list(client.list(filter="servicePrincipalNames/any(c:c eq '{}')".format(identifier))) - elif appid: - result = list(client.list(filter="appId eq '{}'".format(appid))) - + result = list(client.list(filter="servicePrincipalNames/any(c:c eq '{}')".format(identifier))) if result: return result[0].object_id if _is_guid(identifier): From 63312deb48ffc7f535c5e80a51fe70bdf3cef60e Mon Sep 17 00:00:00 2001 From: Shane Peckham Date: Thu, 27 Sep 2018 15:40:25 +0100 Subject: [PATCH 3/3] Update _help.py --- .../azure-cli-role/azure/cli/command_modules/role/_help.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/command_modules/azure-cli-role/azure/cli/command_modules/role/_help.py b/src/command_modules/azure-cli-role/azure/cli/command_modules/role/_help.py index 94778442dce..93fc3af7f0d 100644 --- a/src/command_modules/azure-cli-role/azure/cli/command_modules/role/_help.py +++ b/src/command_modules/azure-cli-role/azure/cli/command_modules/role/_help.py @@ -159,7 +159,6 @@ az ad app update --id e042ec79-34cd-498f-9d9f-123456781234 --set groupMembershipClaims=All """ -az_ad_app_grant_command helps['ad app permission'] = """ type: group short-summary: manage an application's OAuth2 permissions.