diff --git a/plugins/modules/azure_rm_roleassignment.py b/plugins/modules/azure_rm_roleassignment.py index 8af92b444..6c2373e74 100644 --- a/plugins/modules/azure_rm_roleassignment.py +++ b/plugins/modules/azure_rm_roleassignment.py @@ -23,6 +23,8 @@ - The object id of assignee. This maps to the ID inside the Active Directory. - It can point to a user, service principal or security group. - Required when creating role assignment. + aliases: + - assignee id: description: - Fully qualified id of assignment to delete or create. @@ -157,7 +159,7 @@ class AzureRMRoleAssignment(AzureRMModuleBase): def __init__(self): self.module_arg_spec = dict( - assignee_object_id=dict(type='str'), + assignee_object_id=dict(type='str', aliases=['assignee']), id=dict(type='str'), name=dict(type='str'), role_definition_id=dict(type='str'), @@ -301,7 +303,8 @@ def get_roleassignment(self): if role_assignment and self.assignee_object_id and role_assignment.get('assignee_object_id') != self.assignee_object_id: self.fail('State Mismatch Error: The assignment ID exists, but does not match the provided assignee.') - if role_assignment and self.role_definition_id and role_assignment.get('role_definition_id') != self.role_definition_id: + if role_assignment and self.role_definition_id and (role_assignment.get('role_definition_id').split('/')[-1].lower() + != self.role_definition_id[-1].lower()): self.fail('State Mismatch Error: The assignment ID exists, but does not match the provided role.') except CloudError as ex: @@ -314,7 +317,8 @@ def get_roleassignment(self): if role_assignment and self.assignee_object_id and role_assignment.get('assignee_object_id') != self.assignee_object_id: self.fail('State Mismatch Error: The assignment name exists, but does not match the provided assignee.') - if role_assignment and self.role_definition_id and role_assignment.get('role_definition_id') != self.role_definition_id: + if role_assignment and self.role_definition_id and (role_assignment.get('role_definition_id').split('/')[-1].lower() + != self.role_definition_id[-1].lower()): self.fail('State Mismatch Error: The assignment name exists, but does not match the provided role.') except CloudError as ex: @@ -327,7 +331,8 @@ def get_roleassignment(self): response = [self.roleassignment_to_dict(role_assignment) for role_assignment in response] response = [role_assignment for role_assignment in response if role_assignment.get('scope') == self.scope] response = [role_assignment for role_assignment in response if role_assignment.get('assignee_object_id') == self.assignee_object_id] - response = [role_assignment for role_assignment in response if role_assignment.get('role_definition_id') == self.role_definition_id] + response = [role_assignment for role_assignment in response if (role_assignment.get('role_definition_id').split('/')[-1].lower() + == self.role_definition_id.split('/')[-1].lower())] else: self.fail('If id or name are not supplied, then assignee_object_id and role_definition_id are required.') if response: @@ -351,6 +356,7 @@ def roleassignment_to_dict(self, assignment): assignee_object_id=assignment.principal_id, id=assignment.id, name=assignment.name, + principal_id=assignment.principal_id, principal_type=assignment.principal_type, role_definition_id=assignment.role_definition_id, scope=assignment.scope, diff --git a/plugins/modules/azure_rm_roleassignment_info.py b/plugins/modules/azure_rm_roleassignment_info.py index 2e00985ed..94d994e4a 100644 --- a/plugins/modules/azure_rm_roleassignment_info.py +++ b/plugins/modules/azure_rm_roleassignment_info.py @@ -22,6 +22,8 @@ description: - Object id of a user, group or service principal. - Mutually exclusive with I(name) and I(id). + aliases: + - assignee_object_id id: description: - Fqid of role assignment to look up. @@ -148,7 +150,7 @@ class AzureRMRoleAssignmentInfo(AzureRMModuleBase): def __init__(self): self.module_arg_spec = dict( - assignee=dict(type='str'), + assignee=dict(type='str', aliases=['assignee_object_id']), id=dict(type='str'), name=dict(type='str'), role_definition_id=dict(type='str'), @@ -184,9 +186,7 @@ def exec_module(self, **kwargs): for key in self.module_arg_spec: setattr(self, key, kwargs[key]) - if self.assignee: - self.results['roleassignments'] = self.list_by_assignee() - elif self.id: + if self.id: self.results['roleassignments'] = self.get_by_id() elif self.name and self.scope: self.results['roleassignments'] = self.get_by_name() @@ -194,6 +194,8 @@ def exec_module(self, **kwargs): self.fail("Parameter Error: Name requires a scope to also be set.") elif self.scope: self.results['roleassignments'] = self.list_by_scope() + elif self.assignee: + self.results['roleassignments'] = self.list_by_assignee() else: self.results['roleassignments'] = self.list_assignments() @@ -234,7 +236,8 @@ def get_by_name(self): # If role_definition_id is set, we only want results matching that id. if self.role_definition_id: - response = [role_assignment for role_assignment in response if role_assignment.get('role_definition_id') == self.role_definition_id] + response = [role_assignment for role_assignment in response if (role_assignment.get('role_definition_id').split('/')[-1].lower() + == self.role_definition_id.split('/')[-1].lower())] results = response @@ -261,15 +264,16 @@ def list_assignments(self, filter=None): results = [] try: - response = self.authorization_client.role_assignments.list(filter=filter) + response = list(self.authorization_client.role_assignments.list(filter=filter)) response = [self.roleassignment_to_dict(a) for a in response] # If role_definition_id is set, we only want results matching that id. if self.role_definition_id: - response = [role_assignment for role_assignment in response if role_assignment.get('role_definition_id') == self.role_definition_id] + response = [role_assignment for role_assignment in response if (role_assignment.get('role_definition_id').split('/')[-1].lower() + == self.role_definition_id.split('/')[-1].lower())] + + results = response - else: - results = response except CloudError as ex: self.log("Didn't find role assignments in subscription {0}.".format(self.subscription_id)) @@ -290,13 +294,18 @@ def list_by_scope(self): response = [self.roleassignment_to_dict(role_assignment) for role_assignment in response] + # If assignee is set we only want results matching that assignee. + if self.assignee: + response = [role_assignment for role_assignment in response if role_assignment.get('principal_id').lower() == self.assignee.lower()] + # If strict_scope_match is true we only want results matching exact scope. if self.strict_scope_match: - response = [role_assignment for role_assignment in response if role_assignment.get('scope') == self.scope] + response = [role_assignment for role_assignment in response if role_assignment.get('scope').lower() == self.scope.lower()] # If role_definition_id is set, we only want results matching that id. if self.role_definition_id: - response = [role_assignment for role_assignment in response if role_assignment.get('role_definition_id') == self.role_definition_id] + response = [role_assignment for role_assignment in response if (role_assignment.get('role_definition_id').split('/')[-1].lower() + == self.role_definition_id.split('/')[-1].lower())] results = response @@ -307,6 +316,7 @@ def list_by_scope(self): def roleassignment_to_dict(self, assignment): return dict( + assignee_object_id=assignment.principal_id, id=assignment.id, name=assignment.name, principal_id=assignment.principal_id, diff --git a/tests/integration/targets/azure_rm_roleassignment/aliases b/tests/integration/targets/azure_rm_roleassignment/aliases index 70048be66..8767e0189 100644 --- a/tests/integration/targets/azure_rm_roleassignment/aliases +++ b/tests/integration/targets/azure_rm_roleassignment/aliases @@ -1,3 +1,3 @@ cloud/azure destructive -unsupported +shippable/azure/group10 diff --git a/tests/integration/targets/azure_rm_roleassignment/tasks/main.yml b/tests/integration/targets/azure_rm_roleassignment/tasks/main.yml index 8f0ec3eb4..c4e4d15d6 100644 --- a/tests/integration/targets/azure_rm_roleassignment/tasks/main.yml +++ b/tests/integration/targets/azure_rm_roleassignment/tasks/main.yml @@ -1,11 +1,36 @@ - name: setup basic facts - set_facts: + set_fact: uuid: bb21a88b-30e1-42b5-84e8-1d3f322de033 + # Disk Backup Reader, unlikely to be already assigned in ansible-test resource groups. + az_role_definition_guid: '3e5e47e6-65f7-47ef-90b5-e5dd4d455f24' - name: List All azure_rm_roleassignment_info: register: az_role_assignments +- name: Fetch specific assignments + azure_rm_roleassignment_info: + name: "{{ item.name | default(omit) }}" + assignee: "{{ item.assignee | default(omit) }}" + id: "{{ item.id | default(omit) }}" + role_definition_id: "{{ item.role_definition_id | default(omit) }}" + scope: "{{ item.scope | default(omit) }}" + strict_scope_match: True + register: az_role_assignment_specific + loop: + - name: "{{ az_role_assignments.roleassignments[0].name }}" + scope: "{{ az_role_assignments.roleassignments[0].scope }}" + - assignee: "{{ az_role_assignments.roleassignments[0].principal_id }}" + scope: "{{ az_role_assignments.roleassignments[0].scope }}" + role_definition_id: "{{ az_role_assignments.roleassignments[0].role_definition_id }}" + - id: "{{ az_role_assignments.roleassignments[0].id }}" + +- name: check specific fetch for single return + assert: + that: + - "{{ ( item.roleassignments | length) == 1 }}" + loop: "{{ az_role_assignment_specific.results }}" + - name: Intentional mutual exclusion info azure_rm_roleassignment_info: name: "{{ item.name | default(omit) }}" @@ -22,6 +47,12 @@ - name: "{{ az_role_assignments.roleassignments[0].name }}" id: "{{ az_role_assignments.roleassignments[0].id }}" +- name: check intended failures + assert: + that: + - item.failed + loop: "{{ failures_info.results }}" + - name: Intentional failures mutable azure_rm_roleassignment: name: "{{ item.name | default(omit) }}" @@ -60,7 +91,7 @@ assert: that: - item.failed - loop: "{{ failures_info.results | union(failures_mutable.results) }}" + loop: "{{ failures_mutable.results }} " - name: get resource group info azure_rm_resourcegroup_info: @@ -70,15 +101,15 @@ - name: create role assignment by id azure_rm_roleassignment: id: "{{ az_resource_group.resourcegroups[0].id }}/providers/Microsoft.Authorization/roleAssignments/{{ uuid }}" - assignee_object_id: "{{ az_assignee_object_id }}" - role_definition_id: "/subscriptions/{{ az_resource_group.resourcegroups[0].id.split('/')[2] }}/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c" + assignee_object_id: "{{ az_role_assignments.roleassignments[0].principal_id }}" + role_definition_id: "/subscriptions/{{ az_resource_group.resourcegroups[0].id.split('/')[2] }}/providers/Microsoft.Authorization/roleDefinitions/{{ az_role_definition_guid }}" register: az_role_assignment_create - name: create role assignment by scope azure_rm_roleassignment: scope: "{{ az_resource_group.resourcegroups[0].id }}" - assignee_object_id: "{{ az_assignee_object_id }}" - role_definition_id: "/subscriptions/{{ az_resource_group.resourcegroups[0].id.split('/')[2] }}/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c" + assignee_object_id: "{{ az_role_assignments.roleassignments[0].principal_id }}" + role_definition_id: "/subscriptions/{{ az_resource_group.resourcegroups[0].id.split('/')[2] }}/providers/Microsoft.Authorization/roleDefinitions/{{ az_role_definition_guid }}" register: az_role_assignment_idempotent - name: check idempotence @@ -124,12 +155,13 @@ id: "{{ az_role_assignment_create.id }}" state: absent register: az_role_assignment_delete + when: az_role_assignment_create.changed - name: create role assignment with name azure_rm_roleassignment: scope: "{{ az_resource_group.resourcegroups[0].id }}" - assignee_object_id: "{{ az_assignee_object_id }}" - role_definition_id: "/subscriptions/{{ az_resource_group.resourcegroups[0].id.split('/')[2] }}/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c" + assignee_object_id: "{{ az_role_assignments.roleassignments[0].principal_id }}" + role_definition_id: "/subscriptions/{{ az_resource_group.resourcegroups[0].id.split('/')[2] }}/providers/Microsoft.Authorization/roleDefinitions/{{ az_role_definition_guid }}" name: "{{ uuid }}" register: az_role_assignment_create @@ -139,21 +171,23 @@ name: "{{ uuid }}" state: absent register: az_role_assignment_delete + when: az_role_assignment_create.changed - name: create role assignment by scope azure_rm_roleassignment: scope: "{{ az_resource_group.resourcegroups[0].id }}" - assignee_object_id: "{{ az_assignee_object_id }}" - role_definition_id: "/subscriptions/{{ az_resource_group.resourcegroups[0].id.split('/')[2] }}/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c" + assignee_object_id: "{{ az_role_assignments.roleassignments[0].principal_id }}" + role_definition_id: "/subscriptions/{{ az_resource_group.resourcegroups[0].id.split('/')[2] }}/providers/Microsoft.Authorization/roleDefinitions/{{ az_role_definition_guid }}" register: az_role_assignment_create_by_scope - name: delete by scope, assignee_object_id and role_definition_id azure_rm_roleassignment: scope: "{{ az_resource_group.resourcegroups[0].id }}" - assignee_object_id: "{{ az_assignee_object_id }}" - role_definition_id: "/subscriptions/{{ az_resource_group.resourcegroups[0].id.split('/')[2] }}/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c" + assignee_object_id: "{{ az_role_assignments.roleassignments[0].principal_id }}" + role_definition_id: "/subscriptions/{{ az_resource_group.resourcegroups[0].id.split('/')[2] }}/providers/Microsoft.Authorization/roleDefinitions/{{ az_role_definition_guid }}" state: absent register: az_role_assignment_delete + when: az_role_assignment_create.changed - name: absent assignment that doesn't exist - id azure.azcollection.azure_rm_roleassignment: