1# -------------------------------------------------------------------------------------------- 2# Copyright (c) Microsoft Corporation. All rights reserved. 3# Licensed under the MIT License. See License.txt in the project root for license information. 4# -------------------------------------------------------------------------------------------- 5 6# pylint: disable=line-too-long 7 8from knack.arguments import CLIArgumentType 9from azure.graphrbac.models import ConsentType 10 11from azure.cli.core.commands.parameters import get_enum_type, get_three_state_flag, get_location_type, tags_type 12from azure.cli.core.commands.validators import validate_file_or_dict 13# from azure.cli.core.profiles import ResourceType 14 15 16from azure.cli.command_modules.role._completers import get_role_definition_name_completion_list 17from azure.cli.command_modules.role._validators import validate_group, validate_member_id, validate_cert, VARIANT_GROUP_ID_ARGS 18 19name_arg_type = CLIArgumentType(options_list=('--name', '-n'), metavar='NAME') 20 21 22# pylint: disable=too-many-statements 23def load_arguments(self, _): 24 with self.argument_context('ad') as c: 25 c.ignore('_subscription') # hide global subscription param 26 c.argument('owner_object_id', help="owner's object id") 27 c.argument('show_mine', action='store_true', help='list entities owned by the current user') 28 c.argument('include_all', options_list='--all', action='store_true', 29 help='list all entities, expect long delay if under a big organization') 30 31 with self.argument_context('ad app') as c: 32 c.argument('app_id', help='application id') 33 c.argument('application_object_id', options_list=('--object-id',)) 34 c.argument('display_name', help='the display name of the application') 35 c.argument('homepage', help='the url where users can sign in and use your app.') 36 c.argument('identifier', options_list=['--id'], help='identifier uri, application id, or object id') 37 c.argument('identifier_uris', nargs='+', help='space-separated unique URIs that Azure AD can use for this app.') 38 c.argument('reply_urls', nargs='+', help='space-separated URIs to which Azure AD will redirect in response to an OAuth 2.0 request. The value does not need to be a physical endpoint, but must be a valid URI.') 39 c.argument('start_date', help="Date or datetime at which credentials become valid(e.g. '2017-01-01T01:00:00+00:00' or '2017-01-01'). Default value is current time") 40 c.argument('end_date', help="Date or datetime after which credentials expire(e.g. '2017-12-31T11:59:59+00:00' or '2017-12-31'). Default value is one year after current time") 41 c.argument('available_to_other_tenants', help='the application can be used from any Azure AD tenants', arg_type=get_three_state_flag()) 42 c.argument('key_value', help='the value for the key credentials associated with the application') 43 # TODO: Update these with **enum_choice_list(...) when SDK supports proper enums 44 c.argument('key_type', help='the type of the key credentials associated with the application', arg_type=get_enum_type(['AsymmetricX509Cert', 'Password', 'Symmetric'], default='AsymmetricX509Cert')) 45 c.argument('key_usage', help='the usage of the key credentials associated with the application.', arg_type=get_enum_type(['Sign', 'Verify'], default='Verify')) 46 c.argument('password', help="app password, aka 'client secret'") 47 c.argument('oauth2_allow_implicit_flow', arg_type=get_three_state_flag(), help='whether to allow implicit grant flow for OAuth2') 48 c.argument('required_resource_accesses', type=validate_file_or_dict, 49 help="resource scopes and roles the application requires access to. Should be in manifest json format. See examples below for details") 50 c.argument('app_roles', type=validate_file_or_dict, 51 help="declare the roles you want to associate with your application. Should be in manifest json format. See examples below for details") 52 c.argument('optional_claims', type=validate_file_or_dict, 53 help="declare the optional claims for the application. Should be in manifest json format. See examples below for details. Please reference https://docs.microsoft.com/azure/active-directory/develop/active-directory-optional-claims#optionalclaim-type for optional claim properties.") 54 c.argument('native_app', arg_type=get_three_state_flag(), help="an application which can be installed on a user's device or computer") 55 c.argument('credential_description', help="the description of the password") 56 57 with self.argument_context('ad app owner list') as c: 58 c.argument('identifier', options_list=['--id'], help='identifier uri, application id, or object id of the application') 59 60 with self.argument_context('ad app permission') as c: 61 # https://github.com/Azure/azure-rest-api-specs/blob/32e56f061668a1bf1eeca6209000fad4c09afca8/specification/graphrbac/data-plane/Microsoft.GraphRbac/stable/1.6/graphrbac.json#L2817 62 c.argument('api', help='Specify `RequiredResourceAccess.resourceAppId` - The unique identifier for the resource that the application requires access to. This should be equal to the appId declared on the target resource application.') 63 # https://github.com/Azure/azure-rest-api-specs/blob/32e56f061668a1bf1eeca6209000fad4c09afca8/specification/graphrbac/data-plane/Microsoft.GraphRbac/stable/1.6/graphrbac.json#L2833 64 c.argument('api_permissions', nargs='+', help='Specify `ResourceAccess.id` - The unique identifier for one of the OAuth2Permission or AppRole instances that the resource application exposes. Space-separated list of `<resource-access-id>=<type>`.') 65 c.argument('expires', help='Expiry date for the permissions in years. e.g. 1, 2 or "never"') 66 c.argument('scope', help='Specifies the value of the scope claim that the resource application should expect in the OAuth 2.0 access token, e.g. User.Read') 67 c.argument('consent_type', arg_type=get_enum_type(ConsentType), default=ConsentType.all_principals.value, 68 help="Indicates if consent was provided by the administrator (on behalf of the organization) or by an individual.") 69 c.argument('principal_id', help='If --consent-type is "Principal", this argument specifies the object of the user that granted consent and applies only for that user.') 70 c.argument('show_resource_name', options_list=['--show-resource-name', '-r'], 71 arg_type=get_three_state_flag(), help="show resource's display name") 72 73 with self.argument_context('ad app permission delete') as c: 74 # `=<type>` is not needed. 75 c.argument('api_permissions', nargs='+', help='Specify `ResourceAccess.id` - The unique identifier for one of the OAuth2Permission or AppRole instances that the resource application exposes. Space-separated list of `<resource-access-id>`.') 76 77 with self.argument_context('ad app permission list') as c: 78 c.argument('identifier', options_list=['--id'], help='identifier uri, application id, or object id of the associated application') 79 80 with self.argument_context('ad sp') as c: 81 c.argument('identifier', options_list=['--id'], help='service principal name, or object id') 82 83 with self.argument_context('ad sp create') as c: 84 c.argument('identifier', options_list=['--id'], help='identifier uri, application id, or object id of the associated application') 85 86 with self.argument_context('ad sp create-for-rbac') as c: 87 c.argument('scopes', nargs='+') 88 c.argument('role', completer=get_role_definition_name_completion_list) 89 c.argument('skip_assignment', arg_type=get_three_state_flag(), 90 help='Skip creating the default assignment, which allows the service principal to access resources under the current subscription. ' 91 'When specified, --scopes will be ignored. You may use `az role assignment create` to create ' 92 'role assignments for this service principal later.') 93 c.argument('show_auth_for_sdk', options_list='--sdk-auth', 94 deprecate_info=c.deprecate(target='--sdk-auth', expiration='3.0.0'), 95 help='output result in compatible with Azure SDK auth file', arg_type=get_three_state_flag()) 96 97 with self.argument_context('ad sp owner list') as c: 98 c.argument('identifier', options_list=['--id'], help='service principal name, or object id or the service principal') 99 100 for item in ['create-for-rbac', 'credential reset']: 101 with self.argument_context('ad sp {}'.format(item)) as c: 102 c.argument('name', name_arg_type) 103 c.argument('cert', arg_group='Credential', validator=validate_cert) 104 c.argument('years', type=int, default=None, arg_group='Credential') 105 c.argument('end_date', default=None, arg_group='Credential', 106 help="Finer grain of expiry time if '--years' is insufficient, e.g. '2020-12-31T11:59:59+00:00' or '2299-12-31'") 107 c.argument('create_cert', action='store_true', arg_group='Credential') 108 c.argument('keyvault', arg_group='Credential') 109 c.argument('append', action='store_true', help='Append the new credential instead of overwriting.') 110 c.argument('credential_description', help="the description of the password", arg_group='Credential') 111 112 with self.argument_context('ad sp credential reset') as c: 113 c.argument('password', options_list=['--password', '-p'], arg_group='Credential', 114 help="If missing, CLI will generate a strong password") 115 116 with self.argument_context('ad app credential reset') as c: 117 c.argument('name', options_list=['--id'], help='identifier uri, application id, or object id') 118 c.argument('cert', arg_group='Credential', validator=validate_cert, help='Certificate to use for credentials') 119 c.argument('password', options_list=['--password', '-p'], arg_group='Credential') 120 c.argument('years', type=int, default=None, arg_group='Credential', help='Number of years for which the credentials will be valid') 121 c.argument('create_cert', action='store_true', arg_group='Credential', help='Create a self-signed certificate to use for the credential') 122 c.argument('keyvault', arg_group='Credential', help='Name or ID of a KeyVault to use for creating or retrieving certificates.') 123 c.argument('append', action='store_true', help='Append the new credential instead of overwriting.') 124 125 for item in ['ad sp credential delete', 'ad sp credential list', 'ad app credential delete', 'ad app credential list']: 126 with self.argument_context(item) as c: 127 c.argument('key_id', help='credential key id') 128 c.argument('cert', action='store_true', help='a certificate based credential') 129 130 with self.argument_context('ad') as c: 131 c.argument('display_name', help='object\'s display name or its prefix') 132 c.argument('identifier_uri', help='graph application identifier, must be in uri format') 133 c.argument('spn', help='service principal name') 134 c.argument('upn', help='user principal name, e.g. john.doe@contoso.com') 135 c.argument('query_filter', options_list=['--filter'], help='OData filter, e.g. --filter "displayname eq \'test\' and servicePrincipalType eq \'Application\'"') 136 137 with self.argument_context('ad user') as c: 138 c.argument('mail_nickname', help='mail alias. Defaults to user principal name') 139 c.argument('force_change_password_next_login', arg_type=get_three_state_flag(), help='Require the user to change their password the next time they log in. Only valid when --password is specified') 140 c.argument('account_enabled', arg_type=get_three_state_flag(), help='enable the user account') 141 c.argument('password', help='user password') 142 c.argument('upn_or_object_id', options_list=['--id', c.deprecate(target='--upn-or-object-id', redirect='--id', hide=True)], help='The object ID or principal name of the user for which to get information') 143 144 with self.argument_context('ad user get-member-groups') as c: 145 c.argument('security_enabled_only', action='store_true', 146 help='If true, only membership in security-enabled groups should be checked. Otherwise, membership in all groups should be checked.') 147 148 group_help_msg = "group's object id or display name(prefix also works if there is a unique match)" 149 with self.argument_context('ad group') as c: 150 for arg in VARIANT_GROUP_ID_ARGS: 151 c.argument(arg, options_list=['--group', '-g'], validator=validate_group, help=group_help_msg) 152 153 with self.argument_context('ad group create') as c: 154 c.argument('mail_nickname', help='Mail nickname') 155 c.argument('force', arg_type=get_three_state_flag(), 156 help='always create a new group instead of updating the one with same display and mail nickname') 157 c.argument('description', help='Group description') 158 159 with self.argument_context('ad group show') as c: 160 c.extra('cmd') 161 162 member_id_help_msg = 'The object ID of the contact, group, user, or service principal' 163 with self.argument_context('ad group get-member-groups') as c: 164 c.argument('security_enabled_only', arg_type=get_three_state_flag(), default=False, required=False) 165 c.extra('cmd') 166 167 with self.argument_context('ad group member add') as c: 168 c.argument('url', options_list='--member-id', validator=validate_member_id, help=member_id_help_msg) 169 170 for item in ['member add', 'member check', 'member list', 'member remove', 'delete']: 171 with self.argument_context('ad group {}'.format(item)) as c: 172 c.extra('cmd') 173 174 with self.argument_context('ad group member') as c: 175 c.argument('member_object_id', options_list='--member-id', help=member_id_help_msg) 176 177 with self.argument_context('ad signed-in-user') as c: 178 c.argument('object_type', options_list=['--type', '-t'], help='object type filter, e.g. "application", "servicePrincipal" "group", etc') 179 180 with self.argument_context('role') as c: 181 c.argument('scope', help='scope at which the role assignment or definition applies to, e.g., /subscriptions/0b1f6471-1bf0-4dda-aec3-111122223333, /subscriptions/0b1f6471-1bf0-4dda-aec3-111122223333/resourceGroups/myGroup, or /subscriptions/0b1f6471-1bf0-4dda-aec3-111122223333/resourceGroups/myGroup/providers/Microsoft.Compute/virtualMachines/myVM') 182 c.argument('resource_group_name', options_list=['--resource-group', '-g'], help='use it only if the role or assignment was added at the level of a resource group') 183 184 with self.argument_context('role assignment') as c: 185 c.argument('role_assignment_name', options_list=['--name', '-n']) 186 c.argument('role', help='role name or id', completer=get_role_definition_name_completion_list) 187 c.argument('show_all', options_list=['--all'], action='store_true', help='show all assignments under the current subscription') 188 c.argument('include_inherited', action='store_true', help='include assignments applied on parent scopes') 189 c.argument('can_delegate', action='store_true', help='when set, the assignee will be able to create further role assignments to the same role') 190 c.argument('assignee', help='represent a user, group, or service principal. supported format: object id, user sign-in name, or service principal name') 191 c.argument('assignee_object_id', help="Use this parameter instead of '--assignee' to bypass Graph API invocation in case of insufficient privileges. " 192 "This parameter only works with object ids for users, groups, service principals, and " 193 "managed identities. For managed identities use the principal id. For service principals, " 194 "use the object id and not the app id.") 195 c.argument('ids', nargs='+', help='space-separated role assignment ids') 196 c.argument('include_classic_administrators', arg_type=get_three_state_flag(), help='list default role assignments for subscription classic administrators, aka co-admins') 197 c.argument('description', is_preview=True, min_api='2020-04-01-preview', help='Description of role assignment.') 198 c.argument('condition', is_preview=True, min_api='2020-04-01-preview', help='Condition under which the user can be granted permission.') 199 c.argument('condition_version', is_preview=True, min_api='2020-04-01-preview', help='Version of the condition syntax. If --condition is specified without --condition-version, default to 2.0.') 200 201 time_help = ('The {} of the query in the format of %Y-%m-%dT%H:%M:%SZ, e.g. 2000-12-31T12:59:59Z. Defaults to {}') 202 with self.argument_context('role assignment list-changelogs') as c: 203 c.argument('start_time', help=time_help.format('start time', '1 Hour prior to the current time')) 204 c.argument('end_time', help=time_help.format('end time', 'the current time')) 205 206 with self.argument_context('role assignment create') as c: 207 # PrincipalType = self.get_models('PrincipalType', resource_type=ResourceType.MGMT_AUTHORIZATION) 208 209 # A temporary fix for https://github.com/Azure/azure-cli/issues/11594 210 # As only 'User', 'Group' or 'ServicePrincipal' are allowed values, the REST spec contains invalid values 211 # (like MSI) which are used only internally by the service. So hide them. 212 # https://github.com/Azure/azure-rest-api-specs/blob/962013a1cf9bf5b87e3aad75a14c7dd620acda62/specification/authorization/resource-manager/Microsoft.Authorization/preview/2020-04-01-preview/authorization-RoleAssignmentsCalls.json#L508-L522 213 from enum import Enum 214 215 class PrincipalType(str, Enum): 216 user = "User" 217 group = "Group" 218 service_principal = "ServicePrincipal" 219 foreign_group = "ForeignGroup" 220 221 c.argument('assignee_principal_type', min_api='2018-09-01-preview', arg_type=get_enum_type(PrincipalType), 222 help='use with --assignee-object-id to avoid errors caused by propagation latency in AAD Graph') 223 224 with self.argument_context('role assignment update') as c: 225 c.argument('role_assignment', 226 help='Description of an existing role assignment as JSON, or a path to a file containing a ' 227 'JSON description.') 228 229 with self.argument_context('role assignment delete') as c: 230 c.argument('yes', options_list=['--yes', '-y'], action='store_true', help='Continue to delete all assignments under the subscription') 231 232 with self.argument_context('role definition') as c: 233 c.argument('role_definition_id', options_list=['--name', '-n'], help='the role definition name') 234 c.argument('custom_role_only', arg_type=get_three_state_flag(), help='custom roles only(vs. build-in ones)') 235 c.argument('role_definition', help="json formatted content which defines the new role.") 236 c.argument('name', arg_type=name_arg_type, completer=get_role_definition_name_completion_list, help="the role's name") 237 238 with self.argument_context('identity') as c: 239 c.argument('resource_name', arg_type=name_arg_type, id_part='name') 240 241 with self.argument_context('identity create') as c: 242 c.argument('location', get_location_type(self.cli_ctx)) 243 c.argument('tags', tags_type) 244