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 56c8652635d..02574605d30 100644 --- a/src/azure-cli/azure/cli/command_modules/role/_help.py +++ b/src/azure-cli/azure/cli/command_modules/role/_help.py @@ -322,6 +322,78 @@ """ +helps['ad app federated-credential'] = """ +type: group +short-summary: Manage application federated identity credentials. +""" + +helps['ad app federated-credential list'] = """ +type: command +short-summary: List application federated identity credentials. +examples: + - name: List application federated identity credentials. + text: az ad app federated-credential list --id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +""" + + +helps['ad app federated-credential create'] = """ +type: command +short-summary: Create application federated identity credential. +examples: + - name: Create application federated identity credential. + text: | + az ad app federated-credential create --id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --parameters credential.json + ("credential.json" contains the following content) + { + "name": "Testing", + "issuer": "https://token.actions.githubusercontent.com/", + "subject": "repo:octo-org/octo-repo:environment:Production", + "description": "Testing", + "audiences": [ + "api://AzureADTokenExchange" + ] + } +""" + + +helps['ad app federated-credential show'] = """ +type: command +short-summary: Show application federated identity credential. +examples: + - name: Show application federated identity credential. + text: az ad app federated-credential show --id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --credential-id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +""" + + +helps['ad app federated-credential update'] = """ +type: command +short-summary: Update application federated identity credential. +examples: + - name: Update application federated identity credential. + text: | + az ad app federated-credential update --id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --credential-id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --parameters credential.json + ("credential.json" contains the following content) + { + "name": "Testing", + "issuer": "https://token.actions.githubusercontent.com/", + "subject": "repo:octo-org/octo-repo:environment:Production", + "description": "Testing", + "audiences": [ + "api://AzureADTokenExchange" + ] + } +""" + + +helps['ad app federated-credential delete'] = """ +type: command +short-summary: Delete application federated identity credential. +examples: + - name: Delete application federated identity credential. + text: az ad app federated-credential delete --id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --credential-id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +""" + + helps['ad group'] = """ type: group short-summary: Manage Azure Active Directory groups. diff --git a/src/azure-cli/azure/cli/command_modules/role/_msgrpah/_graph_client.py b/src/azure-cli/azure/cli/command_modules/role/_msgrpah/_graph_client.py index 58cd3de51b1..8ed84461351 100644 --- a/src/azure-cli/azure/cli/command_modules/role/_msgrpah/_graph_client.py +++ b/src/azure-cli/azure/cli/command_modules/role/_msgrpah/_graph_client.py @@ -2,6 +2,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. # -------------------------------------------------------------------------------------------- + +# pylint: disable=line-too-long, redefined-builtin, too-many-public-methods + import json from azure.cli.core._profile import Profile @@ -10,8 +13,6 @@ from azure.cli.core.azclierror import HTTPError -# pylint: disable=redefined-builtin, too-many-public-methods - class GraphClient: """A lightweight Microsoft Graph API client. @@ -20,21 +21,25 @@ class GraphClient: For full documentation, see doc/microsoft_graph_client.md in this repo. """ + + # API versions + V1_0 = 'v1.0' + BETA = 'beta' + def __init__(self, cli_ctx): - self.cli_ctx = cli_ctx - self.tenant = Profile(cli_ctx).get_login_credentials()[2] - self.scopes = resource_to_scopes(cli_ctx.cloud.endpoints.microsoft_graph_resource_id) + self._cli_ctx = cli_ctx + self._scopes = resource_to_scopes(cli_ctx.cloud.endpoints.microsoft_graph_resource_id) # https://graph.microsoft.com/ (AzureCloud) # https://microsoftgraph.chinacloudapi.cn (AzureChinaCloud) - self.resource = cli_ctx.cloud.endpoints.microsoft_graph_resource_id + self._resource = cli_ctx.cloud.endpoints.microsoft_graph_resource_id - # https://graph.microsoft.com/v1.0 - # https://microsoftgraph.chinacloudapi.cn/v1.0 - self.base_url = cli_ctx.cloud.endpoints.microsoft_graph_resource_id.rstrip('/') + '/v1.0' + # https://graph.microsoft.com + # https://microsoftgraph.chinacloudapi.cn + self._endpoint = cli_ctx.cloud.endpoints.microsoft_graph_resource_id.rstrip('/') - def _send(self, method, url, param=None, body=None): - url = self.base_url + url + def _send(self, method, url, param=None, body=None, api_version=V1_0): + url = f'{self._endpoint}/{api_version}{url}' if body: body = json.dumps(body) @@ -44,7 +49,8 @@ def _send(self, method, url, param=None, body=None): while True: try: - r = send_raw_request(self.cli_ctx, method, url, resource=self.resource, uri_parameters=param, body=body) + r = send_raw_request(self._cli_ctx, method, url, resource=self._resource, uri_parameters=param, + body=body) except HTTPError as ex: raise GraphError(ex.response.json()['error']['message'], ex.response) from ex # Other exceptions like AuthenticationError should not be handled here, so we don't catch CLIError @@ -75,6 +81,11 @@ def _send(self, method, url, param=None, body=None): # id is python built-in name: https://docs.python.org/3/library/functions.html#id # filter is python built-in name: https://docs.python.org/3/library/functions.html#filter + def application_list(self, filter=None): + # https://docs.microsoft.com/en-us/graph/api/application-list + result = self._send("GET", "/applications" + _filter_to_query(filter)) + return result + def application_create(self, body): # https://docs.microsoft.com/en-us/graph/api/application-post-applications result = self._send("POST", "/applications", body=body) @@ -85,9 +96,13 @@ def application_get(self, id): result = self._send("GET", "/applications/{id}".format(id=id)) return result - def application_list(self, filter=None): - # https://docs.microsoft.com/en-us/graph/api/application-list - result = self._send("GET", "/applications" + _filter_to_query(filter)) + def application_update(self, id, body): + # https://docs.microsoft.com/en-us/graph/api/application-update + # AD Graph SDK uses verb 'patch', instead of 'update': + # azure.graphrbac.operations.applications_operations.ApplicationsOperations.patch + # We use 'update' to align with other update operations: + # azure.graphrbac.operations.users_operations.UsersOperations.update + result = self._send("PATCH", "/applications/{id}".format(id=id), body=body) return result def application_delete(self, id): @@ -95,9 +110,9 @@ def application_delete(self, id): result = self._send("DELETE", "/applications/{id}".format(id=id)) return result - def application_update(self, id, body): - # https://docs.microsoft.com/en-us/graph/api/application-update - result = self._send("PATCH", "/applications/{id}".format(id=id), body=body) + def application_owner_list(self, id): + # https://docs.microsoft.com/en-us/graph/api/application-list-owners + result = self._send("GET", "/applications/{id}/owners".format(id=id)) return result def application_owner_add(self, id, body): @@ -105,11 +120,6 @@ def application_owner_add(self, id, body): result = self._send("POST", "/applications/{id}/owners/$ref".format(id=id), body=body) return result - def application_owner_list(self, id): - # https://docs.microsoft.com/en-us/graph/api/application-list-owners - result = self._send("GET", "/applications/{id}/owners".format(id=id)) - return result - def application_owner_remove(self, id, owner_id): # https://docs.microsoft.com/en-us/graph/api/application-delete-owners result = self._send("DELETE", "/applications/{id}/owners/{owner_id}/$ref".format(id=id, owner_id=owner_id)) @@ -126,6 +136,52 @@ def application_remove_password(self, id, body): result = self._send("POST", "/applications/{id}/removePassword".format(id=id), body=body) return result + def application_federated_identity_credential_list(self, application_id, filter=None): + # https://docs.microsoft.com/en-us/graph/api/application-list-federatedidentitycredentials + result = self._send( + "GET", + f"/applications/{application_id}/federatedIdentityCredentials" + _filter_to_query(filter), + api_version=GraphClient.BETA) + return result + + def application_federated_identity_credential_create(self, application_id, body): + # https://docs.microsoft.com/en-us/graph/api/application-post-federatedidentitycredentials + result = self._send( + "POST", + f"/applications/{application_id}/federatedIdentityCredentials", + body=body, api_version=GraphClient.BETA) + return result + + def application_federated_identity_credential_get(self, application_id, federated_identity_credential_id_or_name): + # https://docs.microsoft.com/en-us/graph/api/federatedidentitycredential-get + result = self._send( + "GET", + f"/applications/{application_id}/federatedIdentityCredentials/{federated_identity_credential_id_or_name}", + api_version=GraphClient.BETA) + return result + + def application_federated_identity_credential_update( + self, application_id, federated_identity_credential_id_or_name, body): + # https://docs.microsoft.com/en-us/graph/api/federatedidentitycredential-update + result = self._send( + "PATCH", + f"/applications/{application_id}/federatedIdentityCredentials/{federated_identity_credential_id_or_name}", + body=body, api_version=GraphClient.BETA) + return result + + def application_federated_identity_credential_delete(self, application_id, federated_identity_credential_id_or_name): + # https://docs.microsoft.com/en-us/graph/api/federatedidentitycredential-delete + result = self._send( + "DELETE", + f"/applications/{application_id}/federatedIdentityCredentials/{federated_identity_credential_id_or_name}", + api_version=GraphClient.BETA) + return result + + def service_principal_list(self, filter=None): + # https://docs.microsoft.com/en-us/graph/api/serviceprincipal-list + result = self._send("GET", "/servicePrincipals" + _filter_to_query(filter)) + return result + def service_principal_create(self, body): # https://docs.microsoft.com/en-us/graph/api/serviceprincipal-post-serviceprincipals result = self._send("POST", "/servicePrincipals", body=body) @@ -136,9 +192,9 @@ def service_principal_get(self, id): result = self._send("GET", "/servicePrincipals/{id}".format(id=id)) return result - def service_principal_list(self, filter=None): - # https://docs.microsoft.com/en-us/graph/api/serviceprincipal-list - result = self._send("GET", "/servicePrincipals" + _filter_to_query(filter)) + def service_principal_update(self, id, body): + # https://docs.microsoft.com/en-us/graph/api/serviceprincipal-update + result = self._send("PATCH", "/servicePrincipals/{id}".format(id=id), body=body) return result def service_principal_delete(self, id): @@ -146,11 +202,6 @@ def service_principal_delete(self, id): result = self._send("DELETE", "/servicePrincipals/{id}".format(id=id)) return result - def service_principal_update(self, id, body): - # https://docs.microsoft.com/en-us/graph/api/serviceprincipal-update - result = self._send("PATCH", "/servicePrincipals/{id}".format(id=id), body=body) - return result - def service_principal_add_password(self, id, body): # https://docs.microsoft.com/en-us/graph/api/serviceprincipal-addpassword result = self._send("POST", "/servicePrincipals/{id}/addPassword".format(id=id), body=body) @@ -166,6 +217,47 @@ def service_principal_owner_list(self, id): result = self._send("GET", "/servicePrincipals/{id}/owners".format(id=id)) return result + def service_principal_federated_identity_credential_list(self, application_id, filter=None): + # https://docs.microsoft.com/en-us/graph/api/application-list-federatedidentitycredentials + result = self._send( + "GET", + f"/servicePrincipals/{application_id}/federatedIdentityCredentials" + _filter_to_query(filter), + api_version=GraphClient.BETA) + return result + + def service_principal_federated_identity_credential_create(self, application_id, body): + # https://docs.microsoft.com/en-us/graph/api/application-post-federatedidentitycredentials + result = self._send( + "POST", + f"/servicePrincipals/{application_id}/federatedIdentityCredentials", + body=body, api_version=GraphClient.BETA) + return result + + def service_principal_federated_identity_credential_get(self, application_id, federated_identity_credential_id_or_name): + # https://docs.microsoft.com/en-us/graph/api/federatedidentitycredential-get + result = self._send( + "GET", + f"/servicePrincipals/{application_id}/federatedIdentityCredentials/{federated_identity_credential_id_or_name}", + api_version=GraphClient.BETA) + return result + + def service_principal_federated_identity_credential_update( + self, application_id, federated_identity_credential_id_or_name, body): + # https://docs.microsoft.com/en-us/graph/api/federatedidentitycredential-update + result = self._send( + "PATCH", + f"/servicePrincipals/{application_id}/federatedIdentityCredentials/{federated_identity_credential_id_or_name}", + body=body, api_version=GraphClient.BETA) + return result + + def service_principal_federated_identity_credential_delete(self, application_id, federated_identity_credential_id_or_name): + # https://docs.microsoft.com/en-us/graph/api/federatedidentitycredential-delete + result = self._send( + "DELETE", + f"/servicePrincipals/{application_id}/federatedIdentityCredentials/{federated_identity_credential_id_or_name}", + api_version=GraphClient.BETA) + return result + def owned_objects_list(self): # https://docs.microsoft.com/en-us/graph/api/user-list-ownedobjects result = self._send("GET", "/me/ownedObjects") @@ -191,6 +283,11 @@ def group_get_member_groups(self, id, body): result = self._send("POST", "/groups/{id}/getMemberGroups".format(id=id), body=body) return result + def group_list(self, filter=None): + # https://docs.microsoft.com/en-us/graph/api/group-list + result = self._send("GET", "/groups" + _filter_to_query(filter)) + return result + def group_create(self, body): # https://docs.microsoft.com/en-us/graph/api/group-post-groups result = self._send("POST", "/groups", body=body) @@ -201,11 +298,6 @@ def group_get(self, id): result = self._send("GET", "/groups/{id}".format(id=id)) return result - def group_list(self, filter=None): - # https://docs.microsoft.com/en-us/graph/api/group-list - result = self._send("GET", "/groups" + _filter_to_query(filter)) - return result - def group_delete(self, id): # https://docs.microsoft.com/en-us/graph/api/group-delete result = self._send("DELETE", "/groups/{id}".format(id=id)) @@ -241,6 +333,11 @@ def group_member_remove(self, id, member_id): result = self._send("DELETE", "/groups/{id}/members/{member_id}/$ref".format(id=id, member_id=member_id)) return result + def user_list(self, filter): + # https://docs.microsoft.com/graph/api/user-list + result = self._send("GET", "/users" + _filter_to_query(filter)) + return result + def user_create(self, body): # https://docs.microsoft.com/graph/api/user-post-users result = self._send("POST", "/users", body=body) @@ -258,9 +355,9 @@ def user_get(self, id_or_upn): result = self._send("GET", "/users/{}".format(id_or_upn)) return result - def user_list(self, filter): - # https://docs.microsoft.com/graph/api/user-list - result = self._send("GET", "/users" + _filter_to_query(filter)) + def user_update(self, id_or_upn, body): + # https://docs.microsoft.com/graph/api/user-update + result = self._send("PATCH", "/users/{}".format(id_or_upn), body=body) return result def user_delete(self, id_or_upn): @@ -268,31 +365,39 @@ def user_delete(self, id_or_upn): result = self._send("DELETE", "/users/{}".format(id_or_upn)) return result - def user_update(self, id_or_upn, body): - # https://docs.microsoft.com/graph/api/user-update - result = self._send("PATCH", "/users/{}".format(id_or_upn), body=body) - return result - def user_get_member_groups(self, id_or_upn, body): # https://docs.microsoft.com/en-us/graph/api/directoryobject-getmembergroups result = self._send("POST", "/users/{}/getMemberGroups".format(id_or_upn), body=body) return result - def oauth2_permission_grant_create(self, body): - # https://docs.microsoft.com/en-us/graph/api/oauth2permissiongrant-post - result = self._send("POST", "/oauth2PermissionGrants", body=body) - return result - def oauth2_permission_grant_list(self, filter=None): # https://docs.microsoft.com/en-us/graph/api/oauth2permissiongrant-list result = self._send("GET", "/oauth2PermissionGrants" + _filter_to_query(filter)) return result + def oauth2_permission_grant_create(self, body): + # https://docs.microsoft.com/en-us/graph/api/oauth2permissiongrant-post + result = self._send("POST", "/oauth2PermissionGrants", body=body) + return result + def oauth2_permission_grant_delete(self, id): # https://docs.microsoft.com/en-us/graph/api/oauth2permissiongrant-delete result = self._send("DELETE", "/oAuth2PermissionGrants/{id}".format(id=id)) return result + def get_object_url(self, object_id_or_url, api_version=V1_0): + """The object URL should be in the form of https://graph.microsoft.com/v1.0/directoryObjects/{id} + If object_id_or_url is a GUID, convert it to a URL. + Otherwise, it may already be a URL, use it as-is. + """ + from azure.cli.core.util import is_guid + return f'{self._endpoint}/{api_version}/directoryObjects/{object_id_or_url}' if is_guid(object_id_or_url) \ + else object_id_or_url + + @property + def tenant(self): + return Profile(self._cli_ctx).get_login_credentials()[2] + def _filter_to_query(filter): if filter is not None: diff --git a/src/azure-cli/azure/cli/command_modules/role/_msgrpah/_graph_objects.py b/src/azure-cli/azure/cli/command_modules/role/_msgrpah/_graph_objects.py index 847ea5f948a..025a37b7786 100644 --- a/src/azure-cli/azure/cli/command_modules/role/_msgrpah/_graph_objects.py +++ b/src/azure-cli/azure/cli/command_modules/role/_msgrpah/_graph_objects.py @@ -48,7 +48,6 @@ 'description': 'description' } - _object_type_to_property_map = { 'application': _application_property_map, 'user': _user_property_map, 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 81228c01f0b..0c8d494df62 100644 --- a/src/azure-cli/azure/cli/command_modules/role/_params.py +++ b/src/azure-cli/azure/cli/command_modules/role/_params.py @@ -18,6 +18,9 @@ name_arg_type = CLIArgumentType(options_list=('--name', '-n'), metavar='NAME') +JSON_PROPERTY_HELP = "Should be in JSON format. See examples below for details" + + # pylint: disable=too-many-statements def load_arguments(self, _): with self.argument_context('ad') as c: @@ -91,21 +94,20 @@ def load_arguments(self, _): help="Friendly name for the key.") # JSON properties - json_property_help = "Should be in manifest JSON format. See examples below for details" c.argument('required_resource_accesses', arg_group='JSON property', type=validate_file_or_dict, help="Specifies the resources that the application needs to access. This property also specifies " "the set of delegated permissions and application roles that it needs for each of those " "resources. This configuration of access to the required resources drives the consent " - "experience. " + json_property_help) + "experience. " + JSON_PROPERTY_HELP) c.argument('app_roles', arg_group='JSON property', type=validate_file_or_dict, help="The collection of roles assigned to the application. With app role assignments, these roles " "can be assigned to users, groups, or service principals associated with other applications. " + - json_property_help) + JSON_PROPERTY_HELP) c.argument('optional_claims', arg_group='JSON property', type=validate_file_or_dict, help="Application developers can configure optional claims in their Azure AD applications to " "specify the claims that are sent to their application by the Microsoft security token " "service. For more information, see https://docs.microsoft.com/azure/active-directory/develop" - "/active-directory-optional-claims. " + json_property_help) + "/active-directory-optional-claims. " + JSON_PROPERTY_HELP) with self.argument_context('ad app owner list') as c: c.argument('identifier', options_list=['--id'], help='identifier uri, application id, or object id of the application') @@ -205,6 +207,16 @@ def load_arguments(self, _): c.argument('create_cert', action='store_true', arg_group='keyCredentials', help='Create a self-signed certificate to use for the credential') c.argument('keyvault', arg_group='keyCredentials', help='Name or ID of a KeyVault to use for creating or retrieving certificates.') + for item in ['app', 'sp']: + with self.argument_context(f'ad {item} federated-credential') as c: + # TODO: We have to decide which name to use + # --credential-id is consistent with API + # --key-id is consistent with passwordCredentials and keyCredentials + c.argument('parameters', type=validate_file_or_dict, + help='Parameters for creating federated identity credential. ' + JSON_PROPERTY_HELP) + c.argument('credential_id_or_name', options_list=['--credential-id', '--key-id'], + help='Name or ID of the federated identity credential') + for item in ['ad sp credential delete', 'ad sp credential list', 'ad app credential delete', 'ad app credential list']: with self.argument_context(item) as c: c.argument('key_id', help='credential key id') diff --git a/src/azure-cli/azure/cli/command_modules/role/commands.py b/src/azure-cli/azure/cli/command_modules/role/commands.py index aa40c33f949..cd1bd6bd51f 100644 --- a/src/azure-cli/azure/cli/command_modules/role/commands.py +++ b/src/azure-cli/azure/cli/command_modules/role/commands.py @@ -99,6 +99,18 @@ def load_command_table(self, _): g.custom_command('credential list', 'list_application_credentials') g.custom_command('credential delete', 'delete_application_credential') + # Register federated-credential command group under both app and sp. + # We use federated-credential instead of federated-identity-credential or fic, in order to align with + # Azure Portal. + # It seems sp doesn't work with federatedIdentityCredentials yet. + # for item in ['app', 'sp']: + for item in ['app']: + with self.command_group(f'ad {item} federated-credential', + client_factory=get_graph_client, resource_type=PROFILE_TYPE, + exception_handler=graph_err_handler, is_experimental=True) as g: + for command in ['list', 'create', 'show', 'update', 'delete']: + g.custom_command(command, f'{item}_federated_credential_{command}') + with self.command_group('ad app owner', client_factory=get_graph_client, exception_handler=graph_err_handler) as g: g.custom_command('list', 'list_application_owners') g.custom_command('add', 'add_application_owner') 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 10f47b3b996..f81e3748078 100644 --- a/src/azure-cli/azure/cli/command_modules/role/custom.py +++ b/src/azure-cli/azure/cli/command_modules/role/custom.py @@ -983,6 +983,34 @@ def list_permission_grants(client, identifier=None, query_filter=None, show_reso return result +def app_federated_credential_list(client, identifier): + object_id = _resolve_application(client, identifier) + # This call is too simple, so it's unnecessary to extract a common method for both application and servicePrincipal + # and invoke it like + # _federated_identity_credential_list(client.application_federated_identity_credential_list, object_id) + return client.application_federated_identity_credential_list(object_id) + + +def app_federated_credential_create(client, identifier, parameters): + object_id = _resolve_application(client, identifier) + return client.application_federated_identity_credential_create(object_id, parameters) + + +def app_federated_credential_show(client, identifier, credential_id_or_name): + object_id = _resolve_application(client, identifier) + return client.application_federated_identity_credential_get(object_id, credential_id_or_name) + + +def app_federated_credential_update(client, identifier, credential_id_or_name, parameters): + object_id = _resolve_application(client, identifier) + return client.application_federated_identity_credential_update(object_id, credential_id_or_name, parameters) + + +def app_federated_credential_delete(client, identifier, credential_id_or_name): + object_id = _resolve_application(client, identifier) + return client.application_federated_identity_credential_delete(object_id, credential_id_or_name) + + def create_service_principal(cmd, identifier): return _create_service_principal(cmd.cli_ctx, identifier) @@ -1088,6 +1116,31 @@ def list_service_principal_credentials(cmd, identifier, cert=False): return _list_credentials(sp, cert) +def sp_federated_credential_list(client, identifier): + object_id = _resolve_service_principal(client, identifier) + return client.service_principal_federated_identity_credential_list(object_id) + + +def sp_federated_credential_create(client, identifier, parameters): + object_id = _resolve_service_principal(client, identifier) + return client.service_principal_federated_identity_credential_create(object_id, parameters) + + +def sp_federated_credential_show(client, identifier, credential_id_or_name): + object_id = _resolve_service_principal(client, identifier) + return client.service_principal_federated_identity_credential_get(object_id, credential_id_or_name) + + +def sp_federated_credential_update(client, identifier, credential_id_or_name, parameters): + object_id = _resolve_service_principal(client, identifier) + return client.service_principal_federated_identity_credential_update(object_id, credential_id_or_name, parameters) + + +def sp_federated_credential_delete(client, identifier, credential_id_or_name): + object_id = _resolve_service_principal(client, identifier) + return client.service_principal_federated_identity_credential_delete(object_id, credential_id_or_name) + + def _get_app_object_id_from_sp_object_id(client, sp_object_id): sp = client.service_principals.get(sp_object_id) result = list(client.applications.list(filter="appId eq '{}'".format(sp.app_id))) @@ -1948,13 +2001,9 @@ def _resolve_group(client, identifier): def _build_directory_object_json(client, object_id): - """Get JSON representation of the id of the directoryObject. - The object URL should be in the form of https://graph.microsoft.com/v1.0/directoryObjects/{id} - """ - # If object_id is not a GUID, use it as-is. - object_url = f'{client.base_url}/directoryObjects/{object_id}'if is_guid(object_id) else object_id + """Get JSON representation of the id of the directoryObject.""" body = { - "@odata.id": object_url + "@odata.id": client.get_object_url(object_id) } return body diff --git a/src/azure-cli/azure/cli/command_modules/role/tests/latest/recordings/test_app_federated_credential.yaml b/src/azure-cli/azure/cli/command_modules/role/tests/latest/recordings/test_app_federated_credential.yaml new file mode 100644 index 00000000000..7da05202744 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/role/tests/latest/recordings/test_app_federated_credential.yaml @@ -0,0 +1,1063 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - ad app create + Connection: + - keep-alive + ParameterSetName: + - --display-name + User-Agent: + - python/3.10.4 (Windows-10-10.0.22000-SP0) AZURECLI/2.37.0 + method: GET + uri: https://graph.microsoft.com/v1.0/applications?$filter=startswith(displayName,'azure-cli-test000001') + response: + body: + string: '{"@odata.context":"https://graph.microsoft.com/v1.0/$metadata#applications","value":[]}' + headers: + cache-control: + - no-cache + content-length: + - '87' + content-type: + - application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8 + date: + - Mon, 13 Jun 2022 09:27:30 GMT + odata-version: + - '4.0' + request-id: + - 96302f8e-ab27-4cd5-a90e-5aa09e2a0001 + strict-transport-security: + - max-age=31536000 + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-ms-ags-diagnostic: + - '{"ServerInfo":{"DataCenter":"Southeast Asia","Slice":"E","Ring":"5","ScaleUnit":"001","RoleInstance":"SI2PEPF00000BCF"}}' + x-ms-resource-unit: + - '2' + status: + code: 200 + message: OK +- request: + body: '{"displayName": "azure-cli-test000001", "keyCredentials": []}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - ad app create + Connection: + - keep-alive + Content-Length: + - '61' + Content-Type: + - application/json + ParameterSetName: + - --display-name + User-Agent: + - python/3.10.4 (Windows-10-10.0.22000-SP0) AZURECLI/2.37.0 + method: POST + uri: https://graph.microsoft.com/v1.0/applications + response: + body: + string: '{"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#applications/$entity", + "id": "4d5c0e0b-9816-4aa2-a444-395e807c6f80", "deletedDateTime": null, "appId": + "1a139bcd-74f9-48e2-834a-d897c7a9b4d6", "applicationTemplateId": null, "disabledByMicrosoftStatus": + null, "createdDateTime": "2022-06-13T09:27:32.2479019Z", "displayName": "azure-cli-test000001", + "description": null, "groupMembershipClaims": null, "identifierUris": [], + "isDeviceOnlyAuthSupported": null, "isFallbackPublicClient": null, "notes": + null, "publisherDomain": "AzureSDKTeam.onmicrosoft.com", "serviceManagementReference": + null, "signInAudience": "AzureADandPersonalMicrosoftAccount", "tags": [], + "tokenEncryptionKeyId": null, "defaultRedirectUri": null, "certification": + null, "optionalClaims": null, "addIns": [], "api": {"acceptMappedClaims": + null, "knownClientApplications": [], "requestedAccessTokenVersion": 2, "oauth2PermissionScopes": + [], "preAuthorizedApplications": []}, "appRoles": [], "info": {"logoUrl": + null, "marketingUrl": null, "privacyStatementUrl": null, "supportUrl": null, + "termsOfServiceUrl": null}, "keyCredentials": [], "parentalControlSettings": + {"countriesBlockedForMinors": [], "legalAgeGroupRule": "Allow"}, "passwordCredentials": + [], "publicClient": {"redirectUris": []}, "requiredResourceAccess": [], "verifiedPublisher": + {"displayName": null, "verifiedPublisherId": null, "addedDateTime": null}, + "web": {"homePageUrl": null, "logoutUrl": null, "redirectUris": [], "implicitGrantSettings": + {"enableAccessTokenIssuance": false, "enableIdTokenIssuance": false}}, "spa": + {"redirectUris": []}}' + headers: + cache-control: + - no-cache + content-length: + - '1595' + content-type: + - application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8 + date: + - Mon, 13 Jun 2022 09:27:32 GMT + location: + - https://graph.microsoft.com/v2/54826b22-38d6-4fb2-bad9-b7b93a3e9c5a/directoryObjects/4d5c0e0b-9816-4aa2-a444-395e807c6f80/Microsoft.DirectoryServices.Application + odata-version: + - '4.0' + request-id: + - 39f4b235-24f4-4f8d-8648-61905079e0e7 + strict-transport-security: + - max-age=31536000 + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-ms-ags-diagnostic: + - '{"ServerInfo":{"DataCenter":"Southeast Asia","Slice":"E","Ring":"5","ScaleUnit":"001","RoleInstance":"SI2PEPF00001E1F"}}' + x-ms-resource-unit: + - '1' + status: + code: 201 + message: Created +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - ad app federated-credential create + Connection: + - keep-alive + ParameterSetName: + - --id --parameters + User-Agent: + - python/3.10.4 (Windows-10-10.0.22000-SP0) AZURECLI/2.37.0 + method: GET + uri: https://graph.microsoft.com/v1.0/applications?$filter=appId%20eq%20'1a139bcd-74f9-48e2-834a-d897c7a9b4d6' + response: + body: + string: '{"@odata.context":"https://graph.microsoft.com/v1.0/$metadata#applications","value":[{"id":"4d5c0e0b-9816-4aa2-a444-395e807c6f80","deletedDateTime":null,"appId":"1a139bcd-74f9-48e2-834a-d897c7a9b4d6","applicationTemplateId":null,"disabledByMicrosoftStatus":null,"createdDateTime":"2022-06-13T09:27:32Z","displayName":"azure-cli-test000001","description":null,"groupMembershipClaims":null,"identifierUris":[],"isDeviceOnlyAuthSupported":null,"isFallbackPublicClient":null,"notes":null,"publisherDomain":"AzureSDKTeam.onmicrosoft.com","serviceManagementReference":null,"signInAudience":"AzureADandPersonalMicrosoftAccount","tags":[],"tokenEncryptionKeyId":null,"defaultRedirectUri":null,"certification":null,"optionalClaims":null,"addIns":[],"api":{"acceptMappedClaims":null,"knownClientApplications":[],"requestedAccessTokenVersion":2,"oauth2PermissionScopes":[],"preAuthorizedApplications":[]},"appRoles":[],"info":{"logoUrl":null,"marketingUrl":null,"privacyStatementUrl":null,"supportUrl":null,"termsOfServiceUrl":null},"keyCredentials":[],"parentalControlSettings":{"countriesBlockedForMinors":[],"legalAgeGroupRule":"Allow"},"passwordCredentials":[],"publicClient":{"redirectUris":[]},"requiredResourceAccess":[],"verifiedPublisher":{"displayName":null,"verifiedPublisherId":null,"addedDateTime":null},"web":{"homePageUrl":null,"logoutUrl":null,"redirectUris":[],"implicitGrantSettings":{"enableAccessTokenIssuance":false,"enableIdTokenIssuance":false}},"spa":{"redirectUris":[]}}]}' + headers: + cache-control: + - no-cache + content-length: + - '1486' + content-type: + - application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8 + date: + - Mon, 13 Jun 2022 09:27:33 GMT + odata-version: + - '4.0' + request-id: + - 72318deb-9535-46eb-affa-83a3a59aa9df + strict-transport-security: + - max-age=31536000 + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-ms-ags-diagnostic: + - '{"ServerInfo":{"DataCenter":"Southeast Asia","Slice":"E","Ring":"5","ScaleUnit":"001","RoleInstance":"SI2PEPF000022D5"}}' + x-ms-resource-unit: + - '2' + status: + code: 200 + message: OK +- request: + body: '{"name": "Testing", "issuer": "https://token.actions.githubusercontent.com/", + "subject": "repo:octo-org/octo-repo:environment:Production", "description": + "Testing", "audiences": ["api://AzureADTokenExchange"]}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - ad app federated-credential create + Connection: + - keep-alive + Content-Length: + - '209' + Content-Type: + - application/json + ParameterSetName: + - --id --parameters + User-Agent: + - python/3.10.4 (Windows-10-10.0.22000-SP0) AZURECLI/2.37.0 + method: POST + uri: https://graph.microsoft.com/beta/applications/4d5c0e0b-9816-4aa2-a444-395e807c6f80/federatedIdentityCredentials + response: + body: + string: '{"@odata.context":"https://graph.microsoft.com/beta/$metadata#applications(''4d5c0e0b-9816-4aa2-a444-395e807c6f80'')/federatedIdentityCredentials/$entity","id":"2276d18a-223c-46d9-83a6-cfaadcb4c258","name":"Testing","issuer":"https://token.actions.githubusercontent.com/","subject":"repo:octo-org/octo-repo:environment:Production","description":"Testing","audiences":["api://AzureADTokenExchange"]}' + headers: + cache-control: + - no-cache + content-length: + - '396' + content-type: + - application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8 + date: + - Mon, 13 Jun 2022 09:27:35 GMT + location: + - https://graph.microsoft.com/v2/54826b22-38d6-4fb2-bad9-b7b93a3e9c5a/federatedIdentityCredentials/2276d18a-223c-46d9-83a6-cfaadcb4c258 + odata-version: + - '4.0' + request-id: + - c9a6b63f-ee88-401a-8b0f-d497900b7285 + strict-transport-security: + - max-age=31536000 + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-ms-ags-diagnostic: + - '{"ServerInfo":{"DataCenter":"Southeast Asia","Slice":"E","Ring":"5","ScaleUnit":"001","RoleInstance":"SI2PEPF00002404"}}' + x-ms-resource-unit: + - '1' + status: + code: 201 + message: Created +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - ad app federated-credential list + Connection: + - keep-alive + ParameterSetName: + - --id + User-Agent: + - python/3.10.4 (Windows-10-10.0.22000-SP0) AZURECLI/2.37.0 + method: GET + uri: https://graph.microsoft.com/v1.0/applications?$filter=appId%20eq%20'1a139bcd-74f9-48e2-834a-d897c7a9b4d6' + response: + body: + string: '{"@odata.context":"https://graph.microsoft.com/v1.0/$metadata#applications","value":[{"id":"4d5c0e0b-9816-4aa2-a444-395e807c6f80","deletedDateTime":null,"appId":"1a139bcd-74f9-48e2-834a-d897c7a9b4d6","applicationTemplateId":null,"disabledByMicrosoftStatus":null,"createdDateTime":"2022-06-13T09:27:32Z","displayName":"azure-cli-test000001","description":null,"groupMembershipClaims":null,"identifierUris":[],"isDeviceOnlyAuthSupported":null,"isFallbackPublicClient":null,"notes":null,"publisherDomain":"AzureSDKTeam.onmicrosoft.com","serviceManagementReference":null,"signInAudience":"AzureADandPersonalMicrosoftAccount","tags":[],"tokenEncryptionKeyId":null,"defaultRedirectUri":null,"certification":null,"optionalClaims":null,"addIns":[],"api":{"acceptMappedClaims":null,"knownClientApplications":[],"requestedAccessTokenVersion":2,"oauth2PermissionScopes":[],"preAuthorizedApplications":[]},"appRoles":[],"info":{"logoUrl":null,"marketingUrl":null,"privacyStatementUrl":null,"supportUrl":null,"termsOfServiceUrl":null},"keyCredentials":[],"parentalControlSettings":{"countriesBlockedForMinors":[],"legalAgeGroupRule":"Allow"},"passwordCredentials":[],"publicClient":{"redirectUris":[]},"requiredResourceAccess":[],"verifiedPublisher":{"displayName":null,"verifiedPublisherId":null,"addedDateTime":null},"web":{"homePageUrl":null,"logoutUrl":null,"redirectUris":[],"implicitGrantSettings":{"enableAccessTokenIssuance":false,"enableIdTokenIssuance":false}},"spa":{"redirectUris":[]}}]}' + headers: + cache-control: + - no-cache + content-length: + - '1486' + content-type: + - application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8 + date: + - Mon, 13 Jun 2022 09:27:36 GMT + odata-version: + - '4.0' + request-id: + - 68712da1-2585-4ccb-87db-051ec8a4a0ca + strict-transport-security: + - max-age=31536000 + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-ms-ags-diagnostic: + - '{"ServerInfo":{"DataCenter":"Southeast Asia","Slice":"E","Ring":"5","ScaleUnit":"001","RoleInstance":"SI2PEPF00002334"}}' + x-ms-resource-unit: + - '2' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - ad app federated-credential list + Connection: + - keep-alive + ParameterSetName: + - --id + User-Agent: + - python/3.10.4 (Windows-10-10.0.22000-SP0) AZURECLI/2.37.0 + method: GET + uri: https://graph.microsoft.com/beta/applications/4d5c0e0b-9816-4aa2-a444-395e807c6f80/federatedIdentityCredentials + response: + body: + string: '{"@odata.context":"https://graph.microsoft.com/beta/$metadata#applications(''4d5c0e0b-9816-4aa2-a444-395e807c6f80'')/federatedIdentityCredentials","value":[{"id":"2276d18a-223c-46d9-83a6-cfaadcb4c258","name":"Testing","issuer":"https://token.actions.githubusercontent.com/","subject":"repo:octo-org/octo-repo:environment:Production","description":"Testing","audiences":["api://AzureADTokenExchange"]}]}' + headers: + cache-control: + - no-cache + content-length: + - '400' + content-type: + - application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8 + date: + - Mon, 13 Jun 2022 09:27:37 GMT + odata-version: + - '4.0' + request-id: + - d01c0461-c988-4fcd-9169-0e020b3c4731 + strict-transport-security: + - max-age=31536000 + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-ms-ags-diagnostic: + - '{"ServerInfo":{"DataCenter":"Southeast Asia","Slice":"E","Ring":"5","ScaleUnit":"001","RoleInstance":"SI2PEPF000017E9"}}' + x-ms-resource-unit: + - '1' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - ad app federated-credential show + Connection: + - keep-alive + ParameterSetName: + - --id --credential-id + User-Agent: + - python/3.10.4 (Windows-10-10.0.22000-SP0) AZURECLI/2.37.0 + method: GET + uri: https://graph.microsoft.com/v1.0/applications?$filter=appId%20eq%20'1a139bcd-74f9-48e2-834a-d897c7a9b4d6' + response: + body: + string: '{"@odata.context":"https://graph.microsoft.com/v1.0/$metadata#applications","value":[{"id":"4d5c0e0b-9816-4aa2-a444-395e807c6f80","deletedDateTime":null,"appId":"1a139bcd-74f9-48e2-834a-d897c7a9b4d6","applicationTemplateId":null,"disabledByMicrosoftStatus":null,"createdDateTime":"2022-06-13T09:27:32Z","displayName":"azure-cli-test000001","description":null,"groupMembershipClaims":null,"identifierUris":[],"isDeviceOnlyAuthSupported":null,"isFallbackPublicClient":null,"notes":null,"publisherDomain":"AzureSDKTeam.onmicrosoft.com","serviceManagementReference":null,"signInAudience":"AzureADandPersonalMicrosoftAccount","tags":[],"tokenEncryptionKeyId":null,"defaultRedirectUri":null,"certification":null,"optionalClaims":null,"addIns":[],"api":{"acceptMappedClaims":null,"knownClientApplications":[],"requestedAccessTokenVersion":2,"oauth2PermissionScopes":[],"preAuthorizedApplications":[]},"appRoles":[],"info":{"logoUrl":null,"marketingUrl":null,"privacyStatementUrl":null,"supportUrl":null,"termsOfServiceUrl":null},"keyCredentials":[],"parentalControlSettings":{"countriesBlockedForMinors":[],"legalAgeGroupRule":"Allow"},"passwordCredentials":[],"publicClient":{"redirectUris":[]},"requiredResourceAccess":[],"verifiedPublisher":{"displayName":null,"verifiedPublisherId":null,"addedDateTime":null},"web":{"homePageUrl":null,"logoutUrl":null,"redirectUris":[],"implicitGrantSettings":{"enableAccessTokenIssuance":false,"enableIdTokenIssuance":false}},"spa":{"redirectUris":[]}}]}' + headers: + cache-control: + - no-cache + content-length: + - '1486' + content-type: + - application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8 + date: + - Mon, 13 Jun 2022 09:27:38 GMT + odata-version: + - '4.0' + request-id: + - 1160542b-0ef2-4c85-b672-f3d67c7f0861 + strict-transport-security: + - max-age=31536000 + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-ms-ags-diagnostic: + - '{"ServerInfo":{"DataCenter":"Southeast Asia","Slice":"E","Ring":"5","ScaleUnit":"001","RoleInstance":"SI2PEPF00002404"}}' + x-ms-resource-unit: + - '2' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - ad app federated-credential show + Connection: + - keep-alive + ParameterSetName: + - --id --credential-id + User-Agent: + - python/3.10.4 (Windows-10-10.0.22000-SP0) AZURECLI/2.37.0 + method: GET + uri: https://graph.microsoft.com/beta/applications/4d5c0e0b-9816-4aa2-a444-395e807c6f80/federatedIdentityCredentials/2276d18a-223c-46d9-83a6-cfaadcb4c258 + response: + body: + string: '{"@odata.context":"https://graph.microsoft.com/beta/$metadata#applications(''4d5c0e0b-9816-4aa2-a444-395e807c6f80'')/federatedIdentityCredentials/$entity","id":"2276d18a-223c-46d9-83a6-cfaadcb4c258","name":"Testing","issuer":"https://token.actions.githubusercontent.com/","subject":"repo:octo-org/octo-repo:environment:Production","description":"Testing","audiences":["api://AzureADTokenExchange"]}' + headers: + cache-control: + - no-cache + content-length: + - '396' + content-type: + - application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8 + date: + - Mon, 13 Jun 2022 09:27:39 GMT + odata-version: + - '4.0' + request-id: + - d51a2ac4-24e9-46b7-b747-e2b4fd8d18e9 + strict-transport-security: + - max-age=31536000 + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-ms-ags-diagnostic: + - '{"ServerInfo":{"DataCenter":"Southeast Asia","Slice":"E","Ring":"5","ScaleUnit":"001","RoleInstance":"SI2PEPF00002335"}}' + x-ms-resource-unit: + - '1' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - ad app federated-credential show + Connection: + - keep-alive + ParameterSetName: + - --id --credential-id + User-Agent: + - python/3.10.4 (Windows-10-10.0.22000-SP0) AZURECLI/2.37.0 + method: GET + uri: https://graph.microsoft.com/v1.0/applications?$filter=appId%20eq%20'1a139bcd-74f9-48e2-834a-d897c7a9b4d6' + response: + body: + string: '{"@odata.context":"https://graph.microsoft.com/v1.0/$metadata#applications","value":[{"id":"4d5c0e0b-9816-4aa2-a444-395e807c6f80","deletedDateTime":null,"appId":"1a139bcd-74f9-48e2-834a-d897c7a9b4d6","applicationTemplateId":null,"disabledByMicrosoftStatus":null,"createdDateTime":"2022-06-13T09:27:32Z","displayName":"azure-cli-test000001","description":null,"groupMembershipClaims":null,"identifierUris":[],"isDeviceOnlyAuthSupported":null,"isFallbackPublicClient":null,"notes":null,"publisherDomain":"AzureSDKTeam.onmicrosoft.com","serviceManagementReference":null,"signInAudience":"AzureADandPersonalMicrosoftAccount","tags":[],"tokenEncryptionKeyId":null,"defaultRedirectUri":null,"certification":null,"optionalClaims":null,"addIns":[],"api":{"acceptMappedClaims":null,"knownClientApplications":[],"requestedAccessTokenVersion":2,"oauth2PermissionScopes":[],"preAuthorizedApplications":[]},"appRoles":[],"info":{"logoUrl":null,"marketingUrl":null,"privacyStatementUrl":null,"supportUrl":null,"termsOfServiceUrl":null},"keyCredentials":[],"parentalControlSettings":{"countriesBlockedForMinors":[],"legalAgeGroupRule":"Allow"},"passwordCredentials":[],"publicClient":{"redirectUris":[]},"requiredResourceAccess":[],"verifiedPublisher":{"displayName":null,"verifiedPublisherId":null,"addedDateTime":null},"web":{"homePageUrl":null,"logoutUrl":null,"redirectUris":[],"implicitGrantSettings":{"enableAccessTokenIssuance":false,"enableIdTokenIssuance":false}},"spa":{"redirectUris":[]}}]}' + headers: + cache-control: + - no-cache + content-length: + - '1486' + content-type: + - application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8 + date: + - Mon, 13 Jun 2022 09:27:40 GMT + odata-version: + - '4.0' + request-id: + - 3f39d30e-a849-4e9f-8cd5-3ddc53ae0a23 + strict-transport-security: + - max-age=31536000 + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-ms-ags-diagnostic: + - '{"ServerInfo":{"DataCenter":"Southeast Asia","Slice":"E","Ring":"5","ScaleUnit":"001","RoleInstance":"SI2PEPF000022D4"}}' + x-ms-resource-unit: + - '2' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - ad app federated-credential show + Connection: + - keep-alive + ParameterSetName: + - --id --credential-id + User-Agent: + - python/3.10.4 (Windows-10-10.0.22000-SP0) AZURECLI/2.37.0 + method: GET + uri: https://graph.microsoft.com/beta/applications/4d5c0e0b-9816-4aa2-a444-395e807c6f80/federatedIdentityCredentials/Testing + response: + body: + string: '{"@odata.context":"https://graph.microsoft.com/beta/$metadata#applications(''4d5c0e0b-9816-4aa2-a444-395e807c6f80'')/federatedIdentityCredentials/$entity","id":"2276d18a-223c-46d9-83a6-cfaadcb4c258","name":"Testing","issuer":"https://token.actions.githubusercontent.com/","subject":"repo:octo-org/octo-repo:environment:Production","description":"Testing","audiences":["api://AzureADTokenExchange"]}' + headers: + cache-control: + - no-cache + content-length: + - '396' + content-type: + - application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8 + date: + - Mon, 13 Jun 2022 09:27:40 GMT + odata-version: + - '4.0' + request-id: + - 35f43230-8164-489f-84fe-41ccff454cc4 + strict-transport-security: + - max-age=31536000 + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-ms-ags-diagnostic: + - '{"ServerInfo":{"DataCenter":"Southeast Asia","Slice":"E","Ring":"5","ScaleUnit":"001","RoleInstance":"SI2PEPF00002336"}}' + x-ms-resource-unit: + - '1' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - ad app federated-credential update + Connection: + - keep-alive + ParameterSetName: + - --id --credential-id --parameters + User-Agent: + - python/3.10.4 (Windows-10-10.0.22000-SP0) AZURECLI/2.37.0 + method: GET + uri: https://graph.microsoft.com/v1.0/applications?$filter=appId%20eq%20'1a139bcd-74f9-48e2-834a-d897c7a9b4d6' + response: + body: + string: '{"@odata.context":"https://graph.microsoft.com/v1.0/$metadata#applications","value":[{"id":"4d5c0e0b-9816-4aa2-a444-395e807c6f80","deletedDateTime":null,"appId":"1a139bcd-74f9-48e2-834a-d897c7a9b4d6","applicationTemplateId":null,"disabledByMicrosoftStatus":null,"createdDateTime":"2022-06-13T09:27:32Z","displayName":"azure-cli-test000001","description":null,"groupMembershipClaims":null,"identifierUris":[],"isDeviceOnlyAuthSupported":null,"isFallbackPublicClient":null,"notes":null,"publisherDomain":"AzureSDKTeam.onmicrosoft.com","serviceManagementReference":null,"signInAudience":"AzureADandPersonalMicrosoftAccount","tags":[],"tokenEncryptionKeyId":null,"defaultRedirectUri":null,"certification":null,"optionalClaims":null,"addIns":[],"api":{"acceptMappedClaims":null,"knownClientApplications":[],"requestedAccessTokenVersion":2,"oauth2PermissionScopes":[],"preAuthorizedApplications":[]},"appRoles":[],"info":{"logoUrl":null,"marketingUrl":null,"privacyStatementUrl":null,"supportUrl":null,"termsOfServiceUrl":null},"keyCredentials":[],"parentalControlSettings":{"countriesBlockedForMinors":[],"legalAgeGroupRule":"Allow"},"passwordCredentials":[],"publicClient":{"redirectUris":[]},"requiredResourceAccess":[],"verifiedPublisher":{"displayName":null,"verifiedPublisherId":null,"addedDateTime":null},"web":{"homePageUrl":null,"logoutUrl":null,"redirectUris":[],"implicitGrantSettings":{"enableAccessTokenIssuance":false,"enableIdTokenIssuance":false}},"spa":{"redirectUris":[]}}]}' + headers: + cache-control: + - no-cache + content-length: + - '1486' + content-type: + - application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8 + date: + - Mon, 13 Jun 2022 09:27:41 GMT + odata-version: + - '4.0' + request-id: + - 32076d9c-fa53-4392-8dba-09417dc89546 + strict-transport-security: + - max-age=31536000 + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-ms-ags-diagnostic: + - '{"ServerInfo":{"DataCenter":"Southeast Asia","Slice":"E","Ring":"5","ScaleUnit":"001","RoleInstance":"SI2PEPF000023F9"}}' + x-ms-resource-unit: + - '2' + status: + code: 200 + message: OK +- request: + body: '{"subject": "repo:octo-org/octo-repo:environment:Staging"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - ad app federated-credential update + Connection: + - keep-alive + Content-Length: + - '58' + Content-Type: + - application/json + ParameterSetName: + - --id --credential-id --parameters + User-Agent: + - python/3.10.4 (Windows-10-10.0.22000-SP0) AZURECLI/2.37.0 + method: PATCH + uri: https://graph.microsoft.com/beta/applications/4d5c0e0b-9816-4aa2-a444-395e807c6f80/federatedIdentityCredentials/2276d18a-223c-46d9-83a6-cfaadcb4c258 + response: + body: + string: '' + headers: + cache-control: + - no-cache + date: + - Mon, 13 Jun 2022 09:27:43 GMT + request-id: + - d9418acf-5912-4f09-9d26-6bf66e2f0c86 + strict-transport-security: + - max-age=31536000 + x-ms-ags-diagnostic: + - '{"ServerInfo":{"DataCenter":"Southeast Asia","Slice":"E","Ring":"5","ScaleUnit":"001","RoleInstance":"SI2PEPF000018C7"}}' + x-ms-resource-unit: + - '1' + status: + code: 204 + message: No Content +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - ad app federated-credential show + Connection: + - keep-alive + ParameterSetName: + - --id --credential-id + User-Agent: + - python/3.10.4 (Windows-10-10.0.22000-SP0) AZURECLI/2.37.0 + method: GET + uri: https://graph.microsoft.com/v1.0/applications?$filter=appId%20eq%20'1a139bcd-74f9-48e2-834a-d897c7a9b4d6' + response: + body: + string: '{"@odata.context":"https://graph.microsoft.com/v1.0/$metadata#applications","value":[{"id":"4d5c0e0b-9816-4aa2-a444-395e807c6f80","deletedDateTime":null,"appId":"1a139bcd-74f9-48e2-834a-d897c7a9b4d6","applicationTemplateId":null,"disabledByMicrosoftStatus":null,"createdDateTime":"2022-06-13T09:27:32Z","displayName":"azure-cli-test000001","description":null,"groupMembershipClaims":null,"identifierUris":[],"isDeviceOnlyAuthSupported":null,"isFallbackPublicClient":null,"notes":null,"publisherDomain":"AzureSDKTeam.onmicrosoft.com","serviceManagementReference":null,"signInAudience":"AzureADandPersonalMicrosoftAccount","tags":[],"tokenEncryptionKeyId":null,"defaultRedirectUri":null,"certification":null,"optionalClaims":null,"addIns":[],"api":{"acceptMappedClaims":null,"knownClientApplications":[],"requestedAccessTokenVersion":2,"oauth2PermissionScopes":[],"preAuthorizedApplications":[]},"appRoles":[],"info":{"logoUrl":null,"marketingUrl":null,"privacyStatementUrl":null,"supportUrl":null,"termsOfServiceUrl":null},"keyCredentials":[],"parentalControlSettings":{"countriesBlockedForMinors":[],"legalAgeGroupRule":"Allow"},"passwordCredentials":[],"publicClient":{"redirectUris":[]},"requiredResourceAccess":[],"verifiedPublisher":{"displayName":null,"verifiedPublisherId":null,"addedDateTime":null},"web":{"homePageUrl":null,"logoutUrl":null,"redirectUris":[],"implicitGrantSettings":{"enableAccessTokenIssuance":false,"enableIdTokenIssuance":false}},"spa":{"redirectUris":[]}}]}' + headers: + cache-control: + - no-cache + content-length: + - '1486' + content-type: + - application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8 + date: + - Mon, 13 Jun 2022 09:27:44 GMT + odata-version: + - '4.0' + request-id: + - 44520a5d-8022-437f-bb04-b2547a0198b9 + strict-transport-security: + - max-age=31536000 + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-ms-ags-diagnostic: + - '{"ServerInfo":{"DataCenter":"Southeast Asia","Slice":"E","Ring":"5","ScaleUnit":"001","RoleInstance":"SI2PEPF00000BC4"}}' + x-ms-resource-unit: + - '2' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - ad app federated-credential show + Connection: + - keep-alive + ParameterSetName: + - --id --credential-id + User-Agent: + - python/3.10.4 (Windows-10-10.0.22000-SP0) AZURECLI/2.37.0 + method: GET + uri: https://graph.microsoft.com/beta/applications/4d5c0e0b-9816-4aa2-a444-395e807c6f80/federatedIdentityCredentials/2276d18a-223c-46d9-83a6-cfaadcb4c258 + response: + body: + string: '{"@odata.context":"https://graph.microsoft.com/beta/$metadata#applications(''4d5c0e0b-9816-4aa2-a444-395e807c6f80'')/federatedIdentityCredentials/$entity","id":"2276d18a-223c-46d9-83a6-cfaadcb4c258","name":"Testing","issuer":"https://token.actions.githubusercontent.com/","subject":"repo:octo-org/octo-repo:environment:Staging","description":"Testing","audiences":["api://AzureADTokenExchange"]}' + headers: + cache-control: + - no-cache + content-length: + - '393' + content-type: + - application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8 + date: + - Mon, 13 Jun 2022 09:27:45 GMT + odata-version: + - '4.0' + request-id: + - 53f1e19c-b776-4798-98cd-b11befd9491c + strict-transport-security: + - max-age=31536000 + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-ms-ags-diagnostic: + - '{"ServerInfo":{"DataCenter":"Southeast Asia","Slice":"E","Ring":"5","ScaleUnit":"001","RoleInstance":"SI2PEPF00000BCF"}}' + x-ms-resource-unit: + - '1' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - ad app federated-credential delete + Connection: + - keep-alive + ParameterSetName: + - --id --credential-id + User-Agent: + - python/3.10.4 (Windows-10-10.0.22000-SP0) AZURECLI/2.37.0 + method: GET + uri: https://graph.microsoft.com/v1.0/applications?$filter=appId%20eq%20'1a139bcd-74f9-48e2-834a-d897c7a9b4d6' + response: + body: + string: '{"@odata.context":"https://graph.microsoft.com/v1.0/$metadata#applications","value":[{"id":"4d5c0e0b-9816-4aa2-a444-395e807c6f80","deletedDateTime":null,"appId":"1a139bcd-74f9-48e2-834a-d897c7a9b4d6","applicationTemplateId":null,"disabledByMicrosoftStatus":null,"createdDateTime":"2022-06-13T09:27:32Z","displayName":"azure-cli-test000001","description":null,"groupMembershipClaims":null,"identifierUris":[],"isDeviceOnlyAuthSupported":null,"isFallbackPublicClient":null,"notes":null,"publisherDomain":"AzureSDKTeam.onmicrosoft.com","serviceManagementReference":null,"signInAudience":"AzureADandPersonalMicrosoftAccount","tags":[],"tokenEncryptionKeyId":null,"defaultRedirectUri":null,"certification":null,"optionalClaims":null,"addIns":[],"api":{"acceptMappedClaims":null,"knownClientApplications":[],"requestedAccessTokenVersion":2,"oauth2PermissionScopes":[],"preAuthorizedApplications":[]},"appRoles":[],"info":{"logoUrl":null,"marketingUrl":null,"privacyStatementUrl":null,"supportUrl":null,"termsOfServiceUrl":null},"keyCredentials":[],"parentalControlSettings":{"countriesBlockedForMinors":[],"legalAgeGroupRule":"Allow"},"passwordCredentials":[],"publicClient":{"redirectUris":[]},"requiredResourceAccess":[],"verifiedPublisher":{"displayName":null,"verifiedPublisherId":null,"addedDateTime":null},"web":{"homePageUrl":null,"logoutUrl":null,"redirectUris":[],"implicitGrantSettings":{"enableAccessTokenIssuance":false,"enableIdTokenIssuance":false}},"spa":{"redirectUris":[]}}]}' + headers: + cache-control: + - no-cache + content-length: + - '1486' + content-type: + - application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8 + date: + - Mon, 13 Jun 2022 09:27:46 GMT + odata-version: + - '4.0' + request-id: + - 2e866f28-e98a-4cf4-a250-46a003752dd7 + strict-transport-security: + - max-age=31536000 + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-ms-ags-diagnostic: + - '{"ServerInfo":{"DataCenter":"Southeast Asia","Slice":"E","Ring":"5","ScaleUnit":"001","RoleInstance":"SI2PEPF00002401"}}' + x-ms-resource-unit: + - '2' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - ad app federated-credential delete + Connection: + - keep-alive + Content-Length: + - '0' + ParameterSetName: + - --id --credential-id + User-Agent: + - python/3.10.4 (Windows-10-10.0.22000-SP0) AZURECLI/2.37.0 + method: DELETE + uri: https://graph.microsoft.com/beta/applications/4d5c0e0b-9816-4aa2-a444-395e807c6f80/federatedIdentityCredentials/2276d18a-223c-46d9-83a6-cfaadcb4c258 + response: + body: + string: '' + headers: + cache-control: + - no-cache + date: + - Mon, 13 Jun 2022 09:27:47 GMT + request-id: + - 895b3f4d-a164-4274-a0f4-662322d6e5f7 + strict-transport-security: + - max-age=31536000 + x-ms-ags-diagnostic: + - '{"ServerInfo":{"DataCenter":"Southeast Asia","Slice":"E","Ring":"5","ScaleUnit":"001","RoleInstance":"SI2PEPF000017E9"}}' + x-ms-resource-unit: + - '1' + status: + code: 204 + message: No Content +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - ad app federated-credential list + Connection: + - keep-alive + ParameterSetName: + - --id + User-Agent: + - python/3.10.4 (Windows-10-10.0.22000-SP0) AZURECLI/2.37.0 + method: GET + uri: https://graph.microsoft.com/v1.0/applications?$filter=appId%20eq%20'1a139bcd-74f9-48e2-834a-d897c7a9b4d6' + response: + body: + string: '{"@odata.context":"https://graph.microsoft.com/v1.0/$metadata#applications","value":[{"id":"4d5c0e0b-9816-4aa2-a444-395e807c6f80","deletedDateTime":null,"appId":"1a139bcd-74f9-48e2-834a-d897c7a9b4d6","applicationTemplateId":null,"disabledByMicrosoftStatus":null,"createdDateTime":"2022-06-13T09:27:32Z","displayName":"azure-cli-test000001","description":null,"groupMembershipClaims":null,"identifierUris":[],"isDeviceOnlyAuthSupported":null,"isFallbackPublicClient":null,"notes":null,"publisherDomain":"AzureSDKTeam.onmicrosoft.com","serviceManagementReference":null,"signInAudience":"AzureADandPersonalMicrosoftAccount","tags":[],"tokenEncryptionKeyId":null,"defaultRedirectUri":null,"certification":null,"optionalClaims":null,"addIns":[],"api":{"acceptMappedClaims":null,"knownClientApplications":[],"requestedAccessTokenVersion":2,"oauth2PermissionScopes":[],"preAuthorizedApplications":[]},"appRoles":[],"info":{"logoUrl":null,"marketingUrl":null,"privacyStatementUrl":null,"supportUrl":null,"termsOfServiceUrl":null},"keyCredentials":[],"parentalControlSettings":{"countriesBlockedForMinors":[],"legalAgeGroupRule":"Allow"},"passwordCredentials":[],"publicClient":{"redirectUris":[]},"requiredResourceAccess":[],"verifiedPublisher":{"displayName":null,"verifiedPublisherId":null,"addedDateTime":null},"web":{"homePageUrl":null,"logoutUrl":null,"redirectUris":[],"implicitGrantSettings":{"enableAccessTokenIssuance":false,"enableIdTokenIssuance":false}},"spa":{"redirectUris":[]}}]}' + headers: + cache-control: + - no-cache + content-length: + - '1486' + content-type: + - application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8 + date: + - Mon, 13 Jun 2022 09:27:48 GMT + odata-version: + - '4.0' + request-id: + - 6999710b-6568-4a95-8c2a-0fe1344ff879 + strict-transport-security: + - max-age=31536000 + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-ms-ags-diagnostic: + - '{"ServerInfo":{"DataCenter":"Southeast Asia","Slice":"E","Ring":"5","ScaleUnit":"001","RoleInstance":"SI2PEPF00002334"}}' + x-ms-resource-unit: + - '2' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - ad app federated-credential list + Connection: + - keep-alive + ParameterSetName: + - --id + User-Agent: + - python/3.10.4 (Windows-10-10.0.22000-SP0) AZURECLI/2.37.0 + method: GET + uri: https://graph.microsoft.com/beta/applications/4d5c0e0b-9816-4aa2-a444-395e807c6f80/federatedIdentityCredentials + response: + body: + string: '{"@odata.context":"https://graph.microsoft.com/beta/$metadata#applications(''4d5c0e0b-9816-4aa2-a444-395e807c6f80'')/federatedIdentityCredentials","value":[]}' + headers: + cache-control: + - no-cache + content-length: + - '156' + content-type: + - application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8 + date: + - Mon, 13 Jun 2022 09:27:49 GMT + odata-version: + - '4.0' + request-id: + - 541c2ab6-f8ca-4408-bcf3-08fae13f79f6 + strict-transport-security: + - max-age=31536000 + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-ms-ags-diagnostic: + - '{"ServerInfo":{"DataCenter":"Southeast Asia","Slice":"E","Ring":"5","ScaleUnit":"001","RoleInstance":"SI2PEPF00001643"}}' + x-ms-resource-unit: + - '1' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - ad app show + Connection: + - keep-alive + ParameterSetName: + - --id + User-Agent: + - python/3.10.4 (Windows-10-10.0.22000-SP0) AZURECLI/2.37.0 + method: GET + uri: https://graph.microsoft.com/v1.0/applications?$filter=appId%20eq%20'1a139bcd-74f9-48e2-834a-d897c7a9b4d6' + response: + body: + string: '{"@odata.context":"https://graph.microsoft.com/v1.0/$metadata#applications","value":[{"id":"4d5c0e0b-9816-4aa2-a444-395e807c6f80","deletedDateTime":null,"appId":"1a139bcd-74f9-48e2-834a-d897c7a9b4d6","applicationTemplateId":null,"disabledByMicrosoftStatus":null,"createdDateTime":"2022-06-13T09:27:32Z","displayName":"azure-cli-test000001","description":null,"groupMembershipClaims":null,"identifierUris":[],"isDeviceOnlyAuthSupported":null,"isFallbackPublicClient":null,"notes":null,"publisherDomain":"AzureSDKTeam.onmicrosoft.com","serviceManagementReference":null,"signInAudience":"AzureADandPersonalMicrosoftAccount","tags":[],"tokenEncryptionKeyId":null,"defaultRedirectUri":null,"certification":null,"optionalClaims":null,"addIns":[],"api":{"acceptMappedClaims":null,"knownClientApplications":[],"requestedAccessTokenVersion":2,"oauth2PermissionScopes":[],"preAuthorizedApplications":[]},"appRoles":[],"info":{"logoUrl":null,"marketingUrl":null,"privacyStatementUrl":null,"supportUrl":null,"termsOfServiceUrl":null},"keyCredentials":[],"parentalControlSettings":{"countriesBlockedForMinors":[],"legalAgeGroupRule":"Allow"},"passwordCredentials":[],"publicClient":{"redirectUris":[]},"requiredResourceAccess":[],"verifiedPublisher":{"displayName":null,"verifiedPublisherId":null,"addedDateTime":null},"web":{"homePageUrl":null,"logoutUrl":null,"redirectUris":[],"implicitGrantSettings":{"enableAccessTokenIssuance":false,"enableIdTokenIssuance":false}},"spa":{"redirectUris":[]}}]}' + headers: + cache-control: + - no-cache + content-length: + - '1486' + content-type: + - application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8 + date: + - Mon, 13 Jun 2022 09:27:50 GMT + odata-version: + - '4.0' + request-id: + - 69328b4b-64cd-4911-a5ab-c5e03aa6fd28 + strict-transport-security: + - max-age=31536000 + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-ms-ags-diagnostic: + - '{"ServerInfo":{"DataCenter":"Southeast Asia","Slice":"E","Ring":"5","ScaleUnit":"001","RoleInstance":"SI2PEPF000022D5"}}' + x-ms-resource-unit: + - '2' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - ad app show + Connection: + - keep-alive + ParameterSetName: + - --id + User-Agent: + - python/3.10.4 (Windows-10-10.0.22000-SP0) AZURECLI/2.37.0 + method: GET + uri: https://graph.microsoft.com/v1.0/applications/4d5c0e0b-9816-4aa2-a444-395e807c6f80 + response: + body: + string: '{"@odata.context":"https://graph.microsoft.com/v1.0/$metadata#applications/$entity","id":"4d5c0e0b-9816-4aa2-a444-395e807c6f80","deletedDateTime":null,"appId":"1a139bcd-74f9-48e2-834a-d897c7a9b4d6","applicationTemplateId":null,"disabledByMicrosoftStatus":null,"createdDateTime":"2022-06-13T09:27:32Z","displayName":"azure-cli-test000001","description":null,"groupMembershipClaims":null,"identifierUris":[],"isDeviceOnlyAuthSupported":null,"isFallbackPublicClient":null,"notes":null,"publisherDomain":"AzureSDKTeam.onmicrosoft.com","serviceManagementReference":null,"signInAudience":"AzureADandPersonalMicrosoftAccount","tags":[],"tokenEncryptionKeyId":null,"defaultRedirectUri":null,"certification":null,"optionalClaims":null,"addIns":[],"api":{"acceptMappedClaims":null,"knownClientApplications":[],"requestedAccessTokenVersion":2,"oauth2PermissionScopes":[],"preAuthorizedApplications":[]},"appRoles":[],"info":{"logoUrl":null,"marketingUrl":null,"privacyStatementUrl":null,"supportUrl":null,"termsOfServiceUrl":null},"keyCredentials":[],"parentalControlSettings":{"countriesBlockedForMinors":[],"legalAgeGroupRule":"Allow"},"passwordCredentials":[],"publicClient":{"redirectUris":[]},"requiredResourceAccess":[],"verifiedPublisher":{"displayName":null,"verifiedPublisherId":null,"addedDateTime":null},"web":{"homePageUrl":null,"logoutUrl":null,"redirectUris":[],"implicitGrantSettings":{"enableAccessTokenIssuance":false,"enableIdTokenIssuance":false}},"spa":{"redirectUris":[]}}' + headers: + cache-control: + - no-cache + content-length: + - '1482' + content-type: + - application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8 + date: + - Mon, 13 Jun 2022 09:27:51 GMT + odata-version: + - '4.0' + request-id: + - 88ae8bb3-8a27-404c-9fdd-3f5186e35495 + strict-transport-security: + - max-age=31536000 + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-ms-ags-diagnostic: + - '{"ServerInfo":{"DataCenter":"Southeast Asia","Slice":"E","Ring":"5","ScaleUnit":"001","RoleInstance":"SI2PEPF000017E9"}}' + x-ms-resource-unit: + - '1' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - ad app delete + Connection: + - keep-alive + ParameterSetName: + - --id + User-Agent: + - python/3.10.4 (Windows-10-10.0.22000-SP0) AZURECLI/2.37.0 + method: GET + uri: https://graph.microsoft.com/v1.0/applications?$filter=appId%20eq%20'1a139bcd-74f9-48e2-834a-d897c7a9b4d6' + response: + body: + string: '{"@odata.context":"https://graph.microsoft.com/v1.0/$metadata#applications","value":[{"id":"4d5c0e0b-9816-4aa2-a444-395e807c6f80","deletedDateTime":null,"appId":"1a139bcd-74f9-48e2-834a-d897c7a9b4d6","applicationTemplateId":null,"disabledByMicrosoftStatus":null,"createdDateTime":"2022-06-13T09:27:32Z","displayName":"azure-cli-test000001","description":null,"groupMembershipClaims":null,"identifierUris":[],"isDeviceOnlyAuthSupported":null,"isFallbackPublicClient":null,"notes":null,"publisherDomain":"AzureSDKTeam.onmicrosoft.com","serviceManagementReference":null,"signInAudience":"AzureADandPersonalMicrosoftAccount","tags":[],"tokenEncryptionKeyId":null,"defaultRedirectUri":null,"certification":null,"optionalClaims":null,"addIns":[],"api":{"acceptMappedClaims":null,"knownClientApplications":[],"requestedAccessTokenVersion":2,"oauth2PermissionScopes":[],"preAuthorizedApplications":[]},"appRoles":[],"info":{"logoUrl":null,"marketingUrl":null,"privacyStatementUrl":null,"supportUrl":null,"termsOfServiceUrl":null},"keyCredentials":[],"parentalControlSettings":{"countriesBlockedForMinors":[],"legalAgeGroupRule":"Allow"},"passwordCredentials":[],"publicClient":{"redirectUris":[]},"requiredResourceAccess":[],"verifiedPublisher":{"displayName":null,"verifiedPublisherId":null,"addedDateTime":null},"web":{"homePageUrl":null,"logoutUrl":null,"redirectUris":[],"implicitGrantSettings":{"enableAccessTokenIssuance":false,"enableIdTokenIssuance":false}},"spa":{"redirectUris":[]}}]}' + headers: + cache-control: + - no-cache + content-length: + - '1486' + content-type: + - application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8 + date: + - Mon, 13 Jun 2022 09:27:51 GMT + odata-version: + - '4.0' + request-id: + - 77090461-f7ac-49d1-b0f7-a7220640e741 + strict-transport-security: + - max-age=31536000 + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-ms-ags-diagnostic: + - '{"ServerInfo":{"DataCenter":"Southeast Asia","Slice":"E","Ring":"5","ScaleUnit":"001","RoleInstance":"SI2PEPF00001E1F"}}' + x-ms-resource-unit: + - '2' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - ad app delete + Connection: + - keep-alive + Content-Length: + - '0' + ParameterSetName: + - --id + User-Agent: + - python/3.10.4 (Windows-10-10.0.22000-SP0) AZURECLI/2.37.0 + method: DELETE + uri: https://graph.microsoft.com/v1.0/applications/4d5c0e0b-9816-4aa2-a444-395e807c6f80 + response: + body: + string: '' + headers: + cache-control: + - no-cache + date: + - Mon, 13 Jun 2022 09:27:52 GMT + request-id: + - d4f7d222-e910-4b66-b6cc-308b4732c9bd + strict-transport-security: + - max-age=31536000 + x-ms-ags-diagnostic: + - '{"ServerInfo":{"DataCenter":"Southeast Asia","Slice":"E","Ring":"5","ScaleUnit":"001","RoleInstance":"SI2PEPF000022D5"}}' + x-ms-resource-unit: + - '1' + status: + code: 204 + message: No Content +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - rest + Connection: + - keep-alive + Content-Length: + - '0' + ParameterSetName: + - --method --url + User-Agent: + - python/3.10.4 (Windows-10-10.0.22000-SP0) AZURECLI/2.37.0 + method: DELETE + uri: https://graph.microsoft.com/v1.0/directory/deletedItems/4d5c0e0b-9816-4aa2-a444-395e807c6f80 + response: + body: + string: '' + headers: + cache-control: + - no-cache + date: + - Mon, 13 Jun 2022 09:27:54 GMT + request-id: + - f086ee43-a4bd-4e89-9142-0960ccece6f0 + strict-transport-security: + - max-age=31536000 + x-ms-ags-diagnostic: + - '{"ServerInfo":{"DataCenter":"Southeast Asia","Slice":"E","Ring":"5","ScaleUnit":"001","RoleInstance":"SI2PEPF000017E9"}}' + x-ms-resource-unit: + - '1' + status: + code: 204 + message: No Content +version: 1 diff --git a/src/azure-cli/azure/cli/command_modules/role/tests/latest/test_graph.py b/src/azure-cli/azure/cli/command_modules/role/tests/latest/test_graph.py index d24c19691d6..842193842ac 100644 --- a/src/azure-cli/azure/cli/command_modules/role/tests/latest/test_graph.py +++ b/src/azure-cli/azure/cli/command_modules/role/tests/latest/test_graph.py @@ -40,7 +40,8 @@ "description": "Consumer apps have access to the consumer data.", "value": "Consumer" } -]''' +] +''' # This test example is from # https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-optional-claims#configuring-optional-claims @@ -68,7 +69,8 @@ "essential": false } ] -}''' +} +''' TEST_REQUIRED_RESOURCE_ACCESS = '''[ { @@ -93,7 +95,22 @@ ], "resourceAppId": "00000003-0000-0000-c000-000000000000" } -]''' +] +''' + +# This test example is from +# https://docs.microsoft.com/en-us/azure/active-directory/develop/workload-identity-federation-create-trust-github?tabs=microsoft-graph +TEST_FEDERATED_IDENTITY_CREDENTIAL = '''{ + "name": "Testing", + "issuer": "https://token.actions.githubusercontent.com/", + "subject": "repo:octo-org/octo-repo:environment:Production", + "description": "Testing", + "audiences": [ + "api://AzureADTokenExchange" + ] +} +''' + # TODO: https://github.com/Azure/azure-cli/pull/13769 fails to work # Cert created with @@ -184,6 +201,40 @@ def _test_credential(self, object_type): self.cmd('ad {object_type} credential list --id {app_id}', checks=self.check('[0].endDateTime', '2100-12-31T00:00:00Z')) + def _test_federated_credential(self, object_type): + self.kwargs['object_type'] = object_type + self.kwargs['parameters'] = TEST_FEDERATED_IDENTITY_CREDENTIAL + self.kwargs['name'] = 'Testing' + + # Create credential + result = self.cmd("ad {object_type} federated-credential create --id {app_id} --parameters '{parameters}'", + checks=[self.check('name', '{name}')]).get_output_in_json() + self.kwargs['credential_id'] = result['id'] + + # List credential + self.cmd("ad {object_type} federated-credential list --id {app_id}", + checks=[self.check('length(@)', 1)]) + + # Show credential with credential ID + self.cmd("ad {object_type} federated-credential show --id {app_id} --credential-id {credential_id}", + checks=[self.check('name', '{name}')]) + # Show with credential name + self.cmd("ad {object_type} federated-credential show --id {app_id} --credential-id {name}", + checks=[self.check('name', '{name}')]) + + # Update credential's subject + update_subject = "repo:octo-org/octo-repo:environment:Staging" + self.kwargs['update_json'] = json.dumps({'subject': update_subject}) + self.cmd("ad {object_type} federated-credential update --id {app_id} --credential-id {credential_id} " + "--parameters '{update_json}'") + self.cmd("ad {object_type} federated-credential show --id {app_id} --credential-id {credential_id}", + checks=self.check('subject', update_subject)) + + # Delete credential + self.cmd("ad {object_type} federated-credential delete --id {app_id} --credential-id {credential_id}") + self.cmd("ad {object_type} federated-credential list --id {app_id}", + checks=[self.check('length(@)', 0)]) + class ApplicationScenarioTest(GraphScenarioTestBase): @@ -590,6 +641,10 @@ def test_app_permission_grant(self): self.cmd('ad app permission delete --id {app_id} --api {microsoft_graph_api}') self.cmd('ad app permission list --id {app_id}', checks=self.check('length([*])', 0)) + def test_app_federated_credential(self): + self._create_app() + self._test_federated_credential('app') + class ServicePrincipalScenarioTest(GraphScenarioTestBase): @@ -660,6 +715,11 @@ def test_sp_credential(self): self._create_sp() self._test_credential('sp') + @unittest.skip("It seems sp doesn't work with federatedIdentityCredentials yet.") + def test_sp_federated_credential(self): + self._create_sp() + self._test_federated_credential('sp') + class UserScenarioTest(GraphScenarioTestBase): def test_user_scenario(self):