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 6from azure.cli.core.profiles import ResourceType, get_sdk, supported_api_version 7 8 9class MultiAPIAdaptor: 10 # We will bridge all the code difference here caused by SDK breaking changes 11 def __init__(self, cli_ctx): 12 self.old_api = supported_api_version(cli_ctx, resource_type=ResourceType.MGMT_AUTHORIZATION, 13 max_api='2015-07-01') 14 self.cli_ctx = cli_ctx 15 16 def _init_individual_permission(self, cfg): 17 Permission = get_sdk(self.cli_ctx, ResourceType.MGMT_AUTHORIZATION, 'Permission', mod='models', 18 operation_group='role_definitions') 19 permission = Permission(actions=cfg.get('actions', None), 20 not_actions=cfg.get('notActions', None)) 21 if not self.old_api: 22 permission.data_actions = cfg.get('dataActions', None) 23 permission.not_data_actions = cfg.get('notDataActions', None) 24 return permission 25 26 def _init_permissions(self, role_definition_input): 27 # we will handle with or w/o 'permissions' 28 if 'permissions' in role_definition_input: 29 return [self._init_individual_permission(p) for p in role_definition_input['permissions']] 30 return [self._init_individual_permission(role_definition_input)] 31 32 def create_role_definition(self, client, role_name, role_id, role_definition_input): 33 RoleDefinitionBase = get_sdk(self.cli_ctx, ResourceType.MGMT_AUTHORIZATION, 'RoleDefinition', 34 mod='models', operation_group='role_definitions') 35 role_configuration = RoleDefinitionBase(role_name=role_name, 36 description=role_definition_input.get('description', None), 37 type='CustomRole', 38 assignable_scopes=role_definition_input['assignableScopes'], 39 permissions=self._init_permissions(role_definition_input)) 40 scope = role_definition_input['assignableScopes'][0] 41 return client.create_or_update(role_definition_id=role_id, scope=scope, role_definition=role_configuration) 42 43 def create_role_assignment(self, client, assignment_name, role_id, object_id, scope, assignee_principal_type=None, 44 description=None, condition=None, condition_version=None): 45 RoleAssignmentCreateParameters = get_sdk( 46 self.cli_ctx, ResourceType.MGMT_AUTHORIZATION, 47 'RoleAssignmentProperties' if self.old_api else 'RoleAssignmentCreateParameters', 48 mod='models', operation_group='role_assignments') 49 parameters = RoleAssignmentCreateParameters(role_definition_id=role_id, principal_id=object_id) 50 if assignee_principal_type: 51 parameters.principal_type = assignee_principal_type 52 if description: 53 parameters.description = description 54 if condition: 55 parameters.condition = condition 56 if condition_version: 57 parameters.condition_version = condition_version 58 return client.create(scope, assignment_name, parameters) 59 60 def get_role_property(self, obj, property_name): # pylint: disable=no-self-use 61 """Get property for RoleDefinition and RoleAssignment object.""" 62 # 2015-07-01 RoleDefinition: flattened, RoleAssignment: unflattened 63 # 2018-01-01-preview RoleDefinition: flattened 64 # 2020-04-01-preview RoleAssignment: flattened 65 # Get property_name from properties if the model is unflattened. 66 if isinstance(obj, dict): 67 if 'properties' in obj: 68 obj = obj['properties'] 69 return obj[property_name] 70 71 if hasattr(obj, 'properties'): 72 obj = obj.properties 73 return getattr(obj, property_name) 74 75 def set_role_property(self, obj, property_name, property_value): # pylint: disable=no-self-use 76 """Set property for RoleDefinition and RoleAssignment object. 77 Luckily this function is only called for an RoleAssignment `obj` returned by the service, and `properties` 78 has been processed, either by being flattened or set. We can definitively know whether `obj` is flattened 79 or not. 80 There is NO use case where `obj` is provided by the user and `properties` has not been processed. 81 In such case, we won't be able to decide if `obj` is flattened or not.""" 82 if isinstance(obj, dict): 83 if 'properties' in obj: 84 obj = obj['properties'] 85 obj[property_name] = property_value 86 else: 87 if hasattr(obj, 'properties'): 88 obj = obj.properties 89 obj.property_name = property_value 90