diff --git a/plugins/modules/iam_access_key.py b/plugins/modules/iam_access_key.py deleted file mode 100644 index ae3e9e7dd11..00000000000 --- a/plugins/modules/iam_access_key.py +++ /dev/null @@ -1,311 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright (c) 2021 Ansible Project -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -DOCUMENTATION = r""" ---- -module: iam_access_key -version_added: 2.1.0 -short_description: Manage AWS IAM User access keys -description: - - Manage AWS IAM user access keys. -author: - - Mark Chappell (@tremble) -options: - user_name: - description: - - The name of the IAM User to which the key belongs. - required: true - type: str - aliases: ['username'] - id: - description: - - The ID of the access key. - - Required when I(state=absent). - - Mutually exclusive with I(rotate_keys). - required: false - type: str - state: - description: - - Create or remove the access key. - - When I(state=present) and I(id) is not defined a new key will be created. - required: false - type: str - default: 'present' - choices: [ 'present', 'absent' ] - active: - description: - - Whether the key should be enabled or disabled. - - Defaults to C(true) when creating a new key. - required: false - type: bool - aliases: ['enabled'] - rotate_keys: - description: - - When there are already 2 access keys attached to the IAM user the oldest - key will be removed and a new key created. - - Ignored if I(state=absent) - - Mutually exclusive with I(id). - required: false - type: bool - default: false - -extends_documentation_fragment: - - amazon.aws.common.modules - - amazon.aws.region.modules - - amazon.aws.boto3 -""" - -EXAMPLES = r""" -# Note: These examples do not set authentication details, see the AWS Guide for details. - -- name: Create a new access key - community.aws.iam_access_key: - user_name: example_user - state: present - -- name: Delete the access_key - community.aws.iam_access_key: - user_name: example_user - id: AKIA1EXAMPLE1EXAMPLE - state: absent -""" - -RETURN = r""" -access_key: - description: A dictionary containing all the access key information. - returned: When the key exists. - type: complex - contains: - access_key_id: - description: The ID for the access key. - returned: success - type: str - sample: AKIA1EXAMPLE1EXAMPLE - create_date: - description: The date and time, in ISO 8601 date-time format, when the access key was created. - returned: success - type: str - sample: "2021-10-09T13:25:42+00:00" - user_name: - description: The name of the IAM user to which the key is attached. - returned: success - type: str - sample: example_user - status: - description: - - The status of the key. - - C(Active) means it can be used. - - C(Inactive) means it can not be used. - returned: success - type: str - sample: Inactive -secret_access_key: - description: - - The secret access key. - - A secret access key is the equivalent of a password which can not be changed and as such should be considered sensitive data. - - Secret access keys can only be accessed at creation time. - returned: When a new key is created. - type: str - sample: example/Example+EXAMPLE+example/Example -deleted_access_key_id: - description: - - The access key deleted during rotation. - returned: When a key was deleted during the rotation of access keys - type: str - sample: AKIA1EXAMPLE1EXAMPLE -""" - -try: - import botocore -except ImportError: - pass # caught by AnsibleAWSModule - -from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict - -from ansible_collections.amazon.aws.plugins.module_utils.botocore import is_boto3_error_code -from ansible_collections.amazon.aws.plugins.module_utils.botocore import normalize_boto3_result -from ansible_collections.amazon.aws.plugins.module_utils.retries import AWSRetry -from ansible_collections.amazon.aws.plugins.module_utils.transformation import scrub_none_parameters - -from ansible_collections.community.aws.plugins.module_utils.modules import AnsibleCommunityAWSModule as AnsibleAWSModule - - -def delete_access_key(access_keys, user, access_key_id): - if not access_key_id: - return False - - if access_key_id not in access_keys: - return False - - if module.check_mode: - return True - - try: - client.delete_access_key( - aws_retry=True, - UserName=user, - AccessKeyId=access_key_id, - ) - except is_boto3_error_code("NoSuchEntityException"): - # Generally occurs when race conditions have happened and someone - # deleted the key while we were checking to see if it existed. - return False - except ( - botocore.exceptions.ClientError, - botocore.exceptions.BotoCoreError, - ) as e: # pylint: disable=duplicate-except - module.fail_json_aws(e, msg=f'Failed to delete access key "{access_key_id}" for user "{user}"') - - return True - - -def update_access_key(access_keys, user, access_key_id, enabled): - if access_key_id not in access_keys: - module.fail_json( - msg=f'Access key "{access_key_id}" not found attached to User "{user}"', - ) - - changes = dict() - access_key = access_keys.get(access_key_id) - - if enabled is not None: - desired_status = "Active" if enabled else "Inactive" - if access_key.get("status") != desired_status: - changes["Status"] = desired_status - - if not changes: - return False - - if module.check_mode: - return True - - try: - client.update_access_key(aws_retry=True, UserName=user, AccessKeyId=access_key_id, **changes) - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - module.fail_json_aws( - e, - changes=changes, - msg=f'Failed to update access key "{access_key_id}" for user "{user}"', - ) - return True - - -def create_access_key(access_keys, user, rotate_keys, enabled): - changed = False - oldest_key = False - - if len(access_keys) > 1 and rotate_keys: - sorted_keys = sorted(list(access_keys), key=lambda k: access_keys[k].get("create_date", None)) - oldest_key = sorted_keys[0] - changed |= delete_access_key(access_keys, user, oldest_key) - - if module.check_mode: - if changed: - return dict(deleted_access_key=oldest_key) - return True - - try: - results = client.create_access_key(aws_retry=True, UserName=user) - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - module.fail_json_aws(e, msg=f'Failed to create access key for user "{user}"') - results = camel_dict_to_snake_dict(results) - access_key = results.get("access_key") - access_key = normalize_boto3_result(access_key) - - # Update settings which can't be managed on creation - if enabled is False: - access_key_id = access_key["access_key_id"] - access_keys = {access_key_id: access_key} - update_access_key(access_keys, user, access_key_id, enabled) - access_key["status"] = "Inactive" - - if oldest_key: - access_key["deleted_access_key"] = oldest_key - - return access_key - - -def get_access_keys(user): - try: - results = client.list_access_keys(aws_retry=True, UserName=user) - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - module.fail_json_aws(e, msg=f'Failed to get access keys for user "{user}"') - if not results: - return None - - results = camel_dict_to_snake_dict(results) - access_keys = results.get("access_key_metadata", []) - if not access_keys: - return [] - - access_keys = normalize_boto3_result(access_keys) - access_keys = {k["access_key_id"]: k for k in access_keys} - return access_keys - - -def main(): - global module - global client - - argument_spec = dict( - user_name=dict(required=True, type="str", aliases=["username"]), - id=dict(required=False, type="str"), - state=dict(required=False, choices=["present", "absent"], default="present"), - active=dict(required=False, type="bool", aliases=["enabled"]), - rotate_keys=dict(required=False, type="bool", default=False), - ) - - required_if = [ - ["state", "absent", ("id",)], - ] - mutually_exclusive = [ - ["rotate_keys", "id"], - ] - - module = AnsibleAWSModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - client = module.client("iam", retry_decorator=AWSRetry.jittered_backoff()) - - changed = False - state = module.params.get("state") - user = module.params.get("user_name") - access_key_id = module.params.get("id") - rotate_keys = module.params.get("rotate_keys") - enabled = module.params.get("active") - - access_keys = get_access_keys(user) - results = dict() - - if state == "absent": - changed |= delete_access_key(access_keys, user, access_key_id) - else: - # If we have an ID then we should try to update it - if access_key_id: - changed |= update_access_key(access_keys, user, access_key_id, enabled) - access_keys = get_access_keys(user) - results["access_key"] = access_keys.get(access_key_id, None) - # Otherwise we try to create a new one - else: - secret_key = create_access_key(access_keys, user, rotate_keys, enabled) - if isinstance(secret_key, bool): - changed |= secret_key - else: - changed = True - results["access_key_id"] = secret_key.get("access_key_id", None) - results["secret_access_key"] = secret_key.pop("secret_access_key", None) - results["deleted_access_key_id"] = secret_key.pop("deleted_access_key", None) - if secret_key: - results["access_key"] = secret_key - results = scrub_none_parameters(results) - - module.exit_json(changed=changed, **results) - - -if __name__ == "__main__": - main() diff --git a/plugins/modules/iam_access_key_info.py b/plugins/modules/iam_access_key_info.py deleted file mode 100644 index 0ea8b514122..00000000000 --- a/plugins/modules/iam_access_key_info.py +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright (c) 2021 Ansible Project -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -DOCUMENTATION = r""" ---- -module: iam_access_key_info -version_added: 2.1.0 -short_description: fetch information about AWS IAM User access keys -description: - - 'Fetches information AWS IAM user access keys.' - - 'Note: It is not possible to fetch the secret access key.' -author: - - Mark Chappell (@tremble) -options: - user_name: - description: - - The name of the IAM User to which the keys belong. - required: true - type: str - aliases: ['username'] - -extends_documentation_fragment: - - amazon.aws.common.modules - - amazon.aws.region.modules - - amazon.aws.boto3 -""" - -EXAMPLES = r""" -# Note: These examples do not set authentication details, see the AWS Guide for details. - -- name: Fetch Access keys for a user - community.aws.iam_access_key_info: - user_name: example_user -""" - -RETURN = r""" -access_key: - description: A dictionary containing all the access key information. - returned: When the key exists. - type: list - elements: dict - contains: - access_key_id: - description: The ID for the access key. - returned: success - type: str - sample: AKIA1EXAMPLE1EXAMPLE - create_date: - description: The date and time, in ISO 8601 date-time format, when the access key was created. - returned: success - type: str - sample: "2021-10-09T13:25:42+00:00" - user_name: - description: The name of the IAM user to which the key is attached. - returned: success - type: str - sample: example_user - status: - description: - - The status of the key. - - C(Active) means it can be used. - - C(Inactive) means it can not be used. - returned: success - type: str - sample: Inactive -""" - -try: - import botocore -except ImportError: - pass # caught by AnsibleAWSModule - -from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict - -from ansible_collections.amazon.aws.plugins.module_utils.botocore import normalize_boto3_result -from ansible_collections.amazon.aws.plugins.module_utils.retries import AWSRetry - -from ansible_collections.community.aws.plugins.module_utils.modules import AnsibleCommunityAWSModule as AnsibleAWSModule - - -def get_access_keys(user): - try: - results = client.list_access_keys(aws_retry=True, UserName=user) - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - module.fail_json_aws(e, msg=f'Failed to get access keys for user "{user}"') - if not results: - return None - - results = camel_dict_to_snake_dict(results) - access_keys = results.get("access_key_metadata", []) - if not access_keys: - return [] - - access_keys = normalize_boto3_result(access_keys) - access_keys = sorted(access_keys, key=lambda d: d.get("create_date", None)) - return access_keys - - -def main(): - global module - global client - - argument_spec = dict( - user_name=dict(required=True, type="str", aliases=["username"]), - ) - - module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) - - client = module.client("iam", retry_decorator=AWSRetry.jittered_backoff()) - - changed = False - user = module.params.get("user_name") - access_keys = get_access_keys(user) - - module.exit_json(changed=changed, access_keys=access_keys) - - -if __name__ == "__main__": - main() diff --git a/tests/integration/targets/iam_access_key/aliases b/tests/integration/targets/iam_access_key/aliases deleted file mode 100644 index ffceccfcc41..00000000000 --- a/tests/integration/targets/iam_access_key/aliases +++ /dev/null @@ -1,9 +0,0 @@ -# reason: missing-policy -# It should be possible to test iam_user by limiting which policies can be -# attached to the users. -# Careful review is needed prior to adding this to the main CI. -unsupported - -cloud/aws - -iam_access_key_info diff --git a/tests/integration/targets/iam_access_key/defaults/main.yml b/tests/integration/targets/iam_access_key/defaults/main.yml deleted file mode 100644 index eaaa3523e19..00000000000 --- a/tests/integration/targets/iam_access_key/defaults/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -test_user: '{{ resource_prefix }}' diff --git a/tests/integration/targets/iam_access_key/meta/main.yml b/tests/integration/targets/iam_access_key/meta/main.yml deleted file mode 100644 index 32cf5dda7ed..00000000000 --- a/tests/integration/targets/iam_access_key/meta/main.yml +++ /dev/null @@ -1 +0,0 @@ -dependencies: [] diff --git a/tests/integration/targets/iam_access_key/tasks/main.yml b/tests/integration/targets/iam_access_key/tasks/main.yml deleted file mode 100644 index 572e53cc8a3..00000000000 --- a/tests/integration/targets/iam_access_key/tasks/main.yml +++ /dev/null @@ -1,808 +0,0 @@ ---- -- name: AWS AuthN details - module_defaults: - group/aws: - access_key: "{{ aws_access_key }}" - secret_key: "{{ aws_secret_key }}" - session_token: "{{ security_token | default(omit) }}" - region: "{{ aws_region }}" - collections: - - amazon.aws - - community.aws - block: - # ================================================================================== - # Preparation - # ================================================================================== - # We create an IAM user with no attached permissions. The *only* thing the - # user will be able to do is call sts.get_caller_identity - # https://docs.aws.amazon.com/STS/latest/APIReference/API_GetCallerIdentity.html - - name: Create test user - iam_user: - name: '{{ test_user }}' - state: present - register: iam_user - - - assert: - that: - - iam_user is successful - - iam_user is changed - - # ================================================================================== - - - name: Fetch IAM key info (no keys) - iam_access_key_info: - user_name: '{{ test_user }}' - register: access_key_info - - - assert: - that: - - access_key_info is successful - - '"access_keys" in access_key_info' - - access_key_info.access_keys | length == 0 - - # ================================================================================== - - - name: Create a key (check_mode) - iam_access_key: - user_name: '{{ test_user }}' - state: present - register: create_key_1 - check_mode: true - - - assert: - that: - - create_key_1 is successful - - create_key_1 is changed - - - name: Create a key - iam_access_key: - user_name: '{{ test_user }}' - state: present - register: create_key_1 - - - assert: - that: - - create_key_1 is successful - - create_key_1 is changed - - '"access_key" in create_key_1' - - '"secret_access_key" in create_key_1' - - '"deleted_access_key_id" not in create_key_1' - - '"access_key_id" in create_key_1.access_key' - - '"create_date" in create_key_1.access_key' - - '"user_name" in create_key_1.access_key' - - '"status" in create_key_1.access_key' - - create_key_1.access_key.user_name == test_user - - create_key_1.access_key.status == 'Active' - - - name: Fetch IAM key info (1 key) - iam_access_key_info: - user_name: '{{ test_user }}' - register: access_key_info - - - assert: - that: - - access_key_info is successful - - '"access_keys" in access_key_info' - - access_key_info.access_keys | length == 1 - - '"access_key_id" in access_key_1' - - '"create_date" in access_key_1' - - '"user_name" in access_key_1' - - '"status" in access_key_1' - - access_key_1.user_name == test_user - - access_key_1.access_key_id == create_key_1.access_key.access_key_id - - access_key_1.create_date == create_key_1.access_key.create_date - - access_key_1.status == 'Active' - vars: - access_key_1: '{{ access_key_info.access_keys[0] }}' - - # ================================================================================== - - - name: Create a second key (check_mode) - iam_access_key: - user_name: '{{ test_user }}' - state: present - register: create_key_2 - check_mode: true - - - assert: - that: - - create_key_2 is successful - - create_key_2 is changed - - - name: Create a second key - iam_access_key: - user_name: '{{ test_user }}' - state: present - register: create_key_2 - - - assert: - that: - - create_key_2 is successful - - create_key_2 is changed - - '"access_key" in create_key_2' - - '"secret_access_key" in create_key_2' - - '"deleted_access_key_id" not in create_key_2' - - '"access_key_id" in create_key_2.access_key' - - '"create_date" in create_key_2.access_key' - - '"user_name" in create_key_2.access_key' - - '"status" in create_key_2.access_key' - - create_key_2.access_key.user_name == test_user - - create_key_2.access_key.status == 'Active' - - - name: Fetch IAM key info (2 keys) - iam_access_key_info: - user_name: '{{ test_user }}' - register: access_key_info - - - assert: - that: - - access_key_info is successful - - '"access_keys" in access_key_info' - - access_key_info.access_keys | length == 2 - - '"access_key_id" in access_key_1' - - '"create_date" in access_key_1' - - '"user_name" in access_key_1' - - '"status" in access_key_1' - - access_key_1.user_name == test_user - - access_key_1.access_key_id == create_key_1.access_key.access_key_id - - access_key_1.create_date == create_key_1.access_key.create_date - - access_key_1.status == 'Active' - - '"access_key_id" in access_key_2' - - '"create_date" in access_key_2' - - '"user_name" in access_key_2' - - '"status" in access_key_2' - - access_key_2.user_name == test_user - - access_key_2.access_key_id == create_key_2.access_key.access_key_id - - access_key_2.create_date == create_key_2.access_key.create_date - - access_key_2.status == 'Active' - vars: - access_key_1: '{{ access_key_info.access_keys[0] }}' - access_key_2: '{{ access_key_info.access_keys[1] }}' - - # ================================================================================== - - # We don't block the attempt to create a third access key - should AWS change - # the limits this will "JustWork". - - # - name: Create a third key (check_mode) - # iam_access_key: - # user_name: '{{ test_user }}' - # state: present - # register: create_key_3 - # ignore_errors: True - # check_mode: true - - # - assert: - # that: - # - create_key_3 is successful - # - create_key_3 is changed - - - name: Create a third key without rotation - iam_access_key: - user_name: '{{ test_user }}' - state: present - register: create_key_3 - ignore_errors: True - - - assert: - that: - # If Amazon update the limits we may need to change the expectation here. - - create_key_3 is failed - - - name: Fetch IAM key info (2 keys - not changed) - iam_access_key_info: - user_name: '{{ test_user }}' - register: access_key_info - - - assert: - that: - - access_key_info is successful - - '"access_keys" in access_key_info' - - access_key_info.access_keys | length == 2 - - '"access_key_id" in access_key_1' - - '"create_date" in access_key_1' - - '"user_name" in access_key_1' - - '"status" in access_key_1' - - access_key_1.user_name == test_user - - access_key_1.access_key_id == create_key_1.access_key.access_key_id - - access_key_1.create_date == create_key_1.access_key.create_date - - access_key_1.status == 'Active' - - '"access_key_id" in access_key_2' - - '"create_date" in access_key_2' - - '"user_name" in access_key_2' - - '"status" in access_key_2' - - access_key_2.user_name == test_user - - access_key_2.access_key_id == create_key_2.access_key.access_key_id - - access_key_2.create_date == create_key_2.access_key.create_date - - access_key_2.status == 'Active' - vars: - access_key_1: '{{ access_key_info.access_keys[0] }}' - access_key_2: '{{ access_key_info.access_keys[1] }}' - - # ================================================================================== - - - name: Create a third key - rotation enabled (check_mode) - iam_access_key: - user_name: '{{ test_user }}' - state: present - rotate_keys: true - register: create_key_3 - check_mode: true - - - assert: - that: - - create_key_3 is successful - - create_key_3 is changed - - '"deleted_access_key_id" in create_key_3' - - create_key_3.deleted_access_key_id == create_key_1.access_key.access_key_id - - - name: Create a second key - iam_access_key: - user_name: '{{ test_user }}' - state: present - rotate_keys: true - register: create_key_3 - - - assert: - that: - - create_key_3 is successful - - create_key_3 is changed - - '"access_key" in create_key_3' - - '"secret_access_key" in create_key_3' - - '"deleted_access_key_id" in create_key_3' - - create_key_3.deleted_access_key_id == create_key_1.access_key.access_key_id - - '"access_key_id" in create_key_3.access_key' - - '"create_date" in create_key_3.access_key' - - '"user_name" in create_key_3.access_key' - - '"status" in create_key_3.access_key' - - create_key_3.access_key.user_name == test_user - - create_key_3.access_key.status == 'Active' - - - name: Fetch IAM key info (2 keys - oldest rotated) - iam_access_key_info: - user_name: '{{ test_user }}' - register: access_key_info - - - assert: - that: - - access_key_info is successful - - '"access_keys" in access_key_info' - - access_key_info.access_keys | length == 2 - - '"access_key_id" in access_key_1' - - '"create_date" in access_key_1' - - '"user_name" in access_key_1' - - '"status" in access_key_1' - - access_key_1.user_name == test_user - - access_key_1.access_key_id == create_key_2.access_key.access_key_id - - access_key_1.create_date == create_key_2.access_key.create_date - - access_key_1.status == 'Active' - - '"access_key_id" in access_key_2' - - '"create_date" in access_key_2' - - '"user_name" in access_key_2' - - '"status" in access_key_2' - - access_key_2.user_name == test_user - - access_key_2.access_key_id == create_key_3.access_key.access_key_id - - access_key_2.create_date == create_key_3.access_key.create_date - - access_key_2.status == 'Active' - vars: - access_key_1: '{{ access_key_info.access_keys[0] }}' - access_key_2: '{{ access_key_info.access_keys[1] }}' - - # ================================================================================== - - - name: Disable third key (check_mode) - iam_access_key: - user_name: '{{ test_user }}' - id: '{{ create_key_3.access_key.access_key_id }}' - enabled: False - register: disable_key - check_mode: true - - - assert: - that: - - disable_key is successful - - disable_key is changed - - - name: Disable third key - iam_access_key: - user_name: '{{ test_user }}' - id: '{{ create_key_3.access_key.access_key_id }}' - enabled: False - register: disable_key - - - assert: - that: - - disable_key is successful - - disable_key is changed - - '"access_key" in disable_key' - - '"secret_access_key" not in disable_key' - - '"deleted_access_key_id" not in disable_key' - - '"access_key_id" in disable_key.access_key' - - '"create_date" in disable_key.access_key' - - '"user_name" in disable_key.access_key' - - '"status" in disable_key.access_key' - - disable_key.access_key.user_name == test_user - - disable_key.access_key.status == 'Inactive' - - - name: Disable third key - idempotency (check_mode) - iam_access_key: - user_name: '{{ test_user }}' - id: '{{ create_key_3.access_key.access_key_id }}' - enabled: False - register: disable_key - check_mode: true - - - assert: - that: - - disable_key is successful - - disable_key is not changed - - - name: Disable third key - idempotency - iam_access_key: - user_name: '{{ test_user }}' - id: '{{ create_key_3.access_key.access_key_id }}' - enabled: False - register: disable_key - - - assert: - that: - - disable_key is successful - - disable_key is not changed - - '"access_key" in disable_key' - - '"secret_access_key" not in disable_key' - - '"deleted_access_key_id" not in disable_key' - - '"access_key_id" in disable_key.access_key' - - '"create_date" in disable_key.access_key' - - '"user_name" in disable_key.access_key' - - '"status" in disable_key.access_key' - - disable_key.access_key.user_name == test_user - - disable_key.access_key.status == 'Inactive' - - - name: Fetch IAM key info (2 keys - 1 disabled) - iam_access_key_info: - user_name: '{{ test_user }}' - register: access_key_info - - - assert: - that: - - access_key_info is successful - - '"access_keys" in access_key_info' - - access_key_info.access_keys | length == 2 - - '"access_key_id" in access_key_1' - - '"create_date" in access_key_1' - - '"user_name" in access_key_1' - - '"status" in access_key_1' - - access_key_1.user_name == test_user - - access_key_1.access_key_id == create_key_2.access_key.access_key_id - - access_key_1.create_date == create_key_2.access_key.create_date - - access_key_1.status == 'Active' - - '"access_key_id" in access_key_2' - - '"create_date" in access_key_2' - - '"user_name" in access_key_2' - - '"status" in access_key_2' - - access_key_2.user_name == test_user - - access_key_2.access_key_id == create_key_3.access_key.access_key_id - - access_key_2.create_date == create_key_3.access_key.create_date - - access_key_2.status == 'Inactive' - vars: - access_key_1: '{{ access_key_info.access_keys[0] }}' - access_key_2: '{{ access_key_info.access_keys[1] }}' - - # ================================================================================== - - - name: Touch third key - no change (check_mode) - iam_access_key: - user_name: '{{ test_user }}' - id: '{{ create_key_3.access_key.access_key_id }}' - register: touch_key - check_mode: true - - - assert: - that: - - touch_key is successful - - touch_key is not changed - - - name: Touch third key - no change - iam_access_key: - user_name: '{{ test_user }}' - id: '{{ create_key_3.access_key.access_key_id }}' - register: touch_key - - - assert: - that: - - touch_key is successful - - touch_key is not changed - - '"access_key" in touch_key' - - '"secret_access_key" not in touch_key' - - '"deleted_access_key_id" not in touch_key' - - '"access_key_id" in touch_key.access_key' - - '"create_date" in touch_key.access_key' - - '"user_name" in touch_key.access_key' - - '"status" in touch_key.access_key' - - touch_key.access_key.user_name == test_user - - touch_key.access_key.status == 'Inactive' - - # ================================================================================== - - - name: Enable third key (check_mode) - iam_access_key: - user_name: '{{ test_user }}' - id: '{{ create_key_3.access_key.access_key_id }}' - enabled: True - register: enable_key - check_mode: true - - - assert: - that: - - enable_key is successful - - enable_key is changed - - - name: Enable third key - iam_access_key: - user_name: '{{ test_user }}' - id: '{{ create_key_3.access_key.access_key_id }}' - enabled: True - register: enable_key - - - assert: - that: - - enable_key is successful - - enable_key is changed - - '"access_key" in enable_key' - - '"secret_access_key" not in enable_key' - - '"deleted_access_key_id" not in enable_key' - - '"access_key_id" in enable_key.access_key' - - '"create_date" in enable_key.access_key' - - '"user_name" in enable_key.access_key' - - '"status" in enable_key.access_key' - - enable_key.access_key.user_name == test_user - - enable_key.access_key.status == 'Active' - - - name: Enable third key - idempotency (check_mode) - iam_access_key: - user_name: '{{ test_user }}' - id: '{{ create_key_3.access_key.access_key_id }}' - enabled: True - register: enable_key - check_mode: true - - - assert: - that: - - enable_key is successful - - enable_key is not changed - - - name: Enable third key - idempotency - iam_access_key: - user_name: '{{ test_user }}' - id: '{{ create_key_3.access_key.access_key_id }}' - enabled: True - register: enable_key - - - assert: - that: - - enable_key is successful - - enable_key is not changed - - '"access_key" in enable_key' - - '"secret_access_key" not in enable_key' - - '"deleted_access_key_id" not in enable_key' - - '"access_key_id" in enable_key.access_key' - - '"create_date" in enable_key.access_key' - - '"user_name" in enable_key.access_key' - - '"status" in enable_key.access_key' - - enable_key.access_key.user_name == test_user - - enable_key.access_key.status == 'Active' - - # ================================================================================== - - - name: Touch third key again - no change (check_mode) - iam_access_key: - user_name: '{{ test_user }}' - id: '{{ create_key_3.access_key.access_key_id }}' - register: touch_key - check_mode: true - - - assert: - that: - - touch_key is successful - - touch_key is not changed - - - name: Touch third key again - no change - iam_access_key: - user_name: '{{ test_user }}' - id: '{{ create_key_3.access_key.access_key_id }}' - register: touch_key - - - assert: - that: - - touch_key is successful - - touch_key is not changed - - '"access_key" in touch_key' - - '"secret_access_key" not in touch_key' - - '"deleted_access_key_id" not in touch_key' - - '"access_key_id" in touch_key.access_key' - - '"create_date" in touch_key.access_key' - - '"user_name" in touch_key.access_key' - - '"status" in touch_key.access_key' - - touch_key.access_key.user_name == test_user - - touch_key.access_key.status == 'Active' - - # ================================================================================== - - - name: Re-Disable third key - iam_access_key: - user_name: '{{ test_user }}' - id: '{{ create_key_3.access_key.access_key_id }}' - enabled: False - register: redisable_key - - - assert: - that: - - redisable_key is successful - - redisable_key is changed - - redisable_key.access_key.status == 'Inactive' - - - pause: - seconds: 10 - - # ================================================================================== - - - name: Test GetCallerIdentity - Key 2 - aws_caller_info: - access_key: "{{ create_key_2.access_key.access_key_id }}" - secret_key: "{{ create_key_2.secret_access_key }}" - session_token: "{{ omit }}" - register: caller_identity_2 - - - assert: - that: - - caller_identity_2 is successful - - caller_identity_2.arn == iam_user.iam_user.user.arn - - - name: Test GetCallerIdentity - Key 1 (gone) - aws_caller_info: - access_key: "{{ create_key_1.access_key.access_key_id }}" - secret_key: "{{ create_key_1.secret_access_key }}" - session_token: "{{ omit }}" - register: caller_identity_1 - ignore_errors: true - - - assert: - that: - - caller_identity_1 is failed - - caller_identity_1.error.code == 'InvalidClientTokenId' - - - name: Test GetCallerIdentity - Key 3 (disabled) - aws_caller_info: - access_key: "{{ create_key_3.access_key.access_key_id }}" - secret_key: "{{ create_key_3.secret_access_key }}" - session_token: "{{ omit }}" - register: caller_identity_3 - ignore_errors: true - - - assert: - that: - - caller_identity_3 is failed - - caller_identity_3.error.code == 'InvalidClientTokenId' - - # ================================================================================== - - - name: Delete active key (check_mode) - iam_access_key: - user_name: '{{ test_user }}' - id: '{{ create_key_2.access_key.access_key_id }}' - state: absent - register: delete_active_key - check_mode: true - - - assert: - that: - - delete_active_key is successful - - delete_active_key is changed - - - name: Delete active key - iam_access_key: - user_name: '{{ test_user }}' - id: '{{ create_key_2.access_key.access_key_id }}' - state: absent - register: delete_active_key - - - assert: - that: - - delete_active_key is successful - - delete_active_key is changed - - - name: Delete active key - idempotency (check_mode) - iam_access_key: - user_name: '{{ test_user }}' - id: '{{ create_key_2.access_key.access_key_id }}' - state: absent - register: delete_active_key - check_mode: true - - - assert: - that: - - delete_active_key is successful - - delete_active_key is not changed - - - name: Delete active key - idempotency - iam_access_key: - user_name: '{{ test_user }}' - id: '{{ create_key_2.access_key.access_key_id }}' - state: absent - register: delete_active_key - - - assert: - that: - - delete_active_key is successful - - delete_active_key is not changed - - # ================================================================================== - - - name: Delete inactive key (check_mode) - iam_access_key: - user_name: '{{ test_user }}' - id: '{{ create_key_3.access_key.access_key_id }}' - state: absent - register: delete_inactive_key - check_mode: true - - - assert: - that: - - delete_inactive_key is successful - - delete_inactive_key is changed - - - name: Delete inactive key - iam_access_key: - user_name: '{{ test_user }}' - id: '{{ create_key_3.access_key.access_key_id }}' - state: absent - register: delete_inactive_key - - - assert: - that: - - delete_inactive_key is successful - - delete_inactive_key is changed - - - name: Delete inactive key - idempotency (check_mode) - iam_access_key: - user_name: '{{ test_user }}' - id: '{{ create_key_3.access_key.access_key_id }}' - state: absent - register: delete_inactive_key - check_mode: true - - - assert: - that: - - delete_inactive_key is successful - - delete_inactive_key is not changed - - - name: Delete inactive key - idempotency - iam_access_key: - user_name: '{{ test_user }}' - id: '{{ create_key_3.access_key.access_key_id }}' - state: absent - register: delete_inactive_key - - - assert: - that: - - delete_inactive_key is successful - - delete_inactive_key is not changed - - # ================================================================================== - - - name: Fetch IAM key info (no keys) - iam_access_key_info: - user_name: '{{ test_user }}' - register: access_key_info - - - assert: - that: - - access_key_info is successful - - '"access_keys" in access_key_info' - - access_key_info.access_keys | length == 0 - - # ================================================================================== - - - name: Create an inactive key (check_mode) - iam_access_key: - user_name: '{{ test_user }}' - state: present - enabled: false - register: create_key_4 - check_mode: true - - - assert: - that: - - create_key_4 is successful - - create_key_4 is changed - - - name: Create a key - iam_access_key: - user_name: '{{ test_user }}' - state: present - enabled: false - register: create_key_4 - - - assert: - that: - - create_key_4 is successful - - create_key_4 is changed - - '"access_key" in create_key_4' - - '"secret_access_key" in create_key_4' - - '"deleted_access_key_id" not in create_key_4' - - '"access_key_id" in create_key_4.access_key' - - '"create_date" in create_key_4.access_key' - - '"user_name" in create_key_4.access_key' - - '"status" in create_key_4.access_key' - - create_key_4.access_key.user_name == test_user - - create_key_4.access_key.status == 'Inactive' - - - name: Fetch IAM key info (1 inactive key) - iam_access_key_info: - user_name: '{{ test_user }}' - register: access_key_info - - - assert: - that: - - access_key_info is successful - - '"access_keys" in access_key_info' - - access_key_info.access_keys | length == 1 - - '"access_key_id" in access_key_1' - - '"create_date" in access_key_1' - - '"user_name" in access_key_1' - - '"status" in access_key_1' - - access_key_1.user_name == test_user - - access_key_1.access_key_id == create_key_4.access_key.access_key_id - - access_key_1.create_date == create_key_4.access_key.create_date - - access_key_1.status == 'Inactive' - vars: - access_key_1: '{{ access_key_info.access_keys[0] }}' - - # We already tested the idempotency of disabling keys, use this to verify that - # the key is disabled - - name: Disable new key - iam_access_key: - user_name: '{{ test_user }}' - id: '{{ create_key_4.access_key.access_key_id }}' - enabled: False - register: disable_new_key - - - assert: - that: - - disable_new_key is successful - - disable_new_key is not changed - - '"access_key" in disable_new_key' - - # ================================================================================== - # Cleanup - - - name: Delete new key - iam_access_key: - user_name: '{{ test_user }}' - id: '{{ create_key_4.access_key.access_key_id }}' - state: absent - register: delete_new_key - - - assert: - that: - - delete_new_key is successful - - delete_new_key is changed - - - name: Remove test user - iam_user: - name: '{{ test_user }}' - state: absent - register: delete_user - - - assert: - that: - - delete_user is successful - - delete_user is changed - - always: - - - name: Remove test user - iam_user: - name: '{{ test_user }}' - state: absent - ignore_errors: yes