diff --git a/lib/ansible/config/module_defaults.yml b/lib/ansible/config/module_defaults.yml index 9d41783a1b8..6a6978f8726 100644 --- a/lib/ansible/config/module_defaults.yml +++ b/lib/ansible/config/module_defaults.yml @@ -455,6 +455,8 @@ groupings: - aws iam_policy: - aws + iam_policy_info: + - aws iam_role: - aws iam_role_facts: diff --git a/lib/ansible/modules/cloud/amazon/iam_policy_info.py b/lib/ansible/modules/cloud/amazon/iam_policy_info.py new file mode 100644 index 00000000000..30f45e754b1 --- /dev/null +++ b/lib/ansible/modules/cloud/amazon/iam_policy_info.py @@ -0,0 +1,230 @@ +#!/usr/bin/python +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['stableinterface'], + 'supported_by': 'community'} + +DOCUMENTATION = ''' +--- +module: iam_policy_info +short_description: Retrieve inline IAM policies for users, groups, and roles +description: + - Supports fetching of inline IAM policies for IAM users, groups and roles. +version_added: "2.10" +options: + iam_type: + description: + - Type of IAM resource you wish to retrieve inline policies for. + required: yes + choices: [ "user", "group", "role"] + type: str + iam_name: + description: + - Name of IAM resource you wish to retrieve inline policies for. In other words, the user name, group name or role name. + required: yes + type: str + policy_name: + description: + - Name of a specific IAM inline policy you with to retrieve. + required: no + type: str + +author: + - Mark Chappell (@tremble) + +extends_documentation_fragment: + - aws + - ec2 +''' + +EXAMPLES = ''' +# Describe all inline IAM policies on an IAM User +- iam_policy_info: + iam_type: user + iam_name: example_user + +# Describe a specific inline policy on an IAM Role +- iam_policy_info: + iam_type: role + iam_name: example_role + policy_name: example_policy + +''' +RETURN = ''' +policies: + description: A list containing the matching IAM inline policy names and their data + returned: success + type: complex + contains: + policy_name: + description: The Name of the inline policy + returned: success + type: str + policy_document: + description: The JSON document representing the inline IAM policy + returned: success + type: list +policy_names: + description: A list of matching names of the IAM inline policies on the queried object + returned: success + type: list +all_policy_names: + description: A list of names of all of the IAM inline policies on the queried object + returned: success + type: list +''' + +import json + +try: + from botocore.exceptions import BotoCoreError, ClientError +except ImportError: + pass + +from ansible.module_utils.aws.core import AnsibleAWSModule +from ansible.module_utils.six import string_types + + +class PolicyError(Exception): + pass + + +class Policy: + + def __init__(self, client, name, policy_name): + self.client = client + self.name = name + self.policy_name = policy_name + self.changed = False + + @staticmethod + def _iam_type(): + return '' + + def _list(self, name): + return {} + + def list(self): + return self._list(self.name).get('PolicyNames', []) + + def _get(self, name, policy_name): + return '{}' + + def get(self, policy_name): + return self._get(self.name, policy_name)['PolicyDocument'] + + def get_all(self): + policies = list() + for policy in self.list(): + policies.append({"policy_name": policy, "policy_document": self.get(policy)}) + return policies + + def run(self): + policy_list = self.list() + ret_val = { + 'changed': False, + self._iam_type() + '_name': self.name, + 'all_policy_names': policy_list + } + if self.policy_name is None: + ret_val.update(policies=self.get_all()) + ret_val.update(policy_names=policy_list) + elif self.policy_name in policy_list: + ret_val.update(policies=[{ + "policy_name": self.policy_name, + "policy_document": self.get(self.policy_name)}]) + ret_val.update(policy_names=[self.policy_name]) + return ret_val + + +class UserPolicy(Policy): + + @staticmethod + def _iam_type(): + return 'user' + + def _list(self, name): + return self.client.list_user_policies(UserName=name) + + def _get(self, name, policy_name): + return self.client.get_user_policy(UserName=name, PolicyName=policy_name) + + +class RolePolicy(Policy): + + @staticmethod + def _iam_type(): + return 'role' + + def _list(self, name): + return self.client.list_role_policies(RoleName=name) + + def _get(self, name, policy_name): + return self.client.get_role_policy(RoleName=name, PolicyName=policy_name) + + +class GroupPolicy(Policy): + + @staticmethod + def _iam_type(): + return 'group' + + def _list(self, name): + return self.client.list_group_policies(GroupName=name) + + def _get(self, name, policy_name): + return self.client.get_group_policy(GroupName=name, PolicyName=policy_name) + + +def main(): + argument_spec = dict( + iam_type=dict(required=True, choices=['user', 'group', 'role']), + iam_name=dict(required=True), + policy_name=dict(default=None, required=False), + ) + + module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) + + args = dict( + client=module.client('iam'), + name=module.params.get('iam_name'), + policy_name=module.params.get('policy_name'), + ) + iam_type = module.params.get('iam_type') + + try: + if iam_type == 'user': + policy = UserPolicy(**args) + elif iam_type == 'role': + policy = RolePolicy(**args) + elif iam_type == 'group': + policy = GroupPolicy(**args) + + module.exit_json(**(policy.run())) + except (BotoCoreError, ClientError) as e: + if e.response['Error']['Code'] == 'NoSuchEntity': + module.exit_json(changed=False, msg=e.response['Error']['Message']) + module.fail_json_aws(e) + except PolicyError as e: + module.fail_json(msg=str(e)) + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/iam_policy/aliases b/test/integration/targets/iam_policy/aliases index 56927195182..3f812e19142 100644 --- a/test/integration/targets/iam_policy/aliases +++ b/test/integration/targets/iam_policy/aliases @@ -1,2 +1,3 @@ +iam_policy_info cloud/aws unsupported diff --git a/test/integration/targets/iam_policy/defaults/main.yml b/test/integration/targets/iam_policy/defaults/main.yml index 1d65af04d26..93759404df4 100644 --- a/test/integration/targets/iam_policy/defaults/main.yml +++ b/test/integration/targets/iam_policy/defaults/main.yml @@ -1,5 +1,6 @@ --- -iam_user_name: '{{resource_prefix}}' -iam_role_name: '{{resource_prefix}}' -iam_group_name: '{{resource_prefix}}' -iam_policy_name: '{{resource_prefix}}' +iam_name: '{{resource_prefix}}' +iam_policy_name_a: '{{resource_prefix}}-document-a' +iam_policy_name_b: '{{resource_prefix}}-document-b' +iam_policy_name_c: '{{resource_prefix}}-json-a' +iam_policy_name_d: '{{resource_prefix}}-json-b' diff --git a/test/integration/targets/iam_policy/files/no_access_with_second_id.json b/test/integration/targets/iam_policy/files/no_access_with_second_id.json new file mode 100644 index 00000000000..0efbc31d496 --- /dev/null +++ b/test/integration/targets/iam_policy/files/no_access_with_second_id.json @@ -0,0 +1,11 @@ +{ + "Id": "MyOtherId", + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Deny", + "Action": "*", + "Resource": "*" + } + ] +} diff --git a/test/integration/targets/iam_policy/tasks/main.yml b/test/integration/targets/iam_policy/tasks/main.yml index 891d0607aa9..b9f35429150 100644 --- a/test/integration/targets/iam_policy/tasks/main.yml +++ b/test/integration/targets/iam_policy/tasks/main.yml @@ -1,323 +1,95 @@ --- -- block: - # ============================================================ - - name: set up aws connection info - set_fact: - aws_connection_info: &aws_connection_info - aws_access_key: "{{ aws_access_key }}" - aws_secret_key: "{{ aws_secret_key }}" - security_token: "{{ security_token }}" - region: "{{ aws_region }}" - no_log: yes +- name: 'Run integration tests for IAM (inline) Policy management' + module_defaults: + group/aws: + aws_access_key: "{{ aws_access_key }}" + aws_secret_key: "{{ aws_secret_key }}" + security_token: "{{ security_token | default(omit) }}" + region: "{{ aws_region }}" + block: # ============================================================ - name: Create a temporary folder for the policies tempfile: state: directory register: tmpdir - # ============================================================ - name: Copy over policy copy: src: no_access.json dest: "{{ tmpdir.path }}" - # ============================================================ - name: Copy over other policy copy: src: no_access_with_id.json dest: "{{ tmpdir.path }}" + - name: Copy over other policy + copy: + src: no_access_with_second_id.json + dest: "{{ tmpdir.path }}" + # ============================================================ - name: Create user for tests iam_user: - name: "{{ iam_user_name }}" - state: present - <<: *aws_connection_info - # ============================================================ - - name: Create role for tests - iam_role: - name: "{{ iam_role_name }}" - assume_role_policy_document: "{{ lookup('file','no_trust.json') }}" - state: present - <<: *aws_connection_info - # ============================================================ - - name: Create group for tests - iam_group: - name: "{{ iam_group_name }}" - state: present - <<: *aws_connection_info - # ============================================================ - - name: Create policy for user - iam_policy: - iam_type: user - iam_name: "{{ iam_user_name }}" - policy_name: "{{ iam_policy_name }}" - state: present - policy_document: "{{ tmpdir.path }}/no_access.json" - <<: *aws_connection_info - register: result - # ============================================================ - - name: Assert policy was added for user - assert: - that: - - result.changed == True - - result.policies == ["{{ iam_policy_name }}"] - - result.user_name == "{{ iam_user_name }}" - # ============================================================ - - name: Update policy for user - iam_policy: - iam_type: user - iam_name: "{{ iam_user_name }}" - policy_name: "{{ iam_policy_name }}" state: present - policy_document: "{{ tmpdir.path }}/no_access_with_id.json" - <<: *aws_connection_info - register: result - # ============================================================ - - name: Assert policy was updated for user + name: "{{ iam_name }}" + register: result + - name: Ensure user was created assert: that: - - result.changed == True - # ============================================================ - - name: Update policy for user with same policy - iam_policy: - iam_type: user - iam_name: "{{ iam_user_name }}" - policy_name: "{{ iam_policy_name }}" - state: present - policy_document: "{{ tmpdir.path }}/no_access_with_id.json" - <<: *aws_connection_info - register: result - # ============================================================ - - name: Assert policy did not change for user - assert: - that: - - result.changed == False - # ============================================================ - - name: Create policy for user using policy_json - iam_policy: - iam_type: user - iam_name: "{{ iam_user_name }}" - policy_name: "{{ iam_policy_name }}" - state: present - policy_json: "{{ lookup('file', '{{ tmpdir.path }}/no_access.json') }}" - <<: *aws_connection_info - register: result - # ============================================================ - - name: Assert policy was added for user - assert: - that: - - result.changed == True - - result.policies == ["{{ iam_policy_name }}"] - - result.user_name == "{{ iam_user_name }}" - # ============================================================ - - name: Create policy for role - iam_policy: - iam_type: role - iam_name: "{{ iam_role_name }}" - policy_name: "{{ iam_policy_name }}" - state: present - policy_document: "{{ tmpdir.path }}/no_access.json" - <<: *aws_connection_info - register: result - # ============================================================ - - name: Assert policy was added for role - assert: - that: - - result.changed == True - - result.policies == ["{{ iam_policy_name }}"] - - result.role_name == "{{ iam_role_name }}" - # ============================================================ - - name: Update policy for role - iam_policy: - iam_type: role - iam_name: "{{ iam_role_name }}" - policy_name: "{{ iam_policy_name }}" - state: present - policy_document: "{{ tmpdir.path }}/no_access_with_id.json" - <<: *aws_connection_info - register: result - # ============================================================ - - name: Assert policy was updated for role - assert: - that: - - result.changed == True - # ============================================================ - - name: Update policy for role with same policy - iam_policy: - iam_type: role - iam_name: "{{ iam_role_name }}" - policy_name: "{{ iam_policy_name }}" - state: present - policy_document: "{{ tmpdir.path }}/no_access_with_id.json" - <<: *aws_connection_info - register: result - # ============================================================ - - name: Assert policy did not change for role - assert: - that: - - result.changed == False - # ============================================================ - - name: Create policy for role using policy_json - iam_policy: - iam_type: role - iam_name: "{{ iam_role_name }}" - policy_name: "{{ iam_policy_name }}" - state: present - policy_json: "{{ lookup('file', '{{ tmpdir.path }}/no_access.json') }}" - <<: *aws_connection_info - register: result - # ============================================================ - - name: Assert policy was added for role - assert: - that: - - result.changed == True - - result.policies == ["{{ iam_policy_name }}"] - - result.role_name == "{{ iam_role_name }}" - # ============================================================ - - name: Create policy for group - iam_policy: - iam_type: group - iam_name: "{{ iam_group_name }}" - policy_name: "{{ iam_policy_name }}" - state: present - policy_document: "{{ tmpdir.path }}/no_access.json" - <<: *aws_connection_info - register: result - # ============================================================ - - name: Assert policy was added for group - assert: - that: - - result.changed == True - - result.policies == ["{{ iam_policy_name }}"] - - result.group_name == "{{ iam_group_name }}" - # ============================================================ - - name: Update policy for group - iam_policy: - iam_type: group - iam_name: "{{ iam_group_name }}" - policy_name: "{{ iam_policy_name }}" - state: present - policy_document: "{{ tmpdir.path }}/no_access_with_id.json" - <<: *aws_connection_info - register: result - # ============================================================ - - name: Assert policy was updated for group - assert: - that: - - result.changed == True - # ============================================================ - - name: Update policy for group with same policy - iam_policy: - iam_type: group - iam_name: "{{ iam_group_name }}" - policy_name: "{{ iam_policy_name }}" + - result is changed + + - name: Create role for tests + iam_role: state: present - policy_document: "{{ tmpdir.path }}/no_access_with_id.json" - <<: *aws_connection_info - register: result - # ============================================================ - - name: Assert policy did not change for group + name: "{{ iam_name }}" + assume_role_policy_document: "{{ lookup('file','no_trust.json') }}" + register: result + - name: Ensure role was created assert: that: - - result.changed == False - # ============================================================ - - name: Create policy for group using policy_json - iam_policy: - iam_type: group - iam_name: "{{ iam_group_name }}" - policy_name: "{{ iam_policy_name }}" + - result is changed + + - name: Create group for tests + iam_group: state: present - policy_json: "{{ lookup('file', '{{ tmpdir.path }}/no_access.json') }}" - <<: *aws_connection_info - register: result - # ============================================================ - - name: Assert policy was added for group + name: "{{ iam_name }}" + register: result + - name: Ensure group was created assert: that: - - result.changed == True - - result.policies == ["{{ iam_policy_name }}"] - - result.group_name == "{{ iam_group_name }}" - # ============================================================ - - name: Delete policy for user - iam_policy: - iam_type: user - iam_name: "{{ iam_user_name }}" - policy_name: "{{ iam_policy_name }}" - state: absent - <<: *aws_connection_info - - assert: - that: - - result.changed == True - # ============================================================ - - name: Delete policy for role - iam_policy: - iam_type: role - iam_name: "{{ iam_role_name }}" - policy_name: "{{ iam_policy_name }}" - state: absent - <<: *aws_connection_info - - assert: - that: - - result.changed == True - # ============================================================ - - name: Delete policy for group - iam_policy: - iam_type: group - iam_name: "{{ iam_group_name }}" - policy_name: "{{ iam_policy_name }}" - state: absent - <<: *aws_connection_info - - assert: - that: - - result.changed == True - # ============================================================ + - result is changed + + # ============================================================ + + - name: Run tests for each type of object + include_tasks: object.yml + loop_control: + loop_var: iam_type + with_items: + - user + - group + - role + + # ============================================================ + always: # ============================================================ - - name: Delete policy for user - iam_policy: - iam_type: user - iam_name: "{{ iam_user_name }}" - policy_name: "{{ iam_policy_name }}" - state: absent - <<: *aws_connection_info - ignore_errors: yes - # ============================================================ - - name: Delete user for tests + - name: Remove user iam_user: - name: "{{ iam_user_name }}" - state: absent - <<: *aws_connection_info - ignore_errors: yes - # ============================================================ - - name: Delete policy for role - iam_policy: - iam_type: role - iam_name: "{{ iam_role_name }}" - policy_name: "{{ iam_policy_name }}" state: absent - <<: *aws_connection_info + name: "{{ iam_name }}" ignore_errors: yes - # ============================================================ - - name: Delete role for tests + + - name: Remove role iam_role: - name: "{{ iam_role_name }}" state: absent - <<: *aws_connection_info + name: "{{ iam_name }}" ignore_errors: yes - # ============================================================ - - name: Delete policy for group - iam_policy: - iam_type: group - iam_name: "{{ iam_group_name }}" - policy_name: "{{ iam_policy_name }}" - state: absent - <<: *aws_connection_info - ignore_errors: yes - # ============================================================ - - name: Delete group for tests + + - name: Remove group iam_group: - name: "{{ iam_group_name }}" state: absent - <<: *aws_connection_info + name: "{{ iam_name }}" ignore_errors: yes + # ============================================================ - name: Delete temporary folder containing the policies file: diff --git a/test/integration/targets/iam_policy/tasks/object.yml b/test/integration/targets/iam_policy/tasks/object.yml new file mode 100644 index 00000000000..f0d0190ddc6 --- /dev/null +++ b/test/integration/targets/iam_policy/tasks/object.yml @@ -0,0 +1,1044 @@ +--- +- name: 'Run integration tests for IAM (inline) Policy management on {{ iam_type }}s' + vars: + iam_object_key: '{{ iam_type }}_name' + block: + # ============================================================ + - name: 'Fetch policies from {{ iam_type }} before making changes' + iam_policy_info: + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + register: iam_policy_info + + - name: 'Assert empty policy list' + assert: + that: + - iam_policy_info is succeeded + - iam_policy_info.policies | length == 0 + - iam_policy_info.all_policy_names | length == 0 + - iam_policy_info.policy_names | length == 0 + + - name: 'Fetch policies from non-existent {{ iam_type }}' + iam_policy_info: + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}-junk' + register: iam_policy_info + + - name: 'Assert not failed' + assert: + that: + - iam_policy_info is succeeded + + # ============================================================ + #- name: 'Create policy using document for {{ iam_type }} (check mode)' + # check_mode: yes + # iam_policy: + # state: present + # iam_type: '{{ iam_type }}' + # iam_name: '{{ iam_name }}' + # policy_name: '{{ iam_policy_name_a }}' + # policy_document: '{{ tmpdir.path }}/no_access.json' + # skip_duplicates: yes + # register: result + + #- name: 'Assert policy would be added for {{ iam_type }}' + # assert: + # that: + # - result is changed + + - name: 'Create policy using document for {{ iam_type }}' + iam_policy: + state: present + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_a }}' + policy_document: '{{ tmpdir.path }}/no_access.json' + skip_duplicates: yes + register: result + - iam_policy_info: + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + register: iam_policy_info + + - name: 'Assert policy was added for {{ iam_type }}' + assert: + that: + - result is changed + - result.policies | length == 1 + - iam_policy_name_a in result.policies + - result[iam_object_key] == iam_name + - iam_policy_name_a in iam_policy_info.policy_names + - iam_policy_info.policy_names | length == 1 + - iam_policy_info.policies | length == 1 + - iam_policy_name_a in iam_policy_info.all_policy_names + - iam_policy_info.all_policy_names | length == 1 + - iam_policy_info.policies[0].policy_name == iam_policy_name_a + - '"Id" not in iam_policy_info.policies[0].policy_document' + + - name: 'Create policy using document for {{ iam_type }} (idempotency)' + iam_policy: + state: present + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_a }}' + policy_document: '{{ tmpdir.path }}/no_access.json' + skip_duplicates: yes + register: result + - iam_policy_info: + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + register: iam_policy_info + + - name: 'Assert no change' + assert: + that: + - result is not changed + - result.policies | length == 1 + - iam_policy_name_a in result.policies + - result[iam_object_key] == iam_name + - iam_policy_info.policies | length == 1 + - iam_policy_info.all_policy_names | length == 1 + - iam_policy_name_a in iam_policy_info.all_policy_names + - iam_policy_info.policies[0].policy_name == iam_policy_name_a + - '"Id" not in iam_policy_info.policies[0].policy_document' + + # ============================================================ + #- name: 'Create policy using document for {{ iam_type }} (check mode) (skip_duplicates)' + # check_mode: yes + # iam_policy: + # state: present + # iam_type: '{{ iam_type }}' + # iam_name: '{{ iam_name }}' + # policy_name: '{{ iam_policy_name_b }}' + # policy_document: '{{ tmpdir.path }}/no_access.json' + # skip_duplicates: yes + # register: result + #- iam_policy_info: + # iam_type: '{{ iam_type }}' + # iam_name: '{{ iam_name }}' + # policy_name: '{{ iam_policy_name_b }}' + # register: iam_policy_info + + #- name: 'Assert policy would be added for {{ iam_type }}' + # assert: + # that: + # - result is not changed + # - iam_policy_info.all_policy_names | length == 1 + # - '"policies" not in iam_policy_info' + # - iam_policy_name_b not in iam_policy_info.all_policy_names + + - name: 'Create policy using document for {{ iam_type }} (skip_duplicates)' + iam_policy: + state: present + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_b }}' + policy_document: '{{ tmpdir.path }}/no_access.json' + skip_duplicates: yes + register: result + - iam_policy_info: + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_b }}' + register: iam_policy_info + + - name: 'Assert policy was not added for {{ iam_type }} (skip_duplicates)' + assert: + that: + - result is not changed + - result.policies | length == 1 + - iam_policy_name_b not in result.policies + - result[iam_object_key] == iam_name + - '"policies" not in iam_policy_info' + - '"policy_names" not in iam_policy_info' + - iam_policy_info.all_policy_names | length == 1 + - iam_policy_name_b not in iam_policy_info.all_policy_names + + #- name: 'Create policy using document for {{ iam_type }} (check mode) (skip_duplicates = no)' + # check_mode: yes + # iam_policy: + # state: present + # iam_type: '{{ iam_type }}' + # iam_name: '{{ iam_name }}' + # policy_name: '{{ iam_policy_name_b }}' + # policy_document: '{{ tmpdir.path }}/no_access.json' + # skip_duplicates: no + # register: result + #- iam_policy_info: + # iam_type: '{{ iam_type }}' + # iam_name: '{{ iam_name }}' + # policy_name: '{{ iam_policy_name_b }}' + # register: iam_policy_info + + #- name: 'Assert policy would be added for {{ iam_type }}' + # assert: + # that: + # - result.changed == True + # - '"policies" not in iam_policy_info' + # - iam_policy_info.all_policy_names | length == 1 + # - iam_policy_name_a in iam_policy_info.all_policy_names + # - iam_policy_name_b not in iam_policy_info.all_policy_names + + - name: 'Create policy using document for {{ iam_type }} (skip_duplicates = no)' + iam_policy: + state: present + skip_duplicates: no + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_b }}' + policy_document: '{{ tmpdir.path }}/no_access.json' + register: result + - iam_policy_info: + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_b }}' + register: iam_policy_info + + - name: 'Assert policy was added for {{ iam_type }}' + assert: + that: + - result is changed + - result.policies | length == 2 + - iam_policy_name_b in result.policies + - result[iam_object_key] == iam_name + - iam_policy_info.policies | length == 1 + - iam_policy_info.all_policy_names | length == 2 + - iam_policy_name_a in iam_policy_info.all_policy_names + - iam_policy_name_b in iam_policy_info.all_policy_names + - iam_policy_info.policies[0].policy_name == iam_policy_name_b + - '"Id" not in iam_policy_info.policies[0].policy_document' + + - name: 'Create policy using document for {{ iam_type }} (idempotency) (skip_duplicates = no)' + iam_policy: + state: present + skip_duplicates: no + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_b }}' + policy_document: '{{ tmpdir.path }}/no_access.json' + register: result + - iam_policy_info: + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_b }}' + register: iam_policy_info + + - name: 'Assert no change' + assert: + that: + - result is not changed + - result.policies | length == 2 + - iam_policy_name_b in result.policies + - result[iam_object_key] == iam_name + - iam_policy_info.policies | length == 1 + - iam_policy_name_a in iam_policy_info.all_policy_names + - iam_policy_name_b in iam_policy_info.all_policy_names + - iam_policy_info.all_policy_names | length == 2 + - iam_policy_info.policies[0].policy_name == iam_policy_name_b + - '"Id" not in iam_policy_info.policies[0].policy_document' + + # ============================================================ + #- name: 'Create policy using json for {{ iam_type }} (check mode)' + # check_mode: yes + # iam_policy: + # state: present + # iam_type: '{{ iam_type }}' + # iam_name: '{{ iam_name }}' + # policy_name: '{{ iam_policy_name_c }}' + # policy_json: '{{ lookup("file", "{{ tmpdir.path }}/no_access_with_id.json") }}' + # skip_duplicates: yes + # register: result + #- iam_policy_info: + # iam_type: '{{ iam_type }}' + # iam_name: '{{ iam_name }}' + # policy_name: '{{ iam_policy_name_c }}' + # register: iam_policy_info + + #- name: 'Assert policy would be added for {{ iam_type }}' + # assert: + # that: + # - result is changed + # - '"policies" not in iam_policy_info' + # - iam_policy_info.all_policy_names | length == 2 + # - iam_policy_name_c not in iam_policy_info.all_policy_names + # - iam_policy_name_a in iam_policy_info.all_policy_names + # - iam_policy_name_b in iam_policy_info.all_policy_names + + - name: 'Create policy using json for {{ iam_type }}' + iam_policy: + state: present + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_c }}' + policy_json: '{{ lookup("file", "{{ tmpdir.path }}/no_access_with_id.json") }}' + skip_duplicates: yes + register: result + - iam_policy_info: + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_c }}' + register: iam_policy_info + + - name: 'Assert policy was added for {{ iam_type }}' + assert: + that: + - result is changed + - result.policies | length == 3 + - iam_policy_name_c in result.policies + - result[iam_object_key] == iam_name + - iam_policy_info.policies | length == 1 + - iam_policy_name_a in iam_policy_info.all_policy_names + - iam_policy_name_b in iam_policy_info.all_policy_names + - iam_policy_name_c in iam_policy_info.all_policy_names + - iam_policy_info.all_policy_names | length == 3 + - iam_policy_info.policies[0].policy_name == iam_policy_name_c + - iam_policy_info.policies[0].policy_document.Id == 'MyId' + + - name: 'Create policy using json for {{ iam_type }} (idempotency)' + iam_policy: + state: present + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_c }}' + policy_json: '{{ lookup("file", "{{ tmpdir.path }}/no_access_with_id.json") }}' + skip_duplicates: yes + register: result + - iam_policy_info: + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_c }}' + register: iam_policy_info + + - name: 'Assert no change' + assert: + that: + - result is not changed + - result.policies | length == 3 + - iam_policy_name_c in result.policies + - result[iam_object_key] == iam_name + - iam_policy_name_a in iam_policy_info.all_policy_names + - iam_policy_name_b in iam_policy_info.all_policy_names + - iam_policy_name_c in iam_policy_info.all_policy_names + - iam_policy_info.all_policy_names | length == 3 + - iam_policy_info.policies[0].policy_name == iam_policy_name_c + - iam_policy_info.policies[0].policy_document.Id == 'MyId' + + # ============================================================ + #- name: 'Create policy using json for {{ iam_type }} (check mode) (skip_duplicates)' + # check_mode: yes + # iam_policy: + # state: present + # iam_type: '{{ iam_type }}' + # iam_name: '{{ iam_name }}' + # policy_name: '{{ iam_policy_name_d }}' + # policy_json: '{{ lookup("file", "{{ tmpdir.path }}/no_access_with_id.json") }}' + # skip_duplicates: yes + # register: result + #- iam_policy_info: + # iam_type: '{{ iam_type }}' + # iam_name: '{{ iam_name }}' + # policy_name: '{{ iam_policy_name_d }}' + # register: iam_policy_info + + #- name: 'Assert policy would be added for {{ iam_type }}' + # assert: + # that: + # - result is not changed + # - iam_policy_name_a in iam_policy_info.all_policy_names + # - iam_policy_name_b in iam_policy_info.all_policy_names + # - iam_policy_name_c in iam_policy_info.all_policy_names + # - iam_policy_name_d not in iam_policy_info.all_policy_names + # - iam_policy_info.all_policy_names | length == 3 + # - '"policies" not in iam_policy_info' + + - name: 'Create policy using json for {{ iam_type }} (skip_duplicates)' + iam_policy: + state: present + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_d }}' + policy_json: '{{ lookup("file", "{{ tmpdir.path }}/no_access_with_id.json") }}' + skip_duplicates: yes + register: result + - iam_policy_info: + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_d }}' + register: iam_policy_info + + - name: 'Assert policy was not added for {{ iam_type }} (skip_duplicates)' + assert: + that: + - result is not changed + - result.policies | length == 3 + - iam_policy_name_d not in result.policies + - result[iam_object_key] == iam_name + - iam_policy_name_a in iam_policy_info.all_policy_names + - iam_policy_name_b in iam_policy_info.all_policy_names + - iam_policy_name_c in iam_policy_info.all_policy_names + - iam_policy_name_d not in iam_policy_info.all_policy_names + - iam_policy_info.all_policy_names | length == 3 + - '"policies" not in iam_policy_info' + + #- name: 'Create policy using json for {{ iam_type }} (check mode) (skip_duplicates = no)' + # check_mode: yes + # iam_policy: + # state: present + # iam_type: '{{ iam_type }}' + # iam_name: '{{ iam_name }}' + # policy_name: '{{ iam_policy_name_d }}' + # policy_json: '{{ lookup("file", "{{ tmpdir.path }}/no_access_with_id.json") }}' + # skip_duplicates: no + # register: result + #- iam_policy_info: + # iam_type: '{{ iam_type }}' + # iam_name: '{{ iam_name }}' + # policy_name: '{{ iam_policy_name_d }}' + # register: iam_policy_info + + #- name: 'Assert policy would be added for {{ iam_type }}' + # assert: + # that: + # - result.changed == True + + - name: 'Create policy using json for {{ iam_type }} (skip_duplicates = no)' + iam_policy: + state: present + skip_duplicates: no + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_d }}' + policy_json: '{{ lookup("file", "{{ tmpdir.path }}/no_access_with_id.json") }}' + register: result + - iam_policy_info: + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_d }}' + register: iam_policy_info + + - name: 'Assert policy was added for {{ iam_type }}' + assert: + that: + - result is changed + - result.policies | length == 4 + - iam_policy_name_d in result.policies + - result[iam_object_key] == iam_name + - iam_policy_name_a in iam_policy_info.all_policy_names + - iam_policy_name_b in iam_policy_info.all_policy_names + - iam_policy_name_c in iam_policy_info.all_policy_names + - iam_policy_name_d in iam_policy_info.all_policy_names + - iam_policy_name_a not in iam_policy_info.policy_names + - iam_policy_name_b not in iam_policy_info.policy_names + - iam_policy_name_c not in iam_policy_info.policy_names + - iam_policy_name_d in iam_policy_info.policy_names + - iam_policy_info.policy_names | length == 1 + - iam_policy_info.all_policy_names | length == 4 + - iam_policy_info.policies[0].policy_name == iam_policy_name_d + - iam_policy_info.policies[0].policy_document.Id == 'MyId' + + - name: 'Create policy using json for {{ iam_type }} (idempotency) (skip_duplicates = no)' + iam_policy: + state: present + skip_duplicates: no + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_d }}' + policy_json: '{{ lookup("file", "{{ tmpdir.path }}/no_access_with_id.json") }}' + register: result + - iam_policy_info: + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_d }}' + register: iam_policy_info + + - name: 'Assert no change' + assert: + that: + - result is not changed + - result.policies | length == 4 + - iam_policy_name_d in result.policies + - result[iam_object_key] == iam_name + - iam_policy_name_a in iam_policy_info.all_policy_names + - iam_policy_name_b in iam_policy_info.all_policy_names + - iam_policy_name_c in iam_policy_info.all_policy_names + - iam_policy_name_d in iam_policy_info.all_policy_names + - iam_policy_info.all_policy_names | length == 4 + - iam_policy_info.policies[0].policy_name == iam_policy_name_d + - iam_policy_info.policies[0].policy_document.Id == 'MyId' + + # ============================================================ + - name: 'Test fetching multiple policies from {{ iam_type }}' + iam_policy_info: + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + register: iam_policy_info + + - name: 'Assert all policies returned' + assert: + that: + - iam_policy_info is succeeded + - iam_policy_info.policies | length == 4 + - iam_policy_info.all_policy_names | length == 4 + - iam_policy_name_a in iam_policy_info.all_policy_names + - iam_policy_name_b in iam_policy_info.all_policy_names + - iam_policy_name_c in iam_policy_info.all_policy_names + - iam_policy_name_d in iam_policy_info.all_policy_names + # Quick test that the policies are the ones we expect + - iam_policy_info.policies | json_query('[*].policy_name') | length == 4 + - iam_policy_info.policies | json_query('[?policy_document.Id == `MyId`].policy_name') | length == 2 + - iam_policy_name_c in (iam_policy_info.policies | json_query('[?policy_document.Id == `MyId`].policy_name') | list) + - iam_policy_name_d in (iam_policy_info.policies | json_query('[?policy_document.Id == `MyId`].policy_name') | list) + + # ============================================================ + #- name: 'Update policy using document for {{ iam_type }} (check mode) (skip_duplicates)' + # check_mode: yes + # iam_policy: + # state: present + # iam_type: '{{ iam_type }}' + # iam_name: '{{ iam_name }}' + # policy_name: '{{ iam_policy_name_a }}' + # policy_document: '{{ tmpdir.path }}/no_access_with_id.json' + # skip_duplicates: yes + # register: result + #- iam_policy_info: + # iam_type: '{{ iam_type }}' + # iam_name: '{{ iam_name }}' + # policy_name: '{{ iam_policy_name_a }}' + # register: iam_policy_info + + #- name: 'Assert policy would be added for {{ iam_type }}' + # assert: + # that: + # - result is not changed + # - iam_policy_info.policies[0].policy_name == iam_policy_name_a + # - '"Id" not in iam_policy_info.policies[0].policy_document' + + - name: 'Update policy using document for {{ iam_type }} (skip_duplicates)' + iam_policy: + state: present + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_a }}' + policy_document: '{{ tmpdir.path }}/no_access_with_id.json' + skip_duplicates: yes + register: result + - iam_policy_info: + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_a }}' + register: iam_policy_info + + - name: 'Assert policy was not updated for {{ iam_type }} (skip_duplicates)' + assert: + that: + - result is not changed + - result.policies | length == 4 + - iam_policy_name_a in result.policies + - result[iam_object_key] == iam_name + - iam_policy_info.all_policy_names | length == 4 + - iam_policy_info.policies[0].policy_name == iam_policy_name_a + - '"Id" not in iam_policy_info.policies[0].policy_document' + + #- name: 'Update policy using document for {{ iam_type }} (check mode) (skip_duplicates = no)' + # check_mode: yes + # iam_policy: + # state: present + # iam_type: '{{ iam_type }}' + # iam_name: '{{ iam_name }}' + # policy_name: '{{ iam_policy_name_a }}' + # policy_document: '{{ tmpdir.path }}/no_access_with_id.json' + # skip_duplicates: no + # register: result + #- iam_policy_info: + # iam_type: '{{ iam_type }}' + # iam_name: '{{ iam_name }}' + # policy_name: '{{ iam_policy_name_a }}' + # register: iam_policy_info + + #- name: 'Assert policy would be updated for {{ iam_type }}' + # assert: + # that: + # - result.changed == True + # - iam_policy_info.all_policy_names | length == 4 + # - iam_policy_info.policies[0].policy_name == iam_policy_name_a + # - '"Id" not in iam_policy_info.policies[0].policy_document' + + - name: 'Update policy using document for {{ iam_type }} (skip_duplicates = no)' + iam_policy: + state: present + skip_duplicates: no + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_a }}' + policy_document: '{{ tmpdir.path }}/no_access_with_id.json' + register: result + - iam_policy_info: + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_a }}' + register: iam_policy_info + + - name: 'Assert policy was updated for {{ iam_type }}' + assert: + that: + - result is changed + - result.policies | length == 4 + - iam_policy_name_a in result.policies + - result[iam_object_key] == iam_name + - iam_policy_info.policies[0].policy_document.Id == 'MyId' + + - name: 'Update policy using document for {{ iam_type }} (idempotency) (skip_duplicates = no)' + iam_policy: + state: present + skip_duplicates: no + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_a }}' + policy_document: '{{ tmpdir.path }}/no_access_with_id.json' + register: result + - iam_policy_info: + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_a }}' + register: iam_policy_info + + - name: 'Assert no change' + assert: + that: + - result is not changed + - result.policies | length == 4 + - iam_policy_name_a in result.policies + - result[iam_object_key] == iam_name + - iam_policy_info.policies[0].policy_document.Id == 'MyId' + + - name: 'Delete policy A' + iam_policy: + state: absent + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_a }}' + register: result + - iam_policy_info: + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_a }}' + register: iam_policy_info + + - name: 'Assert deleted' + assert: + that: + - result is changed + - result.policies | length == 3 + - iam_policy_name_a not in result.policies + - result[iam_object_key] == iam_name + - '"policies" not in iam_policy_info' + - iam_policy_info.all_policy_names | length == 3 + - iam_policy_name_a not in iam_policy_info.all_policy_names + + # ============================================================ + # Update C with no_access.json + # Delete C + # + #- name: 'Update policy using json for {{ iam_type }} (check mode) (skip_duplicates)' + # check_mode: yes + # iam_policy: + # state: present + # iam_type: '{{ iam_type }}' + # iam_name: '{{ iam_name }}' + # policy_name: '{{ iam_policy_name_c }}' + # policy_json: '{{ lookup("file", "{{ tmpdir.path }}/no_access.json") }}' + # skip_duplicates: yes + # register: result + #- iam_policy_info: + # iam_type: '{{ iam_type }}' + # iam_name: '{{ iam_name }}' + # policy_name: '{{ iam_policy_name_c }}' + # register: iam_policy_info + + #- name: 'Assert policy would be added for {{ iam_type }}' + # assert: + # that: + # - result is not changed + # - iam_policy_info.policies[0].policy_document.Id == 'MyId' + + - name: 'Update policy using json for {{ iam_type }} (skip_duplicates)' + iam_policy: + state: present + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_c }}' + policy_json: '{{ lookup("file", "{{ tmpdir.path }}/no_access.json") }}' + skip_duplicates: yes + register: result + - iam_policy_info: + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_c }}' + register: iam_policy_info + + - name: 'Assert policy was not updated for {{ iam_type }} (skip_duplicates)' + assert: + that: + - result is not changed + - result.policies | length == 3 + - iam_policy_name_c in result.policies + - result[iam_object_key] == iam_name + - iam_policy_info.policies[0].policy_document.Id == 'MyId' + + #- name: 'Update policy using json for {{ iam_type }} (check mode) (skip_duplicates = no)' + # check_mode: yes + # iam_policy: + # state: present + # iam_type: '{{ iam_type }}' + # iam_name: '{{ iam_name }}' + # policy_name: '{{ iam_policy_name_c }}' + # policy_json: '{{ lookup("file", "{{ tmpdir.path }}/no_access.json") }}' + # skip_duplicates: no + # register: result + #- iam_policy_info: + # iam_type: '{{ iam_type }}' + # iam_name: '{{ iam_name }}' + # policy_name: '{{ iam_policy_name_c }}' + # register: iam_policy_info + + #- name: 'Assert policy would be updated for {{ iam_type }}' + # assert: + # that: + # - result.changed == True + # - iam_policy_info.policies[0].policy_document.Id == 'MyId' + + - name: 'Update policy using json for {{ iam_type }} (skip_duplicates = no)' + iam_policy: + state: present + skip_duplicates: no + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_c }}' + policy_json: '{{ lookup("file", "{{ tmpdir.path }}/no_access.json") }}' + register: result + - iam_policy_info: + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_c }}' + register: iam_policy_info + + - name: 'Assert policy was updated for {{ iam_type }}' + assert: + that: + - result is changed + - result.policies | length == 3 + - iam_policy_name_c in result.policies + - result[iam_object_key] == iam_name + - '"Id" not in iam_policy_info.policies[0].policy_document' + + - name: 'Update policy using json for {{ iam_type }} (idempotency) (skip_duplicates = no)' + iam_policy: + state: present + skip_duplicates: no + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_c }}' + policy_json: '{{ lookup("file", "{{ tmpdir.path }}/no_access.json") }}' + register: result + - iam_policy_info: + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_c }}' + register: iam_policy_info + + - name: 'Assert no change' + assert: + that: + - result is not changed + - result.policies | length == 3 + - iam_policy_name_c in result.policies + - result[iam_object_key] == iam_name + - '"Id" not in iam_policy_info.policies[0].policy_document' + + - name: 'Delete policy C' + iam_policy: + state: absent + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_c }}' + register: result + - iam_policy_info: + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_c }}' + register: iam_policy_info + + - name: 'Assert deleted' + assert: + that: + - result is changed + - result.policies | length == 2 + - iam_policy_name_c not in result.policies + - result[iam_object_key] == iam_name + - '"policies" not in iam_policy_info' + - iam_policy_info.all_policy_names | length == 2 + - iam_policy_name_c not in iam_policy_info.all_policy_names + + # ============================================================ + #- name: 'Update policy using document for {{ iam_type }} (check mode)' + # check_mode: yes + # iam_policy: + # state: present + # iam_type: '{{ iam_type }}' + # iam_name: '{{ iam_name }}' + # policy_name: '{{ iam_policy_name_b }}' + # policy_document: '{{ tmpdir.path }}/no_access_with_second_id.json' + # register: result + #- iam_policy_info: + # iam_type: '{{ iam_type }}' + # iam_name: '{{ iam_name }}' + # policy_name: '{{ iam_policy_name_b }}' + # register: iam_policy_info + + #- name: 'Assert policy would be updated for {{ iam_type }}' + # assert: + # that: + # - result.changed == True + # - '"Id" not in iam_policy_info.policies[0].policy_document' + + - name: 'Update policy using document for {{ iam_type }}' + iam_policy: + state: present + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_b }}' + policy_document: '{{ tmpdir.path }}/no_access_with_second_id.json' + register: result + - iam_policy_info: + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_b }}' + register: iam_policy_info + + - name: 'Assert policy was updated for {{ iam_type }}' + assert: + that: + - result is changed + - result.policies | length == 2 + - iam_policy_name_b in result.policies + - result[iam_object_key] == iam_name + - iam_policy_info.policies[0].policy_document.Id == 'MyOtherId' + + - name: 'Update policy using document for {{ iam_type }} (idempotency)' + iam_policy: + state: present + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_b }}' + policy_document: '{{ tmpdir.path }}/no_access_with_second_id.json' + register: result + - iam_policy_info: + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_b }}' + register: iam_policy_info + + - name: 'Assert no change' + assert: + that: + - result is not changed + - result.policies | length == 2 + - iam_policy_name_b in result.policies + - result[iam_object_key] == iam_name + - iam_policy_info.policies[0].policy_document.Id == 'MyOtherId' + + - name: 'Delete policy B' + iam_policy: + state: absent + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_b }}' + register: result + - iam_policy_info: + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_b }}' + register: iam_policy_info + + - name: 'Assert deleted' + assert: + that: + - result is changed + - result.policies | length == 1 + - iam_policy_name_b not in result.policies + - result[iam_object_key] == iam_name + - '"policies" not in iam_policy_info' + - iam_policy_info.all_policy_names | length == 1 + - iam_policy_name_b not in iam_policy_info.all_policy_names + + # ============================================================ + #- name: 'Update policy using json for {{ iam_type }} (check mode)' + # check_mode: yes + # iam_policy: + # state: present + # iam_type: '{{ iam_type }}' + # iam_name: '{{ iam_name }}' + # policy_name: '{{ iam_policy_name_d }}' + # policy_json: '{{ lookup("file", "{{ tmpdir.path }}/no_access_with_second_id.json") }}' + # register: result + #- iam_policy_info: + # iam_type: '{{ iam_type }}' + # iam_name: '{{ iam_name }}' + # policy_name: '{{ iam_policy_name_d }}' + # register: iam_policy_info + + #- name: 'Assert policy would be updated for {{ iam_type }}' + # assert: + # that: + # - result.changed == True + # - iam_policy_info.policies[0].policy_document.Id == 'MyId' + + - name: 'Update policy using json for {{ iam_type }}' + iam_policy: + state: present + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_d }}' + policy_json: '{{ lookup("file", "{{ tmpdir.path }}/no_access_with_second_id.json") }}' + register: result + - iam_policy_info: + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_d }}' + register: iam_policy_info + + - name: 'Assert policy was updated for {{ iam_type }}' + assert: + that: + - result is changed + - result.policies | length == 1 + - iam_policy_name_d in result.policies + - result[iam_object_key] == iam_name + - iam_policy_info.policies[0].policy_document.Id == 'MyOtherId' + + - name: 'Update policy using json for {{ iam_type }} (idempotency)' + iam_policy: + state: present + skip_duplicates: no + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_d }}' + policy_json: '{{ lookup("file", "{{ tmpdir.path }}/no_access_with_second_id.json") }}' + register: result + - iam_policy_info: + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_d }}' + register: iam_policy_info + + - name: 'Assert no change' + assert: + that: + - result is not changed + - result.policies | length == 1 + - iam_policy_name_d in result.policies + - result[iam_object_key] == iam_name + - iam_policy_info.policies[0].policy_document.Id == 'MyOtherId' + + # ============================================================ + #- name: 'Delete policy D (check_mode)' + # check_mode: yes + # iam_policy: + # state: absent + # iam_type: '{{ iam_type }}' + # iam_name: '{{ iam_name }}' + # policy_name: '{{ iam_policy_name_d }}' + # register: result + #- iam_policy_info: + # iam_type: '{{ iam_type }}' + # iam_name: '{{ iam_name }}' + # policy_name: '{{ iam_policy_name_d }}' + # register: iam_policy_info + + #- name: 'Assert not deleted' + # assert: + # that: + # - result is changed + # - result.policies | length == 1 + # - iam_policy_name_d in result.policies + # - result[iam_object_key] == iam_name + # - iam_policy_info.all_policy_names | length == 1 + # - iam_policy_name_d in iam_policy_info.all_policy_names + # - iam_policy_info.policies[0].policy_document.Id == 'MyOtherId' + + - name: 'Delete policy D' + iam_policy: + state: absent + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_d }}' + register: result + - iam_policy_info: + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_d }}' + register: iam_policy_info + + - name: 'Assert deleted' + assert: + that: + - result is changed + - '"policies" not in iam_policy_info' + - iam_policy_name_d not in result.policies + - result[iam_object_key] == iam_name + - '"policies" not in iam_policy_info' + - iam_policy_info.all_policy_names | length == 0 + + - name: 'Delete policy D (test idempotency)' + iam_policy: + state: absent + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_d }}' + register: result + - iam_policy_info: + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_d }}' + register: iam_policy_info + + - name: 'Assert deleted' + assert: + that: + - result is not changed + - '"policies" not in iam_policy_info' + - iam_policy_info.all_policy_names | length == 0 + + always: + # ============================================================ + - name: 'Delete policy A for {{ iam_type }}' + iam_policy: + state: absent + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_a }}' + ignore_errors: yes + + - name: 'Delete policy B for {{ iam_type }}' + iam_policy: + state: absent + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_b }}' + ignore_errors: yes + + - name: 'Delete policy C for {{ iam_type }}' + iam_policy: + state: absent + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_c }}' + ignore_errors: yes + + - name: 'Delete policy D for {{ iam_type }}' + iam_policy: + state: absent + iam_type: '{{ iam_type }}' + iam_name: '{{ iam_name }}' + policy_name: '{{ iam_policy_name_d }}' + ignore_errors: yes