Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

azure_rm_roleassignment bugfix #464

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
5a2c0fa
pushing fixes.
paultaiton Mar 22, 2021
e7b4e24
whitespace
paultaiton Mar 22, 2021
e10cf3f
Merge branch 'dev' into paultaiton_20210319-roleassignment
paultaiton Mar 22, 2021
0f4f036
whitespace
paultaiton Mar 22, 2021
162fe00
Merge branch 'dev' into paultaiton_20210319-roleassignment
paultaiton Mar 23, 2021
2bae720
Update aliases
paultaiton Mar 23, 2021
212ede1
Merge branch 'dev' into paultaiton_20210319-roleassignment
Fred-sun Mar 23, 2021
0598d11
Merge branch 'dev' into paultaiton_20210319-roleassignment
paultaiton Mar 30, 2021
c1db494
Merge branch 'dev' into paultaiton_20210319-roleassignment
paultaiton Apr 1, 2021
5c2d5b2
add assignee filter to triplet lookup
paultaiton Apr 6, 2021
b0bd6a4
Merge branch 'dev' into paultaiton_20210319-roleassignment
paultaiton Apr 12, 2021
d3be4e1
Merge branch 'dev' into paultaiton_20210319-roleassignment
paultaiton Apr 21, 2021
2a1d92f
Merge branch 'dev' into paultaiton_20210319-roleassignment
paultaiton Apr 27, 2021
0bb2fdd
Merge branch 'dev' into paultaiton_20210319-roleassignment
paultaiton May 14, 2021
ea9ae83
Merge branch 'dev' into paultaiton_20210319-roleassignment
paultaiton May 18, 2021
0ae92de
Merge branch 'dev' into paultaiton_20210319-roleassignment
Fred-sun May 19, 2021
863b5a2
Merge branch 'dev' into paultaiton_20210319-roleassignment
paultaiton May 23, 2021
87e8836
Merge branch 'dev' into paultaiton_20210319-roleassignment
paultaiton Jun 7, 2021
6c08d5e
Merge branch 'dev' into paultaiton_20210319-roleassignment
paultaiton Jul 15, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions plugins/modules/azure_rm_roleassignment.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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'),
Expand Down Expand Up @@ -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:
Expand All @@ -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:
Expand All @@ -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:
Expand All @@ -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,
Expand Down
32 changes: 21 additions & 11 deletions plugins/modules/azure_rm_roleassignment_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand 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'),
Expand Down Expand Up @@ -184,16 +186,16 @@ 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()
elif self.name and not self.scope:
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()

Expand Down Expand Up @@ -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

Expand All @@ -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))

Expand All @@ -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

Expand All @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/targets/azure_rm_roleassignment/aliases
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
cloud/azure
destructive
unsupported
paultaiton marked this conversation as resolved.
Show resolved Hide resolved
shippable/azure/group10
58 changes: 46 additions & 12 deletions tests/integration/targets/azure_rm_roleassignment/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -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 }}"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@paultaiton If get role assignments info by assignee, scope and role_definition_id, It will return role assignments more than one! It will lead line 31 fail! Thank you very much!

Copy link
Contributor Author

@paultaiton paultaiton Apr 6, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@paultaiton If get role assignments info by assignee, scope and role_definition_id, It will return role assignments more than one! It will lead line 31 fail! Thank you very much!

That was a bug that was legitimately caught by the test. I reordered the main 'module_exec' case in info module, but didn't add the assignee filter to the case that catches the assignment triplet. I just added it in latest commit, so test should pass now.

Thanks @Fred-sun

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) }}"
Expand All @@ -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) }}"
Expand Down Expand Up @@ -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:
Expand All @@ -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
Expand Down Expand Up @@ -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

Expand All @@ -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:
Expand Down