From 91050042f8b2aed2713d7363252bb57dba0a9d63 Mon Sep 17 00:00:00 2001 From: jillr Date: Mon, 2 Mar 2020 19:25:18 +0000 Subject: [PATCH 001/129] Initial commit This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/eb75681585a23ea79e642b86a0f8e64e0f40a6d7 --- plugins/modules/iam_mfa_device_info.py | 117 +++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 plugins/modules/iam_mfa_device_info.py diff --git a/plugins/modules/iam_mfa_device_info.py b/plugins/modules/iam_mfa_device_info.py new file mode 100644 index 00000000000..712a951a5d9 --- /dev/null +++ b/plugins/modules/iam_mfa_device_info.py @@ -0,0 +1,117 @@ +#!/usr/bin/python +# Copyright: Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'community'} + + +DOCUMENTATION = ''' +--- +module: iam_mfa_device_info +short_description: List the MFA (Multi-Factor Authentication) devices registered for a user +description: + - List the MFA (Multi-Factor Authentication) devices registered for a user + - This module was called C(iam_mfa_device_facts) before Ansible 2.9. The usage did not change. +author: Victor Costan (@pwnall) +options: + user_name: + description: + - The name of the user whose MFA devices will be listed + type: str +extends_documentation_fragment: +- ansible.amazon.aws +- ansible.amazon.ec2 + +requirements: + - boto3 + - botocore +''' + +RETURN = """ +mfa_devices: + description: The MFA devices registered for the given user + returned: always + type: list + sample: + - enable_date: "2016-03-11T23:25:36+00:00" + serial_number: arn:aws:iam::085120003701:mfa/pwnall + user_name: pwnall + - enable_date: "2016-03-11T23:25:37+00:00" + serial_number: arn:aws:iam::085120003702:mfa/pwnall + user_name: pwnall +""" + +EXAMPLES = ''' +# Note: These examples do not set authentication details, see the AWS Guide for details. + +# List MFA devices (more details: https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListMFADevices.html) +- iam_mfa_device_info: + register: mfa_devices + +# Assume an existing role (more details: https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html) +- sts_assume_role: + mfa_serial_number: "{{ mfa_devices.mfa_devices[0].serial_number }}" + role_arn: "arn:aws:iam::123456789012:role/someRole" + role_session_name: "someRoleSession" + register: assumed_role +''' + +try: + import boto3 + from botocore.exceptions import ClientError + HAS_BOTO3 = True +except ImportError: + HAS_BOTO3 = False + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.ansible.amazon.plugins.module_utils.ec2 import (HAS_BOTO3, boto3_conn, camel_dict_to_snake_dict, ec2_argument_spec, + get_aws_connection_info) + + +def list_mfa_devices(connection, module): + user_name = module.params.get('user_name') + changed = False + + args = {} + if user_name is not None: + args['UserName'] = user_name + try: + response = connection.list_mfa_devices(**args) + except ClientError as e: + module.fail_json(msg=e.message, **camel_dict_to_snake_dict(e.response)) + + module.exit_json(changed=changed, **camel_dict_to_snake_dict(response)) + + +def main(): + argument_spec = ec2_argument_spec() + argument_spec.update( + dict( + user_name=dict(required=False, default=None) + ) + ) + + module = AnsibleModule(argument_spec=argument_spec) + if module._name == 'iam_mfa_device_facts': + module.deprecate("The 'iam_mfa_device_facts' module has been renamed to 'iam_mfa_device_info'", version='2.13') + + if not HAS_BOTO3: + module.fail_json(msg='boto3 required for this module') + + region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True) + if region: + connection = boto3_conn(module, conn_type='client', resource='iam', region=region, endpoint=ec2_url, **aws_connect_kwargs) + else: + module.fail_json(msg="region must be specified") + + list_mfa_devices(connection, module) + + +if __name__ == '__main__': + main() From 1a4da2c6759f477b5728c91c00f13cc6f80406c9 Mon Sep 17 00:00:00 2001 From: jillr Date: Tue, 3 Mar 2020 19:43:21 +0000 Subject: [PATCH 002/129] migration test cleanup This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/13b104b912784bb31a0bff23eed4c27b0f5e0283 --- plugins/modules/iam_mfa_device_info.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/plugins/modules/iam_mfa_device_info.py b/plugins/modules/iam_mfa_device_info.py index 712a951a5d9..6f7b9f1e3da 100644 --- a/plugins/modules/iam_mfa_device_info.py +++ b/plugins/modules/iam_mfa_device_info.py @@ -70,8 +70,12 @@ HAS_BOTO3 = False from ansible.module_utils.basic import AnsibleModule -from ansible_collections.ansible.amazon.plugins.module_utils.ec2 import (HAS_BOTO3, boto3_conn, camel_dict_to_snake_dict, ec2_argument_spec, - get_aws_connection_info) +from ansible_collections.ansible.amazon.plugins.module_utils.ec2 import (HAS_BOTO3, + boto3_conn, + camel_dict_to_snake_dict, + ec2_argument_spec, + get_aws_connection_info, + ) def list_mfa_devices(connection, module): From f0a2030250a16c1a846226d88f63518d327c8f7f Mon Sep 17 00:00:00 2001 From: Jill R <4121322+jillr@users.noreply.github.com> Date: Wed, 25 Mar 2020 15:39:40 -0700 Subject: [PATCH 003/129] Rename collection (#12) * Rename core collection Rename references to ansible.amazon to amazon.aws. * Rename community.amazon to community.aws Fix pep8 line lengths for rewritten amazon.aws imports * Missed a path in shippable.sh * Dependency repos moved This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/235c5db571cc45db5839476c94356c9b91e1f228 --- plugins/modules/iam_mfa_device_info.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/modules/iam_mfa_device_info.py b/plugins/modules/iam_mfa_device_info.py index 6f7b9f1e3da..12dae087a70 100644 --- a/plugins/modules/iam_mfa_device_info.py +++ b/plugins/modules/iam_mfa_device_info.py @@ -25,8 +25,8 @@ - The name of the user whose MFA devices will be listed type: str extends_documentation_fragment: -- ansible.amazon.aws -- ansible.amazon.ec2 +- amazon.aws.aws +- amazon.aws.ec2 requirements: - boto3 @@ -70,12 +70,12 @@ HAS_BOTO3 = False from ansible.module_utils.basic import AnsibleModule -from ansible_collections.ansible.amazon.plugins.module_utils.ec2 import (HAS_BOTO3, - boto3_conn, - camel_dict_to_snake_dict, - ec2_argument_spec, - get_aws_connection_info, - ) +from ansible_collections.amazon.aws.plugins.module_utils.ec2 import (HAS_BOTO3, + boto3_conn, + camel_dict_to_snake_dict, + ec2_argument_spec, + get_aws_connection_info, + ) def list_mfa_devices(connection, module): From 4ab93ff81a88f0aa51b9ba0e8932a93cb49dbff3 Mon Sep 17 00:00:00 2001 From: Jill R <4121322+jillr@users.noreply.github.com> Date: Tue, 19 May 2020 16:06:12 -0700 Subject: [PATCH 004/129] Remove METADATA and cleanup galaxy.yml (#70) * Remove ANSIBLE_METADATA entirely, see ansible/ansible/pull/69454. Remove `license` field from galaxy.yml, in favor of `license_file`. This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/05672a64e2362cc2d865b5af6a57da6bc3cd08e3 --- plugins/modules/iam_mfa_device_info.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/plugins/modules/iam_mfa_device_info.py b/plugins/modules/iam_mfa_device_info.py index 12dae087a70..2431a57c063 100644 --- a/plugins/modules/iam_mfa_device_info.py +++ b/plugins/modules/iam_mfa_device_info.py @@ -6,11 +6,6 @@ __metaclass__ = type -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - DOCUMENTATION = ''' --- module: iam_mfa_device_info From e763c8ff420533e81b6c9b6d1a098ad1b5c88502 Mon Sep 17 00:00:00 2001 From: Jill R <4121322+jillr@users.noreply.github.com> Date: Tue, 16 Jun 2020 11:23:52 -0700 Subject: [PATCH 005/129] Collections related fixes for CI (#96) * Update module deprecations Switch version to `removed_at_date` * Don't install amazon.aws from galaxy We've been using galaxy to install amazon.aws in shippable, but that doesn't really work if we aren't publising faster. Get that collection from git so it is most up to date. * We need to declare python test deps now * missed a python dep This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/7cd211e9383db26bc2aa4cc06e657cf60ed0acc0 --- plugins/modules/iam_mfa_device_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/iam_mfa_device_info.py b/plugins/modules/iam_mfa_device_info.py index 2431a57c063..bb59d8d8177 100644 --- a/plugins/modules/iam_mfa_device_info.py +++ b/plugins/modules/iam_mfa_device_info.py @@ -98,7 +98,7 @@ def main(): module = AnsibleModule(argument_spec=argument_spec) if module._name == 'iam_mfa_device_facts': - module.deprecate("The 'iam_mfa_device_facts' module has been renamed to 'iam_mfa_device_info'", version='2.13') + module.deprecate("The 'iam_mfa_device_facts' module has been renamed to 'iam_mfa_device_info'", date='2021-12-01', collection_name='community.aws') if not HAS_BOTO3: module.fail_json(msg='boto3 required for this module') From cc731da18258fb8a191545166b54fca7ac18d1f5 Mon Sep 17 00:00:00 2001 From: Abhijeet Kasurde Date: Wed, 17 Jun 2020 01:24:54 +0530 Subject: [PATCH 006/129] Update Examples with FQCN (#67) Updated module examples with FQCN Signed-off-by: Abhijeet Kasurde This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/98173aefbbceed7fc0d9db62687b73f96a55a999 --- plugins/modules/iam_mfa_device_info.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/plugins/modules/iam_mfa_device_info.py b/plugins/modules/iam_mfa_device_info.py index bb59d8d8177..07e98d6851c 100644 --- a/plugins/modules/iam_mfa_device_info.py +++ b/plugins/modules/iam_mfa_device_info.py @@ -42,15 +42,17 @@ user_name: pwnall """ -EXAMPLES = ''' +EXAMPLES = r''' # Note: These examples do not set authentication details, see the AWS Guide for details. -# List MFA devices (more details: https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListMFADevices.html) -- iam_mfa_device_info: +# more details: https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListMFADevices.html +- name: List MFA devices + community.aws.iam_mfa_device_info: register: mfa_devices -# Assume an existing role (more details: https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html) -- sts_assume_role: +# more details: https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html +- name: Assume an existing role + community.aws.sts_assume_role: mfa_serial_number: "{{ mfa_devices.mfa_devices[0].serial_number }}" role_arn: "arn:aws:iam::123456789012:role/someRole" role_session_name: "someRoleSession" From a518f55bc5cc2c82d328e9e89440a2276d9607f0 Mon Sep 17 00:00:00 2001 From: Jill R <4121322+jillr@users.noreply.github.com> Date: Wed, 17 Jun 2020 09:31:32 -0700 Subject: [PATCH 007/129] Update docs (#99) * Update docs Remove .git from repo url so links in readme will generate correctly Add required ansible version Run latest version of add_docs.py Add version_added string to modules * galaxy.yml was missing authors This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/96ee268e5267f5b12c3d59892bc1279f75aa3135 --- plugins/modules/iam_mfa_device_info.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/modules/iam_mfa_device_info.py b/plugins/modules/iam_mfa_device_info.py index 07e98d6851c..f8c37a91acf 100644 --- a/plugins/modules/iam_mfa_device_info.py +++ b/plugins/modules/iam_mfa_device_info.py @@ -9,6 +9,7 @@ DOCUMENTATION = ''' --- module: iam_mfa_device_info +version_added: 1.0.0 short_description: List the MFA (Multi-Factor Authentication) devices registered for a user description: - List the MFA (Multi-Factor Authentication) devices registered for a user From c71dbe40c5e2041a083ec4b7363c28fc9d96bda8 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Wed, 12 Aug 2020 13:06:35 +0200 Subject: [PATCH 008/129] Bulk migration to AnsibleAWSModule (#173) * Update comments to reference AnsibleAWSModule rather than AnsibleModule * Bulk re-order imports and split onto one from import per-line. * Add AnsibleAWSModule imports * Migrate boto 2 based modules to AnsibleAWSModule * Move boto3-only modules over to AnsibleAWSModule * Remove extra ec2_argument_spec calls - not needed now we're using AnsibleAWSModule * Remove most HAS_BOTO3 code, it's handled by AnsibleAWSModule * Handle missing Boto 2 consistently (HAS_BOTO) * Remove AnsibleModule imports * Changelog fragment This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/818c6d2faa046974a9bdfa9346122d11e5bef3b1 --- plugins/modules/iam_mfa_device_info.py | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/plugins/modules/iam_mfa_device_info.py b/plugins/modules/iam_mfa_device_info.py index f8c37a91acf..727242751a6 100644 --- a/plugins/modules/iam_mfa_device_info.py +++ b/plugins/modules/iam_mfa_device_info.py @@ -63,17 +63,13 @@ try: import boto3 from botocore.exceptions import ClientError - HAS_BOTO3 = True except ImportError: - HAS_BOTO3 = False + pass # Handled by AnsibleAWSModule -from ansible.module_utils.basic import AnsibleModule -from ansible_collections.amazon.aws.plugins.module_utils.ec2 import (HAS_BOTO3, - boto3_conn, - camel_dict_to_snake_dict, - ec2_argument_spec, - get_aws_connection_info, - ) +from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule +from ansible_collections.amazon.aws.plugins.module_utils.ec2 import boto3_conn +from ansible_collections.amazon.aws.plugins.module_utils.ec2 import camel_dict_to_snake_dict +from ansible_collections.amazon.aws.plugins.module_utils.ec2 import get_aws_connection_info def list_mfa_devices(connection, module): @@ -92,20 +88,14 @@ def list_mfa_devices(connection, module): def main(): - argument_spec = ec2_argument_spec() - argument_spec.update( - dict( - user_name=dict(required=False, default=None) - ) + argument_spec = dict( + user_name=dict(required=False, default=None), ) - module = AnsibleModule(argument_spec=argument_spec) + module = AnsibleAWSModule(argument_spec=argument_spec) if module._name == 'iam_mfa_device_facts': module.deprecate("The 'iam_mfa_device_facts' module has been renamed to 'iam_mfa_device_info'", date='2021-12-01', collection_name='community.aws') - if not HAS_BOTO3: - module.fail_json(msg='boto3 required for this module') - region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True) if region: connection = boto3_conn(module, conn_type='client', resource='iam', region=region, endpoint=ec2_url, **aws_connect_kwargs) From 38f6e64137dd843a235a2ba401aadbe9f3ccb0bf Mon Sep 17 00:00:00 2001 From: Vincent Vinet Date: Sat, 15 Aug 2020 09:11:59 -0400 Subject: [PATCH 009/129] =?UTF-8?q?Python=203=20compatibility=20error=20ha?= =?UTF-8?q?ndling:=20use=20to=5Fnative(e)=20instead=20of=20str(e)=20or=20e?= =?UTF-8?q?.me=E2=80=A6=20(#26)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Py3 compat error handling: use to_native(e) instead of str(e) or e.message * PR comment changes, use fail_json_aws and is_boto3_error_code This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/ffe14f95186399dc080019554035021015765872 --- plugins/modules/iam_mfa_device_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/iam_mfa_device_info.py b/plugins/modules/iam_mfa_device_info.py index 727242751a6..c107c39f67b 100644 --- a/plugins/modules/iam_mfa_device_info.py +++ b/plugins/modules/iam_mfa_device_info.py @@ -82,7 +82,7 @@ def list_mfa_devices(connection, module): try: response = connection.list_mfa_devices(**args) except ClientError as e: - module.fail_json(msg=e.message, **camel_dict_to_snake_dict(e.response)) + module.fail_json_aws(e, msg="Failed to list MFA devices") module.exit_json(changed=changed, **camel_dict_to_snake_dict(response)) From 8d35a03cfbc096adbff5b42f3c7ac702fdf24d97 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Wed, 26 Aug 2020 11:35:32 +0200 Subject: [PATCH 010/129] Cleanup: Bulk Migration from boto3_conn to module.client() (#188) * Migrate from boto3_conn to module.client * Simplify error handling when creating connections * Simplify Region handling * Remove unused imports * Changelog This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/6bdf00d2198927bdaa119ae76ddd379a8b6eeb3d --- plugins/modules/iam_mfa_device_info.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/plugins/modules/iam_mfa_device_info.py b/plugins/modules/iam_mfa_device_info.py index c107c39f67b..c79afab095f 100644 --- a/plugins/modules/iam_mfa_device_info.py +++ b/plugins/modules/iam_mfa_device_info.py @@ -62,14 +62,13 @@ try: import boto3 + import botocore from botocore.exceptions import ClientError except ImportError: pass # Handled by AnsibleAWSModule from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule -from ansible_collections.amazon.aws.plugins.module_utils.ec2 import boto3_conn from ansible_collections.amazon.aws.plugins.module_utils.ec2 import camel_dict_to_snake_dict -from ansible_collections.amazon.aws.plugins.module_utils.ec2 import get_aws_connection_info def list_mfa_devices(connection, module): @@ -96,11 +95,10 @@ def main(): if module._name == 'iam_mfa_device_facts': module.deprecate("The 'iam_mfa_device_facts' module has been renamed to 'iam_mfa_device_info'", date='2021-12-01', collection_name='community.aws') - region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True) - if region: - connection = boto3_conn(module, conn_type='client', resource='iam', region=region, endpoint=ec2_url, **aws_connect_kwargs) - else: - module.fail_json(msg="region must be specified") + try: + connection = module.client('iam') + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: + module.fail_json_aws(e, msg='Failed to connect to AWS') list_mfa_devices(connection, module) From 05858c283370288276fe40b045ea4a1ce924bdb2 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Sat, 16 Jan 2021 10:50:49 +0100 Subject: [PATCH 011/129] Bulk import cleanup (#360) * Split imports and reorder * Import camel_dict_to_snake_dict and snake_dict_to_camel_dict direct from ansible.module_utils.common.dict_transformations * Remove unused imports * Route53 Info was migrated to Boto3 drop the HAS_BOTO check and import * changelog This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/130cf3cc5980014020632f19fdab79c9bcf28add --- plugins/modules/iam_mfa_device_info.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/modules/iam_mfa_device_info.py b/plugins/modules/iam_mfa_device_info.py index c79afab095f..e86687134a9 100644 --- a/plugins/modules/iam_mfa_device_info.py +++ b/plugins/modules/iam_mfa_device_info.py @@ -61,14 +61,14 @@ ''' try: - import boto3 import botocore from botocore.exceptions import ClientError except ImportError: pass # Handled by AnsibleAWSModule +from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict + from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule -from ansible_collections.amazon.aws.plugins.module_utils.ec2 import camel_dict_to_snake_dict def list_mfa_devices(connection, module): From d22ff45b59c586f08f1efaf1207dcf319d49fe86 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Thu, 6 May 2021 21:01:46 +0200 Subject: [PATCH 012/129] Update the default module requirements from python 2.6/boto to python 3.6/boto3 This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/c097c55293be0834a2b9d394733ec28965d142d7 --- plugins/modules/iam_mfa_device_info.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/plugins/modules/iam_mfa_device_info.py b/plugins/modules/iam_mfa_device_info.py index e86687134a9..b04b912549c 100644 --- a/plugins/modules/iam_mfa_device_info.py +++ b/plugins/modules/iam_mfa_device_info.py @@ -23,10 +23,6 @@ extends_documentation_fragment: - amazon.aws.aws - amazon.aws.ec2 - -requirements: - - boto3 - - botocore ''' RETURN = """ From 18abdc3df2b6ef6ec63eb14813dbf4504d9c9c98 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Wed, 28 Jul 2021 08:47:51 +0200 Subject: [PATCH 013/129] Update remaining _info modules so that they run in check_mode https://github.com/ansible-collections/overview/blob/main/collection_requirements.rst#development-conventions https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_best_practices.html#following-ansible-conventions https://github.com/ansible/ansible/pull/75324 fixes: https://github.com/ansible-collections/community.aws/issues/659 This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/8081e69daacab87c334497782579d2f0de08f63d --- plugins/modules/iam_mfa_device_info.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/modules/iam_mfa_device_info.py b/plugins/modules/iam_mfa_device_info.py index b04b912549c..78cfe8249d0 100644 --- a/plugins/modules/iam_mfa_device_info.py +++ b/plugins/modules/iam_mfa_device_info.py @@ -87,7 +87,10 @@ def main(): user_name=dict(required=False, default=None), ) - module = AnsibleAWSModule(argument_spec=argument_spec) + module = AnsibleAWSModule( + argument_spec=argument_spec, + supports_check_mode=True, + ) if module._name == 'iam_mfa_device_facts': module.deprecate("The 'iam_mfa_device_facts' module has been renamed to 'iam_mfa_device_info'", date='2021-12-01', collection_name='community.aws') From 84094fef7823b99182c6ddd563884410710252a3 Mon Sep 17 00:00:00 2001 From: Jill R <4121322+jillr@users.noreply.github.com> Date: Thu, 2 Dec 2021 02:58:06 -0700 Subject: [PATCH 014/129] Remove deprecated "facts" aliases (#814) Remove deprecated "facts" aliases SUMMARY Modules named "facts.py" that do not return ansible_facts were renamed to "info.py" in 2.9. Remove these aliases now that the deprecation period is over. This PR should be included in 3.0.0 of the collection. ISSUE TYPE Bugfix Pull Request COMPONENT NAME *_facts.py Reviewed-by: Mark Chappell Reviewed-by: Jill R Reviewed-by: None This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/68aaa7057be46a3ab36f572fd0013d64653af909 --- plugins/modules/iam_mfa_device_info.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugins/modules/iam_mfa_device_info.py b/plugins/modules/iam_mfa_device_info.py index 78cfe8249d0..4cd27875273 100644 --- a/plugins/modules/iam_mfa_device_info.py +++ b/plugins/modules/iam_mfa_device_info.py @@ -13,7 +13,6 @@ short_description: List the MFA (Multi-Factor Authentication) devices registered for a user description: - List the MFA (Multi-Factor Authentication) devices registered for a user - - This module was called C(iam_mfa_device_facts) before Ansible 2.9. The usage did not change. author: Victor Costan (@pwnall) options: user_name: @@ -91,8 +90,6 @@ def main(): argument_spec=argument_spec, supports_check_mode=True, ) - if module._name == 'iam_mfa_device_facts': - module.deprecate("The 'iam_mfa_device_facts' module has been renamed to 'iam_mfa_device_info'", date='2021-12-01', collection_name='community.aws') try: connection = module.client('iam') From 8f925558d6c252cd75fcd2a98b4b0b47f7378ee9 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Wed, 28 Sep 2022 13:40:43 +0200 Subject: [PATCH 015/129] Make example AWS UUIDS follow a specific pattern (#1539) Make example AWS UUIDS follow a specific pattern SUMMARY Various AWS IAM resources have UUID which follow a specific pattern. Similarly AWS accounts are all 12 digit numbers (text aliases in a couple of cases). To minimize the risk of accidental data leaks use a consistent Account ID in examples (123456789012), and a specific format for the UUIDS: (AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)12345EXAMPLE54321 While this does nothing about historic data, having consistency makes it easier to prevent future leaks. Note: We should follow this up with an update to the developer docs, however I'd like to get this in prior to 5.0.0 ISSUE TYPE Docs Pull Request COMPONENT NAME plugins/modules/acm_certificate_info.py plugins/modules/application_autoscaling_policy.py plugins/modules/autoscaling_launch_config.py plugins/modules/autoscaling_launch_config_info.py plugins/modules/codecommit_repository.py plugins/modules/directconnect_link_aggregation_group.py plugins/modules/dms_endpoint.py plugins/modules/dynamodb_table.py plugins/modules/ec2_transit_gateway_info.py plugins/modules/ec2_transit_gateway_vpc_attachment.py plugins/modules/ec2_transit_gateway_vpc_attachment_info.py plugins/modules/ec2_vpc_peer.py plugins/modules/ec2_vpc_peering_info.py plugins/modules/ec2_vpc_vpn_info.py plugins/modules/ecs_cluster.py plugins/modules/ecs_ecr.py plugins/modules/ecs_service.py plugins/modules/ecs_service_info.py plugins/modules/ecs_task.py plugins/modules/efs.py plugins/modules/efs_info.py plugins/modules/eks_cluster.py plugins/modules/elasticache_subnet_group.py plugins/modules/elb_network_lb.py plugins/modules/elb_target_group.py plugins/modules/elb_target_group_info.py plugins/modules/elb_target_info.py plugins/modules/iam_group.py plugins/modules/iam_managed_policy.py plugins/modules/iam_mfa_device_info.py plugins/modules/iam_server_certificate_info.py plugins/modules/lightsail.py plugins/modules/lightsail_static_ip.py plugins/modules/msk_cluster.py plugins/modules/s3_bucket_notification.py plugins/modules/sns_topic.py plugins/modules/sns_topic_info.py plugins/modules/sqs_queue.py plugins/modules/stepfunctions_state_machine.py plugins/modules/stepfunctions_state_machine_execution.py plugins/modules/storagegateway_info.py plugins/modules/wafv2_web_acl.py ADDITIONAL INFORMATION While the 'secret' nature of these UUIDs is debatable (they're closer to user names than passwords), deliberately mangling them makes it easier for InfoSec teams to spot when their secret counterparts may have been leaked in combination with a real 'public' part. This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/94764225332c869eefa574a8948da680bb668407 --- plugins/modules/iam_mfa_device_info.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/modules/iam_mfa_device_info.py b/plugins/modules/iam_mfa_device_info.py index 4cd27875273..a2801ca9482 100644 --- a/plugins/modules/iam_mfa_device_info.py +++ b/plugins/modules/iam_mfa_device_info.py @@ -31,11 +31,11 @@ type: list sample: - enable_date: "2016-03-11T23:25:36+00:00" - serial_number: arn:aws:iam::085120003701:mfa/pwnall - user_name: pwnall + serial_number: arn:aws:iam::123456789012:mfa/example + user_name: example - enable_date: "2016-03-11T23:25:37+00:00" - serial_number: arn:aws:iam::085120003702:mfa/pwnall - user_name: pwnall + serial_number: arn:aws:iam::123456789012:mfa/example + user_name: example """ EXAMPLES = r''' From 2f2254019b61e1e8187101f9a0e798abc2d28c5f Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Wed, 5 Oct 2022 17:04:40 +0200 Subject: [PATCH 016/129] Update extends_documentation_fragment with amazon.aws.boto3 (#1459) Update extends_documentation_fragment with amazon.aws.boto3 Depends-On: ansible/ansible-zuul-jobs#1654 SUMMARY As per ansible-collections/amazon.aws#985 add amazon.aws.boto3. ISSUE TYPE Docs Pull Request COMPONENT NAME several Reviewed-by: Jill R Reviewed-by: Mark Chappell Reviewed-by: Markus Bergholz This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/bd3c03fcba0848f593b86309740fa73e986a9646 --- plugins/modules/iam_mfa_device_info.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/modules/iam_mfa_device_info.py b/plugins/modules/iam_mfa_device_info.py index a2801ca9482..16abae17087 100644 --- a/plugins/modules/iam_mfa_device_info.py +++ b/plugins/modules/iam_mfa_device_info.py @@ -22,6 +22,7 @@ extends_documentation_fragment: - amazon.aws.aws - amazon.aws.ec2 +- amazon.aws.boto3 ''' RETURN = """ From 5ad3dbed4018e036f984a6125910483b45ab8bed Mon Sep 17 00:00:00 2001 From: Bikouo Aubin <79859644+abikouo@users.noreply.github.com> Date: Tue, 10 Jan 2023 19:22:13 +0100 Subject: [PATCH 017/129] Ansible User-Agent identification for community.aws (#1632) Ansible User-Agent identification for community.aws SUMMARY The value will be similar to this APN/1.0 Ansible/2.14.1 community.aws/6.0.0-dev0 ISSUE TYPE Feature Pull Request Reviewed-by: Mark Chappell Reviewed-by: Bikouo Aubin Reviewed-by: Alina Buzachis This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/a8cbce24071bcc62fe4594c38aff1baf18bd2862 --- plugins/modules/iam_mfa_device_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/iam_mfa_device_info.py b/plugins/modules/iam_mfa_device_info.py index 16abae17087..8b78eee02f9 100644 --- a/plugins/modules/iam_mfa_device_info.py +++ b/plugins/modules/iam_mfa_device_info.py @@ -64,7 +64,7 @@ from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict -from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule +from ansible_collections.community.aws.plugins.module_utils.modules import AnsibleCommunityAWSModule as AnsibleAWSModule def list_mfa_devices(connection, module): From d4e1904b78013308cbede88e2a976ed8b1f9257c Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Wed, 8 Mar 2023 12:07:26 +0100 Subject: [PATCH 018/129] Cleanup headers and imports (#1738) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cleanup headers and imports SUMMARY Mass update of imports, docs fragments and file headers Many of the amazon.aws module_utils and docs fragments got moved about, update community.aws to reflect this. Consistently apply the comment headers as documented at https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_documenting.html#python-shebang-utf-8-coding ISSUE TYPE Docs Pull Request Feature Pull Request COMPONENT NAME ADDITIONAL INFORMATION Header cleanup based upon: https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_documenting.html#python-shebang-utf-8-coding Begin your Ansible module with #!/usr/bin/python - this “shebang” allows ansible_python_interpreter to work. Follow the shebang immediately with # -*- coding: utf-8 -*- to clarify that the file is UTF-8 encoded. and https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_documenting.html#copyright-and-license After the shebang and UTF-8 coding, add a copyright line with the original copyright holder and a license declaration. The license declaration should be ONLY one line, not the full GPL prefix. ... Additions to the module (for instance, rewrites) are not permitted to add additional copyright lines other than the default copyright statement if missing: Reviewed-by: Alina Buzachis This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/a4f20bf114bfab19b1c84c4ecf42efd5614ab80c --- plugins/modules/iam_mfa_device_info.py | 27 +++++++++++++------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/plugins/modules/iam_mfa_device_info.py b/plugins/modules/iam_mfa_device_info.py index 8b78eee02f9..c0c434a9be9 100644 --- a/plugins/modules/iam_mfa_device_info.py +++ b/plugins/modules/iam_mfa_device_info.py @@ -1,31 +1,30 @@ #!/usr/bin/python +# -*- coding: utf-8 -*- + # Copyright: Ansible Project # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -from __future__ import absolute_import, division, print_function -__metaclass__ = type - - -DOCUMENTATION = ''' +DOCUMENTATION = r""" --- module: iam_mfa_device_info version_added: 1.0.0 short_description: List the MFA (Multi-Factor Authentication) devices registered for a user description: - - List the MFA (Multi-Factor Authentication) devices registered for a user -author: Victor Costan (@pwnall) + - List the MFA (Multi-Factor Authentication) devices registered for a user +author: + - Victor Costan (@pwnall) options: user_name: description: - The name of the user whose MFA devices will be listed type: str extends_documentation_fragment: -- amazon.aws.aws -- amazon.aws.ec2 -- amazon.aws.boto3 -''' + - amazon.aws.common.modules + - amazon.aws.region.modules + - amazon.aws.boto3 +""" -RETURN = """ +RETURN = r""" mfa_devices: description: The MFA devices registered for the given user returned: always @@ -39,7 +38,7 @@ user_name: example """ -EXAMPLES = r''' +EXAMPLES = r""" # Note: These examples do not set authentication details, see the AWS Guide for details. # more details: https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListMFADevices.html @@ -54,7 +53,7 @@ role_arn: "arn:aws:iam::123456789012:role/someRole" role_session_name: "someRoleSession" register: assumed_role -''' +""" try: import botocore From 71a0b1a47420c8734c9fc91c84ab02c8a9990a02 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Wed, 26 Apr 2023 19:26:07 +0200 Subject: [PATCH 019/129] Big Black PR (#1784) * Black prep * Black * changelog * Fix pylint unused-import in tests * Split SSM connection plugin changes * disable glue tests - bucket's missing * Disable s3_logging and s3_sync tests This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/2c4575c248776c65d66b06cd60fa09b0dae1cd6f --- plugins/modules/iam_mfa_device_info.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/modules/iam_mfa_device_info.py b/plugins/modules/iam_mfa_device_info.py index c0c434a9be9..44b38ab90f4 100644 --- a/plugins/modules/iam_mfa_device_info.py +++ b/plugins/modules/iam_mfa_device_info.py @@ -67,12 +67,12 @@ def list_mfa_devices(connection, module): - user_name = module.params.get('user_name') + user_name = module.params.get("user_name") changed = False args = {} if user_name is not None: - args['UserName'] = user_name + args["UserName"] = user_name try: response = connection.list_mfa_devices(**args) except ClientError as e: @@ -92,12 +92,12 @@ def main(): ) try: - connection = module.client('iam') + connection = module.client("iam") except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - module.fail_json_aws(e, msg='Failed to connect to AWS') + module.fail_json_aws(e, msg="Failed to connect to AWS") list_mfa_devices(connection, module) -if __name__ == '__main__': +if __name__ == "__main__": main() From 4b563de5ee417ec0f6c2fccb5f9554981f914f32 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Fri, 22 Sep 2023 14:30:04 +0200 Subject: [PATCH 020/129] Update runtime --- meta/runtime.yml | 1 + plugins/modules/iam_mfa_device_info.py | 1 + 2 files changed, 2 insertions(+) diff --git a/meta/runtime.yml b/meta/runtime.yml index da395988b6f..5de91ba3046 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -106,6 +106,7 @@ action_groups: - s3_bucket - s3_object - s3_object_info + - iam_mfa_device_info plugin_routing: action: aws_s3: diff --git a/plugins/modules/iam_mfa_device_info.py b/plugins/modules/iam_mfa_device_info.py index 44b38ab90f4..3f491fdb4e4 100644 --- a/plugins/modules/iam_mfa_device_info.py +++ b/plugins/modules/iam_mfa_device_info.py @@ -8,6 +8,7 @@ --- module: iam_mfa_device_info version_added: 1.0.0 +version_added_collection: community.aws short_description: List the MFA (Multi-Factor Authentication) devices registered for a user description: - List the MFA (Multi-Factor Authentication) devices registered for a user From f5aa5236169c315b0f964d63474c7e0ed8351ca9 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Fri, 22 Sep 2023 14:30:04 +0200 Subject: [PATCH 021/129] Update FQDN --- plugins/modules/iam_mfa_device_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/iam_mfa_device_info.py b/plugins/modules/iam_mfa_device_info.py index 3f491fdb4e4..6b81f03d162 100644 --- a/plugins/modules/iam_mfa_device_info.py +++ b/plugins/modules/iam_mfa_device_info.py @@ -44,7 +44,7 @@ # more details: https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListMFADevices.html - name: List MFA devices - community.aws.iam_mfa_device_info: + amazon.aws.iam_mfa_device_info: register: mfa_devices # more details: https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html From 8018d3d86adad6a1d9625b640f31d8900d7b9428 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Fri, 22 Sep 2023 14:30:04 +0200 Subject: [PATCH 022/129] Add changelog fragment --- changelogs/fragments/migrate_iam_mfa_device_info.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changelogs/fragments/migrate_iam_mfa_device_info.yml diff --git a/changelogs/fragments/migrate_iam_mfa_device_info.yml b/changelogs/fragments/migrate_iam_mfa_device_info.yml new file mode 100644 index 00000000000..e2ee3133121 --- /dev/null +++ b/changelogs/fragments/migrate_iam_mfa_device_info.yml @@ -0,0 +1,4 @@ +major_changes: +- iam_mfa_device_info - The module has been migrated from the ``community.aws`` collection. + Playbooks using the Fully Qualified Collection Name for this module should be updated + to use ``amazon.aws.iam_mfa_device_info`` (https://github.com/ansible-collections/amazon.aws/pull/1761). From 76035e823e686981323c888073e5e7b469f44b40 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Thu, 28 Sep 2023 15:19:25 +0200 Subject: [PATCH 023/129] Use the amazon.aws path for importing AnsibleAWSModule Signed-off-by: Alina Buzachis --- plugins/modules/iam_mfa_device_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/iam_mfa_device_info.py b/plugins/modules/iam_mfa_device_info.py index 6b81f03d162..6916d60d060 100644 --- a/plugins/modules/iam_mfa_device_info.py +++ b/plugins/modules/iam_mfa_device_info.py @@ -64,7 +64,7 @@ from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict -from ansible_collections.community.aws.plugins.module_utils.modules import AnsibleCommunityAWSModule as AnsibleAWSModule +from ansible_collections.amazon.aws.plugins.module_utils.modules import AnsibleAWSModule def list_mfa_devices(connection, module): From 26563186347d06a458c40c358a525d8ad48650c3 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Mon, 2 Oct 2023 16:37:30 +0200 Subject: [PATCH 024/129] Update meta/runtime.yml Signed-off-by: Alina Buzachis --- meta/runtime.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/runtime.yml b/meta/runtime.yml index 5de91ba3046..dc35a8ec4d2 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -72,6 +72,7 @@ action_groups: - iam_instance_profile - iam_instance_profile_info - iam_managed_policy + - iam_mfa_device_info - iam_policy - iam_policy_info - iam_role @@ -106,7 +107,6 @@ action_groups: - s3_bucket - s3_object - s3_object_info - - iam_mfa_device_info plugin_routing: action: aws_s3: From bcb92ca511a7ca9007bf947add60421dd891da05 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Mon, 11 Oct 2021 14:34:52 +0200 Subject: [PATCH 025/129] Add iam_access_key(_info) new modules This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/dd3e527a1b9a3e367be10c96763f958e918833f0 --- plugins/modules/iam_access_key.py | 316 +++++++ plugins/modules/iam_access_key_info.py | 127 +++ .../targets/iam_access_key/aliases | 9 + .../targets/iam_access_key/defaults/main.yml | 2 + .../targets/iam_access_key/meta/main.yml | 3 + .../targets/iam_access_key/tasks/main.yml | 808 ++++++++++++++++++ 6 files changed, 1265 insertions(+) create mode 100644 plugins/modules/iam_access_key.py create mode 100644 plugins/modules/iam_access_key_info.py create mode 100644 tests/integration/targets/iam_access_key/aliases create mode 100644 tests/integration/targets/iam_access_key/defaults/main.yml create mode 100644 tests/integration/targets/iam_access_key/meta/main.yml create mode 100644 tests/integration/targets/iam_access_key/tasks/main.yml diff --git a/plugins/modules/iam_access_key.py b/plugins/modules/iam_access_key.py new file mode 100644 index 00000000000..1d5701e9d74 --- /dev/null +++ b/plugins/modules/iam_access_key.py @@ -0,0 +1,316 @@ +#!/usr/bin/python +# Copyright (c) 2021 Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +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.aws +- amazon.aws.ec2 +''' + +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: + name: example_user + access_key_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.core import AnsibleAWSModule +from ansible_collections.amazon.aws.plugins.module_utils.core import is_boto3_error_code +from ansible_collections.amazon.aws.plugins.module_utils.core import normalize_boto3_result +from ansible_collections.amazon.aws.plugins.module_utils.core import scrub_none_parameters +from ansible_collections.amazon.aws.plugins.module_utils.ec2 import AWSRetry + + +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='Failed to delete access key "{0}" for user "{1}"'.format(access_key_id, 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='Access key "{0}" not found attached to User "{1}"'.format(access_key_id, 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='Failed to update access key "{0}" for user "{1}"'.format(access_key_id, 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='Failed to create access key for user "{0}"'.format(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='Failed to get access keys for user "{0}"'.format(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 new file mode 100644 index 00000000000..9251cb846f6 --- /dev/null +++ b/plugins/modules/iam_access_key_info.py @@ -0,0 +1,127 @@ +#!/usr/bin/python +# Copyright (c) 2021 Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +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.aws +- amazon.aws.ec2 +''' + +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.core import AnsibleAWSModule +from ansible_collections.amazon.aws.plugins.module_utils.core import normalize_boto3_result +from ansible_collections.amazon.aws.plugins.module_utils.ec2 import AWSRetry + + +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='Failed to get access keys for user "{0}"'.format(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 new file mode 100644 index 00000000000..ffceccfcc41 --- /dev/null +++ b/tests/integration/targets/iam_access_key/aliases @@ -0,0 +1,9 @@ +# 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 new file mode 100644 index 00000000000..eaaa3523e19 --- /dev/null +++ b/tests/integration/targets/iam_access_key/defaults/main.yml @@ -0,0 +1,2 @@ +--- +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 new file mode 100644 index 00000000000..1f64f1169a9 --- /dev/null +++ b/tests/integration/targets/iam_access_key/meta/main.yml @@ -0,0 +1,3 @@ +dependencies: + - prepare_tests + - setup_ec2 diff --git a/tests/integration/targets/iam_access_key/tasks/main.yml b/tests/integration/targets/iam_access_key/tasks/main.yml new file mode 100644 index 00000000000..a7fcc633ce9 --- /dev/null +++ b/tests/integration/targets/iam_access_key/tasks/main.yml @@ -0,0 +1,808 @@ +--- +- name: AWS AuthN details + 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 }}" + 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: + aws_access_key: "{{ create_key_2.access_key.access_key_id }}" + aws_secret_key: "{{ create_key_2.secret_access_key }}" + security_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: + aws_access_key: "{{ create_key_1.access_key.access_key_id }}" + aws_secret_key: "{{ create_key_1.secret_access_key }}" + security_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: + aws_access_key: "{{ create_key_3.access_key.access_key_id }}" + aws_secret_key: "{{ create_key_3.secret_access_key }}" + security_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 From 1f0fd56360437c1574e248354fc56d5922e820a5 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Fri, 22 Apr 2022 11:44:07 +0200 Subject: [PATCH 026/129] Integration test dependency cleanup (#1086) Integration test dependency cleanup SUMMARY remove dependencies on setup_remote_tmp_dir where it's not used (often just copy & paste from another test) remove setup_ec2 (no main.yml means it's not doing anything) remove prepare_tests (empty main.yml means it's not doing anything) ISSUE TYPE Feature Pull Request COMPONENT NAME tests/integration/targets ADDITIONAL INFORMATION By cleaning up what we have we reduce the chance of people copying things about "because that's what test XYZ did". Reviewed-by: Alina Buzachis Reviewed-by: Mark Woolley This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/dd12046a1e2d5f39692b1890ff07e06c56b3bf0e --- tests/integration/targets/iam_access_key/meta/main.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/integration/targets/iam_access_key/meta/main.yml b/tests/integration/targets/iam_access_key/meta/main.yml index 1f64f1169a9..32cf5dda7ed 100644 --- a/tests/integration/targets/iam_access_key/meta/main.yml +++ b/tests/integration/targets/iam_access_key/meta/main.yml @@ -1,3 +1 @@ -dependencies: - - prepare_tests - - setup_ec2 +dependencies: [] From a92b233c50a1b357db59f7caa6590d7f1a4e7d8a Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Wed, 5 Oct 2022 17:04:40 +0200 Subject: [PATCH 027/129] Update extends_documentation_fragment with amazon.aws.boto3 (#1459) Update extends_documentation_fragment with amazon.aws.boto3 Depends-On: ansible/ansible-zuul-jobs#1654 SUMMARY As per ansible-collections/amazon.aws#985 add amazon.aws.boto3. ISSUE TYPE Docs Pull Request COMPONENT NAME several Reviewed-by: Jill R Reviewed-by: Mark Chappell Reviewed-by: Markus Bergholz This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/bd3c03fcba0848f593b86309740fa73e986a9646 --- plugins/modules/iam_access_key.py | 1 + plugins/modules/iam_access_key_info.py | 1 + 2 files changed, 2 insertions(+) diff --git a/plugins/modules/iam_access_key.py b/plugins/modules/iam_access_key.py index 1d5701e9d74..3207741ab94 100644 --- a/plugins/modules/iam_access_key.py +++ b/plugins/modules/iam_access_key.py @@ -56,6 +56,7 @@ extends_documentation_fragment: - amazon.aws.aws - amazon.aws.ec2 +- amazon.aws.boto3 ''' EXAMPLES = r''' diff --git a/plugins/modules/iam_access_key_info.py b/plugins/modules/iam_access_key_info.py index 9251cb846f6..91429eff940 100644 --- a/plugins/modules/iam_access_key_info.py +++ b/plugins/modules/iam_access_key_info.py @@ -26,6 +26,7 @@ extends_documentation_fragment: - amazon.aws.aws - amazon.aws.ec2 +- amazon.aws.boto3 ''' EXAMPLES = r''' From 48bf7437576e3718ef103746d4348ce267d6e8ca Mon Sep 17 00:00:00 2001 From: Bikouo Aubin <79859644+abikouo@users.noreply.github.com> Date: Tue, 10 Jan 2023 19:22:13 +0100 Subject: [PATCH 028/129] Ansible User-Agent identification for community.aws (#1632) Ansible User-Agent identification for community.aws SUMMARY The value will be similar to this APN/1.0 Ansible/2.14.1 community.aws/6.0.0-dev0 ISSUE TYPE Feature Pull Request Reviewed-by: Mark Chappell Reviewed-by: Bikouo Aubin Reviewed-by: Alina Buzachis This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/a8cbce24071bcc62fe4594c38aff1baf18bd2862 --- plugins/modules/iam_access_key.py | 2 +- plugins/modules/iam_access_key_info.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/modules/iam_access_key.py b/plugins/modules/iam_access_key.py index 3207741ab94..ab3e9110604 100644 --- a/plugins/modules/iam_access_key.py +++ b/plugins/modules/iam_access_key.py @@ -126,7 +126,7 @@ from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict -from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule +from ansible_collections.community.aws.plugins.module_utils.modules import AnsibleCommunityAWSModule as AnsibleAWSModule from ansible_collections.amazon.aws.plugins.module_utils.core import is_boto3_error_code from ansible_collections.amazon.aws.plugins.module_utils.core import normalize_boto3_result from ansible_collections.amazon.aws.plugins.module_utils.core import scrub_none_parameters diff --git a/plugins/modules/iam_access_key_info.py b/plugins/modules/iam_access_key_info.py index 91429eff940..9d7363b420a 100644 --- a/plugins/modules/iam_access_key_info.py +++ b/plugins/modules/iam_access_key_info.py @@ -76,7 +76,7 @@ from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict -from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule +from ansible_collections.community.aws.plugins.module_utils.modules import AnsibleCommunityAWSModule as AnsibleAWSModule from ansible_collections.amazon.aws.plugins.module_utils.core import normalize_boto3_result from ansible_collections.amazon.aws.plugins.module_utils.ec2 import AWSRetry From 7c6c9f71dc2509cddd5815a129e28405e51d9fd5 Mon Sep 17 00:00:00 2001 From: Markus Bergholz Date: Wed, 8 Feb 2023 07:34:38 +0100 Subject: [PATCH 029/129] fix (#1711) iam_access_key - fix example docs SUMMARY Closes #1710 ISSUE TYPE Docs Pull Request COMPONENT NAME iam_access_key Reviewed-by: Mark Chappell This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/88872b39fba1b979780d260ea5b0f9f5dcd5aeae --- plugins/modules/iam_access_key.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/modules/iam_access_key.py b/plugins/modules/iam_access_key.py index ab3e9110604..32220a216e3 100644 --- a/plugins/modules/iam_access_key.py +++ b/plugins/modules/iam_access_key.py @@ -69,8 +69,8 @@ - name: Delete the access_key community.aws.iam_access_key: - name: example_user - access_key_id: AKIA1EXAMPLE1EXAMPLE + user_name: example_user + id: AKIA1EXAMPLE1EXAMPLE state: absent ''' From 5989a4fbf0c5b61771ad894ac5da4214ed9ce748 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Wed, 8 Mar 2023 12:07:26 +0100 Subject: [PATCH 030/129] Cleanup headers and imports (#1738) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cleanup headers and imports SUMMARY Mass update of imports, docs fragments and file headers Many of the amazon.aws module_utils and docs fragments got moved about, update community.aws to reflect this. Consistently apply the comment headers as documented at https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_documenting.html#python-shebang-utf-8-coding ISSUE TYPE Docs Pull Request Feature Pull Request COMPONENT NAME ADDITIONAL INFORMATION Header cleanup based upon: https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_documenting.html#python-shebang-utf-8-coding Begin your Ansible module with #!/usr/bin/python - this “shebang” allows ansible_python_interpreter to work. Follow the shebang immediately with # -*- coding: utf-8 -*- to clarify that the file is UTF-8 encoded. and https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_documenting.html#copyright-and-license After the shebang and UTF-8 coding, add a copyright line with the original copyright holder and a license declaration. The license declaration should be ONLY one line, not the full GPL prefix. ... Additions to the module (for instance, rewrites) are not permitted to add additional copyright lines other than the default copyright statement if missing: Reviewed-by: Alina Buzachis This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/a4f20bf114bfab19b1c84c4ecf42efd5614ab80c --- plugins/modules/iam_access_key.py | 36 +++++++++++++------------- plugins/modules/iam_access_key_info.py | 32 +++++++++++------------ 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/plugins/modules/iam_access_key.py b/plugins/modules/iam_access_key.py index 32220a216e3..af472fbe8c6 100644 --- a/plugins/modules/iam_access_key.py +++ b/plugins/modules/iam_access_key.py @@ -1,19 +1,18 @@ #!/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) -from __future__ import absolute_import, division, print_function -__metaclass__ = type - - -DOCUMENTATION = r''' +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) +author: + - Mark Chappell (@tremble) options: user_name: description: @@ -54,12 +53,12 @@ default: false extends_documentation_fragment: -- amazon.aws.aws -- amazon.aws.ec2 -- amazon.aws.boto3 -''' + - amazon.aws.common.modules + - amazon.aws.region.modules + - amazon.aws.boto3 +""" -EXAMPLES = r''' +EXAMPLES = r""" # Note: These examples do not set authentication details, see the AWS Guide for details. - name: Create a new access key @@ -72,9 +71,9 @@ user_name: example_user id: AKIA1EXAMPLE1EXAMPLE state: absent -''' +""" -RETURN = r''' +RETURN = r""" access_key: description: A dictionary containing all the access key information. returned: When the key exists. @@ -117,7 +116,7 @@ returned: When a key was deleted during the rotation of access keys type: str sample: AKIA1EXAMPLE1EXAMPLE -''' +""" try: import botocore @@ -126,11 +125,12 @@ 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 -from ansible_collections.amazon.aws.plugins.module_utils.core import is_boto3_error_code -from ansible_collections.amazon.aws.plugins.module_utils.core import normalize_boto3_result -from ansible_collections.amazon.aws.plugins.module_utils.core import scrub_none_parameters -from ansible_collections.amazon.aws.plugins.module_utils.ec2 import AWSRetry def delete_access_key(access_keys, user, access_key_id): diff --git a/plugins/modules/iam_access_key_info.py b/plugins/modules/iam_access_key_info.py index 9d7363b420a..6573e657a18 100644 --- a/plugins/modules/iam_access_key_info.py +++ b/plugins/modules/iam_access_key_info.py @@ -1,12 +1,10 @@ #!/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) -from __future__ import absolute_import, division, print_function -__metaclass__ = type - - -DOCUMENTATION = r''' +DOCUMENTATION = r""" --- module: iam_access_key_info version_added: 2.1.0 @@ -14,7 +12,8 @@ description: - 'Fetches information AWS IAM user access keys.' - 'Note: It is not possible to fetch the secret access key.' -author: Mark Chappell (@tremble) +author: + - Mark Chappell (@tremble) options: user_name: description: @@ -24,20 +23,20 @@ aliases: ['username'] extends_documentation_fragment: -- amazon.aws.aws -- amazon.aws.ec2 -- amazon.aws.boto3 -''' + - amazon.aws.common.modules + - amazon.aws.region.modules + - amazon.aws.boto3 +""" -EXAMPLES = r''' +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''' +RETURN = r""" access_key: description: A dictionary containing all the access key information. returned: When the key exists. @@ -67,7 +66,7 @@ returned: success type: str sample: Inactive -''' +""" try: import botocore @@ -76,9 +75,10 @@ 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 -from ansible_collections.amazon.aws.plugins.module_utils.core import normalize_boto3_result -from ansible_collections.amazon.aws.plugins.module_utils.ec2 import AWSRetry def get_access_keys(user): From 5e8380744129dc4ad78f40234db37bf65a38083c Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Wed, 26 Apr 2023 19:26:07 +0200 Subject: [PATCH 031/129] Big Black PR (#1784) * Black prep * Black * changelog * Fix pylint unused-import in tests * Split SSM connection plugin changes * disable glue tests - bucket's missing * Disable s3_logging and s3_sync tests This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/2c4575c248776c65d66b06cd60fa09b0dae1cd6f --- plugins/modules/iam_access_key.py | 88 ++++++++++++-------------- plugins/modules/iam_access_key_info.py | 22 +++---- 2 files changed, 49 insertions(+), 61 deletions(-) diff --git a/plugins/modules/iam_access_key.py b/plugins/modules/iam_access_key.py index af472fbe8c6..a8f03d7bced 100644 --- a/plugins/modules/iam_access_key.py +++ b/plugins/modules/iam_access_key.py @@ -149,14 +149,15 @@ def delete_access_key(access_keys, user, access_key_id): UserName=user, AccessKeyId=access_key_id, ) - except is_boto3_error_code('NoSuchEntityException'): + 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='Failed to delete access key "{0}" for user "{1}"'.format(access_key_id, user) - ) + except ( + botocore.exceptions.ClientError, + botocore.exceptions.BotoCoreError, + ) as e: # pylint: disable=duplicate-except + module.fail_json_aws(e, msg='Failed to delete access key "{0}" for user "{1}"'.format(access_key_id, user)) return True @@ -171,9 +172,9 @@ def update_access_key(access_keys, user, access_key_id, enabled): 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 + desired_status = "Active" if enabled else "Inactive" + if access_key.get("status") != desired_status: + changes["Status"] = desired_status if not changes: return False @@ -182,15 +183,11 @@ def update_access_key(access_keys, user, access_key_id, enabled): return True try: - client.update_access_key( - aws_retry=True, - UserName=user, - AccessKeyId=access_key_id, - **changes - ) + 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, + e, + changes=changes, msg='Failed to update access key "{0}" for user "{1}"'.format(access_key_id, user), ) return True @@ -201,7 +198,7 @@ def create_access_key(access_keys, user, rotate_keys, enabled): 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)) + 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) @@ -215,18 +212,18 @@ def create_access_key(access_keys, user, rotate_keys, enabled): except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg='Failed to create access key for user "{0}"'.format(user)) results = camel_dict_to_snake_dict(results) - access_key = results.get('access_key') + 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_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' + access_key["status"] = "Inactive" if oldest_key: - access_key['deleted_access_key'] = oldest_key + access_key["deleted_access_key"] = oldest_key return access_key @@ -235,67 +232,64 @@ 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='Failed to get access keys for user "{0}"'.format(user) - ) + module.fail_json_aws(e, msg='Failed to get access keys for user "{0}"'.format(user)) if not results: return None results = camel_dict_to_snake_dict(results) - access_keys = results.get('access_key_metadata', []) + 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} + 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), + 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')], + ["state", "absent", ("id")], ] mutually_exclusive = [ - ['rotate_keys', 'id'], + ["rotate_keys", "id"], ] module = AnsibleAWSModule( argument_spec=argument_spec, - supports_check_mode=True + supports_check_mode=True, ) - client = module.client('iam', retry_decorator=AWSRetry.jittered_backoff()) + 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') + 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': + 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) + 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) @@ -303,15 +297,15 @@ def main(): 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) + 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["access_key"] = secret_key results = scrub_none_parameters(results) module.exit_json(changed=changed, **results) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/plugins/modules/iam_access_key_info.py b/plugins/modules/iam_access_key_info.py index 6573e657a18..22bbd564cb0 100644 --- a/plugins/modules/iam_access_key_info.py +++ b/plugins/modules/iam_access_key_info.py @@ -85,44 +85,38 @@ 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='Failed to get access keys for user "{0}"'.format(user) - ) + module.fail_json_aws(e, msg='Failed to get access keys for user "{0}"'.format(user)) if not results: return None results = camel_dict_to_snake_dict(results) - access_keys = results.get('access_key_metadata', []) + 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)) + 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']), + user_name=dict(required=True, type="str", aliases=["username"]), ) - module = AnsibleAWSModule( - argument_spec=argument_spec, - supports_check_mode=True - ) + module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) - client = module.client('iam', retry_decorator=AWSRetry.jittered_backoff()) + client = module.client("iam", retry_decorator=AWSRetry.jittered_backoff()) changed = False - user = module.params.get('user_name') + user = module.params.get("user_name") access_keys = get_access_keys(user) module.exit_json(changed=changed, access_keys=access_keys) -if __name__ == '__main__': +if __name__ == "__main__": main() From d748002f976126a0390bce0353ec013d6d74d7bb Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Mon, 8 May 2023 19:21:22 +0200 Subject: [PATCH 032/129] Bulk migration to Python 3.6 f-strings (#1810) Bulk migration to Python 3.6 f-strings SUMMARY We've dropped support for Python <3.6, bulk migrate to fstrings and perform some general string cleanup A combination of black --preview flynt some manual cleanup ISSUE TYPE Feature Pull Request COMPONENT NAME plugins/ tests/ ADDITIONAL INFORMATION Reviewed-by: Alina Buzachis This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/de338210dc1b0bb2eecee1dc16e073163b2d1df7 --- plugins/modules/iam_access_key.py | 12 ++++++------ plugins/modules/iam_access_key_info.py | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/plugins/modules/iam_access_key.py b/plugins/modules/iam_access_key.py index a8f03d7bced..ae3e9e7dd11 100644 --- a/plugins/modules/iam_access_key.py +++ b/plugins/modules/iam_access_key.py @@ -157,7 +157,7 @@ def delete_access_key(access_keys, user, access_key_id): botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError, ) as e: # pylint: disable=duplicate-except - module.fail_json_aws(e, msg='Failed to delete access key "{0}" for user "{1}"'.format(access_key_id, user)) + module.fail_json_aws(e, msg=f'Failed to delete access key "{access_key_id}" for user "{user}"') return True @@ -165,7 +165,7 @@ def delete_access_key(access_keys, user, access_key_id): def update_access_key(access_keys, user, access_key_id, enabled): if access_key_id not in access_keys: module.fail_json( - msg='Access key "{0}" not found attached to User "{1}"'.format(access_key_id, user), + msg=f'Access key "{access_key_id}" not found attached to User "{user}"', ) changes = dict() @@ -188,7 +188,7 @@ def update_access_key(access_keys, user, access_key_id, enabled): module.fail_json_aws( e, changes=changes, - msg='Failed to update access key "{0}" for user "{1}"'.format(access_key_id, user), + msg=f'Failed to update access key "{access_key_id}" for user "{user}"', ) return True @@ -210,7 +210,7 @@ def create_access_key(access_keys, user, rotate_keys, enabled): 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='Failed to create access key for user "{0}"'.format(user)) + 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) @@ -232,7 +232,7 @@ 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='Failed to get access keys for user "{0}"'.format(user)) + module.fail_json_aws(e, msg=f'Failed to get access keys for user "{user}"') if not results: return None @@ -259,7 +259,7 @@ def main(): ) required_if = [ - ["state", "absent", ("id")], + ["state", "absent", ("id",)], ] mutually_exclusive = [ ["rotate_keys", "id"], diff --git a/plugins/modules/iam_access_key_info.py b/plugins/modules/iam_access_key_info.py index 22bbd564cb0..0ea8b514122 100644 --- a/plugins/modules/iam_access_key_info.py +++ b/plugins/modules/iam_access_key_info.py @@ -85,7 +85,7 @@ 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='Failed to get access keys for user "{0}"'.format(user)) + module.fail_json_aws(e, msg=f'Failed to get access keys for user "{user}"') if not results: return None From ac59ed257df4446931625573af629896a6af8ffb Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Thu, 31 Aug 2023 17:58:59 +0200 Subject: [PATCH 033/129] Mass update of docs and tests (credentials/session tokens) (#1921) Mass update of docs and tests (credentials/session tokens) SUMMARY We had a cleanup of credentials/session parameters which included a batch of deprecations and renames. Ensure that all of our tests and docs are using the 'canonical' names ISSUE TYPE Docs Pull Request COMPONENT NAME plugins/modules/batch_compute_environment.py plugins/modules/cloudformation_exports_info.py plugins/modules/ec2_vpc_vpn.py plugins/modules/elasticache.py plugins/modules/elasticache_parameter_group.py plugins/modules/elasticache_snapshot.py plugins/modules/ses_rule_set.py plugins/modules/sts_assume_role.py plugins/modules/sts_session_token.py tests/integration ADDITIONAL INFORMATION See also ansible-collections/amazon.aws#1172 ansible-collections/amazon.aws#1714 Reviewed-by: Alina Buzachis This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/4a5b50e9b9c0d6ca1a1f802f3b03d4f503c16885 --- .../targets/iam_access_key/tasks/main.yml | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/integration/targets/iam_access_key/tasks/main.yml b/tests/integration/targets/iam_access_key/tasks/main.yml index a7fcc633ce9..572e53cc8a3 100644 --- a/tests/integration/targets/iam_access_key/tasks/main.yml +++ b/tests/integration/targets/iam_access_key/tasks/main.yml @@ -2,9 +2,9 @@ - name: AWS AuthN details module_defaults: group/aws: - aws_access_key: "{{ aws_access_key }}" - aws_secret_key: "{{ aws_secret_key }}" - security_token: "{{ security_token | default(omit) }}" + access_key: "{{ aws_access_key }}" + secret_key: "{{ aws_secret_key }}" + session_token: "{{ security_token | default(omit) }}" region: "{{ aws_region }}" collections: - amazon.aws @@ -548,9 +548,9 @@ - name: Test GetCallerIdentity - Key 2 aws_caller_info: - aws_access_key: "{{ create_key_2.access_key.access_key_id }}" - aws_secret_key: "{{ create_key_2.secret_access_key }}" - security_token: "{{ omit }}" + 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: @@ -560,9 +560,9 @@ - name: Test GetCallerIdentity - Key 1 (gone) aws_caller_info: - aws_access_key: "{{ create_key_1.access_key.access_key_id }}" - aws_secret_key: "{{ create_key_1.secret_access_key }}" - security_token: "{{ omit }}" + 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 @@ -573,9 +573,9 @@ - name: Test GetCallerIdentity - Key 3 (disabled) aws_caller_info: - aws_access_key: "{{ create_key_3.access_key.access_key_id }}" - aws_secret_key: "{{ create_key_3.secret_access_key }}" - security_token: "{{ omit }}" + 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 From bbaae8469977e0ca6acf422c3d6760d771687cac Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Wed, 27 Sep 2023 17:58:09 +0200 Subject: [PATCH 034/129] Update runtime --- meta/runtime.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/meta/runtime.yml b/meta/runtime.yml index da395988b6f..0cc7affc04c 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -68,6 +68,8 @@ action_groups: - elb_application_lb_info - elb_classic_lb - execute_lambda + - iam_access_key + - iam_access_key_info - iam_group - iam_instance_profile - iam_instance_profile_info From c8e36732bc9a58cfe739dc31d7075278b29fd02f Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Wed, 27 Sep 2023 17:58:09 +0200 Subject: [PATCH 035/129] Update FQDN --- plugins/modules/iam_access_key.py | 4 ++-- plugins/modules/iam_access_key_info.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/modules/iam_access_key.py b/plugins/modules/iam_access_key.py index ae3e9e7dd11..f53d3bbfc5d 100644 --- a/plugins/modules/iam_access_key.py +++ b/plugins/modules/iam_access_key.py @@ -62,12 +62,12 @@ # 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: + amazon.aws.iam_access_key: user_name: example_user state: present - name: Delete the access_key - community.aws.iam_access_key: + amazon.aws.iam_access_key: user_name: example_user id: AKIA1EXAMPLE1EXAMPLE state: absent diff --git a/plugins/modules/iam_access_key_info.py b/plugins/modules/iam_access_key_info.py index 0ea8b514122..65833bb8c88 100644 --- a/plugins/modules/iam_access_key_info.py +++ b/plugins/modules/iam_access_key_info.py @@ -32,7 +32,7 @@ # 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: + amazon.aws.iam_access_key_info: user_name: example_user """ From 336c2a6822fe24e3c9261739ff8febf4b3ed6e58 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Wed, 27 Sep 2023 17:58:09 +0200 Subject: [PATCH 036/129] Remove collection reference inside the tests --- .../targets/iam_access_key/defaults/main.yml | 3 +- .../targets/iam_access_key/tasks/main.yml | 134 ++++-------------- 2 files changed, 26 insertions(+), 111 deletions(-) diff --git a/tests/integration/targets/iam_access_key/defaults/main.yml b/tests/integration/targets/iam_access_key/defaults/main.yml index eaaa3523e19..d5d0baf6f6d 100644 --- a/tests/integration/targets/iam_access_key/defaults/main.yml +++ b/tests/integration/targets/iam_access_key/defaults/main.yml @@ -1,2 +1 @@ ---- -test_user: '{{ resource_prefix }}' +test_user: '{{ resource_prefix }}' diff --git a/tests/integration/targets/iam_access_key/tasks/main.yml b/tests/integration/targets/iam_access_key/tasks/main.yml index 572e53cc8a3..6628ef65eb7 100644 --- a/tests/integration/targets/iam_access_key/tasks/main.yml +++ b/tests/integration/targets/iam_access_key/tasks/main.yml @@ -1,14 +1,12 @@ ---- - 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 }}" + access_key: '{{ aws_access_key }}' + secret_key: '{{ aws_secret_key }}' + session_token: '{{ security_token | default(omit) }}' + region: '{{ aws_region }}' collections: - - amazon.aws - - community.aws + - community.aws block: # ================================================================================== # Preparation @@ -21,7 +19,6 @@ name: '{{ test_user }}' state: present register: iam_user - - assert: that: - iam_user is successful @@ -33,7 +30,6 @@ iam_access_key_info: user_name: '{{ test_user }}' register: access_key_info - - assert: that: - access_key_info is successful @@ -48,7 +44,6 @@ state: present register: create_key_1 check_mode: true - - assert: that: - create_key_1 is successful @@ -59,7 +54,6 @@ user_name: '{{ test_user }}' state: present register: create_key_1 - - assert: that: - create_key_1 is successful @@ -78,7 +72,6 @@ iam_access_key_info: user_name: '{{ test_user }}' register: access_key_info - - assert: that: - access_key_info is successful @@ -94,16 +87,12 @@ - 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 @@ -114,7 +103,6 @@ user_name: '{{ test_user }}' state: present register: create_key_2 - - assert: that: - create_key_2 is successful @@ -133,7 +121,6 @@ iam_access_key_info: user_name: '{{ test_user }}' register: access_key_info - - assert: that: - access_key_info is successful @@ -158,32 +145,12 @@ 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 - + ignore_errors: true - assert: that: # If Amazon update the limits we may need to change the expectation here. @@ -193,7 +160,6 @@ iam_access_key_info: user_name: '{{ test_user }}' register: access_key_info - - assert: that: - access_key_info is successful @@ -218,9 +184,6 @@ 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 }}' @@ -228,7 +191,6 @@ rotate_keys: true register: create_key_3 check_mode: true - - assert: that: - create_key_3 is successful @@ -242,7 +204,6 @@ state: present rotate_keys: true register: create_key_3 - - assert: that: - create_key_3 is successful @@ -262,7 +223,6 @@ iam_access_key_info: user_name: '{{ test_user }}' register: access_key_info - - assert: that: - access_key_info is successful @@ -287,17 +247,13 @@ 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 + enabled: false register: disable_key check_mode: true - - assert: that: - disable_key is successful @@ -307,9 +263,8 @@ iam_access_key: user_name: '{{ test_user }}' id: '{{ create_key_3.access_key.access_key_id }}' - enabled: False + enabled: false register: disable_key - - assert: that: - disable_key is successful @@ -328,10 +283,9 @@ iam_access_key: user_name: '{{ test_user }}' id: '{{ create_key_3.access_key.access_key_id }}' - enabled: False + enabled: false register: disable_key check_mode: true - - assert: that: - disable_key is successful @@ -341,9 +295,8 @@ iam_access_key: user_name: '{{ test_user }}' id: '{{ create_key_3.access_key.access_key_id }}' - enabled: False + enabled: false register: disable_key - - assert: that: - disable_key is successful @@ -362,7 +315,6 @@ iam_access_key_info: user_name: '{{ test_user }}' register: access_key_info - - assert: that: - access_key_info is successful @@ -387,16 +339,12 @@ 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 @@ -407,7 +355,6 @@ user_name: '{{ test_user }}' id: '{{ create_key_3.access_key.access_key_id }}' register: touch_key - - assert: that: - touch_key is successful @@ -428,10 +375,9 @@ iam_access_key: user_name: '{{ test_user }}' id: '{{ create_key_3.access_key.access_key_id }}' - enabled: True + enabled: true register: enable_key check_mode: true - - assert: that: - enable_key is successful @@ -441,9 +387,8 @@ iam_access_key: user_name: '{{ test_user }}' id: '{{ create_key_3.access_key.access_key_id }}' - enabled: True + enabled: true register: enable_key - - assert: that: - enable_key is successful @@ -462,10 +407,9 @@ iam_access_key: user_name: '{{ test_user }}' id: '{{ create_key_3.access_key.access_key_id }}' - enabled: True + enabled: true register: enable_key check_mode: true - - assert: that: - enable_key is successful @@ -475,9 +419,8 @@ iam_access_key: user_name: '{{ test_user }}' id: '{{ create_key_3.access_key.access_key_id }}' - enabled: True + enabled: true register: enable_key - - assert: that: - enable_key is successful @@ -500,7 +443,6 @@ id: '{{ create_key_3.access_key.access_key_id }}' register: touch_key check_mode: true - - assert: that: - touch_key is successful @@ -511,7 +453,6 @@ user_name: '{{ test_user }}' id: '{{ create_key_3.access_key.access_key_id }}' register: touch_key - - assert: that: - touch_key is successful @@ -532,9 +473,8 @@ iam_access_key: user_name: '{{ test_user }}' id: '{{ create_key_3.access_key.access_key_id }}' - enabled: False + enabled: false register: redisable_key - - assert: that: - redisable_key is successful @@ -543,16 +483,12 @@ - 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 }}" + 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 @@ -560,12 +496,11 @@ - 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 }}" + 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 @@ -573,12 +508,11 @@ - 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 }}" + 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 @@ -593,7 +527,6 @@ state: absent register: delete_active_key check_mode: true - - assert: that: - delete_active_key is successful @@ -605,7 +538,6 @@ id: '{{ create_key_2.access_key.access_key_id }}' state: absent register: delete_active_key - - assert: that: - delete_active_key is successful @@ -618,7 +550,6 @@ state: absent register: delete_active_key check_mode: true - - assert: that: - delete_active_key is successful @@ -630,7 +561,6 @@ id: '{{ create_key_2.access_key.access_key_id }}' state: absent register: delete_active_key - - assert: that: - delete_active_key is successful @@ -645,7 +575,6 @@ state: absent register: delete_inactive_key check_mode: true - - assert: that: - delete_inactive_key is successful @@ -657,7 +586,6 @@ id: '{{ create_key_3.access_key.access_key_id }}' state: absent register: delete_inactive_key - - assert: that: - delete_inactive_key is successful @@ -670,7 +598,6 @@ state: absent register: delete_inactive_key check_mode: true - - assert: that: - delete_inactive_key is successful @@ -682,7 +609,6 @@ id: '{{ create_key_3.access_key.access_key_id }}' state: absent register: delete_inactive_key - - assert: that: - delete_inactive_key is successful @@ -694,7 +620,6 @@ iam_access_key_info: user_name: '{{ test_user }}' register: access_key_info - - assert: that: - access_key_info is successful @@ -710,7 +635,6 @@ enabled: false register: create_key_4 check_mode: true - - assert: that: - create_key_4 is successful @@ -722,7 +646,6 @@ state: present enabled: false register: create_key_4 - - assert: that: - create_key_4 is successful @@ -741,7 +664,6 @@ iam_access_key_info: user_name: '{{ test_user }}' register: access_key_info - - assert: that: - access_key_info is successful @@ -757,16 +679,12 @@ - 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 + enabled: false register: disable_new_key - - assert: that: - disable_new_key is successful @@ -782,7 +700,6 @@ id: '{{ create_key_4.access_key.access_key_id }}' state: absent register: delete_new_key - - assert: that: - delete_new_key is successful @@ -793,7 +710,6 @@ name: '{{ test_user }}' state: absent register: delete_user - - assert: that: - delete_user is successful From a6a42a3c574a47255548700b4bbc6b43ad366e63 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Wed, 27 Sep 2023 17:58:09 +0200 Subject: [PATCH 037/129] Add changelog fragment --- changelogs/fragments/migrate_iam_access_key.yml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 changelogs/fragments/migrate_iam_access_key.yml diff --git a/changelogs/fragments/migrate_iam_access_key.yml b/changelogs/fragments/migrate_iam_access_key.yml new file mode 100644 index 00000000000..4d1f5bea3a9 --- /dev/null +++ b/changelogs/fragments/migrate_iam_access_key.yml @@ -0,0 +1,7 @@ +major_changes: +- iam_access_key - The module has been migrated from the ``community.aws`` collection. + Playbooks using the Fully Qualified Collection Name for this module should be updated + to use ``amazon.aws.iam_access_key``. +- iam_access_key_info - The module has been migrated from the ``community.aws`` collection. + Playbooks using the Fully Qualified Collection Name for this module should be updated + to use ``amazon.aws.iam_access_key_info``. From f20540a83e18e3c1a3cd3fd1ee2a8cfa0d5c1ac0 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Wed, 27 Sep 2023 18:03:30 +0200 Subject: [PATCH 038/129] Add version_added_collection: community.aws Signed-off-by: Alina Buzachis --- plugins/modules/iam_access_key.py | 1 + plugins/modules/iam_access_key_info.py | 1 + 2 files changed, 2 insertions(+) diff --git a/plugins/modules/iam_access_key.py b/plugins/modules/iam_access_key.py index f53d3bbfc5d..aa16855818f 100644 --- a/plugins/modules/iam_access_key.py +++ b/plugins/modules/iam_access_key.py @@ -8,6 +8,7 @@ --- module: iam_access_key version_added: 2.1.0 +version_added_collection: community.aws short_description: Manage AWS IAM User access keys description: - Manage AWS IAM user access keys. diff --git a/plugins/modules/iam_access_key_info.py b/plugins/modules/iam_access_key_info.py index 65833bb8c88..3f0129b5bbb 100644 --- a/plugins/modules/iam_access_key_info.py +++ b/plugins/modules/iam_access_key_info.py @@ -8,6 +8,7 @@ --- module: iam_access_key_info version_added: 2.1.0 +version_added_collection: community.aws short_description: fetch information about AWS IAM User access keys description: - 'Fetches information AWS IAM user access keys.' From bb424bcf1b8078f681be988caf7be87036e17610 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Wed, 27 Sep 2023 18:20:23 +0200 Subject: [PATCH 039/129] Add no_log: true Signed-off-by: Alina Buzachis --- plugins/modules/iam_access_key.py | 5 ++++- tests/integration/targets/iam_access_key/tasks/main.yml | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/plugins/modules/iam_access_key.py b/plugins/modules/iam_access_key.py index aa16855818f..6857b0d08df 100644 --- a/plugins/modules/iam_access_key.py +++ b/plugins/modules/iam_access_key.py @@ -52,7 +52,9 @@ required: false type: bool default: false - +notes: + - For security reasons, this module should be used with B(no_log=true) and (register) functionalities + when creating new access key. extends_documentation_fragment: - amazon.aws.common.modules - amazon.aws.region.modules @@ -66,6 +68,7 @@ amazon.aws.iam_access_key: user_name: example_user state: present + no_log: true - name: Delete the access_key amazon.aws.iam_access_key: diff --git a/tests/integration/targets/iam_access_key/tasks/main.yml b/tests/integration/targets/iam_access_key/tasks/main.yml index 6628ef65eb7..6326ea1dbd6 100644 --- a/tests/integration/targets/iam_access_key/tasks/main.yml +++ b/tests/integration/targets/iam_access_key/tasks/main.yml @@ -53,6 +53,7 @@ iam_access_key: user_name: '{{ test_user }}' state: present + no_log: true register: create_key_1 - assert: that: @@ -102,6 +103,7 @@ iam_access_key: user_name: '{{ test_user }}' state: present + no_log: true register: create_key_2 - assert: that: @@ -149,6 +151,7 @@ iam_access_key: user_name: '{{ test_user }}' state: present + no_log: true register: create_key_3 ignore_errors: true - assert: @@ -203,6 +206,7 @@ user_name: '{{ test_user }}' state: present rotate_keys: true + no_log: true register: create_key_3 - assert: that: @@ -645,6 +649,7 @@ user_name: '{{ test_user }}' state: present enabled: false + no_log: true register: create_key_4 - assert: that: From 3705dd2f7d03d683c0e3aa1f54e4cbb0704b134b Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Thu, 28 Sep 2023 15:15:49 +0200 Subject: [PATCH 040/129] Use the amazon.aws path for importing AnsibleAWSModule Signed-off-by: Alina Buzachis --- plugins/modules/iam_access_key.py | 2 +- plugins/modules/iam_access_key_info.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/modules/iam_access_key.py b/plugins/modules/iam_access_key.py index 6857b0d08df..ed4c2c7ebe0 100644 --- a/plugins/modules/iam_access_key.py +++ b/plugins/modules/iam_access_key.py @@ -134,7 +134,7 @@ 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 +from ansible_collections.amazon.aws.plugins.module_utils.modules import AnsibleAWSModule def delete_access_key(access_keys, user, access_key_id): diff --git a/plugins/modules/iam_access_key_info.py b/plugins/modules/iam_access_key_info.py index 3f0129b5bbb..3a53d57215c 100644 --- a/plugins/modules/iam_access_key_info.py +++ b/plugins/modules/iam_access_key_info.py @@ -79,7 +79,7 @@ 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 +from ansible_collections.amazon.aws.plugins.module_utils.modules import AnsibleAWSModule def get_access_keys(user): From efefb7e88fe971da5af0f5e279272efc58d5ac49 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Thu, 31 Aug 2023 17:58:59 +0200 Subject: [PATCH 041/129] Mass update of docs and tests (credentials/session tokens) (#1921) Mass update of docs and tests (credentials/session tokens) SUMMARY We had a cleanup of credentials/session parameters which included a batch of deprecations and renames. Ensure that all of our tests and docs are using the 'canonical' names ISSUE TYPE Docs Pull Request COMPONENT NAME plugins/modules/batch_compute_environment.py plugins/modules/cloudformation_exports_info.py plugins/modules/ec2_vpc_vpn.py plugins/modules/elasticache.py plugins/modules/elasticache_parameter_group.py plugins/modules/elasticache_snapshot.py plugins/modules/ses_rule_set.py plugins/modules/sts_assume_role.py plugins/modules/sts_session_token.py tests/integration ADDITIONAL INFORMATION See also ansible-collections/amazon.aws#1172 ansible-collections/amazon.aws#1714 Reviewed-by: Alina Buzachis This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/4a5b50e9b9c0d6ca1a1f802f3b03d4f503c16885 --- tests/integration/targets/iam_access_key/tasks/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/targets/iam_access_key/tasks/main.yml b/tests/integration/targets/iam_access_key/tasks/main.yml index 6326ea1dbd6..027c9bb0921 100644 --- a/tests/integration/targets/iam_access_key/tasks/main.yml +++ b/tests/integration/targets/iam_access_key/tasks/main.yml @@ -726,4 +726,4 @@ iam_user: name: '{{ test_user }}' state: absent - ignore_errors: yes + ignore_errors: true From 62ae05650555fc74153502e4afe10bc2413022c9 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Mon, 2 Oct 2023 16:34:37 +0200 Subject: [PATCH 042/129] Apply isort to imports Signed-off-by: Alina Buzachis --- plugins/modules/iam_access_key.py | 3 +-- plugins/modules/iam_access_key_info.py | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/plugins/modules/iam_access_key.py b/plugins/modules/iam_access_key.py index ed4c2c7ebe0..f486d57c091 100644 --- a/plugins/modules/iam_access_key.py +++ b/plugins/modules/iam_access_key.py @@ -131,11 +131,10 @@ 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.modules import AnsibleAWSModule 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.amazon.aws.plugins.module_utils.modules import AnsibleAWSModule - def delete_access_key(access_keys, user, access_key_id): if not access_key_id: diff --git a/plugins/modules/iam_access_key_info.py b/plugins/modules/iam_access_key_info.py index 3a53d57215c..2b7c064d690 100644 --- a/plugins/modules/iam_access_key_info.py +++ b/plugins/modules/iam_access_key_info.py @@ -77,9 +77,8 @@ 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.amazon.aws.plugins.module_utils.modules import AnsibleAWSModule +from ansible_collections.amazon.aws.plugins.module_utils.retries import AWSRetry def get_access_keys(user): From 8aa741994985751a0d75a629cd19a7978395d979 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Tue, 28 Jun 2022 21:49:26 +0200 Subject: [PATCH 043/129] Rename s3 modules (#1271) Rename s3 modules SUMMARY In line with the naming guidelines, removes the aws_ prefix from aws_s3_bucket_info and aws_s3_cors ISSUE TYPE Feature Pull Request COMPONENT NAME plugins/modules/aws_s3_bucket_info.py plugins/modules/aws_s3_cors.py plugins/modules/s3_bucket_info.py plugins/modules/s3_cors.py ADDITIONAL INFORMATION Reviewed-by: Alina Buzachis This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/dd8b18ec8f5d14ae566bb9b9f5701d1d919715b3 --- plugins/modules/s3_bucket_info.py | 628 ++++++++++++++++++ .../targets/s3_bucket_info/aliases | 1 + .../targets/s3_bucket_info/defaults/main.yml | 5 + .../targets/s3_bucket_info/meta/main.yml | 1 + .../targets/s3_bucket_info/tasks/basic.yml | 72 ++ .../tasks/bucket_ownership_controls.yml | 81 +++ .../targets/s3_bucket_info/tasks/main.yml | 30 + 7 files changed, 818 insertions(+) create mode 100644 plugins/modules/s3_bucket_info.py create mode 100644 tests/integration/targets/s3_bucket_info/aliases create mode 100644 tests/integration/targets/s3_bucket_info/defaults/main.yml create mode 100644 tests/integration/targets/s3_bucket_info/meta/main.yml create mode 100644 tests/integration/targets/s3_bucket_info/tasks/basic.yml create mode 100644 tests/integration/targets/s3_bucket_info/tasks/bucket_ownership_controls.yml create mode 100644 tests/integration/targets/s3_bucket_info/tasks/main.yml diff --git a/plugins/modules/s3_bucket_info.py b/plugins/modules/s3_bucket_info.py new file mode 100644 index 00000000000..d164fde5d16 --- /dev/null +++ b/plugins/modules/s3_bucket_info.py @@ -0,0 +1,628 @@ +#!/usr/bin/python +""" +Copyright (c) 2017 Ansible Project +GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +""" + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: s3_bucket_info +version_added: 1.0.0 +author: + - "Gerben Geijteman (@hyperized)" +short_description: Lists S3 buckets in AWS +description: + - Lists S3 buckets and details about those buckets. + - Prior to release 5.0.0 this module was called C(community.aws.aws_s3_bucket_info). + The usage did not change. +options: + name: + description: + - Name of bucket to query. + type: str + default: "" + version_added: 1.4.0 + name_filter: + description: + - Limits buckets to only buckets who's name contain the string in I(name_filter). + type: str + default: "" + version_added: 1.4.0 + bucket_facts: + description: + - Retrieve requested S3 bucket detailed information. + - Each bucket_X option executes one API call, hence many options being set to C(true) will cause slower module execution. + - You can limit buckets by using the I(name) or I(name_filter) option. + suboptions: + bucket_accelerate_configuration: + description: Retrive S3 accelerate configuration. + type: bool + default: False + bucket_location: + description: Retrive S3 bucket location. + type: bool + default: False + bucket_replication: + description: Retrive S3 bucket replication. + type: bool + default: False + bucket_acl: + description: Retrive S3 bucket ACLs. + type: bool + default: False + bucket_logging: + description: Retrive S3 bucket logging. + type: bool + default: False + bucket_request_payment: + description: Retrive S3 bucket request payment. + type: bool + default: False + bucket_tagging: + description: Retrive S3 bucket tagging. + type: bool + default: False + bucket_cors: + description: Retrive S3 bucket CORS configuration. + type: bool + default: False + bucket_notification_configuration: + description: Retrive S3 bucket notification configuration. + type: bool + default: False + bucket_encryption: + description: Retrive S3 bucket encryption. + type: bool + default: False + bucket_ownership_controls: + description: + - Retrive S3 ownership controls. + type: bool + default: False + bucket_website: + description: Retrive S3 bucket website. + type: bool + default: False + bucket_policy: + description: Retrive S3 bucket policy. + type: bool + default: False + bucket_policy_status: + description: Retrive S3 bucket policy status. + type: bool + default: False + bucket_lifecycle_configuration: + description: Retrive S3 bucket lifecycle configuration. + type: bool + default: False + public_access_block: + description: Retrive S3 bucket public access block. + type: bool + default: False + type: dict + version_added: 1.4.0 + transform_location: + description: + - S3 bucket location for default us-east-1 is normally reported as C(null). + - Setting this option to C(true) will return C(us-east-1) instead. + - Affects only queries with I(bucket_facts=true) and I(bucket_location=true). + type: bool + default: False + version_added: 1.4.0 +extends_documentation_fragment: + - amazon.aws.aws + - amazon.aws.ec2 +''' + +EXAMPLES = ''' +# Note: These examples do not set authentication details, see the AWS Guide for details. + +# Note: Only AWS S3 is currently supported + +# Lists all S3 buckets +- community.aws.s3_bucket_info: + register: result + +# Retrieve detailed bucket information +- community.aws.s3_bucket_info: + # Show only buckets with name matching + name_filter: your.testing + # Choose facts to retrieve + bucket_facts: + # bucket_accelerate_configuration: true + bucket_acl: true + bucket_cors: true + bucket_encryption: true + # bucket_lifecycle_configuration: true + bucket_location: true + # bucket_logging: true + # bucket_notification_configuration: true + # bucket_ownership_controls: true + # bucket_policy: true + # bucket_policy_status: true + # bucket_replication: true + # bucket_request_payment: true + # bucket_tagging: true + # bucket_website: true + # public_access_block: true + transform_location: true + register: result + +# Print out result +- name: List buckets + ansible.builtin.debug: + msg: "{{ result['buckets'] }}" +''' + +RETURN = ''' +bucket_list: + description: "List of buckets" + returned: always + type: complex + contains: + name: + description: Bucket name. + returned: always + type: str + sample: a-testing-bucket-name + creation_date: + description: Bucket creation date timestamp. + returned: always + type: str + sample: "2021-01-21T12:44:10+00:00" + public_access_block: + description: Bucket public access block configuration. + returned: when I(bucket_facts=true) and I(public_access_block=true) + type: complex + contains: + PublicAccessBlockConfiguration: + description: PublicAccessBlockConfiguration data. + returned: when PublicAccessBlockConfiguration is defined for the bucket + type: complex + contains: + BlockPublicAcls: + description: BlockPublicAcls setting value. + type: bool + sample: true + BlockPublicPolicy: + description: BlockPublicPolicy setting value. + type: bool + sample: true + IgnorePublicAcls: + description: IgnorePublicAcls setting value. + type: bool + sample: true + RestrictPublicBuckets: + description: RestrictPublicBuckets setting value. + type: bool + sample: true + bucket_name_filter: + description: String used to limit buckets. See I(name_filter). + returned: when I(name_filter) is defined + type: str + sample: filter-by-this-string + bucket_acl: + description: Bucket ACL configuration. + returned: when I(bucket_facts=true) and I(bucket_acl=true) + type: complex + contains: + Grants: + description: List of ACL grants. + type: list + sample: [] + Owner: + description: Bucket owner information. + type: complex + contains: + DisplayName: + description: Bucket owner user display name. + returned: always + type: str + sample: username + ID: + description: Bucket owner user ID. + returned: always + type: str + sample: 123894e509349etc + bucket_cors: + description: Bucket CORS configuration. + returned: when I(bucket_facts=true) and I(bucket_cors=true) + type: complex + contains: + CORSRules: + description: Bucket CORS configuration. + returned: when CORS rules are defined for the bucket + type: list + sample: [] + bucket_encryption: + description: Bucket encryption configuration. + returned: when I(bucket_facts=true) and I(bucket_encryption=true) + type: complex + contains: + ServerSideEncryptionConfiguration: + description: ServerSideEncryptionConfiguration configuration. + returned: when encryption is enabled on the bucket + type: complex + contains: + Rules: + description: List of applied encryptio rules. + returned: when encryption is enabled on the bucket + type: list + sample: { "ApplyServerSideEncryptionByDefault": { "SSEAlgorithm": "AES256" }, "BucketKeyEnabled": False } + bucket_lifecycle_configuration: + description: Bucket lifecycle configuration settings. + returned: when I(bucket_facts=true) and I(bucket_lifecycle_configuration=true) + type: complex + contains: + Rules: + description: List of lifecycle management rules. + returned: when lifecycle configuration is present + type: list + sample: [{ "Status": "Enabled", "ID": "example-rule" }] + bucket_location: + description: Bucket location. + returned: when I(bucket_facts=true) and I(bucket_location=true) + type: complex + contains: + LocationConstraint: + description: AWS region. + returned: always + type: str + sample: us-east-2 + bucket_logging: + description: Server access logging configuration. + returned: when I(bucket_facts=true) and I(bucket_logging=true) + type: complex + contains: + LoggingEnabled: + description: Server access logging configuration. + returned: when server access logging is defined for the bucket + type: complex + contains: + TargetBucket: + description: Target bucket name. + returned: always + type: str + sample: logging-bucket-name + TargetPrefix: + description: Prefix in target bucket. + returned: always + type: str + sample: "" + bucket_notification_configuration: + description: Bucket notification settings. + returned: when I(bucket_facts=true) and I(bucket_notification_configuration=true) + type: complex + contains: + TopicConfigurations: + description: List of notification events configurations. + returned: when at least one notification is configured + type: list + sample: [] + bucket_ownership_controls: + description: Preffered object ownership settings. + returned: when I(bucket_facts=true) and I(bucket_ownership_controls=true) + type: complex + contains: + OwnershipControls: + description: Object ownership settings. + returned: when ownership controls are defined for the bucket + type: complex + contains: + Rules: + description: List of ownership rules. + returned: when ownership rule is defined + type: list + sample: [{ "ObjectOwnership:": "ObjectWriter" }] + bucket_policy: + description: Bucket policy contents. + returned: when I(bucket_facts=true) and I(bucket_policy=true) + type: str + sample: '{"Version":"2012-10-17","Statement":[{"Sid":"AddCannedAcl","Effect":"Allow",..}}]}' + bucket_policy_status: + description: Status of bucket policy. + returned: when I(bucket_facts=true) and I(bucket_policy_status=true) + type: complex + contains: + PolicyStatus: + description: Status of bucket policy. + returned: when bucket policy is present + type: complex + contains: + IsPublic: + description: Report bucket policy public status. + returned: when bucket policy is present + type: bool + sample: True + bucket_replication: + description: Replication configuration settings. + returned: when I(bucket_facts=true) and I(bucket_replication=true) + type: complex + contains: + Role: + description: IAM role used for replication. + returned: when replication rule is defined + type: str + sample: "arn:aws:iam::123:role/example-role" + Rules: + description: List of replication rules. + returned: when replication rule is defined + type: list + sample: [{ "ID": "rule-1", "Filter": "{}" }] + bucket_request_payment: + description: Requester pays setting. + returned: when I(bucket_facts=true) and I(bucket_request_payment=true) + type: complex + contains: + Payer: + description: Current payer. + returned: always + type: str + sample: BucketOwner + bucket_tagging: + description: Bucket tags. + returned: when I(bucket_facts=true) and I(bucket_tagging=true) + type: dict + sample: { "Tag1": "Value1", "Tag2": "Value2" } + bucket_website: + description: Static website hosting. + returned: when I(bucket_facts=true) and I(bucket_website=true) + type: complex + contains: + ErrorDocument: + description: Object serving as HTTP error page. + returned: when static website hosting is enabled + type: dict + sample: { "Key": "error.html" } + IndexDocument: + description: Object serving as HTTP index page. + returned: when static website hosting is enabled + type: dict + sample: { "Suffix": "error.html" } + RedirectAllRequestsTo: + description: Website redict settings. + returned: when redirect requests is configured + type: complex + contains: + HostName: + description: Hostname to redirect. + returned: always + type: str + sample: www.example.com + Protocol: + description: Protocol used for redirect. + returned: always + type: str + sample: https +''' + +try: + import botocore +except ImportError: + pass # Handled by AnsibleAWSModule + +from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule +from ansible_collections.amazon.aws.plugins.module_utils.ec2 import AWSRetry +from ansible_collections.amazon.aws.plugins.module_utils.ec2 import boto3_tag_list_to_ansible_dict +from ansible_collections.amazon.aws.plugins.module_utils.ec2 import camel_dict_to_snake_dict + + +def get_bucket_list(module, connection, name="", name_filter=""): + """ + Return result of list_buckets json encoded + Filter only buckets matching 'name' or name_filter if defined + :param module: + :param connection: + :return: + """ + buckets = [] + filtered_buckets = [] + final_buckets = [] + + # Get all buckets + try: + buckets = camel_dict_to_snake_dict(connection.list_buckets())['buckets'] + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as err_code: + module.fail_json_aws(err_code, msg="Failed to list buckets") + + # Filter buckets if requested + if name_filter: + for bucket in buckets: + if name_filter in bucket['name']: + filtered_buckets.append(bucket) + elif name: + for bucket in buckets: + if name == bucket['name']: + filtered_buckets.append(bucket) + + # Return proper list (filtered or all) + if name or name_filter: + final_buckets = filtered_buckets + else: + final_buckets = buckets + return(final_buckets) + + +def get_buckets_facts(connection, buckets, requested_facts, transform_location): + """ + Retrive additional information about S3 buckets + """ + full_bucket_list = [] + # Iterate over all buckets and append retrived facts to bucket + for bucket in buckets: + bucket.update(get_bucket_details(connection, bucket['name'], requested_facts, transform_location)) + full_bucket_list.append(bucket) + + return(full_bucket_list) + + +def get_bucket_details(connection, name, requested_facts, transform_location): + """ + Execute all enabled S3API get calls for selected bucket + """ + all_facts = {} + + for key in requested_facts: + if requested_facts[key]: + if key == 'bucket_location': + all_facts[key] = {} + try: + all_facts[key] = get_bucket_location(name, connection, transform_location) + # we just pass on error - error means that resources is undefined + except botocore.exceptions.ClientError: + pass + elif key == 'bucket_tagging': + all_facts[key] = {} + try: + all_facts[key] = get_bucket_tagging(name, connection) + # we just pass on error - error means that resources is undefined + except botocore.exceptions.ClientError: + pass + else: + all_facts[key] = {} + try: + all_facts[key] = get_bucket_property(name, connection, key) + # we just pass on error - error means that resources is undefined + except botocore.exceptions.ClientError: + pass + + return(all_facts) + + +@AWSRetry.jittered_backoff(max_delay=120, catch_extra_error_codes=['NoSuchBucket', 'OperationAborted']) +def get_bucket_location(name, connection, transform_location=False): + """ + Get bucket location and optionally transform 'null' to 'us-east-1' + """ + data = connection.get_bucket_location(Bucket=name) + + # Replace 'null' with 'us-east-1'? + if transform_location: + try: + if not data['LocationConstraint']: + data['LocationConstraint'] = 'us-east-1' + except KeyError: + pass + # Strip response metadata (not needed) + try: + data.pop('ResponseMetadata') + return(data) + except KeyError: + return(data) + + +@AWSRetry.jittered_backoff(max_delay=120, catch_extra_error_codes=['NoSuchBucket', 'OperationAborted']) +def get_bucket_tagging(name, connection): + """ + Get bucket tags and transform them using `boto3_tag_list_to_ansible_dict` function + """ + data = connection.get_bucket_tagging(Bucket=name) + + try: + bucket_tags = boto3_tag_list_to_ansible_dict(data['TagSet']) + return(bucket_tags) + except KeyError: + # Strip response metadata (not needed) + try: + data.pop('ResponseMetadata') + return(data) + except KeyError: + return(data) + + +@AWSRetry.jittered_backoff(max_delay=120, catch_extra_error_codes=['NoSuchBucket', 'OperationAborted']) +def get_bucket_property(name, connection, get_api_name): + """ + Get bucket property + """ + api_call = "get_" + get_api_name + api_function = getattr(connection, api_call) + data = api_function(Bucket=name) + + # Strip response metadata (not needed) + try: + data.pop('ResponseMetadata') + return(data) + except KeyError: + return(data) + + +def main(): + """ + Get list of S3 buckets + :return: + """ + argument_spec = dict( + name=dict(type='str', default=""), + name_filter=dict(type='str', default=""), + bucket_facts=dict(type='dict', options=dict( + bucket_accelerate_configuration=dict(type='bool', default=False), + bucket_acl=dict(type='bool', default=False), + bucket_cors=dict(type='bool', default=False), + bucket_encryption=dict(type='bool', default=False), + bucket_lifecycle_configuration=dict(type='bool', default=False), + bucket_location=dict(type='bool', default=False), + bucket_logging=dict(type='bool', default=False), + bucket_notification_configuration=dict(type='bool', default=False), + bucket_ownership_controls=dict(type='bool', default=False), + bucket_policy=dict(type='bool', default=False), + bucket_policy_status=dict(type='bool', default=False), + bucket_replication=dict(type='bool', default=False), + bucket_request_payment=dict(type='bool', default=False), + bucket_tagging=dict(type='bool', default=False), + bucket_website=dict(type='bool', default=False), + public_access_block=dict(type='bool', default=False), + )), + transform_location=dict(type='bool', default=False) + ) + + # Ensure we have an empty dict + result = {} + + # Define mutually exclusive options + mutually_exclusive = [ + ['name', 'name_filter'] + ] + + # Including ec2 argument spec + module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True, mutually_exclusive=mutually_exclusive) + + # Get parameters + name = module.params.get("name") + name_filter = module.params.get("name_filter") + requested_facts = module.params.get("bucket_facts") + transform_location = module.params.get("bucket_facts") + + # Set up connection + connection = {} + try: + connection = module.client('s3') + except (connection.exceptions.ClientError, botocore.exceptions.BotoCoreError) as err_code: + module.fail_json_aws(err_code, msg='Failed to connect to AWS') + + # Get basic bucket list (name + creation date) + bucket_list = get_bucket_list(module, connection, name, name_filter) + + # Add information about name/name_filter to result + if name: + result['bucket_name'] = name + elif name_filter: + result['bucket_name_filter'] = name_filter + + # Gather detailed information about buckets if requested + bucket_facts = module.params.get("bucket_facts") + if bucket_facts: + result['buckets'] = get_buckets_facts(connection, bucket_list, requested_facts, transform_location) + else: + result['buckets'] = bucket_list + + module.exit_json(msg="Retrieved s3 info.", **result) + + +# MAIN +if __name__ == '__main__': + main() diff --git a/tests/integration/targets/s3_bucket_info/aliases b/tests/integration/targets/s3_bucket_info/aliases new file mode 100644 index 00000000000..4ef4b2067d0 --- /dev/null +++ b/tests/integration/targets/s3_bucket_info/aliases @@ -0,0 +1 @@ +cloud/aws diff --git a/tests/integration/targets/s3_bucket_info/defaults/main.yml b/tests/integration/targets/s3_bucket_info/defaults/main.yml new file mode 100644 index 00000000000..464c0a299b7 --- /dev/null +++ b/tests/integration/targets/s3_bucket_info/defaults/main.yml @@ -0,0 +1,5 @@ +--- +name_pattern: "testbucket-ansible-integration" +testing_buckets: + - "{{ tiny_prefix }}-{{ name_pattern }}-1" + - "{{ tiny_prefix }}-{{ name_pattern }}-2" diff --git a/tests/integration/targets/s3_bucket_info/meta/main.yml b/tests/integration/targets/s3_bucket_info/meta/main.yml new file mode 100644 index 00000000000..32cf5dda7ed --- /dev/null +++ b/tests/integration/targets/s3_bucket_info/meta/main.yml @@ -0,0 +1 @@ +dependencies: [] diff --git a/tests/integration/targets/s3_bucket_info/tasks/basic.yml b/tests/integration/targets/s3_bucket_info/tasks/basic.yml new file mode 100644 index 00000000000..bf09665af4c --- /dev/null +++ b/tests/integration/targets/s3_bucket_info/tasks/basic.yml @@ -0,0 +1,72 @@ +--- +- name: Get simple S3 bucket list + aws_s3_bucket_info: + register: bucket_list + +- name: Assert result.changed == False and bucket list was retrieved + assert: + that: + - bucket_list.changed == False + - bucket_list.buckets + +- name: Get complex S3 bucket list + aws_s3_bucket_info: + name_filter: "{{ name_pattern }}" + bucket_facts: + bucket_accelerate_configuration: true + bucket_acl: true + bucket_cors: true + bucket_encryption: true + bucket_lifecycle_configuration: true + bucket_location: true + bucket_logging: true + bucket_notification_configuration: true + bucket_policy: true + bucket_policy_status: true + bucket_replication: true + bucket_request_payment: true + bucket_tagging: true + bucket_website: true + public_access_block: true + transform_location: true + register: bucket_list + +- name: Assert that buckets list contains requested bucket facts + assert: + that: + - item.name is search(name_pattern) + - item.bucket_accelerate_configuration is defined + - item.bucket_acl is defined + - item.bucket_cors is defined + - item.bucket_encryption is defined + - item.bucket_lifecycle_configuration is defined + - item.bucket_location is defined + - item.bucket_logging is defined + - item.bucket_notification_configuration is defined + - item.bucket_policy is defined + - item.bucket_policy_status is defined + - item.bucket_replication is defined + - item.bucket_request_payment is defined + - item.bucket_tagging is defined + - item.bucket_website is defined + - item.public_access_block is defined + loop: "{{ bucket_list.buckets }}" + loop_control: + label: "{{ item.name }}" + +- name: Assert that retrieved bucket facts contains valid data + assert: + that: + - item.bucket_acl.Owner is defined + - item.bucket_tagging.snake_case is defined + - item.bucket_tagging.CamelCase is defined + - item.bucket_tagging["lowercase spaced"] is defined + - item.bucket_tagging["Title Case"] is defined + - item.bucket_tagging.snake_case == 'simple_snake_case' + - item.bucket_tagging.CamelCase == 'SimpleCamelCase' + - item.bucket_tagging["lowercase spaced"] == 'hello cruel world' + - item.bucket_tagging["Title Case"] == 'Hello Cruel World' + - item.bucket_location.LocationConstraint == aws_region + loop: "{{ bucket_list.buckets }}" + loop_control: + label: "{{ item.name }}" diff --git a/tests/integration/targets/s3_bucket_info/tasks/bucket_ownership_controls.yml b/tests/integration/targets/s3_bucket_info/tasks/bucket_ownership_controls.yml new file mode 100644 index 00000000000..3acd99cf6de --- /dev/null +++ b/tests/integration/targets/s3_bucket_info/tasks/bucket_ownership_controls.yml @@ -0,0 +1,81 @@ +--- +- name: Get S3 bucket ownership controls + aws_s3_bucket_info: + name_filter: "{{ name_pattern }}" + bucket_facts: + bucket_ownership_controls: true + transform_location: true + register: bucket_list + +- name: Assert that buckets list contains requested bucket facts + assert: + that: + - item.name is search(name_pattern) + - item.bucket_ownership_controls is defined + loop: "{{ bucket_list.buckets }}" + loop_control: + label: "{{ item.name }}" + +- name: Get complex S3 bucket list (including ownership controls) + aws_s3_bucket_info: + name_filter: "{{ name_pattern }}" + bucket_facts: + bucket_accelerate_configuration: true + bucket_acl: true + bucket_cors: true + bucket_encryption: true + bucket_lifecycle_configuration: true + bucket_location: true + bucket_logging: true + bucket_notification_configuration: true + bucket_ownership_controls: true + bucket_policy: true + bucket_policy_status: true + bucket_replication: true + bucket_request_payment: true + bucket_tagging: true + bucket_website: true + public_access_block: true + transform_location: true + register: bucket_list + +- name: Assert that buckets list contains requested bucket facts + assert: + that: + - item.name is search(name_pattern) + - item.bucket_accelerate_configuration is defined + - item.bucket_acl is defined + - item.bucket_cors is defined + - item.bucket_encryption is defined + - item.bucket_lifecycle_configuration is defined + - item.bucket_location is defined + - item.bucket_logging is defined + - item.bucket_notification_configuration is defined + - item.bucket_ownership_controls is defined + - item.bucket_policy is defined + - item.bucket_policy_status is defined + - item.bucket_replication is defined + - item.bucket_request_payment is defined + - item.bucket_tagging is defined + - item.bucket_website is defined + - item.public_access_block is defined + loop: "{{ bucket_list.buckets }}" + loop_control: + label: "{{ item.name }}" + +- name: Assert that retrieved bucket facts contains valid data + assert: + that: + - item.bucket_acl.Owner is defined + - item.bucket_tagging.snake_case is defined + - item.bucket_tagging.CamelCase is defined + - item.bucket_tagging["lowercase spaced"] is defined + - item.bucket_tagging["Title Case"] is defined + - item.bucket_tagging.snake_case == 'simple_snake_case' + - item.bucket_tagging.CamelCase == 'SimpleCamelCase' + - item.bucket_tagging["lowercase spaced"] == 'hello cruel world' + - item.bucket_tagging["Title Case"] == 'Hello Cruel World' + - item.bucket_location.LocationConstraint == aws_region + loop: "{{ bucket_list.buckets }}" + loop_control: + label: "{{ item.name }}" diff --git a/tests/integration/targets/s3_bucket_info/tasks/main.yml b/tests/integration/targets/s3_bucket_info/tasks/main.yml new file mode 100644 index 00000000000..47d24cd0e3b --- /dev/null +++ b/tests/integration/targets/s3_bucket_info/tasks/main.yml @@ -0,0 +1,30 @@ +--- +- name: Test community.aws.aws_s3_bucket_info + 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 simple s3_bucket + s3_bucket: + name: "{{ item }}" + state: present + tags: + "lowercase spaced": "hello cruel world" + "Title Case": "Hello Cruel World" + CamelCase: "SimpleCamelCase" + snake_case: "simple_snake_case" + register: output + loop: "{{ testing_buckets }}" + + - include_tasks: basic.yml + - include_tasks: bucket_ownership_controls.yml + + always: + - name: Delete simple s3_buckets + s3_bucket: + name: "{{ item }}" + state: absent + loop: "{{ testing_buckets }}" From f600eac7597181066c1bc92f2e2fbcd770ca605c Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Mon, 15 Aug 2022 20:39:10 +0200 Subject: [PATCH 044/129] Minor sanity test fixes. (#1410) Minor sanity test fixes (new devel) SUMMARY ansible-devel has added a new PEP test (missing whitespace after keyword), this adds the fixes before the devel sanity tests are 'voting'. Additionally fixes: unused variables broad catching of Exception ISSUE TYPE Bugfix Pull Request COMPONENT NAME plugins/modules/autoscaling_group_info.py plugins/modules/cloudfront_distribution.py plugins/modules/cloudfront_origin_access_identity.py plugins/modules/cloudtrail.py plugins/modules/ec2_vpc_nacl.py plugins/modules/eks_fargate_profile.py plugins/modules/redshift.py plugins/modules/s3_bucket_info.py ADDITIONAL INFORMATION cloudfront_distribution still has a lot of catch Exception but it's part of parameter validation which should be overhauled separately, unfortunately the tests are rather b0rked. Reviewed-by: Alina Buzachis This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/3d4736bb8c0fa47159a961fdc0d13ed2184b4823 --- plugins/modules/s3_bucket_info.py | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/plugins/modules/s3_bucket_info.py b/plugins/modules/s3_bucket_info.py index d164fde5d16..81e1cd7217b 100644 --- a/plugins/modules/s3_bucket_info.py +++ b/plugins/modules/s3_bucket_info.py @@ -444,7 +444,7 @@ def get_bucket_list(module, connection, name="", name_filter=""): final_buckets = filtered_buckets else: final_buckets = buckets - return(final_buckets) + return final_buckets def get_buckets_facts(connection, buckets, requested_facts, transform_location): @@ -457,7 +457,7 @@ def get_buckets_facts(connection, buckets, requested_facts, transform_location): bucket.update(get_bucket_details(connection, bucket['name'], requested_facts, transform_location)) full_bucket_list.append(bucket) - return(full_bucket_list) + return full_bucket_list def get_bucket_details(connection, name, requested_facts, transform_location): @@ -490,7 +490,7 @@ def get_bucket_details(connection, name, requested_facts, transform_location): except botocore.exceptions.ClientError: pass - return(all_facts) + return all_facts @AWSRetry.jittered_backoff(max_delay=120, catch_extra_error_codes=['NoSuchBucket', 'OperationAborted']) @@ -508,11 +508,8 @@ def get_bucket_location(name, connection, transform_location=False): except KeyError: pass # Strip response metadata (not needed) - try: - data.pop('ResponseMetadata') - return(data) - except KeyError: - return(data) + data.pop('ResponseMetadata', None) + return data @AWSRetry.jittered_backoff(max_delay=120, catch_extra_error_codes=['NoSuchBucket', 'OperationAborted']) @@ -524,14 +521,11 @@ def get_bucket_tagging(name, connection): try: bucket_tags = boto3_tag_list_to_ansible_dict(data['TagSet']) - return(bucket_tags) + return bucket_tags except KeyError: # Strip response metadata (not needed) - try: - data.pop('ResponseMetadata') - return(data) - except KeyError: - return(data) + data.pop('ResponseMetadata', None) + return data @AWSRetry.jittered_backoff(max_delay=120, catch_extra_error_codes=['NoSuchBucket', 'OperationAborted']) @@ -544,11 +538,8 @@ def get_bucket_property(name, connection, get_api_name): data = api_function(Bucket=name) # Strip response metadata (not needed) - try: - data.pop('ResponseMetadata') - return(data) - except KeyError: - return(data) + data.pop('ResponseMetadata', None) + return data def main(): From ccda9626c346355d8cc074e579ad6f0d8edf4c29 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Wed, 5 Oct 2022 17:04:40 +0200 Subject: [PATCH 045/129] Update extends_documentation_fragment with amazon.aws.boto3 (#1459) Update extends_documentation_fragment with amazon.aws.boto3 Depends-On: ansible/ansible-zuul-jobs#1654 SUMMARY As per ansible-collections/amazon.aws#985 add amazon.aws.boto3. ISSUE TYPE Docs Pull Request COMPONENT NAME several Reviewed-by: Jill R Reviewed-by: Mark Chappell Reviewed-by: Markus Bergholz This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/bd3c03fcba0848f593b86309740fa73e986a9646 --- plugins/modules/s3_bucket_info.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/modules/s3_bucket_info.py b/plugins/modules/s3_bucket_info.py index 81e1cd7217b..541a02b0f93 100644 --- a/plugins/modules/s3_bucket_info.py +++ b/plugins/modules/s3_bucket_info.py @@ -116,6 +116,7 @@ extends_documentation_fragment: - amazon.aws.aws - amazon.aws.ec2 + - amazon.aws.boto3 ''' EXAMPLES = ''' From e3318850aa00641c0a06f3837c4f4f9c5a0f5171 Mon Sep 17 00:00:00 2001 From: Bikouo Aubin <79859644+abikouo@users.noreply.github.com> Date: Tue, 10 Jan 2023 19:22:13 +0100 Subject: [PATCH 046/129] Ansible User-Agent identification for community.aws (#1632) Ansible User-Agent identification for community.aws SUMMARY The value will be similar to this APN/1.0 Ansible/2.14.1 community.aws/6.0.0-dev0 ISSUE TYPE Feature Pull Request Reviewed-by: Mark Chappell Reviewed-by: Bikouo Aubin Reviewed-by: Alina Buzachis This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/a8cbce24071bcc62fe4594c38aff1baf18bd2862 --- plugins/modules/s3_bucket_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/s3_bucket_info.py b/plugins/modules/s3_bucket_info.py index 541a02b0f93..b4f72dd55a0 100644 --- a/plugins/modules/s3_bucket_info.py +++ b/plugins/modules/s3_bucket_info.py @@ -406,7 +406,7 @@ except ImportError: pass # Handled by AnsibleAWSModule -from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule +from ansible_collections.community.aws.plugins.module_utils.modules import AnsibleCommunityAWSModule as AnsibleAWSModule from ansible_collections.amazon.aws.plugins.module_utils.ec2 import AWSRetry from ansible_collections.amazon.aws.plugins.module_utils.ec2 import boto3_tag_list_to_ansible_dict from ansible_collections.amazon.aws.plugins.module_utils.ec2 import camel_dict_to_snake_dict From e977525ea0a32cb65d122ef253500a45865e224b Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Wed, 8 Mar 2023 12:07:26 +0100 Subject: [PATCH 047/129] Cleanup headers and imports (#1738) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cleanup headers and imports SUMMARY Mass update of imports, docs fragments and file headers Many of the amazon.aws module_utils and docs fragments got moved about, update community.aws to reflect this. Consistently apply the comment headers as documented at https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_documenting.html#python-shebang-utf-8-coding ISSUE TYPE Docs Pull Request Feature Pull Request COMPONENT NAME ADDITIONAL INFORMATION Header cleanup based upon: https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_documenting.html#python-shebang-utf-8-coding Begin your Ansible module with #!/usr/bin/python - this “shebang” allows ansible_python_interpreter to work. Follow the shebang immediately with # -*- coding: utf-8 -*- to clarify that the file is UTF-8 encoded. and https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_documenting.html#copyright-and-license After the shebang and UTF-8 coding, add a copyright line with the original copyright holder and a license declaration. The license declaration should be ONLY one line, not the full GPL prefix. ... Additions to the module (for instance, rewrites) are not permitted to add additional copyright lines other than the default copyright statement if missing: Reviewed-by: Alina Buzachis This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/a4f20bf114bfab19b1c84c4ecf42efd5614ab80c --- plugins/modules/s3_bucket_info.py | 34 +++++++++++++++---------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/plugins/modules/s3_bucket_info.py b/plugins/modules/s3_bucket_info.py index b4f72dd55a0..20995539c45 100644 --- a/plugins/modules/s3_bucket_info.py +++ b/plugins/modules/s3_bucket_info.py @@ -1,14 +1,10 @@ #!/usr/bin/python -""" -Copyright (c) 2017 Ansible Project -GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -""" +# -*- coding: utf-8 -*- -from __future__ import absolute_import, division, print_function -__metaclass__ = type +# Copyright (c) 2017 Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -DOCUMENTATION = ''' +DOCUMENTATION = r""" --- module: s3_bucket_info version_added: 1.0.0 @@ -114,12 +110,12 @@ default: False version_added: 1.4.0 extends_documentation_fragment: - - amazon.aws.aws - - amazon.aws.ec2 + - amazon.aws.common.modules + - amazon.aws.region.modules - amazon.aws.boto3 -''' +""" -EXAMPLES = ''' +EXAMPLES = r""" # Note: These examples do not set authentication details, see the AWS Guide for details. # Note: Only AWS S3 is currently supported @@ -157,9 +153,9 @@ - name: List buckets ansible.builtin.debug: msg: "{{ result['buckets'] }}" -''' +""" -RETURN = ''' +RETURN = r""" bucket_list: description: "List of buckets" returned: always @@ -399,17 +395,19 @@ returned: always type: str sample: https -''' +""" try: import botocore except ImportError: pass # Handled by AnsibleAWSModule +from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict + +from ansible_collections.amazon.aws.plugins.module_utils.retries import AWSRetry +from ansible_collections.amazon.aws.plugins.module_utils.tagging import boto3_tag_list_to_ansible_dict + from ansible_collections.community.aws.plugins.module_utils.modules import AnsibleCommunityAWSModule as AnsibleAWSModule -from ansible_collections.amazon.aws.plugins.module_utils.ec2 import AWSRetry -from ansible_collections.amazon.aws.plugins.module_utils.ec2 import boto3_tag_list_to_ansible_dict -from ansible_collections.amazon.aws.plugins.module_utils.ec2 import camel_dict_to_snake_dict def get_bucket_list(module, connection, name="", name_filter=""): From 9929628a0219e0306983e659513eac2c596cba32 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Wed, 26 Apr 2023 19:26:07 +0200 Subject: [PATCH 048/129] Big Black PR (#1784) * Black prep * Black * changelog * Fix pylint unused-import in tests * Split SSM connection plugin changes * disable glue tests - bucket's missing * Disable s3_logging and s3_sync tests This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/2c4575c248776c65d66b06cd60fa09b0dae1cd6f --- plugins/modules/s3_bucket_info.py | 97 +++++++++++++++++-------------- 1 file changed, 52 insertions(+), 45 deletions(-) diff --git a/plugins/modules/s3_bucket_info.py b/plugins/modules/s3_bucket_info.py index 20995539c45..ee4c0e2dd3f 100644 --- a/plugins/modules/s3_bucket_info.py +++ b/plugins/modules/s3_bucket_info.py @@ -424,18 +424,18 @@ def get_bucket_list(module, connection, name="", name_filter=""): # Get all buckets try: - buckets = camel_dict_to_snake_dict(connection.list_buckets())['buckets'] + buckets = camel_dict_to_snake_dict(connection.list_buckets())["buckets"] except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as err_code: module.fail_json_aws(err_code, msg="Failed to list buckets") # Filter buckets if requested if name_filter: for bucket in buckets: - if name_filter in bucket['name']: + if name_filter in bucket["name"]: filtered_buckets.append(bucket) elif name: for bucket in buckets: - if name == bucket['name']: + if name == bucket["name"]: filtered_buckets.append(bucket) # Return proper list (filtered or all) @@ -453,7 +453,7 @@ def get_buckets_facts(connection, buckets, requested_facts, transform_location): full_bucket_list = [] # Iterate over all buckets and append retrived facts to bucket for bucket in buckets: - bucket.update(get_bucket_details(connection, bucket['name'], requested_facts, transform_location)) + bucket.update(get_bucket_details(connection, bucket["name"], requested_facts, transform_location)) full_bucket_list.append(bucket) return full_bucket_list @@ -467,14 +467,14 @@ def get_bucket_details(connection, name, requested_facts, transform_location): for key in requested_facts: if requested_facts[key]: - if key == 'bucket_location': + if key == "bucket_location": all_facts[key] = {} try: all_facts[key] = get_bucket_location(name, connection, transform_location) # we just pass on error - error means that resources is undefined except botocore.exceptions.ClientError: pass - elif key == 'bucket_tagging': + elif key == "bucket_tagging": all_facts[key] = {} try: all_facts[key] = get_bucket_tagging(name, connection) @@ -492,7 +492,7 @@ def get_bucket_details(connection, name, requested_facts, transform_location): return all_facts -@AWSRetry.jittered_backoff(max_delay=120, catch_extra_error_codes=['NoSuchBucket', 'OperationAborted']) +@AWSRetry.jittered_backoff(max_delay=120, catch_extra_error_codes=["NoSuchBucket", "OperationAborted"]) def get_bucket_location(name, connection, transform_location=False): """ Get bucket location and optionally transform 'null' to 'us-east-1' @@ -502,16 +502,16 @@ def get_bucket_location(name, connection, transform_location=False): # Replace 'null' with 'us-east-1'? if transform_location: try: - if not data['LocationConstraint']: - data['LocationConstraint'] = 'us-east-1' + if not data["LocationConstraint"]: + data["LocationConstraint"] = "us-east-1" except KeyError: pass # Strip response metadata (not needed) - data.pop('ResponseMetadata', None) + data.pop("ResponseMetadata", None) return data -@AWSRetry.jittered_backoff(max_delay=120, catch_extra_error_codes=['NoSuchBucket', 'OperationAborted']) +@AWSRetry.jittered_backoff(max_delay=120, catch_extra_error_codes=["NoSuchBucket", "OperationAborted"]) def get_bucket_tagging(name, connection): """ Get bucket tags and transform them using `boto3_tag_list_to_ansible_dict` function @@ -519,15 +519,15 @@ def get_bucket_tagging(name, connection): data = connection.get_bucket_tagging(Bucket=name) try: - bucket_tags = boto3_tag_list_to_ansible_dict(data['TagSet']) + bucket_tags = boto3_tag_list_to_ansible_dict(data["TagSet"]) return bucket_tags except KeyError: # Strip response metadata (not needed) - data.pop('ResponseMetadata', None) + data.pop("ResponseMetadata", None) return data -@AWSRetry.jittered_backoff(max_delay=120, catch_extra_error_codes=['NoSuchBucket', 'OperationAborted']) +@AWSRetry.jittered_backoff(max_delay=120, catch_extra_error_codes=["NoSuchBucket", "OperationAborted"]) def get_bucket_property(name, connection, get_api_name): """ Get bucket property @@ -537,7 +537,7 @@ def get_bucket_property(name, connection, get_api_name): data = api_function(Bucket=name) # Strip response metadata (not needed) - data.pop('ResponseMetadata', None) + data.pop("ResponseMetadata", None) return data @@ -547,27 +547,30 @@ def main(): :return: """ argument_spec = dict( - name=dict(type='str', default=""), - name_filter=dict(type='str', default=""), - bucket_facts=dict(type='dict', options=dict( - bucket_accelerate_configuration=dict(type='bool', default=False), - bucket_acl=dict(type='bool', default=False), - bucket_cors=dict(type='bool', default=False), - bucket_encryption=dict(type='bool', default=False), - bucket_lifecycle_configuration=dict(type='bool', default=False), - bucket_location=dict(type='bool', default=False), - bucket_logging=dict(type='bool', default=False), - bucket_notification_configuration=dict(type='bool', default=False), - bucket_ownership_controls=dict(type='bool', default=False), - bucket_policy=dict(type='bool', default=False), - bucket_policy_status=dict(type='bool', default=False), - bucket_replication=dict(type='bool', default=False), - bucket_request_payment=dict(type='bool', default=False), - bucket_tagging=dict(type='bool', default=False), - bucket_website=dict(type='bool', default=False), - public_access_block=dict(type='bool', default=False), - )), - transform_location=dict(type='bool', default=False) + name=dict(type="str", default=""), + name_filter=dict(type="str", default=""), + bucket_facts=dict( + type="dict", + options=dict( + bucket_accelerate_configuration=dict(type="bool", default=False), + bucket_acl=dict(type="bool", default=False), + bucket_cors=dict(type="bool", default=False), + bucket_encryption=dict(type="bool", default=False), + bucket_lifecycle_configuration=dict(type="bool", default=False), + bucket_location=dict(type="bool", default=False), + bucket_logging=dict(type="bool", default=False), + bucket_notification_configuration=dict(type="bool", default=False), + bucket_ownership_controls=dict(type="bool", default=False), + bucket_policy=dict(type="bool", default=False), + bucket_policy_status=dict(type="bool", default=False), + bucket_replication=dict(type="bool", default=False), + bucket_request_payment=dict(type="bool", default=False), + bucket_tagging=dict(type="bool", default=False), + bucket_website=dict(type="bool", default=False), + public_access_block=dict(type="bool", default=False), + ), + ), + transform_location=dict(type="bool", default=False), ) # Ensure we have an empty dict @@ -575,11 +578,15 @@ def main(): # Define mutually exclusive options mutually_exclusive = [ - ['name', 'name_filter'] + ["name", "name_filter"], ] # Including ec2 argument spec - module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True, mutually_exclusive=mutually_exclusive) + module = AnsibleAWSModule( + argument_spec=argument_spec, + supports_check_mode=True, + mutually_exclusive=mutually_exclusive, + ) # Get parameters name = module.params.get("name") @@ -590,29 +597,29 @@ def main(): # Set up connection connection = {} try: - connection = module.client('s3') + connection = module.client("s3") except (connection.exceptions.ClientError, botocore.exceptions.BotoCoreError) as err_code: - module.fail_json_aws(err_code, msg='Failed to connect to AWS') + module.fail_json_aws(err_code, msg="Failed to connect to AWS") # Get basic bucket list (name + creation date) bucket_list = get_bucket_list(module, connection, name, name_filter) # Add information about name/name_filter to result if name: - result['bucket_name'] = name + result["bucket_name"] = name elif name_filter: - result['bucket_name_filter'] = name_filter + result["bucket_name_filter"] = name_filter # Gather detailed information about buckets if requested bucket_facts = module.params.get("bucket_facts") if bucket_facts: - result['buckets'] = get_buckets_facts(connection, bucket_list, requested_facts, transform_location) + result["buckets"] = get_buckets_facts(connection, bucket_list, requested_facts, transform_location) else: - result['buckets'] = bucket_list + result["buckets"] = bucket_list module.exit_json(msg="Retrieved s3 info.", **result) # MAIN -if __name__ == '__main__': +if __name__ == "__main__": main() From 800993a1aafb53f8e584cb1542d36d0a69e2ed2f Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Thu, 31 Aug 2023 17:58:59 +0200 Subject: [PATCH 049/129] Mass update of docs and tests (credentials/session tokens) (#1921) Mass update of docs and tests (credentials/session tokens) SUMMARY We had a cleanup of credentials/session parameters which included a batch of deprecations and renames. Ensure that all of our tests and docs are using the 'canonical' names ISSUE TYPE Docs Pull Request COMPONENT NAME plugins/modules/batch_compute_environment.py plugins/modules/cloudformation_exports_info.py plugins/modules/ec2_vpc_vpn.py plugins/modules/elasticache.py plugins/modules/elasticache_parameter_group.py plugins/modules/elasticache_snapshot.py plugins/modules/ses_rule_set.py plugins/modules/sts_assume_role.py plugins/modules/sts_session_token.py tests/integration ADDITIONAL INFORMATION See also ansible-collections/amazon.aws#1172 ansible-collections/amazon.aws#1714 Reviewed-by: Alina Buzachis This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/4a5b50e9b9c0d6ca1a1f802f3b03d4f503c16885 --- tests/integration/targets/s3_bucket_info/tasks/main.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/integration/targets/s3_bucket_info/tasks/main.yml b/tests/integration/targets/s3_bucket_info/tasks/main.yml index 47d24cd0e3b..043ea157f89 100644 --- a/tests/integration/targets/s3_bucket_info/tasks/main.yml +++ b/tests/integration/targets/s3_bucket_info/tasks/main.yml @@ -2,9 +2,9 @@ - name: Test community.aws.aws_s3_bucket_info module_defaults: group/aws: - aws_access_key: "{{ aws_access_key }}" - aws_secret_key: "{{ aws_secret_key }}" - security_token: "{{ security_token | default(omit) }}" + access_key: "{{ aws_access_key }}" + secret_key: "{{ aws_secret_key }}" + session_token: "{{ security_token | default(omit) }}" region: "{{ aws_region }}" block: - name: Create a simple s3_bucket From 9ddf5cb5557635b32a3e252440ac31f42cfdef4b Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Tue, 12 Sep 2023 07:37:30 +0200 Subject: [PATCH 050/129] Cleanup after renamed plugins (#1940) Cleanup after renamed plugins SUMMARY Prior to 5.0.0 we renamed various modules. Cleanup the integration tests (and some docs). ISSUE TYPE Docs Pull Request COMPONENT NAME plugins/modules/acm_certificate.py plugins/modules/acm_certificate_info.py plugins/modules/autoscaling_policy.py plugins/modules/codepipeline.py plugins/modules/storagegateway_info.py ADDITIONAL INFORMATION Reviewed-by: Alina Buzachis This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/c2fead07d8bd121a399ebcddc65421a6d81a1c8e --- tests/integration/targets/s3_bucket_info/tasks/basic.yml | 4 ++-- .../s3_bucket_info/tasks/bucket_ownership_controls.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/integration/targets/s3_bucket_info/tasks/basic.yml b/tests/integration/targets/s3_bucket_info/tasks/basic.yml index bf09665af4c..cf4ab8881f8 100644 --- a/tests/integration/targets/s3_bucket_info/tasks/basic.yml +++ b/tests/integration/targets/s3_bucket_info/tasks/basic.yml @@ -1,6 +1,6 @@ --- - name: Get simple S3 bucket list - aws_s3_bucket_info: + s3_bucket_info: register: bucket_list - name: Assert result.changed == False and bucket list was retrieved @@ -10,7 +10,7 @@ - bucket_list.buckets - name: Get complex S3 bucket list - aws_s3_bucket_info: + s3_bucket_info: name_filter: "{{ name_pattern }}" bucket_facts: bucket_accelerate_configuration: true diff --git a/tests/integration/targets/s3_bucket_info/tasks/bucket_ownership_controls.yml b/tests/integration/targets/s3_bucket_info/tasks/bucket_ownership_controls.yml index 3acd99cf6de..de0a6d61141 100644 --- a/tests/integration/targets/s3_bucket_info/tasks/bucket_ownership_controls.yml +++ b/tests/integration/targets/s3_bucket_info/tasks/bucket_ownership_controls.yml @@ -1,6 +1,6 @@ --- - name: Get S3 bucket ownership controls - aws_s3_bucket_info: + s3_bucket_info: name_filter: "{{ name_pattern }}" bucket_facts: bucket_ownership_controls: true @@ -17,7 +17,7 @@ label: "{{ item.name }}" - name: Get complex S3 bucket list (including ownership controls) - aws_s3_bucket_info: + s3_bucket_info: name_filter: "{{ name_pattern }}" bucket_facts: bucket_accelerate_configuration: true From 2060d258045a2fabd5b2230513874f56f668e30f Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Mon, 2 Oct 2023 13:59:13 +0200 Subject: [PATCH 051/129] Update runtime --- meta/runtime.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/meta/runtime.yml b/meta/runtime.yml index da395988b6f..18833f8b69e 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -7,6 +7,7 @@ action_groups: - aws_az_info - aws_caller_info - aws_s3 + - aws_s3_bucket_info - backup_plan - backup_plan_info - backup_selection @@ -104,6 +105,7 @@ action_groups: - route53_info - route53_zone - s3_bucket + - s3_bucket_info - s3_object - s3_object_info plugin_routing: @@ -120,6 +122,9 @@ plugin_routing: aws_s3: # Deprecation for this alias should not *start* prior to 2024-09-01 redirect: amazon.aws.s3_object + aws_s3_bucket_info: + # Deprecation for this alias should not *start* prior to 2024-09-01 + redirect: amazon.aws.s3_bucket_info ec2_asg: # Deprecation for this alias should not *start* prior to 2024-09-01 redirect: amazon.aws.autoscaling_group From 6db494854482179a62d38bf5fdcc1fe03fc1e1e1 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Mon, 2 Oct 2023 13:59:13 +0200 Subject: [PATCH 052/129] Update FQDN --- plugins/modules/s3_bucket_info.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/modules/s3_bucket_info.py b/plugins/modules/s3_bucket_info.py index ee4c0e2dd3f..2ed24c7b52d 100644 --- a/plugins/modules/s3_bucket_info.py +++ b/plugins/modules/s3_bucket_info.py @@ -121,11 +121,11 @@ # Note: Only AWS S3 is currently supported # Lists all S3 buckets -- community.aws.s3_bucket_info: +- amazon.aws.s3_bucket_info: register: result # Retrieve detailed bucket information -- community.aws.s3_bucket_info: +- amazon.aws.s3_bucket_info: # Show only buckets with name matching name_filter: your.testing # Choose facts to retrieve From 8b17a9341b50d7f5f8a2a3033ed8b6af5fefa93c Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Mon, 2 Oct 2023 13:59:13 +0200 Subject: [PATCH 053/129] Update AnsibleAWSModule import path --- plugins/modules/s3_bucket_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/s3_bucket_info.py b/plugins/modules/s3_bucket_info.py index 2ed24c7b52d..8bbddaedfef 100644 --- a/plugins/modules/s3_bucket_info.py +++ b/plugins/modules/s3_bucket_info.py @@ -407,7 +407,7 @@ from ansible_collections.amazon.aws.plugins.module_utils.retries import AWSRetry from ansible_collections.amazon.aws.plugins.module_utils.tagging import boto3_tag_list_to_ansible_dict -from ansible_collections.community.aws.plugins.module_utils.modules import AnsibleCommunityAWSModule as AnsibleAWSModule +from ansible_collections.amazon.aws.plugins.module_utils.modules import AnsibleAWSModule def get_bucket_list(module, connection, name="", name_filter=""): From 50706dd7c84617ef9bd06c46536f2c507f29bf99 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Mon, 2 Oct 2023 13:59:13 +0200 Subject: [PATCH 054/129] Remove collection reference inside the tests --- .../targets/s3_bucket_info/defaults/main.yml | 7 +- .../targets/s3_bucket_info/tasks/basic.yml | 70 ++++++++-------- .../tasks/bucket_ownership_controls.yml | 79 +++++++++---------- .../targets/s3_bucket_info/tasks/main.yml | 47 ++++++----- 4 files changed, 95 insertions(+), 108 deletions(-) diff --git a/tests/integration/targets/s3_bucket_info/defaults/main.yml b/tests/integration/targets/s3_bucket_info/defaults/main.yml index 464c0a299b7..5705de120ff 100644 --- a/tests/integration/targets/s3_bucket_info/defaults/main.yml +++ b/tests/integration/targets/s3_bucket_info/defaults/main.yml @@ -1,5 +1,4 @@ ---- -name_pattern: "testbucket-ansible-integration" +name_pattern: testbucket-ansible-integration testing_buckets: - - "{{ tiny_prefix }}-{{ name_pattern }}-1" - - "{{ tiny_prefix }}-{{ name_pattern }}-2" +- '{{ tiny_prefix }}-{{ name_pattern }}-1' +- '{{ tiny_prefix }}-{{ name_pattern }}-2' diff --git a/tests/integration/targets/s3_bucket_info/tasks/basic.yml b/tests/integration/targets/s3_bucket_info/tasks/basic.yml index cf4ab8881f8..90b99abe183 100644 --- a/tests/integration/targets/s3_bucket_info/tasks/basic.yml +++ b/tests/integration/targets/s3_bucket_info/tasks/basic.yml @@ -1,17 +1,15 @@ ---- - name: Get simple S3 bucket list s3_bucket_info: register: bucket_list - - name: Assert result.changed == False and bucket list was retrieved assert: that: - - bucket_list.changed == False - - bucket_list.buckets + - bucket_list.changed == False + - bucket_list.buckets - name: Get complex S3 bucket list s3_bucket_info: - name_filter: "{{ name_pattern }}" + name_filter: '{{ name_pattern }}' bucket_facts: bucket_accelerate_configuration: true bucket_acl: true @@ -30,43 +28,41 @@ public_access_block: true transform_location: true register: bucket_list - - name: Assert that buckets list contains requested bucket facts assert: that: - - item.name is search(name_pattern) - - item.bucket_accelerate_configuration is defined - - item.bucket_acl is defined - - item.bucket_cors is defined - - item.bucket_encryption is defined - - item.bucket_lifecycle_configuration is defined - - item.bucket_location is defined - - item.bucket_logging is defined - - item.bucket_notification_configuration is defined - - item.bucket_policy is defined - - item.bucket_policy_status is defined - - item.bucket_replication is defined - - item.bucket_request_payment is defined - - item.bucket_tagging is defined - - item.bucket_website is defined - - item.public_access_block is defined - loop: "{{ bucket_list.buckets }}" + - item.name is search(name_pattern) + - item.bucket_accelerate_configuration is defined + - item.bucket_acl is defined + - item.bucket_cors is defined + - item.bucket_encryption is defined + - item.bucket_lifecycle_configuration is defined + - item.bucket_location is defined + - item.bucket_logging is defined + - item.bucket_notification_configuration is defined + - item.bucket_policy is defined + - item.bucket_policy_status is defined + - item.bucket_replication is defined + - item.bucket_request_payment is defined + - item.bucket_tagging is defined + - item.bucket_website is defined + - item.public_access_block is defined + loop: '{{ bucket_list.buckets }}' loop_control: - label: "{{ item.name }}" - + label: '{{ item.name }}' - name: Assert that retrieved bucket facts contains valid data assert: that: - - item.bucket_acl.Owner is defined - - item.bucket_tagging.snake_case is defined - - item.bucket_tagging.CamelCase is defined - - item.bucket_tagging["lowercase spaced"] is defined - - item.bucket_tagging["Title Case"] is defined - - item.bucket_tagging.snake_case == 'simple_snake_case' - - item.bucket_tagging.CamelCase == 'SimpleCamelCase' - - item.bucket_tagging["lowercase spaced"] == 'hello cruel world' - - item.bucket_tagging["Title Case"] == 'Hello Cruel World' - - item.bucket_location.LocationConstraint == aws_region - loop: "{{ bucket_list.buckets }}" + - item.bucket_acl.Owner is defined + - item.bucket_tagging.snake_case is defined + - item.bucket_tagging.CamelCase is defined + - item.bucket_tagging["lowercase spaced"] is defined + - item.bucket_tagging["Title Case"] is defined + - item.bucket_tagging.snake_case == 'simple_snake_case' + - item.bucket_tagging.CamelCase == 'SimpleCamelCase' + - item.bucket_tagging["lowercase spaced"] == 'hello cruel world' + - item.bucket_tagging["Title Case"] == 'Hello Cruel World' + - item.bucket_location.LocationConstraint == aws_region + loop: '{{ bucket_list.buckets }}' loop_control: - label: "{{ item.name }}" + label: '{{ item.name }}' diff --git a/tests/integration/targets/s3_bucket_info/tasks/bucket_ownership_controls.yml b/tests/integration/targets/s3_bucket_info/tasks/bucket_ownership_controls.yml index de0a6d61141..33c280873a8 100644 --- a/tests/integration/targets/s3_bucket_info/tasks/bucket_ownership_controls.yml +++ b/tests/integration/targets/s3_bucket_info/tasks/bucket_ownership_controls.yml @@ -1,24 +1,21 @@ ---- - name: Get S3 bucket ownership controls s3_bucket_info: - name_filter: "{{ name_pattern }}" + name_filter: '{{ name_pattern }}' bucket_facts: bucket_ownership_controls: true transform_location: true register: bucket_list - - name: Assert that buckets list contains requested bucket facts assert: that: - - item.name is search(name_pattern) - - item.bucket_ownership_controls is defined - loop: "{{ bucket_list.buckets }}" + - item.name is search(name_pattern) + - item.bucket_ownership_controls is defined + loop: '{{ bucket_list.buckets }}' loop_control: - label: "{{ item.name }}" - + label: '{{ item.name }}' - name: Get complex S3 bucket list (including ownership controls) s3_bucket_info: - name_filter: "{{ name_pattern }}" + name_filter: '{{ name_pattern }}' bucket_facts: bucket_accelerate_configuration: true bucket_acl: true @@ -38,44 +35,42 @@ public_access_block: true transform_location: true register: bucket_list - - name: Assert that buckets list contains requested bucket facts assert: that: - - item.name is search(name_pattern) - - item.bucket_accelerate_configuration is defined - - item.bucket_acl is defined - - item.bucket_cors is defined - - item.bucket_encryption is defined - - item.bucket_lifecycle_configuration is defined - - item.bucket_location is defined - - item.bucket_logging is defined - - item.bucket_notification_configuration is defined - - item.bucket_ownership_controls is defined - - item.bucket_policy is defined - - item.bucket_policy_status is defined - - item.bucket_replication is defined - - item.bucket_request_payment is defined - - item.bucket_tagging is defined - - item.bucket_website is defined - - item.public_access_block is defined - loop: "{{ bucket_list.buckets }}" + - item.name is search(name_pattern) + - item.bucket_accelerate_configuration is defined + - item.bucket_acl is defined + - item.bucket_cors is defined + - item.bucket_encryption is defined + - item.bucket_lifecycle_configuration is defined + - item.bucket_location is defined + - item.bucket_logging is defined + - item.bucket_notification_configuration is defined + - item.bucket_ownership_controls is defined + - item.bucket_policy is defined + - item.bucket_policy_status is defined + - item.bucket_replication is defined + - item.bucket_request_payment is defined + - item.bucket_tagging is defined + - item.bucket_website is defined + - item.public_access_block is defined + loop: '{{ bucket_list.buckets }}' loop_control: - label: "{{ item.name }}" - + label: '{{ item.name }}' - name: Assert that retrieved bucket facts contains valid data assert: that: - - item.bucket_acl.Owner is defined - - item.bucket_tagging.snake_case is defined - - item.bucket_tagging.CamelCase is defined - - item.bucket_tagging["lowercase spaced"] is defined - - item.bucket_tagging["Title Case"] is defined - - item.bucket_tagging.snake_case == 'simple_snake_case' - - item.bucket_tagging.CamelCase == 'SimpleCamelCase' - - item.bucket_tagging["lowercase spaced"] == 'hello cruel world' - - item.bucket_tagging["Title Case"] == 'Hello Cruel World' - - item.bucket_location.LocationConstraint == aws_region - loop: "{{ bucket_list.buckets }}" + - item.bucket_acl.Owner is defined + - item.bucket_tagging.snake_case is defined + - item.bucket_tagging.CamelCase is defined + - item.bucket_tagging["lowercase spaced"] is defined + - item.bucket_tagging["Title Case"] is defined + - item.bucket_tagging.snake_case == 'simple_snake_case' + - item.bucket_tagging.CamelCase == 'SimpleCamelCase' + - item.bucket_tagging["lowercase spaced"] == 'hello cruel world' + - item.bucket_tagging["Title Case"] == 'Hello Cruel World' + - item.bucket_location.LocationConstraint == aws_region + loop: '{{ bucket_list.buckets }}' loop_control: - label: "{{ item.name }}" + label: '{{ item.name }}' diff --git a/tests/integration/targets/s3_bucket_info/tasks/main.yml b/tests/integration/targets/s3_bucket_info/tasks/main.yml index 043ea157f89..16d10acca89 100644 --- a/tests/integration/targets/s3_bucket_info/tasks/main.yml +++ b/tests/integration/targets/s3_bucket_info/tasks/main.yml @@ -1,30 +1,27 @@ ---- - name: Test community.aws.aws_s3_bucket_info module_defaults: group/aws: - access_key: "{{ aws_access_key }}" - secret_key: "{{ aws_secret_key }}" - session_token: "{{ security_token | default(omit) }}" - region: "{{ aws_region }}" + access_key: '{{ aws_access_key }}' + secret_key: '{{ aws_secret_key }}' + session_token: '{{ security_token | default(omit) }}' + region: '{{ aws_region }}' block: - - name: Create a simple s3_bucket - s3_bucket: - name: "{{ item }}" - state: present - tags: - "lowercase spaced": "hello cruel world" - "Title Case": "Hello Cruel World" - CamelCase: "SimpleCamelCase" - snake_case: "simple_snake_case" - register: output - loop: "{{ testing_buckets }}" - - - include_tasks: basic.yml - - include_tasks: bucket_ownership_controls.yml - + - name: Create a simple s3_bucket + s3_bucket: + name: '{{ item }}' + state: present + tags: + lowercase spaced: hello cruel world + Title Case: Hello Cruel World + CamelCase: SimpleCamelCase + snake_case: simple_snake_case + register: output + loop: '{{ testing_buckets }}' + - include_tasks: basic.yml + - include_tasks: bucket_ownership_controls.yml always: - - name: Delete simple s3_buckets - s3_bucket: - name: "{{ item }}" - state: absent - loop: "{{ testing_buckets }}" + - name: Delete simple s3_buckets + s3_bucket: + name: '{{ item }}' + state: absent + loop: '{{ testing_buckets }}' From 4da20a346419a8596b9f6639dad5e05d633d8a2d Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Mon, 2 Oct 2023 13:59:13 +0200 Subject: [PATCH 055/129] Add changelog fragment --- changelogs/fragments/migrate_s3_bucket_info.yml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 changelogs/fragments/migrate_s3_bucket_info.yml diff --git a/changelogs/fragments/migrate_s3_bucket_info.yml b/changelogs/fragments/migrate_s3_bucket_info.yml new file mode 100644 index 00000000000..74784c68cd2 --- /dev/null +++ b/changelogs/fragments/migrate_s3_bucket_info.yml @@ -0,0 +1,8 @@ +--- +major_changes: + - aws_s3_bucket_info - The module has been migrated from the ``community.aws`` collection. + Playbooks using the Fully Qualified Collection Name for this module should be + updated to use ``amazon.aws.aws_s3_bucket_info``. + - s3_bucket_info - The module has been migrated from the ``community.aws`` collection. + Playbooks using the Fully Qualified Collection Name for this module should be + updated to use ``amazon.aws.s3_bucket_info``. From 2c6bd0499796e017e1ae4367edda268be2140663 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Mon, 2 Oct 2023 14:05:52 +0200 Subject: [PATCH 056/129] Update s3_bucket_info.py Add version_added_collection: community.aws --- plugins/modules/s3_bucket_info.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/modules/s3_bucket_info.py b/plugins/modules/s3_bucket_info.py index 8bbddaedfef..bd9faa368a7 100644 --- a/plugins/modules/s3_bucket_info.py +++ b/plugins/modules/s3_bucket_info.py @@ -8,6 +8,7 @@ --- module: s3_bucket_info version_added: 1.0.0 +version_added_collection: community.aws author: - "Gerben Geijteman (@hyperized)" short_description: Lists S3 buckets in AWS From 7678a0b0d36aabb046aaead528b6c2ce46b66ef6 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Mon, 2 Oct 2023 16:58:20 +0200 Subject: [PATCH 057/129] Apply isort Signed-off-by: Alina Buzachis --- plugins/modules/s3_bucket_info.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/modules/s3_bucket_info.py b/plugins/modules/s3_bucket_info.py index bd9faa368a7..91c41539fdd 100644 --- a/plugins/modules/s3_bucket_info.py +++ b/plugins/modules/s3_bucket_info.py @@ -405,11 +405,10 @@ from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict +from ansible_collections.amazon.aws.plugins.module_utils.modules import AnsibleAWSModule from ansible_collections.amazon.aws.plugins.module_utils.retries import AWSRetry from ansible_collections.amazon.aws.plugins.module_utils.tagging import boto3_tag_list_to_ansible_dict -from ansible_collections.amazon.aws.plugins.module_utils.modules import AnsibleAWSModule - def get_bucket_list(module, connection, name="", name_filter=""): """ From 45e086a3a9770cb590b0b3500629e98fe25e72df Mon Sep 17 00:00:00 2001 From: jillr Date: Mon, 2 Mar 2020 19:25:18 +0000 Subject: [PATCH 058/129] Initial commit This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/eb75681585a23ea79e642b86a0f8e64e0f40a6d7 --- plugins/modules/aws_region_info.py | 96 ++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 plugins/modules/aws_region_info.py diff --git a/plugins/modules/aws_region_info.py b/plugins/modules/aws_region_info.py new file mode 100644 index 00000000000..2427beb0841 --- /dev/null +++ b/plugins/modules/aws_region_info.py @@ -0,0 +1,96 @@ +#!/usr/bin/python +# Copyright (c) 2017 Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +ANSIBLE_METADATA = { + 'metadata_version': '1.1', + 'supported_by': 'community', + 'status': ['preview'] +} + +DOCUMENTATION = ''' +module: aws_region_info +short_description: Gather information about AWS regions. +description: + - Gather information about AWS regions. + - This module was called C(aws_region_facts) before Ansible 2.9. The usage did not change. +author: 'Henrique Rodrigues (@Sodki)' +options: + filters: + description: + - A dict of filters to apply. Each dict item consists of a filter key and a filter value. See + U(https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeRegions.html) for + possible filters. Filter names and values are case sensitive. You can also use underscores + instead of dashes (-) in the filter keys, which will take precedence in case of conflict. + default: {} + type: dict +extends_documentation_fragment: +- ansible.amazon.aws +- ansible.amazon.ec2 + +requirements: [botocore, boto3] +''' + +EXAMPLES = ''' +# Note: These examples do not set authentication details, see the AWS Guide for details. + +# Gather information about all regions +- aws_region_info: + +# Gather information about a single region +- aws_region_info: + filters: + region-name: eu-west-1 +''' + +RETURN = ''' +regions: + returned: on success + description: > + Regions that match the provided filters. Each element consists of a dict with all the information related + to that region. + type: list + sample: "[{ + 'endpoint': 'ec2.us-west-1.amazonaws.com', + 'region_name': 'us-west-1' + }]" +''' + +from ansible_collections.ansible.amazon.plugins.module_utils.aws.core import AnsibleAWSModule +from ansible_collections.ansible.amazon.plugins.module_utils.ec2 import AWSRetry, ansible_dict_to_boto3_filter_list, camel_dict_to_snake_dict + +try: + from botocore.exceptions import ClientError, BotoCoreError +except ImportError: + pass # Handled by AnsibleAWSModule + + +def main(): + argument_spec = dict( + filters=dict(default={}, type='dict') + ) + + module = AnsibleAWSModule(argument_spec=argument_spec) + if module._name == 'aws_region_facts': + module.deprecate("The 'aws_region_facts' module has been renamed to 'aws_region_info'", version='2.13') + + connection = module.client('ec2', retry_decorator=AWSRetry.jittered_backoff()) + + # Replace filter key underscores with dashes, for compatibility + sanitized_filters = dict((k.replace('_', '-'), v) for k, v in module.params.get('filters').items()) + + try: + regions = connection.describe_regions( + Filters=ansible_dict_to_boto3_filter_list(sanitized_filters) + ) + except (BotoCoreError, ClientError) as e: + module.fail_json_aws(e, msg="Unable to describe regions.") + + module.exit_json(regions=[camel_dict_to_snake_dict(r) for r in regions['Regions']]) + + +if __name__ == '__main__': + main() From d4cda345c6ef7d615a632029a7a047f592569bd3 Mon Sep 17 00:00:00 2001 From: Jill R <4121322+jillr@users.noreply.github.com> Date: Wed, 25 Mar 2020 15:39:40 -0700 Subject: [PATCH 059/129] Rename collection (#12) * Rename core collection Rename references to ansible.amazon to amazon.aws. * Rename community.amazon to community.aws Fix pep8 line lengths for rewritten amazon.aws imports * Missed a path in shippable.sh * Dependency repos moved This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/235c5db571cc45db5839476c94356c9b91e1f228 --- plugins/modules/aws_region_info.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/modules/aws_region_info.py b/plugins/modules/aws_region_info.py index 2427beb0841..dee88d852ba 100644 --- a/plugins/modules/aws_region_info.py +++ b/plugins/modules/aws_region_info.py @@ -28,8 +28,8 @@ default: {} type: dict extends_documentation_fragment: -- ansible.amazon.aws -- ansible.amazon.ec2 +- amazon.aws.aws +- amazon.aws.ec2 requirements: [botocore, boto3] ''' @@ -59,8 +59,8 @@ }]" ''' -from ansible_collections.ansible.amazon.plugins.module_utils.aws.core import AnsibleAWSModule -from ansible_collections.ansible.amazon.plugins.module_utils.ec2 import AWSRetry, ansible_dict_to_boto3_filter_list, camel_dict_to_snake_dict +from ansible_collections.amazon.aws.plugins.module_utils.aws.core import AnsibleAWSModule +from ansible_collections.amazon.aws.plugins.module_utils.ec2 import AWSRetry, ansible_dict_to_boto3_filter_list, camel_dict_to_snake_dict try: from botocore.exceptions import ClientError, BotoCoreError From 964cc90016789a78bbaaf3d613ee67b76109ba14 Mon Sep 17 00:00:00 2001 From: Jill R <4121322+jillr@users.noreply.github.com> Date: Tue, 19 May 2020 16:06:12 -0700 Subject: [PATCH 060/129] Remove METADATA and cleanup galaxy.yml (#70) * Remove ANSIBLE_METADATA entirely, see ansible/ansible/pull/69454. Remove `license` field from galaxy.yml, in favor of `license_file`. This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/05672a64e2362cc2d865b5af6a57da6bc3cd08e3 --- plugins/modules/aws_region_info.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/plugins/modules/aws_region_info.py b/plugins/modules/aws_region_info.py index dee88d852ba..b20bf9f84ef 100644 --- a/plugins/modules/aws_region_info.py +++ b/plugins/modules/aws_region_info.py @@ -5,11 +5,6 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -ANSIBLE_METADATA = { - 'metadata_version': '1.1', - 'supported_by': 'community', - 'status': ['preview'] -} DOCUMENTATION = ''' module: aws_region_info From 1264ff884208ee9869e68a894c2440882fb611fa Mon Sep 17 00:00:00 2001 From: Jill R <4121322+jillr@users.noreply.github.com> Date: Tue, 16 Jun 2020 11:23:52 -0700 Subject: [PATCH 061/129] Collections related fixes for CI (#96) * Update module deprecations Switch version to `removed_at_date` * Don't install amazon.aws from galaxy We've been using galaxy to install amazon.aws in shippable, but that doesn't really work if we aren't publising faster. Get that collection from git so it is most up to date. * We need to declare python test deps now * missed a python dep This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/7cd211e9383db26bc2aa4cc06e657cf60ed0acc0 --- plugins/modules/aws_region_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/aws_region_info.py b/plugins/modules/aws_region_info.py index b20bf9f84ef..cafb743ece1 100644 --- a/plugins/modules/aws_region_info.py +++ b/plugins/modules/aws_region_info.py @@ -70,7 +70,7 @@ def main(): module = AnsibleAWSModule(argument_spec=argument_spec) if module._name == 'aws_region_facts': - module.deprecate("The 'aws_region_facts' module has been renamed to 'aws_region_info'", version='2.13') + module.deprecate("The 'aws_region_facts' module has been renamed to 'aws_region_info'", date='2021-12-01', collection_name='community.aws') connection = module.client('ec2', retry_decorator=AWSRetry.jittered_backoff()) From 472cba0021088c927f8e6139fdd93b9cf6253d9d Mon Sep 17 00:00:00 2001 From: Abhijeet Kasurde Date: Wed, 17 Jun 2020 01:24:54 +0530 Subject: [PATCH 062/129] Update Examples with FQCN (#67) Updated module examples with FQCN Signed-off-by: Abhijeet Kasurde This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/98173aefbbceed7fc0d9db62687b73f96a55a999 --- plugins/modules/aws_region_info.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/modules/aws_region_info.py b/plugins/modules/aws_region_info.py index cafb743ece1..719cce0cec8 100644 --- a/plugins/modules/aws_region_info.py +++ b/plugins/modules/aws_region_info.py @@ -33,10 +33,10 @@ # Note: These examples do not set authentication details, see the AWS Guide for details. # Gather information about all regions -- aws_region_info: +- community.aws.aws_region_info: # Gather information about a single region -- aws_region_info: +- community.aws.aws_region_info: filters: region-name: eu-west-1 ''' From 6b47f3a10218022c9ed55bc32b3aa71d113944b1 Mon Sep 17 00:00:00 2001 From: flowerysong Date: Tue, 16 Jun 2020 19:30:00 -0400 Subject: [PATCH 063/129] Update module_utils paths to remove aws subdir (#23) Co-authored-by: Ezekiel Hendrickson This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/10853d9441a586ba177006dd889325cfb24a3dd6 --- plugins/modules/aws_region_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/aws_region_info.py b/plugins/modules/aws_region_info.py index 719cce0cec8..dfe7892164b 100644 --- a/plugins/modules/aws_region_info.py +++ b/plugins/modules/aws_region_info.py @@ -54,7 +54,7 @@ }]" ''' -from ansible_collections.amazon.aws.plugins.module_utils.aws.core import AnsibleAWSModule +from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule from ansible_collections.amazon.aws.plugins.module_utils.ec2 import AWSRetry, ansible_dict_to_boto3_filter_list, camel_dict_to_snake_dict try: From dc43507e097adfecf6cfcc834e2975eda8966ef3 Mon Sep 17 00:00:00 2001 From: Jill R <4121322+jillr@users.noreply.github.com> Date: Wed, 17 Jun 2020 09:31:32 -0700 Subject: [PATCH 064/129] Update docs (#99) * Update docs Remove .git from repo url so links in readme will generate correctly Add required ansible version Run latest version of add_docs.py Add version_added string to modules * galaxy.yml was missing authors This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/96ee268e5267f5b12c3d59892bc1279f75aa3135 --- plugins/modules/aws_region_info.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/modules/aws_region_info.py b/plugins/modules/aws_region_info.py index dfe7892164b..09a548b54a7 100644 --- a/plugins/modules/aws_region_info.py +++ b/plugins/modules/aws_region_info.py @@ -9,6 +9,7 @@ DOCUMENTATION = ''' module: aws_region_info short_description: Gather information about AWS regions. +version_added: 1.0.0 description: - Gather information about AWS regions. - This module was called C(aws_region_facts) before Ansible 2.9. The usage did not change. From d6802f3d83887264a6cbda2e288d9f405a1dddb2 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Thu, 30 Jul 2020 19:04:44 +0200 Subject: [PATCH 065/129] Add check_mode support and integration tests for aws_region_info (#139) * Add integration tests for aws_region_info * Add support for check_mode * aws_region_info: clarify "-" vs "_" precedence and make the implementation deterministic This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/39b140ae593d68fdb206b7bc35b71bd24abf7633 --- plugins/modules/aws_region_info.py | 18 ++- .../targets/aws_region_info/aliases | 2 + .../targets/aws_region_info/main.yml | 5 + .../targets/aws_region_info/meta/main.yml | 2 + .../targets/aws_region_info/tasks/main.yml | 107 ++++++++++++++++++ 5 files changed, 128 insertions(+), 6 deletions(-) create mode 100644 tests/integration/targets/aws_region_info/aliases create mode 100644 tests/integration/targets/aws_region_info/main.yml create mode 100644 tests/integration/targets/aws_region_info/meta/main.yml create mode 100644 tests/integration/targets/aws_region_info/tasks/main.yml diff --git a/plugins/modules/aws_region_info.py b/plugins/modules/aws_region_info.py index 09a548b54a7..d0b74e3f112 100644 --- a/plugins/modules/aws_region_info.py +++ b/plugins/modules/aws_region_info.py @@ -17,10 +17,12 @@ options: filters: description: - - A dict of filters to apply. Each dict item consists of a filter key and a filter value. See - U(https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeRegions.html) for - possible filters. Filter names and values are case sensitive. You can also use underscores - instead of dashes (-) in the filter keys, which will take precedence in case of conflict. + - A dict of filters to apply. + - Each dict item consists of a filter key and a filter value. + - See U(https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeRegions.html) for possible filters. + - Filter names and values are case sensitive. + - You can use underscores instead of dashes (-) in the filter keys. + - Filter keys with underscores will take precedence in case of conflict. default: {} type: dict extends_documentation_fragment: @@ -69,14 +71,18 @@ def main(): filters=dict(default={}, type='dict') ) - module = AnsibleAWSModule(argument_spec=argument_spec) + module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) if module._name == 'aws_region_facts': module.deprecate("The 'aws_region_facts' module has been renamed to 'aws_region_info'", date='2021-12-01', collection_name='community.aws') connection = module.client('ec2', retry_decorator=AWSRetry.jittered_backoff()) # Replace filter key underscores with dashes, for compatibility - sanitized_filters = dict((k.replace('_', '-'), v) for k, v in module.params.get('filters').items()) + sanitized_filters = dict(module.params.get('filters')) + for k in module.params.get('filters').keys(): + if "_" in k: + sanitized_filters[k.replace('_', '-')] = sanitized_filters[k] + del sanitized_filters[k] try: regions = connection.describe_regions( diff --git a/tests/integration/targets/aws_region_info/aliases b/tests/integration/targets/aws_region_info/aliases new file mode 100644 index 00000000000..72a9fb4f570 --- /dev/null +++ b/tests/integration/targets/aws_region_info/aliases @@ -0,0 +1,2 @@ +cloud/aws +shippable/aws/group4 diff --git a/tests/integration/targets/aws_region_info/main.yml b/tests/integration/targets/aws_region_info/main.yml new file mode 100644 index 00000000000..abffda9161e --- /dev/null +++ b/tests/integration/targets/aws_region_info/main.yml @@ -0,0 +1,5 @@ +- hosts: localhost + connection: local + environment: "{{ ansible_test.environment }}" + tasks: + - include_tasks: 'tasks/tests.yml' diff --git a/tests/integration/targets/aws_region_info/meta/main.yml b/tests/integration/targets/aws_region_info/meta/main.yml new file mode 100644 index 00000000000..1810d4bec98 --- /dev/null +++ b/tests/integration/targets/aws_region_info/meta/main.yml @@ -0,0 +1,2 @@ +dependencies: + - setup_remote_tmp_dir diff --git a/tests/integration/targets/aws_region_info/tasks/main.yml b/tests/integration/targets/aws_region_info/tasks/main.yml new file mode 100644 index 00000000000..3edbbaded2a --- /dev/null +++ b/tests/integration/targets/aws_region_info/tasks/main.yml @@ -0,0 +1,107 @@ +--- +- module_defaults: + group/aws: + aws_access_key: '{{ aws_access_key | default(omit) }}' + aws_secret_key: '{{ aws_secret_key | default(omit) }}' + security_token: '{{ security_token | default(omit) }}' + region: '{{ aws_region | default(omit) }}' + + block: + - name: 'List available Regions' + aws_region_info: + register: regions + + - name: check task return attributes + vars: + first_region: '{{ regions.regions[0] }}' + assert: + that: + - regions is successful + - regions is not changed + - '"regions" in regions' + - '"endpoint" in first_region' + - '"opt_in_status" in first_region' + - '"region_name" in first_region' + + - name: 'List available Regions - check_mode' + aws_region_info: + register: check_regions + + - name: check task return attributes - check_mode + vars: + first_region: '{{ check_regions.regions[0] }}' + assert: + that: + - check_regions is successful + - check_regions is not changed + - '"regions" in check_regions' + - '"endpoint" in first_region' + - '"opt_in_status" in first_region' + - '"region_name" in first_region' + + - name: 'Filter available Regions using - ("region-name")' + aws_region_info: + filters: + region-name: 'us-west-1' + register: us_west_1 + + - name: check task return attributes - filtering using - + vars: + first_region: '{{ us_west_1.regions[0] }}' + assert: + that: + - us_west_1 is successful + - us_west_1 is not changed + - '"regions" in us_west_1' + - us_west_1.regions | length == 1 + - '"endpoint" in first_region' + - first_region.endpoint == 'ec2.us-west-1.amazonaws.com' + - '"opt_in_status" in first_region' + - first_region.opt_in_status == 'opt-in-not-required' + - '"region_name" in first_region' + - first_region.region_name == 'us-west-1' + + - name: 'Filter available Regions using _ ("region_name")' + aws_region_info: + filters: + region_name: 'us-west-2' + register: us_west_2 + + - name: check task return attributes - filtering using _ + vars: + first_region: '{{ us_west_2.regions[0] }}' + assert: + that: + - us_west_2 is successful + - us_west_2 is not changed + - '"regions" in us_west_2' + - us_west_2.regions | length == 1 + - '"endpoint" in first_region' + - first_region.endpoint == 'ec2.us-west-2.amazonaws.com' + - '"opt_in_status" in first_region' + - first_region.opt_in_status == 'opt-in-not-required' + - '"region_name" in first_region' + - first_region.region_name == 'us-west-2' + + - name: 'Filter available Regions using _ and - to check precedence' + aws_region_info: + filters: + region-name: 'eu-west-1' + region_name: 'eu-central-1' + register: regions_prededence + + - name: check task return attributes - precedence + vars: + first_region: '{{ regions_prededence.regions[0] }}' + assert: + that: + - regions_prededence is successful + - regions_prededence is not changed + - '"regions" in regions_prededence' + - regions_prededence.regions | length == 1 + - '"endpoint" in first_region' + - first_region.endpoint == 'ec2.eu-central-1.amazonaws.com' + - '"opt_in_status" in first_region' + - first_region.opt_in_status == 'opt-in-not-required' + - '"region_name" in first_region' + - first_region.region_name == 'eu-central-1' From 02cc13ba47c0fa3988ba4ee4403a2b8da015ede9 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Fri, 19 Feb 2021 00:55:39 +0100 Subject: [PATCH 066/129] Enable AWSRetry on aws_region_info (#422) * Enable AWSRetry on aws_region_info * changelog This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/ea740a2a681080358250e69fd66a6dae72a8d92b --- plugins/modules/aws_region_info.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/modules/aws_region_info.py b/plugins/modules/aws_region_info.py index d0b74e3f112..bedb8a5f1fa 100644 --- a/plugins/modules/aws_region_info.py +++ b/plugins/modules/aws_region_info.py @@ -58,7 +58,9 @@ ''' from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule -from ansible_collections.amazon.aws.plugins.module_utils.ec2 import AWSRetry, ansible_dict_to_boto3_filter_list, camel_dict_to_snake_dict +from ansible_collections.amazon.aws.plugins.module_utils.ec2 import AWSRetry +from ansible_collections.amazon.aws.plugins.module_utils.ec2 import ansible_dict_to_boto3_filter_list +from ansible_collections.amazon.aws.plugins.module_utils.ec2 import camel_dict_to_snake_dict try: from botocore.exceptions import ClientError, BotoCoreError @@ -86,6 +88,7 @@ def main(): try: regions = connection.describe_regions( + aws_retry=True, Filters=ansible_dict_to_boto3_filter_list(sanitized_filters) ) except (BotoCoreError, ClientError) as e: From 51f467b22b138b40ec9ccf798d5b271a4e064da1 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Thu, 6 May 2021 21:01:46 +0200 Subject: [PATCH 067/129] Update the default module requirements from python 2.6/boto to python 3.6/boto3 This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/c097c55293be0834a2b9d394733ec28965d142d7 --- plugins/modules/aws_region_info.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/modules/aws_region_info.py b/plugins/modules/aws_region_info.py index bedb8a5f1fa..67b71d6f868 100644 --- a/plugins/modules/aws_region_info.py +++ b/plugins/modules/aws_region_info.py @@ -28,8 +28,6 @@ extends_documentation_fragment: - amazon.aws.aws - amazon.aws.ec2 - -requirements: [botocore, boto3] ''' EXAMPLES = ''' From 9b442bc8bef7c9c332d498f4b71c009a5b8a6091 Mon Sep 17 00:00:00 2001 From: jillr Date: Thu, 29 Apr 2021 21:58:50 +0000 Subject: [PATCH 068/129] Remove shippable references from repo This collection has been operating on Zuul CI for some weeks now This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/4e0d83c65568a99a24307e37a14e6e0b173c948b --- tests/integration/targets/aws_region_info/aliases | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/integration/targets/aws_region_info/aliases b/tests/integration/targets/aws_region_info/aliases index 72a9fb4f570..4ef4b2067d0 100644 --- a/tests/integration/targets/aws_region_info/aliases +++ b/tests/integration/targets/aws_region_info/aliases @@ -1,2 +1 @@ cloud/aws -shippable/aws/group4 From 795eb79ad9b9e77c41d012c1837b735a014387cb Mon Sep 17 00:00:00 2001 From: Jill R <4121322+jillr@users.noreply.github.com> Date: Thu, 2 Dec 2021 02:58:06 -0700 Subject: [PATCH 069/129] Remove deprecated "facts" aliases (#814) Remove deprecated "facts" aliases SUMMARY Modules named "facts.py" that do not return ansible_facts were renamed to "info.py" in 2.9. Remove these aliases now that the deprecation period is over. This PR should be included in 3.0.0 of the collection. ISSUE TYPE Bugfix Pull Request COMPONENT NAME *_facts.py Reviewed-by: Mark Chappell Reviewed-by: Jill R Reviewed-by: None This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/68aaa7057be46a3ab36f572fd0013d64653af909 --- plugins/modules/aws_region_info.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugins/modules/aws_region_info.py b/plugins/modules/aws_region_info.py index 67b71d6f868..66349e318a8 100644 --- a/plugins/modules/aws_region_info.py +++ b/plugins/modules/aws_region_info.py @@ -12,7 +12,6 @@ version_added: 1.0.0 description: - Gather information about AWS regions. - - This module was called C(aws_region_facts) before Ansible 2.9. The usage did not change. author: 'Henrique Rodrigues (@Sodki)' options: filters: @@ -72,8 +71,6 @@ def main(): ) module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) - if module._name == 'aws_region_facts': - module.deprecate("The 'aws_region_facts' module has been renamed to 'aws_region_info'", date='2021-12-01', collection_name='community.aws') connection = module.client('ec2', retry_decorator=AWSRetry.jittered_backoff()) From 8c5aa4cf27de4465586f5b5d0c87d339064d3fda Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Fri, 22 Apr 2022 11:44:07 +0200 Subject: [PATCH 070/129] Integration test dependency cleanup (#1086) Integration test dependency cleanup SUMMARY remove dependencies on setup_remote_tmp_dir where it's not used (often just copy & paste from another test) remove setup_ec2 (no main.yml means it's not doing anything) remove prepare_tests (empty main.yml means it's not doing anything) ISSUE TYPE Feature Pull Request COMPONENT NAME tests/integration/targets ADDITIONAL INFORMATION By cleaning up what we have we reduce the chance of people copying things about "because that's what test XYZ did". Reviewed-by: Alina Buzachis Reviewed-by: Mark Woolley This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/dd12046a1e2d5f39692b1890ff07e06c56b3bf0e --- tests/integration/targets/aws_region_info/meta/main.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/integration/targets/aws_region_info/meta/main.yml b/tests/integration/targets/aws_region_info/meta/main.yml index 1810d4bec98..32cf5dda7ed 100644 --- a/tests/integration/targets/aws_region_info/meta/main.yml +++ b/tests/integration/targets/aws_region_info/meta/main.yml @@ -1,2 +1 @@ -dependencies: - - setup_remote_tmp_dir +dependencies: [] From f78422087ebcd6983f8c23bdb4fc0ef9f361c036 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Tue, 26 Jul 2022 12:01:24 +0200 Subject: [PATCH 071/129] Nudge module to trigger Sanity tests (#1372) aws_region_info - Minor docs linting SUMMARY Nudge a module to trigger the sanity tests ISSUE TYPE Docs Pull Request COMPONENT NAME plugins/modules/aws_region_info.py ADDITIONAL INFORMATION Reviewed-by: Alina Buzachis This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/41c7dd04df82974a468cdcb15c8373f25c58bc61 --- plugins/modules/aws_region_info.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/plugins/modules/aws_region_info.py b/plugins/modules/aws_region_info.py index 66349e318a8..fc4c38b2579 100644 --- a/plugins/modules/aws_region_info.py +++ b/plugins/modules/aws_region_info.py @@ -8,11 +8,12 @@ DOCUMENTATION = ''' module: aws_region_info -short_description: Gather information about AWS regions. +short_description: Gather information about AWS regions version_added: 1.0.0 description: - - Gather information about AWS regions. -author: 'Henrique Rodrigues (@Sodki)' + - Gather information about AWS regions. +author: + - 'Henrique Rodrigues (@Sodki)' options: filters: description: @@ -25,8 +26,8 @@ default: {} type: dict extends_documentation_fragment: -- amazon.aws.aws -- amazon.aws.ec2 + - amazon.aws.aws + - amazon.aws.ec2 ''' EXAMPLES = ''' From 23b8b75387a474e78d1e3798c80323e1c05afd85 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Wed, 5 Oct 2022 17:04:40 +0200 Subject: [PATCH 072/129] Update extends_documentation_fragment with amazon.aws.boto3 (#1459) Update extends_documentation_fragment with amazon.aws.boto3 Depends-On: ansible/ansible-zuul-jobs#1654 SUMMARY As per ansible-collections/amazon.aws#985 add amazon.aws.boto3. ISSUE TYPE Docs Pull Request COMPONENT NAME several Reviewed-by: Jill R Reviewed-by: Mark Chappell Reviewed-by: Markus Bergholz This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/bd3c03fcba0848f593b86309740fa73e986a9646 --- plugins/modules/aws_region_info.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/modules/aws_region_info.py b/plugins/modules/aws_region_info.py index fc4c38b2579..126455a8cff 100644 --- a/plugins/modules/aws_region_info.py +++ b/plugins/modules/aws_region_info.py @@ -28,6 +28,7 @@ extends_documentation_fragment: - amazon.aws.aws - amazon.aws.ec2 + - amazon.aws.boto3 ''' EXAMPLES = ''' From a1ad4bb87e17b36dcda8d973265d0fe64fbb3fcc Mon Sep 17 00:00:00 2001 From: Bikouo Aubin <79859644+abikouo@users.noreply.github.com> Date: Tue, 10 Jan 2023 19:22:13 +0100 Subject: [PATCH 073/129] Ansible User-Agent identification for community.aws (#1632) Ansible User-Agent identification for community.aws SUMMARY The value will be similar to this APN/1.0 Ansible/2.14.1 community.aws/6.0.0-dev0 ISSUE TYPE Feature Pull Request Reviewed-by: Mark Chappell Reviewed-by: Bikouo Aubin Reviewed-by: Alina Buzachis This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/a8cbce24071bcc62fe4594c38aff1baf18bd2862 --- plugins/modules/aws_region_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/aws_region_info.py b/plugins/modules/aws_region_info.py index 126455a8cff..ad9368ef14c 100644 --- a/plugins/modules/aws_region_info.py +++ b/plugins/modules/aws_region_info.py @@ -56,7 +56,7 @@ }]" ''' -from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule +from ansible_collections.community.aws.plugins.module_utils.modules import AnsibleCommunityAWSModule as AnsibleAWSModule from ansible_collections.amazon.aws.plugins.module_utils.ec2 import AWSRetry from ansible_collections.amazon.aws.plugins.module_utils.ec2 import ansible_dict_to_boto3_filter_list from ansible_collections.amazon.aws.plugins.module_utils.ec2 import camel_dict_to_snake_dict From a9def4616ceec10c8b82d978137ea8ee6aeee695 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Wed, 8 Mar 2023 12:07:26 +0100 Subject: [PATCH 074/129] Cleanup headers and imports (#1738) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cleanup headers and imports SUMMARY Mass update of imports, docs fragments and file headers Many of the amazon.aws module_utils and docs fragments got moved about, update community.aws to reflect this. Consistently apply the comment headers as documented at https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_documenting.html#python-shebang-utf-8-coding ISSUE TYPE Docs Pull Request Feature Pull Request COMPONENT NAME ADDITIONAL INFORMATION Header cleanup based upon: https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_documenting.html#python-shebang-utf-8-coding Begin your Ansible module with #!/usr/bin/python - this “shebang” allows ansible_python_interpreter to work. Follow the shebang immediately with # -*- coding: utf-8 -*- to clarify that the file is UTF-8 encoded. and https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_documenting.html#copyright-and-license After the shebang and UTF-8 coding, add a copyright line with the original copyright holder and a license declaration. The license declaration should be ONLY one line, not the full GPL prefix. ... Additions to the module (for instance, rewrites) are not permitted to add additional copyright lines other than the default copyright statement if missing: Reviewed-by: Alina Buzachis This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/a4f20bf114bfab19b1c84c4ecf42efd5614ab80c --- plugins/modules/aws_region_info.py | 37 +++++++++++++++--------------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/plugins/modules/aws_region_info.py b/plugins/modules/aws_region_info.py index ad9368ef14c..837e9326552 100644 --- a/plugins/modules/aws_region_info.py +++ b/plugins/modules/aws_region_info.py @@ -1,12 +1,10 @@ #!/usr/bin/python +# -*- coding: utf-8 -*- + # Copyright (c) 2017 Ansible Project # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - - -DOCUMENTATION = ''' +DOCUMENTATION = r""" module: aws_region_info short_description: Gather information about AWS regions version_added: 1.0.0 @@ -26,12 +24,12 @@ default: {} type: dict extends_documentation_fragment: - - amazon.aws.aws - - amazon.aws.ec2 + - amazon.aws.common.modules + - amazon.aws.region.modules - amazon.aws.boto3 -''' +""" -EXAMPLES = ''' +EXAMPLES = r""" # Note: These examples do not set authentication details, see the AWS Guide for details. # Gather information about all regions @@ -41,9 +39,9 @@ - community.aws.aws_region_info: filters: region-name: eu-west-1 -''' +""" -RETURN = ''' +RETURN = r""" regions: returned: on success description: > @@ -54,18 +52,21 @@ 'endpoint': 'ec2.us-west-1.amazonaws.com', 'region_name': 'us-west-1' }]" -''' - -from ansible_collections.community.aws.plugins.module_utils.modules import AnsibleCommunityAWSModule as AnsibleAWSModule -from ansible_collections.amazon.aws.plugins.module_utils.ec2 import AWSRetry -from ansible_collections.amazon.aws.plugins.module_utils.ec2 import ansible_dict_to_boto3_filter_list -from ansible_collections.amazon.aws.plugins.module_utils.ec2 import camel_dict_to_snake_dict +""" try: - from botocore.exceptions import ClientError, BotoCoreError + from botocore.exceptions import BotoCoreError + from botocore.exceptions import ClientError except ImportError: pass # Handled by AnsibleAWSModule +from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict + +from ansible_collections.amazon.aws.plugins.module_utils.retries import AWSRetry +from ansible_collections.amazon.aws.plugins.module_utils.transformation import ansible_dict_to_boto3_filter_list + +from ansible_collections.community.aws.plugins.module_utils.modules import AnsibleCommunityAWSModule as AnsibleAWSModule + def main(): argument_spec = dict( From a042a4fe21c4f3dc5cb26f6c88795553d01941ef Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Wed, 26 Apr 2023 19:26:07 +0200 Subject: [PATCH 075/129] Big Black PR (#1784) * Black prep * Black * changelog * Fix pylint unused-import in tests * Split SSM connection plugin changes * disable glue tests - bucket's missing * Disable s3_logging and s3_sync tests This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/2c4575c248776c65d66b06cd60fa09b0dae1cd6f --- plugins/modules/aws_region_info.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/plugins/modules/aws_region_info.py b/plugins/modules/aws_region_info.py index 837e9326552..a268c13b3c8 100644 --- a/plugins/modules/aws_region_info.py +++ b/plugins/modules/aws_region_info.py @@ -70,30 +70,29 @@ def main(): argument_spec = dict( - filters=dict(default={}, type='dict') + filters=dict(default={}, type="dict"), ) module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) - connection = module.client('ec2', retry_decorator=AWSRetry.jittered_backoff()) + connection = module.client("ec2", retry_decorator=AWSRetry.jittered_backoff()) # Replace filter key underscores with dashes, for compatibility - sanitized_filters = dict(module.params.get('filters')) - for k in module.params.get('filters').keys(): + sanitized_filters = dict(module.params.get("filters")) + for k in module.params.get("filters").keys(): if "_" in k: - sanitized_filters[k.replace('_', '-')] = sanitized_filters[k] + sanitized_filters[k.replace("_", "-")] = sanitized_filters[k] del sanitized_filters[k] try: regions = connection.describe_regions( - aws_retry=True, - Filters=ansible_dict_to_boto3_filter_list(sanitized_filters) + aws_retry=True, Filters=ansible_dict_to_boto3_filter_list(sanitized_filters) ) except (BotoCoreError, ClientError) as e: module.fail_json_aws(e, msg="Unable to describe regions.") - module.exit_json(regions=[camel_dict_to_snake_dict(r) for r in regions['Regions']]) + module.exit_json(regions=[camel_dict_to_snake_dict(r) for r in regions["Regions"]]) -if __name__ == '__main__': +if __name__ == "__main__": main() From a2c9fbb0770caec1a157c1ab49e432cc977e3579 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Thu, 31 Aug 2023 17:58:59 +0200 Subject: [PATCH 076/129] Mass update of docs and tests (credentials/session tokens) (#1921) Mass update of docs and tests (credentials/session tokens) SUMMARY We had a cleanup of credentials/session parameters which included a batch of deprecations and renames. Ensure that all of our tests and docs are using the 'canonical' names ISSUE TYPE Docs Pull Request COMPONENT NAME plugins/modules/batch_compute_environment.py plugins/modules/cloudformation_exports_info.py plugins/modules/ec2_vpc_vpn.py plugins/modules/elasticache.py plugins/modules/elasticache_parameter_group.py plugins/modules/elasticache_snapshot.py plugins/modules/ses_rule_set.py plugins/modules/sts_assume_role.py plugins/modules/sts_session_token.py tests/integration ADDITIONAL INFORMATION See also ansible-collections/amazon.aws#1172 ansible-collections/amazon.aws#1714 Reviewed-by: Alina Buzachis This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/4a5b50e9b9c0d6ca1a1f802f3b03d4f503c16885 --- tests/integration/targets/aws_region_info/tasks/main.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/integration/targets/aws_region_info/tasks/main.yml b/tests/integration/targets/aws_region_info/tasks/main.yml index 3edbbaded2a..4391bd242ef 100644 --- a/tests/integration/targets/aws_region_info/tasks/main.yml +++ b/tests/integration/targets/aws_region_info/tasks/main.yml @@ -1,10 +1,10 @@ --- - module_defaults: group/aws: - aws_access_key: '{{ aws_access_key | default(omit) }}' - aws_secret_key: '{{ aws_secret_key | default(omit) }}' - security_token: '{{ security_token | default(omit) }}' - region: '{{ aws_region | default(omit) }}' + access_key: '{{ aws_access_key }}' + secret_key: '{{ aws_secret_key }}' + session_token: '{{ security_token | default(omit) }}' + region: '{{ aws_region }}' block: - name: 'List available Regions' From 2376b61a615902ab92ce1e9cc6142d60b4a18540 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Mon, 2 Oct 2023 17:19:32 +0200 Subject: [PATCH 077/129] Update runtime --- meta/runtime.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/meta/runtime.yml b/meta/runtime.yml index da395988b6f..7ea864da1e5 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -6,6 +6,7 @@ action_groups: - autoscaling_group_info - aws_az_info - aws_caller_info + - aws_region_info - aws_s3 - backup_plan - backup_plan_info From c9df243f6b1319010e65f307beca996357597b85 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Mon, 2 Oct 2023 17:19:32 +0200 Subject: [PATCH 078/129] Update FQDN --- plugins/modules/aws_region_info.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/modules/aws_region_info.py b/plugins/modules/aws_region_info.py index a268c13b3c8..9260589b3e9 100644 --- a/plugins/modules/aws_region_info.py +++ b/plugins/modules/aws_region_info.py @@ -33,10 +33,10 @@ # Note: These examples do not set authentication details, see the AWS Guide for details. # Gather information about all regions -- community.aws.aws_region_info: +- amazon.aws.aws_region_info: # Gather information about a single region -- community.aws.aws_region_info: +- amazon.aws.aws_region_info: filters: region-name: eu-west-1 """ From ee68f019ac6381789d7be68e51ebe50b02148da1 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Mon, 2 Oct 2023 17:19:32 +0200 Subject: [PATCH 079/129] Update AnsibleAWSModule import path --- plugins/modules/aws_region_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/aws_region_info.py b/plugins/modules/aws_region_info.py index 9260589b3e9..0bf8cc6b284 100644 --- a/plugins/modules/aws_region_info.py +++ b/plugins/modules/aws_region_info.py @@ -65,7 +65,7 @@ from ansible_collections.amazon.aws.plugins.module_utils.retries import AWSRetry from ansible_collections.amazon.aws.plugins.module_utils.transformation import ansible_dict_to_boto3_filter_list -from ansible_collections.community.aws.plugins.module_utils.modules import AnsibleCommunityAWSModule as AnsibleAWSModule +from ansible_collections.amazon.aws.plugins.module_utils.modules import AnsibleAWSModule def main(): From 3e20c2d0512c2518eb9e4fc531883a73c20afc47 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Mon, 2 Oct 2023 17:19:32 +0200 Subject: [PATCH 080/129] Remove collection reference inside the tests --- .../targets/aws_region_info/main.yml | 4 +-- .../targets/aws_region_info/tasks/main.yml | 25 +++++++------------ 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/tests/integration/targets/aws_region_info/main.yml b/tests/integration/targets/aws_region_info/main.yml index abffda9161e..f90869efe55 100644 --- a/tests/integration/targets/aws_region_info/main.yml +++ b/tests/integration/targets/aws_region_info/main.yml @@ -1,5 +1,5 @@ - hosts: localhost connection: local - environment: "{{ ansible_test.environment }}" + environment: '{{ ansible_test.environment }}' tasks: - - include_tasks: 'tasks/tests.yml' + - include_tasks: tasks/tests.yml diff --git a/tests/integration/targets/aws_region_info/tasks/main.yml b/tests/integration/targets/aws_region_info/tasks/main.yml index 4391bd242ef..cb592de207a 100644 --- a/tests/integration/targets/aws_region_info/tasks/main.yml +++ b/tests/integration/targets/aws_region_info/tasks/main.yml @@ -1,16 +1,13 @@ ---- - module_defaults: group/aws: access_key: '{{ aws_access_key }}' secret_key: '{{ aws_secret_key }}' session_token: '{{ security_token | default(omit) }}' region: '{{ aws_region }}' - block: - - name: 'List available Regions' + - name: List available Regions aws_region_info: register: regions - - name: check task return attributes vars: first_region: '{{ regions.regions[0] }}' @@ -23,10 +20,9 @@ - '"opt_in_status" in first_region' - '"region_name" in first_region' - - name: 'List available Regions - check_mode' + - name: List available Regions - check_mode aws_region_info: register: check_regions - - name: check task return attributes - check_mode vars: first_region: '{{ check_regions.regions[0] }}' @@ -39,12 +35,11 @@ - '"opt_in_status" in first_region' - '"region_name" in first_region' - - name: 'Filter available Regions using - ("region-name")' + - name: Filter available Regions using - ("region-name") aws_region_info: filters: - region-name: 'us-west-1' + region-name: us-west-1 register: us_west_1 - - name: check task return attributes - filtering using - vars: first_region: '{{ us_west_1.regions[0] }}' @@ -61,12 +56,11 @@ - '"region_name" in first_region' - first_region.region_name == 'us-west-1' - - name: 'Filter available Regions using _ ("region_name")' + - name: Filter available Regions using _ ("region_name") aws_region_info: filters: - region_name: 'us-west-2' + region_name: us-west-2 register: us_west_2 - - name: check task return attributes - filtering using _ vars: first_region: '{{ us_west_2.regions[0] }}' @@ -83,13 +77,12 @@ - '"region_name" in first_region' - first_region.region_name == 'us-west-2' - - name: 'Filter available Regions using _ and - to check precedence' + - name: Filter available Regions using _ and - to check precedence aws_region_info: filters: - region-name: 'eu-west-1' - region_name: 'eu-central-1' + region-name: eu-west-1 + region_name: eu-central-1 register: regions_prededence - - name: check task return attributes - precedence vars: first_region: '{{ regions_prededence.regions[0] }}' From d1d5b3309c167ac0df3094e4a3397835915a4dd7 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Mon, 2 Oct 2023 17:19:32 +0200 Subject: [PATCH 081/129] Add changelog fragment --- changelogs/fragments/migrate_aws_region_info.yml | 5 +++++ plugins/modules/aws_region_info.py | 1 + 2 files changed, 6 insertions(+) create mode 100644 changelogs/fragments/migrate_aws_region_info.yml diff --git a/changelogs/fragments/migrate_aws_region_info.yml b/changelogs/fragments/migrate_aws_region_info.yml new file mode 100644 index 00000000000..189f1955d29 --- /dev/null +++ b/changelogs/fragments/migrate_aws_region_info.yml @@ -0,0 +1,5 @@ +--- +major_changes: + - aws_region_info - The module has been migrated from the ``community.aws`` collection. + Playbooks using the Fully Qualified Collection Name for this module should be + updated to use ``amazon.aws.aws_region_info``. diff --git a/plugins/modules/aws_region_info.py b/plugins/modules/aws_region_info.py index 0bf8cc6b284..bb3f7896d49 100644 --- a/plugins/modules/aws_region_info.py +++ b/plugins/modules/aws_region_info.py @@ -8,6 +8,7 @@ module: aws_region_info short_description: Gather information about AWS regions version_added: 1.0.0 +version_added_collection: community.aws description: - Gather information about AWS regions. author: From 0e70ea30c8443b60749a0d89c4c315c1c2a3dfb4 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Mon, 2 Oct 2023 17:25:23 +0200 Subject: [PATCH 082/129] Apply isort Signed-off-by: Alina Buzachis --- plugins/modules/aws_region_info.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/modules/aws_region_info.py b/plugins/modules/aws_region_info.py index bb3f7896d49..ccec48bd94e 100644 --- a/plugins/modules/aws_region_info.py +++ b/plugins/modules/aws_region_info.py @@ -63,11 +63,10 @@ from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict +from ansible_collections.amazon.aws.plugins.module_utils.modules import AnsibleAWSModule from ansible_collections.amazon.aws.plugins.module_utils.retries import AWSRetry from ansible_collections.amazon.aws.plugins.module_utils.transformation import ansible_dict_to_boto3_filter_list -from ansible_collections.amazon.aws.plugins.module_utils.modules import AnsibleAWSModule - def main(): argument_spec = dict( From 2f21617cedc5374125ff26b78762954591a15cf7 Mon Sep 17 00:00:00 2001 From: jillr Date: Mon, 2 Mar 2020 19:25:18 +0000 Subject: [PATCH 083/129] Initial commit This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/eb75681585a23ea79e642b86a0f8e64e0f40a6d7 --- plugins/modules/sts_assume_role.py | 180 ++++++++ .../targets/sts_assume_role/aliases | 2 + .../targets/sts_assume_role/meta/main.yml | 3 + .../targets/sts_assume_role/tasks/main.yml | 384 ++++++++++++++++++ .../sts_assume_role/templates/policy.json.j2 | 12 + 5 files changed, 581 insertions(+) create mode 100644 plugins/modules/sts_assume_role.py create mode 100644 tests/integration/targets/sts_assume_role/aliases create mode 100644 tests/integration/targets/sts_assume_role/meta/main.yml create mode 100644 tests/integration/targets/sts_assume_role/tasks/main.yml create mode 100644 tests/integration/targets/sts_assume_role/templates/policy.json.j2 diff --git a/plugins/modules/sts_assume_role.py b/plugins/modules/sts_assume_role.py new file mode 100644 index 00000000000..3c03f291706 --- /dev/null +++ b/plugins/modules/sts_assume_role.py @@ -0,0 +1,180 @@ +#!/usr/bin/python +# Copyright: Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['stableinterface'], + 'supported_by': 'community'} + + +DOCUMENTATION = ''' +--- +module: sts_assume_role +short_description: Assume a role using AWS Security Token Service and obtain temporary credentials +description: + - Assume a role using AWS Security Token Service and obtain temporary credentials. +author: + - Boris Ekelchik (@bekelchik) + - Marek Piatek (@piontas) +options: + role_arn: + description: + - The Amazon Resource Name (ARN) of the role that the caller is + assuming U(https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_Identifiers.html#Identifiers_ARNs). + required: true + type: str + role_session_name: + description: + - Name of the role's session - will be used by CloudTrail. + required: true + type: str + policy: + description: + - Supplemental policy to use in addition to assumed role's policies. + type: str + duration_seconds: + description: + - The duration, in seconds, of the role session. The value can range from 900 seconds (15 minutes) to 43200 seconds (12 hours). + - The max depends on the IAM role's sessions duration setting. + - By default, the value is set to 3600 seconds. + type: int + external_id: + description: + - A unique identifier that is used by third parties to assume a role in their customers' accounts. + type: str + mfa_serial_number: + description: + - The identification number of the MFA device that is associated with the user who is making the AssumeRole call. + type: str + mfa_token: + description: + - The value provided by the MFA device, if the trust policy of the role being assumed requires MFA. + type: str +notes: + - In order to use the assumed role in a following playbook task you must pass the access_key, access_secret and access_token. +extends_documentation_fragment: +- ansible.amazon.aws +- ansible.amazon.ec2 + +requirements: + - boto3 + - botocore + - python >= 2.6 +''' + +RETURN = ''' +sts_creds: + description: The temporary security credentials, which include an access key ID, a secret access key, and a security (or session) token + returned: always + type: dict + sample: + access_key: XXXXXXXXXXXXXXXXXXXX + expiration: 2017-11-11T11:11:11+00:00 + secret_key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + session_token: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +sts_user: + description: The Amazon Resource Name (ARN) and the assumed role ID + returned: always + type: dict + sample: + assumed_role_id: arn:aws:sts::123456789012:assumed-role/demo/Bob + arn: ARO123EXAMPLE123:Bob +changed: + description: True if obtaining the credentials succeeds + type: bool + returned: always +''' + +EXAMPLES = ''' +# Note: These examples do not set authentication details, see the AWS Guide for details. + +# Assume an existing role (more details: https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html) +- sts_assume_role: + role_arn: "arn:aws:iam::123456789012:role/someRole" + role_session_name: "someRoleSession" + register: assumed_role + +# Use the assumed role above to tag an instance in account 123456789012 +- ec2_tag: + aws_access_key: "{{ assumed_role.sts_creds.access_key }}" + aws_secret_key: "{{ assumed_role.sts_creds.secret_key }}" + security_token: "{{ assumed_role.sts_creds.session_token }}" + resource: i-xyzxyz01 + state: present + tags: + MyNewTag: value + +''' + +from ansible_collections.ansible.amazon.plugins.module_utils.aws.core import AnsibleAWSModule +from ansible_collections.ansible.amazon.plugins.module_utils.ec2 import camel_dict_to_snake_dict + +try: + from botocore.exceptions import ClientError, ParamValidationError +except ImportError: + pass # caught by AnsibleAWSModule + + +def _parse_response(response): + credentials = response.get('Credentials', {}) + user = response.get('AssumedRoleUser', {}) + + sts_cred = { + 'access_key': credentials.get('AccessKeyId'), + 'secret_key': credentials.get('SecretAccessKey'), + 'session_token': credentials.get('SessionToken'), + 'expiration': credentials.get('Expiration') + + } + sts_user = camel_dict_to_snake_dict(user) + return sts_cred, sts_user + + +def assume_role_policy(connection, module): + params = { + 'RoleArn': module.params.get('role_arn'), + 'RoleSessionName': module.params.get('role_session_name'), + 'Policy': module.params.get('policy'), + 'DurationSeconds': module.params.get('duration_seconds'), + 'ExternalId': module.params.get('external_id'), + 'SerialNumber': module.params.get('mfa_serial_number'), + 'TokenCode': module.params.get('mfa_token') + } + changed = False + + kwargs = dict((k, v) for k, v in params.items() if v is not None) + + try: + response = connection.assume_role(**kwargs) + changed = True + except (ClientError, ParamValidationError) as e: + module.fail_json_aws(e) + + sts_cred, sts_user = _parse_response(response) + module.exit_json(changed=changed, sts_creds=sts_cred, sts_user=sts_user) + + +def main(): + argument_spec = dict( + role_arn=dict(required=True), + role_session_name=dict(required=True), + duration_seconds=dict(required=False, default=None, type='int'), + external_id=dict(required=False, default=None), + policy=dict(required=False, default=None), + mfa_serial_number=dict(required=False, default=None), + mfa_token=dict(required=False, default=None) + ) + + module = AnsibleAWSModule(argument_spec=argument_spec) + + connection = module.client('sts') + + assume_role_policy(connection, module) + + +if __name__ == '__main__': + main() diff --git a/tests/integration/targets/sts_assume_role/aliases b/tests/integration/targets/sts_assume_role/aliases new file mode 100644 index 00000000000..6e3860bee23 --- /dev/null +++ b/tests/integration/targets/sts_assume_role/aliases @@ -0,0 +1,2 @@ +cloud/aws +shippable/aws/group2 diff --git a/tests/integration/targets/sts_assume_role/meta/main.yml b/tests/integration/targets/sts_assume_role/meta/main.yml new file mode 100644 index 00000000000..1f64f1169a9 --- /dev/null +++ b/tests/integration/targets/sts_assume_role/meta/main.yml @@ -0,0 +1,3 @@ +dependencies: + - prepare_tests + - setup_ec2 diff --git a/tests/integration/targets/sts_assume_role/tasks/main.yml b/tests/integration/targets/sts_assume_role/tasks/main.yml new file mode 100644 index 00000000000..345454932f7 --- /dev/null +++ b/tests/integration/targets/sts_assume_role/tasks/main.yml @@ -0,0 +1,384 @@ +--- +# tasks file for sts_assume_role + +- block: + + # ============================================================ + # TODO create simple ansible sts_get_caller_identity module + - blockinfile: + path: "{{ output_dir }}/sts.py" + create: yes + block: | + #!/usr/bin/env python + import boto3 + sts = boto3.client('sts') + response = sts.get_caller_identity() + print(response['Account']) + + - name: get the aws account id + command: "{{ ansible_python.executable }} '{{ output_dir }}/sts.py'" + environment: + AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" + AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" + AWS_SESSION_TOKEN: "{{ security_token }}" + register: result + + - name: register account id + set_fact: + aws_account: "{{ result.stdout | replace('\n', '') }}" + + # ============================================================ + - name: create test iam role + iam_role: + aws_access_key: "{{ aws_access_key }}" + aws_secret_key: "{{ aws_secret_key }}" + security_token: "{{ security_token }}" + name: "ansible-test-sts-{{ resource_prefix }}" + assume_role_policy_document: "{{ lookup('template','policy.json.j2') }}" + create_instance_profile: False + managed_policy: + - arn:aws:iam::aws:policy/IAMReadOnlyAccess + state: present + register: test_role + + # ============================================================ + - name: pause to ensure role exists before using + pause: + seconds: 30 + + # ============================================================ + - name: test with no parameters + sts_assume_role: + register: result + ignore_errors: true + + - name: assert with no parameters + assert: + that: + - 'result.failed' + - "'missing required arguments:' in result.msg" + + # ============================================================ + - name: test with empty parameters + sts_assume_role: + aws_access_key: "{{ aws_access_key }}" + aws_secret_key: "{{ aws_secret_key }}" + security_token: "{{ security_token }}" + region: "{{ aws_region}}" + role_arn: + role_session_name: + policy: + duration_seconds: + external_id: + mfa_token: + mfa_serial_number: + register: result + ignore_errors: true + + - name: assert with empty parameters + assert: + that: + - 'result.failed' + - "'Missing required parameter in input:' in result.msg" + when: result.module_stderr is not defined + + - name: assert with empty parameters + assert: + that: + - 'result.failed' + - "'Member must have length greater than or equal to 20' in result.module_stderr" + when: result.module_stderr is defined + + # ============================================================ + - name: test with only 'role_arn' parameter + sts_assume_role: + aws_access_key: "{{ aws_access_key }}" + aws_secret_key: "{{ aws_secret_key }}" + security_token: "{{ security_token }}" + role_arn: "{{ test_role.iam_role.arn }}" + register: result + ignore_errors: true + + - name: assert with only 'role_arn' parameter + assert: + that: + - 'result.failed' + - "'missing required arguments: role_session_name' in result.msg" + + # ============================================================ + - name: test with only 'role_session_name' parameter + sts_assume_role: + aws_access_key: "{{ aws_access_key }}" + aws_secret_key: "{{ aws_secret_key }}" + security_token: "{{ security_token }}" + role_session_name: "AnsibleTest" + register: result + ignore_errors: true + + - name: assert with only 'role_session_name' parameter + assert: + that: + - 'result.failed' + - "'missing required arguments: role_arn' in result.msg" + + # ============================================================ + - name: test assume role with invalid policy + sts_assume_role: + aws_access_key: "{{ aws_access_key }}" + aws_secret_key: "{{ aws_secret_key }}" + security_token: "{{ security_token }}" + region: "{{ aws_region }}" + role_arn: "{{ test_role.iam_role.arn }}" + role_session_name: "AnsibleTest" + policy: "invalid policy" + register: result + ignore_errors: true + + - name: assert assume role with invalid policy + assert: + that: + - 'result.failed' + - "'The policy is not in the valid JSON format.' in result.msg" + when: result.module_stderr is not defined + + - name: assert assume role with invalid policy + assert: + that: + - 'result.failed' + - "'The policy is not in the valid JSON format.' in result.module_stderr" + when: result.module_stderr is defined + + # ============================================================ + - name: test assume role with invalid duration seconds + sts_assume_role: + aws_access_key: "{{ aws_access_key }}" + aws_secret_key: "{{ aws_secret_key }}" + security_token: "{{ security_token }}" + region: "{{ aws_region}}" + role_arn: "{{ test_role.iam_role.arn }}" + role_session_name: AnsibleTest + duration_seconds: invalid duration + register: result + ignore_errors: true + + - name: assert assume role with invalid duration seconds + assert: + that: + - result is failed + - 'result.msg is search("argument \w+ is of type <.*> and we were unable to convert to int: <.*> cannot be converted to an int")' + + # ============================================================ + - name: test assume role with invalid external id + sts_assume_role: + aws_access_key: "{{ aws_access_key }}" + aws_secret_key: "{{ aws_secret_key }}" + security_token: "{{ security_token }}" + region: "{{ aws_region}}" + role_arn: "{{ test_role.iam_role.arn }}" + role_session_name: AnsibleTest + external_id: invalid external id + register: result + ignore_errors: true + + - name: assert assume role with invalid external id + assert: + that: + - 'result.failed' + - "'Member must satisfy regular expression pattern:' in result.msg" + when: result.module_stderr is not defined + + - name: assert assume role with invalid external id + assert: + that: + - 'result.failed' + - "'Member must satisfy regular expression pattern:' in result.module_stderr" + when: result.module_stderr is defined + + # ============================================================ + - name: test assume role with invalid mfa serial number + sts_assume_role: + aws_access_key: "{{ aws_access_key }}" + aws_secret_key: "{{ aws_secret_key }}" + security_token: "{{ security_token }}" + region: "{{ aws_region}}" + role_arn: "{{ test_role.iam_role.arn }}" + role_session_name: AnsibleTest + mfa_serial_number: invalid serial number + register: result + ignore_errors: true + + - name: assert assume role with invalid mfa serial number + assert: + that: + - 'result.failed' + - "'Member must satisfy regular expression pattern:' in result.msg" + when: result.module_stderr is not defined + + - name: assert assume role with invalid mfa serial number + assert: + that: + - 'result.failed' + - "'Member must satisfy regular expression pattern:' in result.module_stderr" + when: result.module_stderr is defined + + # ============================================================ + - name: test assume role with invalid mfa token code + sts_assume_role: + aws_access_key: "{{ aws_access_key }}" + aws_secret_key: "{{ aws_secret_key }}" + security_token: "{{ security_token }}" + region: "{{ aws_region}}" + role_arn: "{{ test_role.iam_role.arn }}" + role_session_name: AnsibleTest + mfa_token: invalid token code + register: result + ignore_errors: true + + - name: assert assume role with invalid mfa token code + assert: + that: + - 'result.failed' + - "'Member must satisfy regular expression pattern:' in result.msg" + when: result.module_stderr is not defined + + - name: assert assume role with invalid mfa token code + assert: + that: + - 'result.failed' + - "'Member must satisfy regular expression pattern:' in result.module_stderr" + when: result.module_stderr is defined + + # ============================================================ + - name: test assume role with invalid role_arn + sts_assume_role: + aws_access_key: "{{ aws_access_key }}" + aws_secret_key: "{{ aws_secret_key }}" + security_token: "{{ security_token }}" + region: "{{ aws_region}}" + role_arn: invalid role arn + role_session_name: AnsibleTest + register: result + ignore_errors: true + + - name: assert assume role with invalid role_arn + assert: + that: + - result.failed + - "'Invalid length for parameter RoleArn' in result.msg" + when: result.module_stderr is not defined + + - name: assert assume role with invalid role_arn + assert: + that: + - 'result.failed' + - "'Member must have length greater than or equal to 20' in result.module_stderr" + when: result.module_stderr is defined + + # ============================================================ + - name: test assume not existing sts role + sts_assume_role: + aws_access_key: "{{ aws_access_key }}" + aws_secret_key: "{{ aws_secret_key }}" + security_token: "{{ security_token }}" + region: "{{ aws_region}}" + role_arn: "arn:aws:iam::123456789:role/non-existing-role" + role_session_name: "AnsibleTest" + register: result + ignore_errors: true + + - name: assert assume not existing sts role + assert: + that: + - 'result.failed' + - "'is not authorized to perform: sts:AssumeRole' in result.msg" + when: result.module_stderr is not defined + + - name: assert assume not existing sts role + assert: + that: + - 'result.failed' + - "'is not authorized to perform: sts:AssumeRole' in result.msg" + when: result.module_stderr is defined + + # ============================================================ + - name: test assume role + sts_assume_role: + aws_access_key: "{{ aws_access_key }}" + aws_secret_key: "{{ aws_secret_key }}" + security_token: "{{ security_token }}" + region: "{{ aws_region }}" + role_arn: "{{ test_role.iam_role.arn }}" + role_session_name: AnsibleTest + register: assumed_role + + - name: assert assume role + assert: + that: + - 'not assumed_role.failed' + - "'sts_creds' in assumed_role" + - "'access_key' in assumed_role.sts_creds" + - "'secret_key' in assumed_role.sts_creds" + - "'session_token' in assumed_role.sts_creds" + + # ============================================================ + - name: test that assumed credentials have IAM read-only access + iam_role: + aws_access_key: "{{ assumed_role.sts_creds.access_key }}" + aws_secret_key: "{{ assumed_role.sts_creds.secret_key }}" + security_token: "{{ assumed_role.sts_creds.session_token }}" + region: "{{ aws_region}}" + name: "ansible-test-sts-{{ resource_prefix }}" + assume_role_policy_document: "{{ lookup('template','policy.json.j2') }}" + create_instance_profile: False + state: present + register: result + + - name: assert assumed role with privileged action (expect changed=false) + assert: + that: + - 'not result.failed' + - 'not result.changed' + - "'iam_role' in result" + + # ============================================================ + - name: test assumed role with unprivileged action + iam_role: + aws_access_key: "{{ assumed_role.sts_creds.access_key }}" + aws_secret_key: "{{ assumed_role.sts_creds.secret_key }}" + security_token: "{{ assumed_role.sts_creds.session_token }}" + region: "{{ aws_region}}" + name: "ansible-test-sts-{{ resource_prefix }}-new" + assume_role_policy_document: "{{ lookup('template','policy.json.j2') }}" + state: present + register: result + ignore_errors: true + + - name: assert assumed role with unprivileged action (expect changed=false) + assert: + that: + - 'result.failed' + - "'is not authorized to perform: iam:CreateRole' in result.msg" + # runs on Python2 + when: result.module_stderr is not defined + + - name: assert assumed role with unprivileged action (expect changed=false) + assert: + that: + - 'result.failed' + - "'is not authorized to perform: iam:CreateRole' in result.module_stderr" + # runs on Python3 + when: result.module_stderr is defined + + # ============================================================ + always: + + - name: delete test iam role + iam_role: + aws_access_key: "{{ aws_access_key }}" + aws_secret_key: "{{ aws_secret_key }}" + security_token: "{{ security_token }}" + name: "ansible-test-sts-{{ resource_prefix }}" + assume_role_policy_document: "{{ lookup('template','policy.json.j2') }}" + managed_policy: + - arn:aws:iam::aws:policy/IAMReadOnlyAccess + state: absent diff --git a/tests/integration/targets/sts_assume_role/templates/policy.json.j2 b/tests/integration/targets/sts_assume_role/templates/policy.json.j2 new file mode 100644 index 00000000000..559562fd91d --- /dev/null +++ b/tests/integration/targets/sts_assume_role/templates/policy.json.j2 @@ -0,0 +1,12 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::{{ aws_account }}:root" + }, + "Action": "sts:AssumeRole" + } + ] +} \ No newline at end of file From d7105cf8051e47fd5a44789418148976f604c991 Mon Sep 17 00:00:00 2001 From: Jill R <4121322+jillr@users.noreply.github.com> Date: Wed, 25 Mar 2020 15:39:40 -0700 Subject: [PATCH 084/129] Rename collection (#12) * Rename core collection Rename references to ansible.amazon to amazon.aws. * Rename community.amazon to community.aws Fix pep8 line lengths for rewritten amazon.aws imports * Missed a path in shippable.sh * Dependency repos moved This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/235c5db571cc45db5839476c94356c9b91e1f228 --- plugins/modules/sts_assume_role.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/modules/sts_assume_role.py b/plugins/modules/sts_assume_role.py index 3c03f291706..8283c49d862 100644 --- a/plugins/modules/sts_assume_role.py +++ b/plugins/modules/sts_assume_role.py @@ -57,8 +57,8 @@ notes: - In order to use the assumed role in a following playbook task you must pass the access_key, access_secret and access_token. extends_documentation_fragment: -- ansible.amazon.aws -- ansible.amazon.ec2 +- amazon.aws.aws +- amazon.aws.ec2 requirements: - boto3 @@ -110,8 +110,8 @@ ''' -from ansible_collections.ansible.amazon.plugins.module_utils.aws.core import AnsibleAWSModule -from ansible_collections.ansible.amazon.plugins.module_utils.ec2 import camel_dict_to_snake_dict +from ansible_collections.amazon.aws.plugins.module_utils.aws.core import AnsibleAWSModule +from ansible_collections.amazon.aws.plugins.module_utils.ec2 import camel_dict_to_snake_dict try: from botocore.exceptions import ClientError, ParamValidationError From aee58d39c023b6a0cd7c4495ef5c12581f9b7a81 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 29 Apr 2020 23:19:49 +0200 Subject: [PATCH 085/129] Fix more doc issues where strings are parsed as datetimes by YAML parser. (#55) This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/4a0e1a4d8797e71dbb39ab04d14b41133d01c979 --- plugins/modules/sts_assume_role.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/sts_assume_role.py b/plugins/modules/sts_assume_role.py index 8283c49d862..7f86c34a475 100644 --- a/plugins/modules/sts_assume_role.py +++ b/plugins/modules/sts_assume_role.py @@ -73,7 +73,7 @@ type: dict sample: access_key: XXXXXXXXXXXXXXXXXXXX - expiration: 2017-11-11T11:11:11+00:00 + expiration: '2017-11-11T11:11:11+00:00' secret_key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX session_token: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX sts_user: From eb5af1c531dff304b399d026a8aff5f0f6b5c348 Mon Sep 17 00:00:00 2001 From: Jill R <4121322+jillr@users.noreply.github.com> Date: Tue, 19 May 2020 16:06:12 -0700 Subject: [PATCH 086/129] Remove METADATA and cleanup galaxy.yml (#70) * Remove ANSIBLE_METADATA entirely, see ansible/ansible/pull/69454. Remove `license` field from galaxy.yml, in favor of `license_file`. This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/05672a64e2362cc2d865b5af6a57da6bc3cd08e3 --- plugins/modules/sts_assume_role.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/plugins/modules/sts_assume_role.py b/plugins/modules/sts_assume_role.py index 7f86c34a475..f836e478e23 100644 --- a/plugins/modules/sts_assume_role.py +++ b/plugins/modules/sts_assume_role.py @@ -6,11 +6,6 @@ __metaclass__ = type -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['stableinterface'], - 'supported_by': 'community'} - - DOCUMENTATION = ''' --- module: sts_assume_role From 7c501b738e50404bb4c410be5b4f7fe4af10f22d Mon Sep 17 00:00:00 2001 From: Abhijeet Kasurde Date: Wed, 17 Jun 2020 01:24:54 +0530 Subject: [PATCH 087/129] Update Examples with FQCN (#67) Updated module examples with FQCN Signed-off-by: Abhijeet Kasurde This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/98173aefbbceed7fc0d9db62687b73f96a55a999 --- plugins/modules/sts_assume_role.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/modules/sts_assume_role.py b/plugins/modules/sts_assume_role.py index f836e478e23..4048373c614 100644 --- a/plugins/modules/sts_assume_role.py +++ b/plugins/modules/sts_assume_role.py @@ -88,13 +88,13 @@ # Note: These examples do not set authentication details, see the AWS Guide for details. # Assume an existing role (more details: https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html) -- sts_assume_role: +- community.aws.sts_assume_role: role_arn: "arn:aws:iam::123456789012:role/someRole" role_session_name: "someRoleSession" register: assumed_role # Use the assumed role above to tag an instance in account 123456789012 -- ec2_tag: +- amazon.aws.ec2_tag: aws_access_key: "{{ assumed_role.sts_creds.access_key }}" aws_secret_key: "{{ assumed_role.sts_creds.secret_key }}" security_token: "{{ assumed_role.sts_creds.session_token }}" From 4800bf2363f3a3d6b7ed2da94e88237e7ba90715 Mon Sep 17 00:00:00 2001 From: flowerysong Date: Tue, 16 Jun 2020 19:30:00 -0400 Subject: [PATCH 088/129] Update module_utils paths to remove aws subdir (#23) Co-authored-by: Ezekiel Hendrickson This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/10853d9441a586ba177006dd889325cfb24a3dd6 --- plugins/modules/sts_assume_role.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/sts_assume_role.py b/plugins/modules/sts_assume_role.py index 4048373c614..fca345ad4ac 100644 --- a/plugins/modules/sts_assume_role.py +++ b/plugins/modules/sts_assume_role.py @@ -105,7 +105,7 @@ ''' -from ansible_collections.amazon.aws.plugins.module_utils.aws.core import AnsibleAWSModule +from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule from ansible_collections.amazon.aws.plugins.module_utils.ec2 import camel_dict_to_snake_dict try: From 80e4144dcbbcb37cb021f44405b9849931de49cb Mon Sep 17 00:00:00 2001 From: Jill R <4121322+jillr@users.noreply.github.com> Date: Wed, 17 Jun 2020 09:31:32 -0700 Subject: [PATCH 089/129] Update docs (#99) * Update docs Remove .git from repo url so links in readme will generate correctly Add required ansible version Run latest version of add_docs.py Add version_added string to modules * galaxy.yml was missing authors This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/96ee268e5267f5b12c3d59892bc1279f75aa3135 --- plugins/modules/sts_assume_role.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/modules/sts_assume_role.py b/plugins/modules/sts_assume_role.py index fca345ad4ac..378eb0031f8 100644 --- a/plugins/modules/sts_assume_role.py +++ b/plugins/modules/sts_assume_role.py @@ -9,6 +9,7 @@ DOCUMENTATION = ''' --- module: sts_assume_role +version_added: 1.0.0 short_description: Assume a role using AWS Security Token Service and obtain temporary credentials description: - Assume a role using AWS Security Token Service and obtain temporary credentials. From 7d812e468b7bb6646330915a6f8df8c43df42d1e Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Wed, 17 Feb 2021 17:13:34 +0100 Subject: [PATCH 090/129] sts_assume_role: Relax expectations on message when passing a non-integer as duration (#420) * sts_assume_role: Relax expectations on message when passing a non-integer as duration * Use standard module_defaults block to pass credentials and switch to aws_caller_info * Delete the instance profile when we delete the role This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/b3f5d45d4da4884e0c46e86a0d0ee694847e1ef3 --- .../targets/sts_assume_role/tasks/main.yml | 94 +++++-------------- 1 file changed, 21 insertions(+), 73 deletions(-) diff --git a/tests/integration/targets/sts_assume_role/tasks/main.yml b/tests/integration/targets/sts_assume_role/tasks/main.yml index 345454932f7..4a625a10b6f 100644 --- a/tests/integration/targets/sts_assume_role/tasks/main.yml +++ b/tests/integration/targets/sts_assume_role/tasks/main.yml @@ -1,38 +1,28 @@ --- # tasks file for sts_assume_role -- block: - - # ============================================================ - # TODO create simple ansible sts_get_caller_identity module - - blockinfile: - path: "{{ output_dir }}/sts.py" - create: yes - block: | - #!/usr/bin/env python - import boto3 - sts = boto3.client('sts') - response = sts.get_caller_identity() - print(response['Account']) - - - name: get the aws account id - command: "{{ ansible_python.executable }} '{{ output_dir }}/sts.py'" - environment: - AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" - AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" - AWS_SESSION_TOKEN: "{{ security_token }}" - register: result +- module_defaults: + group/aws: + region: "{{ aws_region }}" + aws_access_key: "{{ aws_access_key }}" + aws_secret_key: "{{ aws_secret_key }}" + security_token: "{{ security_token | default(omit) }}" + collections: + - amazon.aws + block: + # Get some information about who we are before starting our tests + # we'll need this as soon as we start working on the policies + - name: get ARN of calling user + aws_caller_info: + register: aws_caller_info - name: register account id set_fact: - aws_account: "{{ result.stdout | replace('\n', '') }}" + aws_account: "{{ aws_caller_info.account }}" # ============================================================ - name: create test iam role iam_role: - aws_access_key: "{{ aws_access_key }}" - aws_secret_key: "{{ aws_secret_key }}" - security_token: "{{ security_token }}" name: "ansible-test-sts-{{ resource_prefix }}" assume_role_policy_document: "{{ lookup('template','policy.json.j2') }}" create_instance_profile: False @@ -49,6 +39,9 @@ # ============================================================ - name: test with no parameters sts_assume_role: + aws_access_key: '{{ omit }}' + aws_secret_key: '{{ omit }}' + security_token: '{{ omit }}' register: result ignore_errors: true @@ -61,10 +54,6 @@ # ============================================================ - name: test with empty parameters sts_assume_role: - aws_access_key: "{{ aws_access_key }}" - aws_secret_key: "{{ aws_secret_key }}" - security_token: "{{ security_token }}" - region: "{{ aws_region}}" role_arn: role_session_name: policy: @@ -92,9 +81,6 @@ # ============================================================ - name: test with only 'role_arn' parameter sts_assume_role: - aws_access_key: "{{ aws_access_key }}" - aws_secret_key: "{{ aws_secret_key }}" - security_token: "{{ security_token }}" role_arn: "{{ test_role.iam_role.arn }}" register: result ignore_errors: true @@ -108,9 +94,6 @@ # ============================================================ - name: test with only 'role_session_name' parameter sts_assume_role: - aws_access_key: "{{ aws_access_key }}" - aws_secret_key: "{{ aws_secret_key }}" - security_token: "{{ security_token }}" role_session_name: "AnsibleTest" register: result ignore_errors: true @@ -124,10 +107,6 @@ # ============================================================ - name: test assume role with invalid policy sts_assume_role: - aws_access_key: "{{ aws_access_key }}" - aws_secret_key: "{{ aws_secret_key }}" - security_token: "{{ security_token }}" - region: "{{ aws_region }}" role_arn: "{{ test_role.iam_role.arn }}" role_session_name: "AnsibleTest" policy: "invalid policy" @@ -151,10 +130,6 @@ # ============================================================ - name: test assume role with invalid duration seconds sts_assume_role: - aws_access_key: "{{ aws_access_key }}" - aws_secret_key: "{{ aws_secret_key }}" - security_token: "{{ security_token }}" - region: "{{ aws_region}}" role_arn: "{{ test_role.iam_role.arn }}" role_session_name: AnsibleTest duration_seconds: invalid duration @@ -165,15 +140,12 @@ assert: that: - result is failed - - 'result.msg is search("argument \w+ is of type <.*> and we were unable to convert to int: <.*> cannot be converted to an int")' + - "'duration_seconds' in result.msg" + - "'cannot be converted to an int' in result.msg" # ============================================================ - name: test assume role with invalid external id sts_assume_role: - aws_access_key: "{{ aws_access_key }}" - aws_secret_key: "{{ aws_secret_key }}" - security_token: "{{ security_token }}" - region: "{{ aws_region}}" role_arn: "{{ test_role.iam_role.arn }}" role_session_name: AnsibleTest external_id: invalid external id @@ -197,10 +169,6 @@ # ============================================================ - name: test assume role with invalid mfa serial number sts_assume_role: - aws_access_key: "{{ aws_access_key }}" - aws_secret_key: "{{ aws_secret_key }}" - security_token: "{{ security_token }}" - region: "{{ aws_region}}" role_arn: "{{ test_role.iam_role.arn }}" role_session_name: AnsibleTest mfa_serial_number: invalid serial number @@ -224,10 +192,6 @@ # ============================================================ - name: test assume role with invalid mfa token code sts_assume_role: - aws_access_key: "{{ aws_access_key }}" - aws_secret_key: "{{ aws_secret_key }}" - security_token: "{{ security_token }}" - region: "{{ aws_region}}" role_arn: "{{ test_role.iam_role.arn }}" role_session_name: AnsibleTest mfa_token: invalid token code @@ -251,10 +215,6 @@ # ============================================================ - name: test assume role with invalid role_arn sts_assume_role: - aws_access_key: "{{ aws_access_key }}" - aws_secret_key: "{{ aws_secret_key }}" - security_token: "{{ security_token }}" - region: "{{ aws_region}}" role_arn: invalid role arn role_session_name: AnsibleTest register: result @@ -277,10 +237,6 @@ # ============================================================ - name: test assume not existing sts role sts_assume_role: - aws_access_key: "{{ aws_access_key }}" - aws_secret_key: "{{ aws_secret_key }}" - security_token: "{{ security_token }}" - region: "{{ aws_region}}" role_arn: "arn:aws:iam::123456789:role/non-existing-role" role_session_name: "AnsibleTest" register: result @@ -303,10 +259,6 @@ # ============================================================ - name: test assume role sts_assume_role: - aws_access_key: "{{ aws_access_key }}" - aws_secret_key: "{{ aws_secret_key }}" - security_token: "{{ security_token }}" - region: "{{ aws_region }}" role_arn: "{{ test_role.iam_role.arn }}" role_session_name: AnsibleTest register: assumed_role @@ -326,7 +278,6 @@ aws_access_key: "{{ assumed_role.sts_creds.access_key }}" aws_secret_key: "{{ assumed_role.sts_creds.secret_key }}" security_token: "{{ assumed_role.sts_creds.session_token }}" - region: "{{ aws_region}}" name: "ansible-test-sts-{{ resource_prefix }}" assume_role_policy_document: "{{ lookup('template','policy.json.j2') }}" create_instance_profile: False @@ -346,7 +297,6 @@ aws_access_key: "{{ assumed_role.sts_creds.access_key }}" aws_secret_key: "{{ assumed_role.sts_creds.secret_key }}" security_token: "{{ assumed_role.sts_creds.session_token }}" - region: "{{ aws_region}}" name: "ansible-test-sts-{{ resource_prefix }}-new" assume_role_policy_document: "{{ lookup('template','policy.json.j2') }}" state: present @@ -374,11 +324,9 @@ - name: delete test iam role iam_role: - aws_access_key: "{{ aws_access_key }}" - aws_secret_key: "{{ aws_secret_key }}" - security_token: "{{ security_token }}" name: "ansible-test-sts-{{ resource_prefix }}" assume_role_policy_document: "{{ lookup('template','policy.json.j2') }}" + delete_instance_profile: True managed_policy: - arn:aws:iam::aws:policy/IAMReadOnlyAccess state: absent From 5876323f0281284919756575812bcbfaac30dbd0 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 13 Mar 2021 17:32:35 +0100 Subject: [PATCH 091/129] Fix missing no_log=True. This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/6b09f2af722af7a97add18ec0c9e229361ce6e88 --- plugins/modules/sts_assume_role.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/sts_assume_role.py b/plugins/modules/sts_assume_role.py index 378eb0031f8..d1203a3c5a5 100644 --- a/plugins/modules/sts_assume_role.py +++ b/plugins/modules/sts_assume_role.py @@ -162,7 +162,7 @@ def main(): external_id=dict(required=False, default=None), policy=dict(required=False, default=None), mfa_serial_number=dict(required=False, default=None), - mfa_token=dict(required=False, default=None) + mfa_token=dict(required=False, default=None, no_log=True) ) module = AnsibleAWSModule(argument_spec=argument_spec) From ede3341a06a9b1650783fbb1bb93706904023f6b Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Thu, 6 May 2021 21:01:46 +0200 Subject: [PATCH 092/129] Update the default module requirements from python 2.6/boto to python 3.6/boto3 This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/c097c55293be0834a2b9d394733ec28965d142d7 --- plugins/modules/sts_assume_role.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/plugins/modules/sts_assume_role.py b/plugins/modules/sts_assume_role.py index d1203a3c5a5..c7435ad6fdc 100644 --- a/plugins/modules/sts_assume_role.py +++ b/plugins/modules/sts_assume_role.py @@ -55,11 +55,6 @@ extends_documentation_fragment: - amazon.aws.aws - amazon.aws.ec2 - -requirements: - - boto3 - - botocore - - python >= 2.6 ''' RETURN = ''' From 7f5f429143058db405f865fed160526791b7dead Mon Sep 17 00:00:00 2001 From: jillr Date: Thu, 29 Apr 2021 21:58:50 +0000 Subject: [PATCH 093/129] Remove shippable references from repo This collection has been operating on Zuul CI for some weeks now This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/4e0d83c65568a99a24307e37a14e6e0b173c948b --- tests/integration/targets/sts_assume_role/aliases | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/integration/targets/sts_assume_role/aliases b/tests/integration/targets/sts_assume_role/aliases index 6e3860bee23..4ef4b2067d0 100644 --- a/tests/integration/targets/sts_assume_role/aliases +++ b/tests/integration/targets/sts_assume_role/aliases @@ -1,2 +1 @@ cloud/aws -shippable/aws/group2 From 72046edd775d79dbd19c93f0a7c50345aa9ba013 Mon Sep 17 00:00:00 2001 From: jillr Date: Sat, 19 Jun 2021 01:15:38 +0000 Subject: [PATCH 094/129] Fix up lambda tests and more iam roles This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/d276a6127640d6eddc83295e3f06f882746d9b34 --- .../integration/targets/sts_assume_role/defaults/main.yml | 2 ++ tests/integration/targets/sts_assume_role/tasks/main.yml | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) create mode 100644 tests/integration/targets/sts_assume_role/defaults/main.yml diff --git a/tests/integration/targets/sts_assume_role/defaults/main.yml b/tests/integration/targets/sts_assume_role/defaults/main.yml new file mode 100644 index 00000000000..1287fe1f5b9 --- /dev/null +++ b/tests/integration/targets/sts_assume_role/defaults/main.yml @@ -0,0 +1,2 @@ +unique_id: "{{ resource_prefix | hash('md5') }}" +iam_role_name: "ansible-test-sts-{{ unique_id }}" diff --git a/tests/integration/targets/sts_assume_role/tasks/main.yml b/tests/integration/targets/sts_assume_role/tasks/main.yml index 4a625a10b6f..be684dcea18 100644 --- a/tests/integration/targets/sts_assume_role/tasks/main.yml +++ b/tests/integration/targets/sts_assume_role/tasks/main.yml @@ -23,7 +23,7 @@ # ============================================================ - name: create test iam role iam_role: - name: "ansible-test-sts-{{ resource_prefix }}" + name: "{{ iam_role_name }}" assume_role_policy_document: "{{ lookup('template','policy.json.j2') }}" create_instance_profile: False managed_policy: @@ -278,7 +278,7 @@ aws_access_key: "{{ assumed_role.sts_creds.access_key }}" aws_secret_key: "{{ assumed_role.sts_creds.secret_key }}" security_token: "{{ assumed_role.sts_creds.session_token }}" - name: "ansible-test-sts-{{ resource_prefix }}" + name: "{{ iam_role_name }}" assume_role_policy_document: "{{ lookup('template','policy.json.j2') }}" create_instance_profile: False state: present @@ -297,7 +297,7 @@ aws_access_key: "{{ assumed_role.sts_creds.access_key }}" aws_secret_key: "{{ assumed_role.sts_creds.secret_key }}" security_token: "{{ assumed_role.sts_creds.session_token }}" - name: "ansible-test-sts-{{ resource_prefix }}-new" + name: "{{ iam_role_name }}-new" assume_role_policy_document: "{{ lookup('template','policy.json.j2') }}" state: present register: result @@ -324,7 +324,7 @@ - name: delete test iam role iam_role: - name: "ansible-test-sts-{{ resource_prefix }}" + name: "{{ iam_role_name }}" assume_role_policy_document: "{{ lookup('template','policy.json.j2') }}" delete_instance_profile: True managed_policy: From f953c0f9e041694313118e75c9698a11ff7dc141 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A9ri=20Le=20Bouder?= Date: Tue, 13 Jul 2021 11:16:57 +0200 Subject: [PATCH 095/129] tests: use the new tiny_prefix variable The new tiny_prefix variable has recently been introduced. It's a 12 characters long string that is reused for the whole job. This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/4d1fa5aa4d7292611d5754b51d0b552ac67ad8b0 --- tests/integration/targets/sts_assume_role/defaults/main.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/integration/targets/sts_assume_role/defaults/main.yml b/tests/integration/targets/sts_assume_role/defaults/main.yml index 1287fe1f5b9..17072d6a4fd 100644 --- a/tests/integration/targets/sts_assume_role/defaults/main.yml +++ b/tests/integration/targets/sts_assume_role/defaults/main.yml @@ -1,2 +1 @@ -unique_id: "{{ resource_prefix | hash('md5') }}" -iam_role_name: "ansible-test-sts-{{ unique_id }}" +iam_role_name: "ansible-test-{{ tiny_prefix }}" From b2557715f11fead78ffd03f3b1691ea9c7071cdc Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Fri, 22 Apr 2022 11:44:07 +0200 Subject: [PATCH 096/129] Integration test dependency cleanup (#1086) Integration test dependency cleanup SUMMARY remove dependencies on setup_remote_tmp_dir where it's not used (often just copy & paste from another test) remove setup_ec2 (no main.yml means it's not doing anything) remove prepare_tests (empty main.yml means it's not doing anything) ISSUE TYPE Feature Pull Request COMPONENT NAME tests/integration/targets ADDITIONAL INFORMATION By cleaning up what we have we reduce the chance of people copying things about "because that's what test XYZ did". Reviewed-by: Alina Buzachis Reviewed-by: Mark Woolley This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/dd12046a1e2d5f39692b1890ff07e06c56b3bf0e --- tests/integration/targets/sts_assume_role/meta/main.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/integration/targets/sts_assume_role/meta/main.yml b/tests/integration/targets/sts_assume_role/meta/main.yml index 1f64f1169a9..32cf5dda7ed 100644 --- a/tests/integration/targets/sts_assume_role/meta/main.yml +++ b/tests/integration/targets/sts_assume_role/meta/main.yml @@ -1,3 +1 @@ -dependencies: - - prepare_tests - - setup_ec2 +dependencies: [] From 729d73240ef54f0b0424f07e3670eecb7621edfc Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Wed, 5 Oct 2022 17:04:40 +0200 Subject: [PATCH 097/129] Update extends_documentation_fragment with amazon.aws.boto3 (#1459) Update extends_documentation_fragment with amazon.aws.boto3 Depends-On: ansible/ansible-zuul-jobs#1654 SUMMARY As per ansible-collections/amazon.aws#985 add amazon.aws.boto3. ISSUE TYPE Docs Pull Request COMPONENT NAME several Reviewed-by: Jill R Reviewed-by: Mark Chappell Reviewed-by: Markus Bergholz This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/bd3c03fcba0848f593b86309740fa73e986a9646 --- plugins/modules/sts_assume_role.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/modules/sts_assume_role.py b/plugins/modules/sts_assume_role.py index c7435ad6fdc..8e5a3b4fed2 100644 --- a/plugins/modules/sts_assume_role.py +++ b/plugins/modules/sts_assume_role.py @@ -55,6 +55,7 @@ extends_documentation_fragment: - amazon.aws.aws - amazon.aws.ec2 +- amazon.aws.boto3 ''' RETURN = ''' From c62018dd2e83c84fa5ee4e8ad3b487b03dba1bbe Mon Sep 17 00:00:00 2001 From: Bikouo Aubin <79859644+abikouo@users.noreply.github.com> Date: Tue, 10 Jan 2023 19:22:13 +0100 Subject: [PATCH 098/129] Ansible User-Agent identification for community.aws (#1632) Ansible User-Agent identification for community.aws SUMMARY The value will be similar to this APN/1.0 Ansible/2.14.1 community.aws/6.0.0-dev0 ISSUE TYPE Feature Pull Request Reviewed-by: Mark Chappell Reviewed-by: Bikouo Aubin Reviewed-by: Alina Buzachis This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/a8cbce24071bcc62fe4594c38aff1baf18bd2862 --- plugins/modules/sts_assume_role.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/sts_assume_role.py b/plugins/modules/sts_assume_role.py index 8e5a3b4fed2..fe29cd3c62a 100644 --- a/plugins/modules/sts_assume_role.py +++ b/plugins/modules/sts_assume_role.py @@ -102,7 +102,7 @@ ''' -from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule +from ansible_collections.community.aws.plugins.module_utils.modules import AnsibleCommunityAWSModule as AnsibleAWSModule from ansible_collections.amazon.aws.plugins.module_utils.ec2 import camel_dict_to_snake_dict try: From bf3231c8608f6a4147b35082478708ba26746850 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Wed, 8 Mar 2023 12:07:26 +0100 Subject: [PATCH 099/129] Cleanup headers and imports (#1738) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cleanup headers and imports SUMMARY Mass update of imports, docs fragments and file headers Many of the amazon.aws module_utils and docs fragments got moved about, update community.aws to reflect this. Consistently apply the comment headers as documented at https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_documenting.html#python-shebang-utf-8-coding ISSUE TYPE Docs Pull Request Feature Pull Request COMPONENT NAME ADDITIONAL INFORMATION Header cleanup based upon: https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_documenting.html#python-shebang-utf-8-coding Begin your Ansible module with #!/usr/bin/python - this “shebang” allows ansible_python_interpreter to work. Follow the shebang immediately with # -*- coding: utf-8 -*- to clarify that the file is UTF-8 encoded. and https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_documenting.html#copyright-and-license After the shebang and UTF-8 coding, add a copyright line with the original copyright holder and a license declaration. The license declaration should be ONLY one line, not the full GPL prefix. ... Additions to the module (for instance, rewrites) are not permitted to add additional copyright lines other than the default copyright statement if missing: Reviewed-by: Alina Buzachis This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/a4f20bf114bfab19b1c84c4ecf42efd5614ab80c --- plugins/modules/sts_assume_role.py | 40 +++++++++++++++--------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/plugins/modules/sts_assume_role.py b/plugins/modules/sts_assume_role.py index fe29cd3c62a..c53bfa9c978 100644 --- a/plugins/modules/sts_assume_role.py +++ b/plugins/modules/sts_assume_role.py @@ -1,21 +1,19 @@ #!/usr/bin/python +# -*- coding: utf-8 -*- + # Copyright: Ansible Project # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -from __future__ import absolute_import, division, print_function -__metaclass__ = type - - -DOCUMENTATION = ''' +DOCUMENTATION = r""" --- module: sts_assume_role version_added: 1.0.0 short_description: Assume a role using AWS Security Token Service and obtain temporary credentials description: - - Assume a role using AWS Security Token Service and obtain temporary credentials. + - Assume a role using AWS Security Token Service and obtain temporary credentials. author: - - Boris Ekelchik (@bekelchik) - - Marek Piatek (@piontas) + - Boris Ekelchik (@bekelchik) + - Marek Piatek (@piontas) options: role_arn: description: @@ -53,12 +51,12 @@ notes: - In order to use the assumed role in a following playbook task you must pass the access_key, access_secret and access_token. extends_documentation_fragment: -- amazon.aws.aws -- amazon.aws.ec2 -- amazon.aws.boto3 -''' + - amazon.aws.common.modules + - amazon.aws.region.modules + - amazon.aws.boto3 +""" -RETURN = ''' +RETURN = r""" sts_creds: description: The temporary security credentials, which include an access key ID, a secret access key, and a security (or session) token returned: always @@ -79,9 +77,9 @@ description: True if obtaining the credentials succeeds type: bool returned: always -''' +""" -EXAMPLES = ''' +EXAMPLES = r""" # Note: These examples do not set authentication details, see the AWS Guide for details. # Assume an existing role (more details: https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html) @@ -100,16 +98,18 @@ tags: MyNewTag: value -''' - -from ansible_collections.community.aws.plugins.module_utils.modules import AnsibleCommunityAWSModule as AnsibleAWSModule -from ansible_collections.amazon.aws.plugins.module_utils.ec2 import camel_dict_to_snake_dict +""" try: - from botocore.exceptions import ClientError, ParamValidationError + from botocore.exceptions import ClientError + from botocore.exceptions import ParamValidationError except ImportError: pass # caught by AnsibleAWSModule +from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict + +from ansible_collections.community.aws.plugins.module_utils.modules import AnsibleCommunityAWSModule as AnsibleAWSModule + def _parse_response(response): credentials = response.get('Credentials', {}) From 98339bf5690d88e84364ae647e0e294c31d4c870 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Wed, 26 Apr 2023 19:26:07 +0200 Subject: [PATCH 100/129] Big Black PR (#1784) * Black prep * Black * changelog * Fix pylint unused-import in tests * Split SSM connection plugin changes * disable glue tests - bucket's missing * Disable s3_logging and s3_sync tests This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/2c4575c248776c65d66b06cd60fa09b0dae1cd6f --- plugins/modules/sts_assume_role.py | 35 +++++++++++++++--------------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/plugins/modules/sts_assume_role.py b/plugins/modules/sts_assume_role.py index c53bfa9c978..4a4860657cf 100644 --- a/plugins/modules/sts_assume_role.py +++ b/plugins/modules/sts_assume_role.py @@ -112,15 +112,14 @@ def _parse_response(response): - credentials = response.get('Credentials', {}) - user = response.get('AssumedRoleUser', {}) + credentials = response.get("Credentials", {}) + user = response.get("AssumedRoleUser", {}) sts_cred = { - 'access_key': credentials.get('AccessKeyId'), - 'secret_key': credentials.get('SecretAccessKey'), - 'session_token': credentials.get('SessionToken'), - 'expiration': credentials.get('Expiration') - + "access_key": credentials.get("AccessKeyId"), + "secret_key": credentials.get("SecretAccessKey"), + "session_token": credentials.get("SessionToken"), + "expiration": credentials.get("Expiration"), } sts_user = camel_dict_to_snake_dict(user) return sts_cred, sts_user @@ -128,13 +127,13 @@ def _parse_response(response): def assume_role_policy(connection, module): params = { - 'RoleArn': module.params.get('role_arn'), - 'RoleSessionName': module.params.get('role_session_name'), - 'Policy': module.params.get('policy'), - 'DurationSeconds': module.params.get('duration_seconds'), - 'ExternalId': module.params.get('external_id'), - 'SerialNumber': module.params.get('mfa_serial_number'), - 'TokenCode': module.params.get('mfa_token') + "RoleArn": module.params.get("role_arn"), + "RoleSessionName": module.params.get("role_session_name"), + "Policy": module.params.get("policy"), + "DurationSeconds": module.params.get("duration_seconds"), + "ExternalId": module.params.get("external_id"), + "SerialNumber": module.params.get("mfa_serial_number"), + "TokenCode": module.params.get("mfa_token"), } changed = False @@ -154,19 +153,19 @@ def main(): argument_spec = dict( role_arn=dict(required=True), role_session_name=dict(required=True), - duration_seconds=dict(required=False, default=None, type='int'), + duration_seconds=dict(required=False, default=None, type="int"), external_id=dict(required=False, default=None), policy=dict(required=False, default=None), mfa_serial_number=dict(required=False, default=None), - mfa_token=dict(required=False, default=None, no_log=True) + mfa_token=dict(required=False, default=None, no_log=True), ) module = AnsibleAWSModule(argument_spec=argument_spec) - connection = module.client('sts') + connection = module.client("sts") assume_role_policy(connection, module) -if __name__ == '__main__': +if __name__ == "__main__": main() From 663d5381077055f99ae011da0c86a6499fea65df Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Sat, 1 Jul 2023 21:39:01 +0200 Subject: [PATCH 101/129] CI test fixups - Ansible milestone update (#1863) CI test fixups - Ansible milestone update SUMMARY Fixups failures exposed by #1852 ISSUE TYPE Bugfix Pull Request COMPONENT NAME dynamodb sts_assume_role ADDITIONAL INFORMATION Reviewed-by: Mark Chappell Reviewed-by: Alina Buzachis This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/7f05515ce1dac9f33b1303386d62dc3531f402e8 --- .../targets/sts_assume_role/tasks/main.yml | 27 ------------------- 1 file changed, 27 deletions(-) diff --git a/tests/integration/targets/sts_assume_role/tasks/main.yml b/tests/integration/targets/sts_assume_role/tasks/main.yml index be684dcea18..42ef51c04d0 100644 --- a/tests/integration/targets/sts_assume_role/tasks/main.yml +++ b/tests/integration/targets/sts_assume_role/tasks/main.yml @@ -51,33 +51,6 @@ - 'result.failed' - "'missing required arguments:' in result.msg" - # ============================================================ - - name: test with empty parameters - sts_assume_role: - role_arn: - role_session_name: - policy: - duration_seconds: - external_id: - mfa_token: - mfa_serial_number: - register: result - ignore_errors: true - - - name: assert with empty parameters - assert: - that: - - 'result.failed' - - "'Missing required parameter in input:' in result.msg" - when: result.module_stderr is not defined - - - name: assert with empty parameters - assert: - that: - - 'result.failed' - - "'Member must have length greater than or equal to 20' in result.module_stderr" - when: result.module_stderr is defined - # ============================================================ - name: test with only 'role_arn' parameter sts_assume_role: From 811357d8367c8c8bf22f8dc02b20c6d8014ebb7d Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Thu, 31 Aug 2023 17:58:59 +0200 Subject: [PATCH 102/129] Mass update of docs and tests (credentials/session tokens) (#1921) Mass update of docs and tests (credentials/session tokens) SUMMARY We had a cleanup of credentials/session parameters which included a batch of deprecations and renames. Ensure that all of our tests and docs are using the 'canonical' names ISSUE TYPE Docs Pull Request COMPONENT NAME plugins/modules/batch_compute_environment.py plugins/modules/cloudformation_exports_info.py plugins/modules/ec2_vpc_vpn.py plugins/modules/elasticache.py plugins/modules/elasticache_parameter_group.py plugins/modules/elasticache_snapshot.py plugins/modules/ses_rule_set.py plugins/modules/sts_assume_role.py plugins/modules/sts_session_token.py tests/integration ADDITIONAL INFORMATION See also ansible-collections/amazon.aws#1172 ansible-collections/amazon.aws#1714 Reviewed-by: Alina Buzachis This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/4a5b50e9b9c0d6ca1a1f802f3b03d4f503c16885 --- plugins/modules/sts_assume_role.py | 13 +++++----- .../targets/sts_assume_role/tasks/main.yml | 24 +++++++++---------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/plugins/modules/sts_assume_role.py b/plugins/modules/sts_assume_role.py index 4a4860657cf..4d934c2d5cd 100644 --- a/plugins/modules/sts_assume_role.py +++ b/plugins/modules/sts_assume_role.py @@ -49,7 +49,8 @@ - The value provided by the MFA device, if the trust policy of the role being assumed requires MFA. type: str notes: - - In order to use the assumed role in a following playbook task you must pass the access_key, access_secret and access_token. + - In order to use the assumed role in a following playbook task you must pass the I(access_key), + I(secret_key) and I(session_token) parameters to modules that should use the assumed credentials. extends_documentation_fragment: - amazon.aws.common.modules - amazon.aws.region.modules @@ -80,19 +81,19 @@ """ EXAMPLES = r""" -# Note: These examples do not set authentication details, see the AWS Guide for details. - # Assume an existing role (more details: https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html) - community.aws.sts_assume_role: + access_key: AKIA1EXAMPLE1EXAMPLE + secret_key: 123456789abcdefghijklmnopqrstuvwxyzABCDE role_arn: "arn:aws:iam::123456789012:role/someRole" role_session_name: "someRoleSession" register: assumed_role # Use the assumed role above to tag an instance in account 123456789012 - amazon.aws.ec2_tag: - aws_access_key: "{{ assumed_role.sts_creds.access_key }}" - aws_secret_key: "{{ assumed_role.sts_creds.secret_key }}" - security_token: "{{ assumed_role.sts_creds.session_token }}" + access_key: "{{ assumed_role.sts_creds.access_key }}" + secret_key: "{{ assumed_role.sts_creds.secret_key }}" + session_token: "{{ assumed_role.sts_creds.session_token }}" resource: i-xyzxyz01 state: present tags: diff --git a/tests/integration/targets/sts_assume_role/tasks/main.yml b/tests/integration/targets/sts_assume_role/tasks/main.yml index 42ef51c04d0..23e0dba7843 100644 --- a/tests/integration/targets/sts_assume_role/tasks/main.yml +++ b/tests/integration/targets/sts_assume_role/tasks/main.yml @@ -4,9 +4,9 @@ - module_defaults: group/aws: region: "{{ aws_region }}" - aws_access_key: "{{ aws_access_key }}" - aws_secret_key: "{{ aws_secret_key }}" - security_token: "{{ security_token | default(omit) }}" + access_key: "{{ aws_access_key }}" + secret_key: "{{ aws_secret_key }}" + session_token: "{{ security_token | default(omit) }}" collections: - amazon.aws block: @@ -39,9 +39,9 @@ # ============================================================ - name: test with no parameters sts_assume_role: - aws_access_key: '{{ omit }}' - aws_secret_key: '{{ omit }}' - security_token: '{{ omit }}' + access_key: '{{ omit }}' + secret_key: '{{ omit }}' + session_token: '{{ omit }}' register: result ignore_errors: true @@ -248,9 +248,9 @@ # ============================================================ - name: test that assumed credentials have IAM read-only access iam_role: - aws_access_key: "{{ assumed_role.sts_creds.access_key }}" - aws_secret_key: "{{ assumed_role.sts_creds.secret_key }}" - security_token: "{{ assumed_role.sts_creds.session_token }}" + access_key: "{{ assumed_role.sts_creds.access_key }}" + secret_key: "{{ assumed_role.sts_creds.secret_key }}" + session_token: "{{ assumed_role.sts_creds.session_token }}" name: "{{ iam_role_name }}" assume_role_policy_document: "{{ lookup('template','policy.json.j2') }}" create_instance_profile: False @@ -267,9 +267,9 @@ # ============================================================ - name: test assumed role with unprivileged action iam_role: - aws_access_key: "{{ assumed_role.sts_creds.access_key }}" - aws_secret_key: "{{ assumed_role.sts_creds.secret_key }}" - security_token: "{{ assumed_role.sts_creds.session_token }}" + access_key: "{{ assumed_role.sts_creds.access_key }}" + secret_key: "{{ assumed_role.sts_creds.secret_key }}" + session_token: "{{ assumed_role.sts_creds.session_token }}" name: "{{ iam_role_name }}-new" assume_role_policy_document: "{{ lookup('template','policy.json.j2') }}" state: present From 37fd8154be6cf60b38fb4350aec64a55511a5076 Mon Sep 17 00:00:00 2001 From: Mandar Kulkarni Date: Thu, 28 Sep 2023 15:56:26 -0700 Subject: [PATCH 103/129] Update runtime --- meta/runtime.yml | 209 ++++++++++++++++++++++++----------------------- 1 file changed, 105 insertions(+), 104 deletions(-) diff --git a/meta/runtime.yml b/meta/runtime.yml index da395988b6f..e1b75a1678d 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -2,110 +2,111 @@ requires_ansible: '>=2.12.0' action_groups: aws: - - autoscaling_group - - autoscaling_group_info - - aws_az_info - - aws_caller_info - - aws_s3 - - backup_plan - - backup_plan_info - - backup_selection - - backup_selection_info - - backup_tag - - backup_tag_info - - backup_vault - - backup_vault_info - - cloudformation - - cloudformation_info - - cloudtrail - - cloudtrail_info - - cloudwatch_metric_alarm - - cloudwatch_metric_alarm_info - - cloudwatchevent_rule - - cloudwatchevent_rule - - cloudwatchlogs_log_group - - cloudwatchlogs_log_group_info - - cloudwatchlogs_log_group_metric_filter - - ec2_ami - - ec2_ami_info - - ec2_eip - - ec2_eip_info - - ec2_elb_lb - - ec2_eni - - ec2_eni_info - - ec2_group - - ec2_group_info - - ec2_instance - - ec2_instance_info - - ec2_key - - ec2_key_info - - ec2_security_group - - ec2_security_group_info - - ec2_snapshot - - ec2_snapshot_info - - ec2_spot_instance - - ec2_spot_instance_info - - ec2_tag - - ec2_tag_info - - ec2_vol - - ec2_vol_info - - ec2_vpc_dhcp_option - - ec2_vpc_dhcp_option_info - - ec2_vpc_endpoint - - ec2_vpc_endpoint_info - - ec2_vpc_endpoint_service_info - - ec2_vpc_igw - - ec2_vpc_igw_info - - ec2_vpc_nat_gateway - - ec2_vpc_nat_gateway_info - - ec2_vpc_net - - ec2_vpc_net_info - - ec2_vpc_route_table - - ec2_vpc_route_table_info - - ec2_vpc_subnet - - ec2_vpc_subnet_info - - elb_application_lb - - elb_application_lb_info - - elb_classic_lb - - execute_lambda - - iam_group - - iam_instance_profile - - iam_instance_profile_info - - iam_managed_policy - - iam_policy - - iam_policy_info - - iam_role - - iam_role_info - - iam_user - - iam_user_info - - kms_key - - kms_key_info - - lambda - - lambda_alias - - lambda_event - - lambda_execute - - lambda_info - - lambda_layer - - lambda_layer_info - - lambda_policy - - rds_cluster - - rds_cluster_info - - rds_cluster_snapshot - - rds_instance - - rds_instance_info - - rds_instance_snapshot - - rds_option_group - - rds_option_group_info - - rds_param_group - - rds_snapshot_info - - rds_subnet_group - - route53 - - route53_health_check - - route53_info - - route53_zone - - s3_bucket - - s3_object - - s3_object_info + - autoscaling_group + - autoscaling_group_info + - aws_az_info + - aws_caller_info + - aws_s3 + - backup_plan + - backup_plan_info + - backup_selection + - backup_selection_info + - backup_tag + - backup_tag_info + - backup_vault + - backup_vault_info + - cloudformation + - cloudformation_info + - cloudtrail + - cloudtrail_info + - cloudwatch_metric_alarm + - cloudwatch_metric_alarm_info + - cloudwatchevent_rule + - cloudwatchevent_rule + - cloudwatchlogs_log_group + - cloudwatchlogs_log_group_info + - cloudwatchlogs_log_group_metric_filter + - ec2_ami + - ec2_ami_info + - ec2_eip + - ec2_eip_info + - ec2_elb_lb + - ec2_eni + - ec2_eni_info + - ec2_group + - ec2_group_info + - ec2_instance + - ec2_instance_info + - ec2_key + - ec2_key_info + - ec2_security_group + - ec2_security_group_info + - ec2_snapshot + - ec2_snapshot_info + - ec2_spot_instance + - ec2_spot_instance_info + - ec2_tag + - ec2_tag_info + - ec2_vol + - ec2_vol_info + - ec2_vpc_dhcp_option + - ec2_vpc_dhcp_option_info + - ec2_vpc_endpoint + - ec2_vpc_endpoint_info + - ec2_vpc_endpoint_service_info + - ec2_vpc_igw + - ec2_vpc_igw_info + - ec2_vpc_nat_gateway + - ec2_vpc_nat_gateway_info + - ec2_vpc_net + - ec2_vpc_net_info + - ec2_vpc_route_table + - ec2_vpc_route_table_info + - ec2_vpc_subnet + - ec2_vpc_subnet_info + - elb_application_lb + - elb_application_lb_info + - elb_classic_lb + - execute_lambda + - iam_group + - iam_instance_profile + - iam_instance_profile_info + - iam_managed_policy + - iam_policy + - iam_policy_info + - iam_role + - iam_role_info + - iam_user + - iam_user_info + - kms_key + - kms_key_info + - lambda + - lambda_alias + - lambda_event + - lambda_execute + - lambda_info + - lambda_layer + - lambda_layer_info + - lambda_policy + - rds_cluster + - rds_cluster_info + - rds_cluster_snapshot + - rds_instance + - rds_instance_info + - rds_instance_snapshot + - rds_option_group + - rds_option_group_info + - rds_param_group + - rds_snapshot_info + - rds_subnet_group + - route53 + - route53_health_check + - route53_info + - route53_zone + - s3_bucket + - s3_object + - s3_object_info + - sts_assume_role plugin_routing: action: aws_s3: From 70a6b901d1a7a25a3813b0b65e3241d45e64589b Mon Sep 17 00:00:00 2001 From: Mandar Kulkarni Date: Thu, 28 Sep 2023 16:00:51 -0700 Subject: [PATCH 104/129] promote sts_assume_role --- changelogs/fragments/migrate_sts_assume_role.yml | 4 ++++ plugins/modules/sts_assume_role.py | 5 +++-- tests/integration/targets/cloudtrail/tasks/main.yml | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 changelogs/fragments/migrate_sts_assume_role.yml diff --git a/changelogs/fragments/migrate_sts_assume_role.yml b/changelogs/fragments/migrate_sts_assume_role.yml new file mode 100644 index 00000000000..f054230de9b --- /dev/null +++ b/changelogs/fragments/migrate_sts_assume_role.yml @@ -0,0 +1,4 @@ +major_changes: +- sts_assume_role - The module has been migrated from the ``community.aws`` collection. + Playbooks using the Fully Qualified Collection Name for this module should be updated + to use ``amazon.aws.sts_assume_role``. diff --git a/plugins/modules/sts_assume_role.py b/plugins/modules/sts_assume_role.py index 4d934c2d5cd..96abfd20136 100644 --- a/plugins/modules/sts_assume_role.py +++ b/plugins/modules/sts_assume_role.py @@ -8,6 +8,7 @@ --- module: sts_assume_role version_added: 1.0.0 +version_added_collection: community.aws short_description: Assume a role using AWS Security Token Service and obtain temporary credentials description: - Assume a role using AWS Security Token Service and obtain temporary credentials. @@ -82,7 +83,7 @@ EXAMPLES = r""" # Assume an existing role (more details: https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html) -- community.aws.sts_assume_role: +- amazon.aws.sts_assume_role: access_key: AKIA1EXAMPLE1EXAMPLE secret_key: 123456789abcdefghijklmnopqrstuvwxyzABCDE role_arn: "arn:aws:iam::123456789012:role/someRole" @@ -109,7 +110,7 @@ from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict -from ansible_collections.community.aws.plugins.module_utils.modules import AnsibleCommunityAWSModule as AnsibleAWSModule +from ansible_collections.amazon.aws.plugins.module_utils.modules import AnsibleAWSModule def _parse_response(response): diff --git a/tests/integration/targets/cloudtrail/tasks/main.yml b/tests/integration/targets/cloudtrail/tasks/main.yml index 60d1dad95c0..86fc7bdc605 100644 --- a/tests/integration/targets/cloudtrail/tasks/main.yml +++ b/tests/integration/targets/cloudtrail/tasks/main.yml @@ -1336,7 +1336,7 @@ # Assume role to a role with Denied access to KMS - - community.aws.sts_assume_role: + - amazon.aws.sts_assume_role: role_arn: '{{ output_cloudwatch_no_kms_role.arn }}' role_session_name: "cloudtrailNoKms" region: '{{ aws_region }}' From 01fbbb61319be1f3142929360871da646e21b32d Mon Sep 17 00:00:00 2001 From: Mandar Kulkarni Date: Thu, 28 Sep 2023 16:08:43 -0700 Subject: [PATCH 105/129] fix indentation for runtime/meta --- meta/runtime.yml | 210 +++++++++++++++++++++++------------------------ 1 file changed, 105 insertions(+), 105 deletions(-) diff --git a/meta/runtime.yml b/meta/runtime.yml index e1b75a1678d..aa51fc25fc0 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -2,111 +2,111 @@ requires_ansible: '>=2.12.0' action_groups: aws: - - autoscaling_group - - autoscaling_group_info - - aws_az_info - - aws_caller_info - - aws_s3 - - backup_plan - - backup_plan_info - - backup_selection - - backup_selection_info - - backup_tag - - backup_tag_info - - backup_vault - - backup_vault_info - - cloudformation - - cloudformation_info - - cloudtrail - - cloudtrail_info - - cloudwatch_metric_alarm - - cloudwatch_metric_alarm_info - - cloudwatchevent_rule - - cloudwatchevent_rule - - cloudwatchlogs_log_group - - cloudwatchlogs_log_group_info - - cloudwatchlogs_log_group_metric_filter - - ec2_ami - - ec2_ami_info - - ec2_eip - - ec2_eip_info - - ec2_elb_lb - - ec2_eni - - ec2_eni_info - - ec2_group - - ec2_group_info - - ec2_instance - - ec2_instance_info - - ec2_key - - ec2_key_info - - ec2_security_group - - ec2_security_group_info - - ec2_snapshot - - ec2_snapshot_info - - ec2_spot_instance - - ec2_spot_instance_info - - ec2_tag - - ec2_tag_info - - ec2_vol - - ec2_vol_info - - ec2_vpc_dhcp_option - - ec2_vpc_dhcp_option_info - - ec2_vpc_endpoint - - ec2_vpc_endpoint_info - - ec2_vpc_endpoint_service_info - - ec2_vpc_igw - - ec2_vpc_igw_info - - ec2_vpc_nat_gateway - - ec2_vpc_nat_gateway_info - - ec2_vpc_net - - ec2_vpc_net_info - - ec2_vpc_route_table - - ec2_vpc_route_table_info - - ec2_vpc_subnet - - ec2_vpc_subnet_info - - elb_application_lb - - elb_application_lb_info - - elb_classic_lb - - execute_lambda - - iam_group - - iam_instance_profile - - iam_instance_profile_info - - iam_managed_policy - - iam_policy - - iam_policy_info - - iam_role - - iam_role_info - - iam_user - - iam_user_info - - kms_key - - kms_key_info - - lambda - - lambda_alias - - lambda_event - - lambda_execute - - lambda_info - - lambda_layer - - lambda_layer_info - - lambda_policy - - rds_cluster - - rds_cluster_info - - rds_cluster_snapshot - - rds_instance - - rds_instance_info - - rds_instance_snapshot - - rds_option_group - - rds_option_group_info - - rds_param_group - - rds_snapshot_info - - rds_subnet_group - - route53 - - route53_health_check - - route53_info - - route53_zone - - s3_bucket - - s3_object - - s3_object_info - - sts_assume_role + - autoscaling_group + - autoscaling_group_info + - aws_az_info + - aws_caller_info + - aws_s3 + - backup_plan + - backup_plan_info + - backup_selection + - backup_selection_info + - backup_tag + - backup_tag_info + - backup_vault + - backup_vault_info + - cloudformation + - cloudformation_info + - cloudtrail + - cloudtrail_info + - cloudwatch_metric_alarm + - cloudwatch_metric_alarm_info + - cloudwatchevent_rule + - cloudwatchevent_rule + - cloudwatchlogs_log_group + - cloudwatchlogs_log_group_info + - cloudwatchlogs_log_group_metric_filter + - ec2_ami + - ec2_ami_info + - ec2_eip + - ec2_eip_info + - ec2_elb_lb + - ec2_eni + - ec2_eni_info + - ec2_group + - ec2_group_info + - ec2_instance + - ec2_instance_info + - ec2_key + - ec2_key_info + - ec2_security_group + - ec2_security_group_info + - ec2_snapshot + - ec2_snapshot_info + - ec2_spot_instance + - ec2_spot_instance_info + - ec2_tag + - ec2_tag_info + - ec2_vol + - ec2_vol_info + - ec2_vpc_dhcp_option + - ec2_vpc_dhcp_option_info + - ec2_vpc_endpoint + - ec2_vpc_endpoint_info + - ec2_vpc_endpoint_service_info + - ec2_vpc_igw + - ec2_vpc_igw_info + - ec2_vpc_nat_gateway + - ec2_vpc_nat_gateway_info + - ec2_vpc_net + - ec2_vpc_net_info + - ec2_vpc_route_table + - ec2_vpc_route_table_info + - ec2_vpc_subnet + - ec2_vpc_subnet_info + - elb_application_lb + - elb_application_lb_info + - elb_classic_lb + - execute_lambda + - iam_group + - iam_instance_profile + - iam_instance_profile_info + - iam_managed_policy + - iam_policy + - iam_policy_info + - iam_role + - iam_role_info + - iam_user + - iam_user_info + - kms_key + - kms_key_info + - lambda + - lambda_alias + - lambda_event + - lambda_execute + - lambda_info + - lambda_layer + - lambda_layer_info + - lambda_policy + - rds_cluster + - rds_cluster_info + - rds_cluster_snapshot + - rds_instance + - rds_instance_info + - rds_instance_snapshot + - rds_option_group + - rds_option_group_info + - rds_param_group + - rds_snapshot_info + - rds_subnet_group + - route53 + - route53_health_check + - route53_info + - route53_zone + - s3_bucket + - s3_object + - s3_object_info + - sts_assume_role plugin_routing: action: aws_s3: From 6d555b1119e23ebc9ba6afdca2418166b48b963f Mon Sep 17 00:00:00 2001 From: jillr Date: Mon, 2 Mar 2020 19:25:18 +0000 Subject: [PATCH 106/129] Initial commit This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/eb75681585a23ea79e642b86a0f8e64e0f40a6d7 --- plugins/modules/iam_password_policy.py | 216 ++++++++++++++++++ .../targets/iam_password_policy/aliases | 2 + .../iam_password_policy/tasks/main.yaml | 105 +++++++++ 3 files changed, 323 insertions(+) create mode 100644 plugins/modules/iam_password_policy.py create mode 100644 tests/integration/targets/iam_password_policy/aliases create mode 100644 tests/integration/targets/iam_password_policy/tasks/main.yaml diff --git a/plugins/modules/iam_password_policy.py b/plugins/modules/iam_password_policy.py new file mode 100644 index 00000000000..8eb03b96f78 --- /dev/null +++ b/plugins/modules/iam_password_policy.py @@ -0,0 +1,216 @@ +#!/usr/bin/python + +# Copyright: (c) 2018, Aaron Smith +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'community'} + + +DOCUMENTATION = ''' +--- +module: iam_password_policy +short_description: Update an IAM Password Policy +description: + - Module updates an IAM Password Policy on a given AWS account +requirements: [ 'botocore', 'boto3' ] +author: + - "Aaron Smith (@slapula)" +options: + state: + description: + - Specifies the overall state of the password policy. + required: true + choices: ['present', 'absent'] + type: str + min_pw_length: + description: + - Minimum password length. + default: 6 + aliases: [minimum_password_length] + type: int + require_symbols: + description: + - Require symbols in password. + default: false + type: bool + require_numbers: + description: + - Require numbers in password. + default: false + type: bool + require_uppercase: + description: + - Require uppercase letters in password. + default: false + type: bool + require_lowercase: + description: + - Require lowercase letters in password. + default: false + type: bool + allow_pw_change: + description: + - Allow users to change their password. + default: false + type: bool + aliases: [allow_password_change] + pw_max_age: + description: + - Maximum age for a password in days. When this option is 0 then passwords + do not expire automatically. + default: 0 + aliases: [password_max_age] + type: int + pw_reuse_prevent: + description: + - Prevent re-use of passwords. + default: 0 + aliases: [password_reuse_prevent, prevent_reuse] + type: int + pw_expire: + description: + - Prevents users from change an expired password. + default: false + type: bool + aliases: [password_expire, expire] +extends_documentation_fragment: +- ansible.amazon.aws +- ansible.amazon.ec2 + +''' + +EXAMPLES = ''' +- name: Password policy for AWS account + iam_password_policy: + state: present + min_pw_length: 8 + require_symbols: false + require_numbers: true + require_uppercase: true + require_lowercase: true + allow_pw_change: true + pw_max_age: 60 + pw_reuse_prevent: 5 + pw_expire: false +''' + +RETURN = ''' # ''' + +try: + import botocore +except ImportError: + pass # caught by AnsibleAWSModule + +from ansible_collections.ansible.amazon.plugins.module_utils.aws.core import AnsibleAWSModule +from ansible_collections.ansible.amazon.plugins.module_utils.ec2 import camel_dict_to_snake_dict + + +class IAMConnection(object): + def __init__(self, module): + try: + self.connection = module.resource('iam') + self.module = module + except Exception as e: + module.fail_json(msg="Failed to connect to AWS: %s" % str(e)) + + def policy_to_dict(self, policy): + policy_attributes = [ + 'allow_users_to_change_password', 'expire_passwords', 'hard_expiry', + 'max_password_age', 'minimum_password_length', 'password_reuse_prevention', + 'require_lowercase_characters', 'require_numbers', 'require_symbols', 'require_uppercase_characters' + ] + ret = {} + for attr in policy_attributes: + ret[attr] = getattr(policy, attr) + return ret + + def update_password_policy(self, module, policy): + min_pw_length = module.params.get('min_pw_length') + require_symbols = module.params.get('require_symbols') + require_numbers = module.params.get('require_numbers') + require_uppercase = module.params.get('require_uppercase') + require_lowercase = module.params.get('require_lowercase') + allow_pw_change = module.params.get('allow_pw_change') + pw_max_age = module.params.get('pw_max_age') + pw_reuse_prevent = module.params.get('pw_reuse_prevent') + pw_expire = module.params.get('pw_expire') + + update_parameters = dict( + MinimumPasswordLength=min_pw_length, + RequireSymbols=require_symbols, + RequireNumbers=require_numbers, + RequireUppercaseCharacters=require_uppercase, + RequireLowercaseCharacters=require_lowercase, + AllowUsersToChangePassword=allow_pw_change, + HardExpiry=pw_expire + ) + if pw_reuse_prevent: + update_parameters.update(PasswordReusePrevention=pw_reuse_prevent) + if pw_max_age: + update_parameters.update(MaxPasswordAge=pw_max_age) + + try: + original_policy = self.policy_to_dict(policy) + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: + original_policy = {} + + try: + results = policy.update(**update_parameters) + policy.reload() + updated_policy = self.policy_to_dict(policy) + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: + self.module.fail_json_aws(e, msg="Couldn't update IAM Password Policy") + + changed = (original_policy != updated_policy) + return (changed, updated_policy, camel_dict_to_snake_dict(results)) + + def delete_password_policy(self, policy): + try: + results = policy.delete() + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: + if e.response['Error']['Code'] == 'NoSuchEntity': + self.module.exit_json(changed=False, task_status={'IAM': "Couldn't find IAM Password Policy"}) + else: + self.module.fail_json_aws(e, msg="Couldn't delete IAM Password Policy") + return camel_dict_to_snake_dict(results) + + +def main(): + module = AnsibleAWSModule( + argument_spec={ + 'state': dict(choices=['present', 'absent'], required=True), + 'min_pw_length': dict(type='int', aliases=['minimum_password_length'], default=6), + 'require_symbols': dict(type='bool', default=False), + 'require_numbers': dict(type='bool', default=False), + 'require_uppercase': dict(type='bool', default=False), + 'require_lowercase': dict(type='bool', default=False), + 'allow_pw_change': dict(type='bool', aliases=['allow_password_change'], default=False), + 'pw_max_age': dict(type='int', aliases=['password_max_age'], default=0), + 'pw_reuse_prevent': dict(type='int', aliases=['password_reuse_prevent', 'prevent_reuse'], default=0), + 'pw_expire': dict(type='bool', aliases=['password_expire', 'expire'], default=False), + }, + supports_check_mode=True, + ) + + resource = IAMConnection(module) + policy = resource.connection.AccountPasswordPolicy() + + state = module.params.get('state') + + if state == 'present': + (changed, new_policy, update_result) = resource.update_password_policy(module, policy) + module.exit_json(changed=changed, task_status={'IAM': update_result}, policy=new_policy) + + if state == 'absent': + delete_result = resource.delete_password_policy(policy) + module.exit_json(changed=True, task_status={'IAM': delete_result}) + + +if __name__ == '__main__': + main() diff --git a/tests/integration/targets/iam_password_policy/aliases b/tests/integration/targets/iam_password_policy/aliases new file mode 100644 index 00000000000..56927195182 --- /dev/null +++ b/tests/integration/targets/iam_password_policy/aliases @@ -0,0 +1,2 @@ +cloud/aws +unsupported diff --git a/tests/integration/targets/iam_password_policy/tasks/main.yaml b/tests/integration/targets/iam_password_policy/tasks/main.yaml new file mode 100644 index 00000000000..6cffea003a9 --- /dev/null +++ b/tests/integration/targets/iam_password_policy/tasks/main.yaml @@ -0,0 +1,105 @@ +- 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: set iam password policy + iam_password_policy: + state: present + min_pw_length: 8 + require_symbols: false + require_numbers: true + require_uppercase: true + require_lowercase: true + allow_pw_change: true + pw_max_age: 60 + pw_reuse_prevent: 5 + pw_expire: false + register: result + + - name: assert that changes were made + assert: + that: + - result.changed + + - name: verify iam password policy has been created + iam_password_policy: + state: present + min_pw_length: 8 + require_symbols: false + require_numbers: true + require_uppercase: true + require_lowercase: true + allow_pw_change: true + pw_max_age: 60 + pw_reuse_prevent: 5 + pw_expire: false + register: result + + - name: assert that no changes were made + assert: + that: + - not result.changed + + - name: update iam password policy with different settings + iam_password_policy: + state: present + min_pw_length: 15 + require_symbols: true + require_numbers: true + require_uppercase: true + require_lowercase: true + allow_pw_change: true + pw_max_age: 30 + pw_reuse_prevent: 10 + pw_expire: true + register: result + + - name: assert that updates were made + assert: + that: + - result.changed + + # Test for regression of #59102 + - name: update iam password policy without expiry + iam_password_policy: + state: present + min_pw_length: 15 + require_symbols: true + require_numbers: true + require_uppercase: true + require_lowercase: true + allow_pw_change: true + register: result + + - name: assert that changes were made + assert: + that: + - result.changed + + - name: remove iam password policy + iam_password_policy: + state: absent + register: result + + - name: assert password policy has been removed + assert: + that: + - result.changed + + - name: verify password policy has been removed + iam_password_policy: + state: absent + register: result + + - name: assert no changes were made + assert: + that: + - not result.changed + always: + - name: remove iam password policy + iam_password_policy: + state: absent + register: result From 6ed219d11e635862924907167a74fab4cb9bf5b6 Mon Sep 17 00:00:00 2001 From: jillr Date: Tue, 3 Mar 2020 19:43:21 +0000 Subject: [PATCH 107/129] migration test cleanup This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/13b104b912784bb31a0bff23eed4c27b0f5e0283 --- tests/integration/targets/iam_password_policy/tasks/main.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/integration/targets/iam_password_policy/tasks/main.yaml b/tests/integration/targets/iam_password_policy/tasks/main.yaml index 6cffea003a9..0b4b8b89917 100644 --- a/tests/integration/targets/iam_password_policy/tasks/main.yaml +++ b/tests/integration/targets/iam_password_policy/tasks/main.yaml @@ -4,6 +4,8 @@ aws_secret_key: "{{ aws_secret_key }}" security_token: "{{ security_token | default(omit) }}" region: "{{ aws_region }}" + collections: + - ansible.amazon block: - name: set iam password policy iam_password_policy: From 46e54579f9743051c961d28b83a9a6439143217f Mon Sep 17 00:00:00 2001 From: Jill R <4121322+jillr@users.noreply.github.com> Date: Wed, 25 Mar 2020 15:39:40 -0700 Subject: [PATCH 108/129] Rename collection (#12) * Rename core collection Rename references to ansible.amazon to amazon.aws. * Rename community.amazon to community.aws Fix pep8 line lengths for rewritten amazon.aws imports * Missed a path in shippable.sh * Dependency repos moved This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/235c5db571cc45db5839476c94356c9b91e1f228 --- plugins/modules/iam_password_policy.py | 8 ++++---- .../targets/iam_password_policy/tasks/main.yaml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/modules/iam_password_policy.py b/plugins/modules/iam_password_policy.py index 8eb03b96f78..ead34bf8868 100644 --- a/plugins/modules/iam_password_policy.py +++ b/plugins/modules/iam_password_policy.py @@ -80,8 +80,8 @@ type: bool aliases: [password_expire, expire] extends_documentation_fragment: -- ansible.amazon.aws -- ansible.amazon.ec2 +- amazon.aws.aws +- amazon.aws.ec2 ''' @@ -107,8 +107,8 @@ except ImportError: pass # caught by AnsibleAWSModule -from ansible_collections.ansible.amazon.plugins.module_utils.aws.core import AnsibleAWSModule -from ansible_collections.ansible.amazon.plugins.module_utils.ec2 import camel_dict_to_snake_dict +from ansible_collections.amazon.aws.plugins.module_utils.aws.core import AnsibleAWSModule +from ansible_collections.amazon.aws.plugins.module_utils.ec2 import camel_dict_to_snake_dict class IAMConnection(object): diff --git a/tests/integration/targets/iam_password_policy/tasks/main.yaml b/tests/integration/targets/iam_password_policy/tasks/main.yaml index 0b4b8b89917..7b773eac808 100644 --- a/tests/integration/targets/iam_password_policy/tasks/main.yaml +++ b/tests/integration/targets/iam_password_policy/tasks/main.yaml @@ -5,7 +5,7 @@ security_token: "{{ security_token | default(omit) }}" region: "{{ aws_region }}" collections: - - ansible.amazon + - amazon.aws block: - name: set iam password policy iam_password_policy: From 7b3f5f97eb5cc1b624c21629f1d8f63bcb1beb62 Mon Sep 17 00:00:00 2001 From: Jill R <4121322+jillr@users.noreply.github.com> Date: Tue, 19 May 2020 16:06:12 -0700 Subject: [PATCH 109/129] Remove METADATA and cleanup galaxy.yml (#70) * Remove ANSIBLE_METADATA entirely, see ansible/ansible/pull/69454. Remove `license` field from galaxy.yml, in favor of `license_file`. This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/05672a64e2362cc2d865b5af6a57da6bc3cd08e3 --- plugins/modules/iam_password_policy.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/plugins/modules/iam_password_policy.py b/plugins/modules/iam_password_policy.py index ead34bf8868..53c1d5bc479 100644 --- a/plugins/modules/iam_password_policy.py +++ b/plugins/modules/iam_password_policy.py @@ -7,11 +7,6 @@ __metaclass__ = type -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - DOCUMENTATION = ''' --- module: iam_password_policy From e3d52b945d0296ec4abb15be5267329bbfbfdd10 Mon Sep 17 00:00:00 2001 From: Abhijeet Kasurde Date: Wed, 17 Jun 2020 01:24:54 +0530 Subject: [PATCH 110/129] Update Examples with FQCN (#67) Updated module examples with FQCN Signed-off-by: Abhijeet Kasurde This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/98173aefbbceed7fc0d9db62687b73f96a55a999 --- plugins/modules/iam_password_policy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/iam_password_policy.py b/plugins/modules/iam_password_policy.py index 53c1d5bc479..a26821e10a4 100644 --- a/plugins/modules/iam_password_policy.py +++ b/plugins/modules/iam_password_policy.py @@ -82,7 +82,7 @@ EXAMPLES = ''' - name: Password policy for AWS account - iam_password_policy: + community.aws.iam_password_policy: state: present min_pw_length: 8 require_symbols: false From 9e107083e2185066d580df71ef52b7ba910cb410 Mon Sep 17 00:00:00 2001 From: flowerysong Date: Tue, 16 Jun 2020 19:30:00 -0400 Subject: [PATCH 111/129] Update module_utils paths to remove aws subdir (#23) Co-authored-by: Ezekiel Hendrickson This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/10853d9441a586ba177006dd889325cfb24a3dd6 --- plugins/modules/iam_password_policy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/iam_password_policy.py b/plugins/modules/iam_password_policy.py index a26821e10a4..fda220c0097 100644 --- a/plugins/modules/iam_password_policy.py +++ b/plugins/modules/iam_password_policy.py @@ -102,7 +102,7 @@ except ImportError: pass # caught by AnsibleAWSModule -from ansible_collections.amazon.aws.plugins.module_utils.aws.core import AnsibleAWSModule +from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule from ansible_collections.amazon.aws.plugins.module_utils.ec2 import camel_dict_to_snake_dict From 3347bff29e7f333d02829bb364eca6cdc8616c2e Mon Sep 17 00:00:00 2001 From: Jill R <4121322+jillr@users.noreply.github.com> Date: Wed, 17 Jun 2020 09:31:32 -0700 Subject: [PATCH 112/129] Update docs (#99) * Update docs Remove .git from repo url so links in readme will generate correctly Add required ansible version Run latest version of add_docs.py Add version_added string to modules * galaxy.yml was missing authors This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/96ee268e5267f5b12c3d59892bc1279f75aa3135 --- plugins/modules/iam_password_policy.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/modules/iam_password_policy.py b/plugins/modules/iam_password_policy.py index fda220c0097..d654a846cfd 100644 --- a/plugins/modules/iam_password_policy.py +++ b/plugins/modules/iam_password_policy.py @@ -10,6 +10,7 @@ DOCUMENTATION = ''' --- module: iam_password_policy +version_added: 1.0.0 short_description: Update an IAM Password Policy description: - Module updates an IAM Password Policy on a given AWS account From 94941984d4f5822e2aef8c6e601fd6f3d7324fd5 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Fri, 5 Feb 2021 09:43:09 +0100 Subject: [PATCH 113/129] Cleanup - use is_boto3_error_(message|code) (#268) * Reorder imports * Make use of is_boto3_error_message * Mass-migration over to is_boto3_error_code * Remove unused imports * unused vars in exception * Improve consistency around catching BotoCoreError and ClientError * Remove unused imports * Remove unused 'PolicyError' from iam_policy_info * Avoid catching botocore.exceptions.ClientError when we only want some error codes * Import camel_dict_to_snake_dict/snake_dict_to_camel_dict from ansible.module_utils.common.dict_transformations This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/4cf52ef67682fd4f9ed2a707adfbafffe7b88f15 --- plugins/modules/iam_password_policy.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/plugins/modules/iam_password_policy.py b/plugins/modules/iam_password_policy.py index d654a846cfd..852deb0d10b 100644 --- a/plugins/modules/iam_password_policy.py +++ b/plugins/modules/iam_password_policy.py @@ -103,8 +103,10 @@ 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.core import AnsibleAWSModule -from ansible_collections.amazon.aws.plugins.module_utils.ec2 import camel_dict_to_snake_dict +from ansible_collections.amazon.aws.plugins.module_utils.core import is_boto3_error_code class IAMConnection(object): @@ -169,11 +171,10 @@ def update_password_policy(self, module, policy): def delete_password_policy(self, policy): try: results = policy.delete() - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - if e.response['Error']['Code'] == 'NoSuchEntity': - self.module.exit_json(changed=False, task_status={'IAM': "Couldn't find IAM Password Policy"}) - else: - self.module.fail_json_aws(e, msg="Couldn't delete IAM Password Policy") + except is_boto3_error_code('NoSuchEntity'): + self.module.exit_json(changed=False, task_status={'IAM': "Couldn't find IAM Password Policy"}) + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: # pylint: disable=duplicate-except + self.module.fail_json_aws(e, msg="Couldn't delete IAM Password Policy") return camel_dict_to_snake_dict(results) From b3de5bae26ee65ab1e8ec2dd1e670de323d559a3 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Sat, 13 Feb 2021 14:19:21 +0100 Subject: [PATCH 114/129] Add comments to the disabled/unsupported integration test aliase files (#411) Add some additional comments so we know *why* the various tests aren't running. Looks like most of them just need policy updates This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/0d245596966100516f1eeab5dcf26ee0ebca24b5 --- tests/integration/targets/iam_password_policy/aliases | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/integration/targets/iam_password_policy/aliases b/tests/integration/targets/iam_password_policy/aliases index 56927195182..de4c8915ab9 100644 --- a/tests/integration/targets/iam_password_policy/aliases +++ b/tests/integration/targets/iam_password_policy/aliases @@ -1,2 +1,6 @@ -cloud/aws +# reason: missing-policy +# IAM Password Policies configure account-wide settings, this makes then +# difficult to safely test unsupported + +cloud/aws From 9be09682b3e21638f4dd7f5ea338c9dbb7f508eb Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Thu, 25 Feb 2021 11:14:13 +0100 Subject: [PATCH 115/129] Move a couple of 4 minute tests out of group 2 into 1&4 (#443) This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/77fdb76e317da356946af33fa6ae2847310cdb71 --- tests/integration/targets/iam_password_policy/aliases | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/integration/targets/iam_password_policy/aliases b/tests/integration/targets/iam_password_policy/aliases index de4c8915ab9..140a2f2dc7d 100644 --- a/tests/integration/targets/iam_password_policy/aliases +++ b/tests/integration/targets/iam_password_policy/aliases @@ -1,6 +1,8 @@ # reason: missing-policy # IAM Password Policies configure account-wide settings, this makes then # difficult to safely test +# reason: serial +# Only one password policy can be configured per account unsupported cloud/aws From 86962e4ee3cb55692da61138dd59cce1fd11d99b Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Thu, 6 May 2021 21:01:46 +0200 Subject: [PATCH 116/129] Update the default module requirements from python 2.6/boto to python 3.6/boto3 This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/c097c55293be0834a2b9d394733ec28965d142d7 --- plugins/modules/iam_password_policy.py | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/modules/iam_password_policy.py b/plugins/modules/iam_password_policy.py index 852deb0d10b..51291092b0b 100644 --- a/plugins/modules/iam_password_policy.py +++ b/plugins/modules/iam_password_policy.py @@ -14,7 +14,6 @@ short_description: Update an IAM Password Policy description: - Module updates an IAM Password Policy on a given AWS account -requirements: [ 'botocore', 'boto3' ] author: - "Aaron Smith (@slapula)" options: From d7fdedc73f09f33df81c77a093738513a3bf8d71 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Fri, 22 Apr 2022 12:20:04 +0200 Subject: [PATCH 117/129] For consistency - add empty dependencies file to targets with no current meta data (#1090) For consistency - add empty dependencies file to targets with no current meta data SUMMARY For consistency - add empty dependencies file to targets with no current meta data ISSUE TYPE Feature Pull Request COMPONENT NAME tests/integration/targets ADDITIONAL INFORMATION Reviewed-by: Alina Buzachis This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/96385803df04cfa34c62d1ab19be21b12f593af6 --- tests/integration/targets/iam_password_policy/meta/main.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 tests/integration/targets/iam_password_policy/meta/main.yml diff --git a/tests/integration/targets/iam_password_policy/meta/main.yml b/tests/integration/targets/iam_password_policy/meta/main.yml new file mode 100644 index 00000000000..32cf5dda7ed --- /dev/null +++ b/tests/integration/targets/iam_password_policy/meta/main.yml @@ -0,0 +1 @@ +dependencies: [] From b5f694c39174f4ad1aadde3347ccc05a4e531630 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Wed, 5 Oct 2022 17:04:40 +0200 Subject: [PATCH 118/129] Update extends_documentation_fragment with amazon.aws.boto3 (#1459) Update extends_documentation_fragment with amazon.aws.boto3 Depends-On: ansible/ansible-zuul-jobs#1654 SUMMARY As per ansible-collections/amazon.aws#985 add amazon.aws.boto3. ISSUE TYPE Docs Pull Request COMPONENT NAME several Reviewed-by: Jill R Reviewed-by: Mark Chappell Reviewed-by: Markus Bergholz This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/bd3c03fcba0848f593b86309740fa73e986a9646 --- plugins/modules/iam_password_policy.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/modules/iam_password_policy.py b/plugins/modules/iam_password_policy.py index 51291092b0b..19614d26da6 100644 --- a/plugins/modules/iam_password_policy.py +++ b/plugins/modules/iam_password_policy.py @@ -77,6 +77,7 @@ extends_documentation_fragment: - amazon.aws.aws - amazon.aws.ec2 +- amazon.aws.boto3 ''' From 6ffaed0ccfc4adbe34920afa95f489575490bdab Mon Sep 17 00:00:00 2001 From: Bikouo Aubin <79859644+abikouo@users.noreply.github.com> Date: Tue, 10 Jan 2023 19:22:13 +0100 Subject: [PATCH 119/129] Ansible User-Agent identification for community.aws (#1632) Ansible User-Agent identification for community.aws SUMMARY The value will be similar to this APN/1.0 Ansible/2.14.1 community.aws/6.0.0-dev0 ISSUE TYPE Feature Pull Request Reviewed-by: Mark Chappell Reviewed-by: Bikouo Aubin Reviewed-by: Alina Buzachis This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/a8cbce24071bcc62fe4594c38aff1baf18bd2862 --- plugins/modules/iam_password_policy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/iam_password_policy.py b/plugins/modules/iam_password_policy.py index 19614d26da6..00b4f8872c0 100644 --- a/plugins/modules/iam_password_policy.py +++ b/plugins/modules/iam_password_policy.py @@ -105,7 +105,7 @@ from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict -from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule +from ansible_collections.community.aws.plugins.module_utils.modules import AnsibleCommunityAWSModule as AnsibleAWSModule from ansible_collections.amazon.aws.plugins.module_utils.core import is_boto3_error_code From 6e9df2febf16c07082fe8cc7191c4b3c97444a80 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Wed, 8 Mar 2023 12:07:26 +0100 Subject: [PATCH 120/129] Cleanup headers and imports (#1738) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cleanup headers and imports SUMMARY Mass update of imports, docs fragments and file headers Many of the amazon.aws module_utils and docs fragments got moved about, update community.aws to reflect this. Consistently apply the comment headers as documented at https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_documenting.html#python-shebang-utf-8-coding ISSUE TYPE Docs Pull Request Feature Pull Request COMPONENT NAME ADDITIONAL INFORMATION Header cleanup based upon: https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_documenting.html#python-shebang-utf-8-coding Begin your Ansible module with #!/usr/bin/python - this “shebang” allows ansible_python_interpreter to work. Follow the shebang immediately with # -*- coding: utf-8 -*- to clarify that the file is UTF-8 encoded. and https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_documenting.html#copyright-and-license After the shebang and UTF-8 coding, add a copyright line with the original copyright holder and a license declaration. The license declaration should be ONLY one line, not the full GPL prefix. ... Additions to the module (for instance, rewrites) are not permitted to add additional copyright lines other than the default copyright statement if missing: Reviewed-by: Alina Buzachis This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/a4f20bf114bfab19b1c84c4ecf42efd5614ab80c --- plugins/modules/iam_password_policy.py | 29 ++++++++++++-------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/plugins/modules/iam_password_policy.py b/plugins/modules/iam_password_policy.py index 00b4f8872c0..a980511c2fa 100644 --- a/plugins/modules/iam_password_policy.py +++ b/plugins/modules/iam_password_policy.py @@ -1,21 +1,18 @@ #!/usr/bin/python +# -*- coding: utf-8 -*- # Copyright: (c) 2018, Aaron Smith # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -from __future__ import absolute_import, division, print_function -__metaclass__ = type - - -DOCUMENTATION = ''' +DOCUMENTATION = r""" --- module: iam_password_policy version_added: 1.0.0 short_description: Update an IAM Password Policy description: - - Module updates an IAM Password Policy on a given AWS account + - Module updates an IAM Password Policy on a given AWS account author: - - "Aaron Smith (@slapula)" + - "Aaron Smith (@slapula)" options: state: description: @@ -75,13 +72,12 @@ type: bool aliases: [password_expire, expire] extends_documentation_fragment: -- amazon.aws.aws -- amazon.aws.ec2 -- amazon.aws.boto3 + - amazon.aws.common.modules + - amazon.aws.region.modules + - amazon.aws.boto3 +""" -''' - -EXAMPLES = ''' +EXAMPLES = r""" - name: Password policy for AWS account community.aws.iam_password_policy: state: present @@ -94,9 +90,9 @@ pw_max_age: 60 pw_reuse_prevent: 5 pw_expire: false -''' +""" -RETURN = ''' # ''' +RETURN = r""" # """ try: import botocore @@ -105,8 +101,9 @@ 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.community.aws.plugins.module_utils.modules import AnsibleCommunityAWSModule as AnsibleAWSModule -from ansible_collections.amazon.aws.plugins.module_utils.core import is_boto3_error_code class IAMConnection(object): From e9fbb06a44f4a20b8abf5f07ffd6873def4f1eed Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Wed, 26 Apr 2023 19:26:07 +0200 Subject: [PATCH 121/129] Big Black PR (#1784) * Black prep * Black * changelog * Fix pylint unused-import in tests * Split SSM connection plugin changes * disable glue tests - bucket's missing * Disable s3_logging and s3_sync tests This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/2c4575c248776c65d66b06cd60fa09b0dae1cd6f --- plugins/modules/iam_password_policy.py | 78 +++++++++++++++----------- 1 file changed, 44 insertions(+), 34 deletions(-) diff --git a/plugins/modules/iam_password_policy.py b/plugins/modules/iam_password_policy.py index a980511c2fa..7c93da4139f 100644 --- a/plugins/modules/iam_password_policy.py +++ b/plugins/modules/iam_password_policy.py @@ -109,16 +109,23 @@ class IAMConnection(object): def __init__(self, module): try: - self.connection = module.resource('iam') + self.connection = module.resource("iam") self.module = module except Exception as e: module.fail_json(msg="Failed to connect to AWS: %s" % str(e)) def policy_to_dict(self, policy): policy_attributes = [ - 'allow_users_to_change_password', 'expire_passwords', 'hard_expiry', - 'max_password_age', 'minimum_password_length', 'password_reuse_prevention', - 'require_lowercase_characters', 'require_numbers', 'require_symbols', 'require_uppercase_characters' + "allow_users_to_change_password", + "expire_passwords", + "hard_expiry", + "max_password_age", + "minimum_password_length", + "password_reuse_prevention", + "require_lowercase_characters", + "require_numbers", + "require_symbols", + "require_uppercase_characters", ] ret = {} for attr in policy_attributes: @@ -126,15 +133,15 @@ def policy_to_dict(self, policy): return ret def update_password_policy(self, module, policy): - min_pw_length = module.params.get('min_pw_length') - require_symbols = module.params.get('require_symbols') - require_numbers = module.params.get('require_numbers') - require_uppercase = module.params.get('require_uppercase') - require_lowercase = module.params.get('require_lowercase') - allow_pw_change = module.params.get('allow_pw_change') - pw_max_age = module.params.get('pw_max_age') - pw_reuse_prevent = module.params.get('pw_reuse_prevent') - pw_expire = module.params.get('pw_expire') + min_pw_length = module.params.get("min_pw_length") + require_symbols = module.params.get("require_symbols") + require_numbers = module.params.get("require_numbers") + require_uppercase = module.params.get("require_uppercase") + require_lowercase = module.params.get("require_lowercase") + allow_pw_change = module.params.get("allow_pw_change") + pw_max_age = module.params.get("pw_max_age") + pw_reuse_prevent = module.params.get("pw_reuse_prevent") + pw_expire = module.params.get("pw_expire") update_parameters = dict( MinimumPasswordLength=min_pw_length, @@ -143,7 +150,7 @@ def update_password_policy(self, module, policy): RequireUppercaseCharacters=require_uppercase, RequireLowercaseCharacters=require_lowercase, AllowUsersToChangePassword=allow_pw_change, - HardExpiry=pw_expire + HardExpiry=pw_expire, ) if pw_reuse_prevent: update_parameters.update(PasswordReusePrevention=pw_reuse_prevent) @@ -162,15 +169,18 @@ def update_password_policy(self, module, policy): except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: self.module.fail_json_aws(e, msg="Couldn't update IAM Password Policy") - changed = (original_policy != updated_policy) + changed = original_policy != updated_policy return (changed, updated_policy, camel_dict_to_snake_dict(results)) def delete_password_policy(self, policy): try: results = policy.delete() - except is_boto3_error_code('NoSuchEntity'): - self.module.exit_json(changed=False, task_status={'IAM': "Couldn't find IAM Password Policy"}) - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: # pylint: disable=duplicate-except + except is_boto3_error_code("NoSuchEntity"): + self.module.exit_json(changed=False, task_status={"IAM": "Couldn't find IAM Password Policy"}) + except ( + botocore.exceptions.ClientError, + botocore.exceptions.BotoCoreError, + ) as e: # pylint: disable=duplicate-except self.module.fail_json_aws(e, msg="Couldn't delete IAM Password Policy") return camel_dict_to_snake_dict(results) @@ -178,16 +188,16 @@ def delete_password_policy(self, policy): def main(): module = AnsibleAWSModule( argument_spec={ - 'state': dict(choices=['present', 'absent'], required=True), - 'min_pw_length': dict(type='int', aliases=['minimum_password_length'], default=6), - 'require_symbols': dict(type='bool', default=False), - 'require_numbers': dict(type='bool', default=False), - 'require_uppercase': dict(type='bool', default=False), - 'require_lowercase': dict(type='bool', default=False), - 'allow_pw_change': dict(type='bool', aliases=['allow_password_change'], default=False), - 'pw_max_age': dict(type='int', aliases=['password_max_age'], default=0), - 'pw_reuse_prevent': dict(type='int', aliases=['password_reuse_prevent', 'prevent_reuse'], default=0), - 'pw_expire': dict(type='bool', aliases=['password_expire', 'expire'], default=False), + "state": dict(choices=["present", "absent"], required=True), + "min_pw_length": dict(type="int", aliases=["minimum_password_length"], default=6), + "require_symbols": dict(type="bool", default=False), + "require_numbers": dict(type="bool", default=False), + "require_uppercase": dict(type="bool", default=False), + "require_lowercase": dict(type="bool", default=False), + "allow_pw_change": dict(type="bool", aliases=["allow_password_change"], default=False), + "pw_max_age": dict(type="int", aliases=["password_max_age"], default=0), + "pw_reuse_prevent": dict(type="int", aliases=["password_reuse_prevent", "prevent_reuse"], default=0), + "pw_expire": dict(type="bool", aliases=["password_expire", "expire"], default=False), }, supports_check_mode=True, ) @@ -195,16 +205,16 @@ def main(): resource = IAMConnection(module) policy = resource.connection.AccountPasswordPolicy() - state = module.params.get('state') + state = module.params.get("state") - if state == 'present': + if state == "present": (changed, new_policy, update_result) = resource.update_password_policy(module, policy) - module.exit_json(changed=changed, task_status={'IAM': update_result}, policy=new_policy) + module.exit_json(changed=changed, task_status={"IAM": update_result}, policy=new_policy) - if state == 'absent': + if state == "absent": delete_result = resource.delete_password_policy(policy) - module.exit_json(changed=True, task_status={'IAM': delete_result}) + module.exit_json(changed=True, task_status={"IAM": delete_result}) -if __name__ == '__main__': +if __name__ == "__main__": main() From 4ca17afb0a2b623ec9a7b58e430860c3be8b7a3c Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Mon, 8 May 2023 19:21:22 +0200 Subject: [PATCH 122/129] Bulk migration to Python 3.6 f-strings (#1810) Bulk migration to Python 3.6 f-strings SUMMARY We've dropped support for Python <3.6, bulk migrate to fstrings and perform some general string cleanup A combination of black --preview flynt some manual cleanup ISSUE TYPE Feature Pull Request COMPONENT NAME plugins/ tests/ ADDITIONAL INFORMATION Reviewed-by: Alina Buzachis This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/de338210dc1b0bb2eecee1dc16e073163b2d1df7 --- plugins/modules/iam_password_policy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/iam_password_policy.py b/plugins/modules/iam_password_policy.py index 7c93da4139f..5c65f7ebaec 100644 --- a/plugins/modules/iam_password_policy.py +++ b/plugins/modules/iam_password_policy.py @@ -112,7 +112,7 @@ def __init__(self, module): self.connection = module.resource("iam") self.module = module except Exception as e: - module.fail_json(msg="Failed to connect to AWS: %s" % str(e)) + module.fail_json(msg=f"Failed to connect to AWS: {str(e)}") def policy_to_dict(self, policy): policy_attributes = [ From f8d4c4a7d552e3e434468be6a502e03b1376bbf1 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Thu, 31 Aug 2023 17:58:59 +0200 Subject: [PATCH 123/129] Mass update of docs and tests (credentials/session tokens) (#1921) Mass update of docs and tests (credentials/session tokens) SUMMARY We had a cleanup of credentials/session parameters which included a batch of deprecations and renames. Ensure that all of our tests and docs are using the 'canonical' names ISSUE TYPE Docs Pull Request COMPONENT NAME plugins/modules/batch_compute_environment.py plugins/modules/cloudformation_exports_info.py plugins/modules/ec2_vpc_vpn.py plugins/modules/elasticache.py plugins/modules/elasticache_parameter_group.py plugins/modules/elasticache_snapshot.py plugins/modules/ses_rule_set.py plugins/modules/sts_assume_role.py plugins/modules/sts_session_token.py tests/integration ADDITIONAL INFORMATION See also ansible-collections/amazon.aws#1172 ansible-collections/amazon.aws#1714 Reviewed-by: Alina Buzachis This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/4a5b50e9b9c0d6ca1a1f802f3b03d4f503c16885 --- .../integration/targets/iam_password_policy/tasks/main.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/integration/targets/iam_password_policy/tasks/main.yaml b/tests/integration/targets/iam_password_policy/tasks/main.yaml index 7b773eac808..c673f74366b 100644 --- a/tests/integration/targets/iam_password_policy/tasks/main.yaml +++ b/tests/integration/targets/iam_password_policy/tasks/main.yaml @@ -1,8 +1,8 @@ - module_defaults: group/aws: - aws_access_key: "{{ aws_access_key }}" - aws_secret_key: "{{ aws_secret_key }}" - security_token: "{{ security_token | default(omit) }}" + access_key: "{{ aws_access_key }}" + secret_key: "{{ aws_secret_key }}" + session_token: "{{ security_token | default(omit) }}" region: "{{ aws_region }}" collections: - amazon.aws From ff504b4bc2353c125ba969c503a1896b86e7505d Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Wed, 27 Sep 2023 18:37:24 +0200 Subject: [PATCH 124/129] Update FQDN --- plugins/modules/iam_password_policy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/iam_password_policy.py b/plugins/modules/iam_password_policy.py index 5c65f7ebaec..77f3b5e7ed1 100644 --- a/plugins/modules/iam_password_policy.py +++ b/plugins/modules/iam_password_policy.py @@ -79,7 +79,7 @@ EXAMPLES = r""" - name: Password policy for AWS account - community.aws.iam_password_policy: + amazon.aws.iam_password_policy: state: present min_pw_length: 8 require_symbols: false From f01e8a6bda00013a5ab925e3bd20ebcd492239df Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Wed, 27 Sep 2023 18:37:24 +0200 Subject: [PATCH 125/129] Add changelog fragment --- changelogs/fragments/migrate_iam_password_policy.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changelogs/fragments/migrate_iam_password_policy.yml diff --git a/changelogs/fragments/migrate_iam_password_policy.yml b/changelogs/fragments/migrate_iam_password_policy.yml new file mode 100644 index 00000000000..6f166cfb9eb --- /dev/null +++ b/changelogs/fragments/migrate_iam_password_policy.yml @@ -0,0 +1,4 @@ +major_changes: +- iam_password_policy - The module has been migrated from the ``community.aws`` collection. + Playbooks using the Fully Qualified Collection Name for this module should be updated + to use ``amazon.aws.iam_password_policy``. From 1ded9d112a846efa06732b1f2ab7092d1d6974ef Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Wed, 27 Sep 2023 18:40:31 +0200 Subject: [PATCH 126/129] Add version_added_collection: community.aws Signed-off-by: Alina Buzachis --- plugins/modules/iam_password_policy.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/modules/iam_password_policy.py b/plugins/modules/iam_password_policy.py index 77f3b5e7ed1..3a455fd627f 100644 --- a/plugins/modules/iam_password_policy.py +++ b/plugins/modules/iam_password_policy.py @@ -8,6 +8,7 @@ --- module: iam_password_policy version_added: 1.0.0 +version_added_collection: community.aws short_description: Update an IAM Password Policy description: - Module updates an IAM Password Policy on a given AWS account From ae76e2376f2f109e6aac5ff3324590de1f61c386 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Thu, 28 Sep 2023 15:18:06 +0200 Subject: [PATCH 127/129] Use the amazon.aws path for importing AnsibleAWSModule Signed-off-by: Alina Buzachis --- plugins/modules/iam_password_policy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/iam_password_policy.py b/plugins/modules/iam_password_policy.py index 3a455fd627f..968c07ee80a 100644 --- a/plugins/modules/iam_password_policy.py +++ b/plugins/modules/iam_password_policy.py @@ -104,7 +104,7 @@ from ansible_collections.amazon.aws.plugins.module_utils.botocore import is_boto3_error_code -from ansible_collections.community.aws.plugins.module_utils.modules import AnsibleCommunityAWSModule as AnsibleAWSModule +from ansible_collections.amazon.aws.plugins.module_utils.modules import AnsibleAWSModule class IAMConnection(object): From 3855172b56cea9300dc88ee5c75c8be17b136c0a Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Mon, 2 Oct 2023 16:44:54 +0200 Subject: [PATCH 128/129] Apply isort Signed-off-by: Alina Buzachis --- meta/runtime.yml | 1 + plugins/modules/iam_password_policy.py | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/runtime.yml b/meta/runtime.yml index 58dcf627c2a..a6ddadfa10c 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -77,6 +77,7 @@ action_groups: - iam_instance_profile_info - iam_managed_policy - iam_mfa_device_info + - iam_password_policy - iam_policy - iam_policy_info - iam_role diff --git a/plugins/modules/iam_password_policy.py b/plugins/modules/iam_password_policy.py index 968c07ee80a..fe6eb9090f2 100644 --- a/plugins/modules/iam_password_policy.py +++ b/plugins/modules/iam_password_policy.py @@ -103,7 +103,6 @@ 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.modules import AnsibleAWSModule From d7fae9dda8c51ab0e2ae17adf1faf81838bfeee5 Mon Sep 17 00:00:00 2001 From: Aditya Putta Date: Thu, 12 Oct 2023 04:21:49 -0500 Subject: [PATCH 129/129] Update aws_az_info.py (#1795) aws_az_info - add example of filtering by state SUMMARY You can filter availability zones based on their state, such as "available," "unavailable," or "modifying." ISSUE TYPE Docs Pull Request COMPONENT NAME amazon.aws.aws_az_info: Reviewed-by: Mark Chappell --- plugins/modules/aws_az_info.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugins/modules/aws_az_info.py b/plugins/modules/aws_az_info.py index 9bbbb9ffd26..a373f41bc85 100644 --- a/plugins/modules/aws_az_info.py +++ b/plugins/modules/aws_az_info.py @@ -39,6 +39,12 @@ amazon.aws.aws_az_info: filters: zone-name: eu-west-1a + +- name: Gather information in a availability zones based on their state, such as "available" + amazon.aws.aws_az_info: + region: us-east-1 + filters: + state: available """ RETURN = r"""