diff --git a/changelogs/fragments/619-inventory-aws_ec2-assume-arn-role-when-listing-regions.yml b/changelogs/fragments/619-inventory-aws_ec2-assume-arn-role-when-listing-regions.yml new file mode 100644 index 00000000000..67451a5ae33 --- /dev/null +++ b/changelogs/fragments/619-inventory-aws_ec2-assume-arn-role-when-listing-regions.yml @@ -0,0 +1,5 @@ +minor_changes: +- >- + aws_ec2 inventory - use the iam_role_arn configuration parameter to assume the role before trying to call DescribeRegions + if the regions configuration is not set and AWS credentials provided without enough privilege to perform the DescribeRegions action. + (https://github.com/ansible-collections/amazon.aws/issues/566) diff --git a/plugins/inventory/aws_ec2.py b/plugins/inventory/aws_ec2.py index 3806a0a2c9f..194dcf05295 100644 --- a/plugins/inventory/aws_ec2.py +++ b/plugins/inventory/aws_ec2.py @@ -227,6 +227,7 @@ 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 boto3_tag_list_to_ansible_dict 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 # The mappings give an array of keys to get from the filter name to the value @@ -408,7 +409,7 @@ def _get_connection(self, credentials, region='us-east-1'): raise AnsibleError("Insufficient credentials found: %s" % to_native(e)) return connection - def _boto3_assume_role(self, credentials, region): + def _boto3_assume_role(self, credentials, region=None): """ Assume an IAM role passed by iam_role_arn parameter @@ -447,6 +448,17 @@ def _boto3_conn(self, regions): except botocore.exceptions.NoRegionError: # above seems to fail depending on boto3 version, ignore and lets try something else pass + except is_boto3_error_code('UnauthorizedOperation'): # pylint: disable=duplicate-except + if iam_role_arn is not None: + try: + # Describe regions assuming arn role + assumed_credentials = self._boto3_assume_role(credentials) + client = self._get_connection(assumed_credentials) + resp = client.describe_regions() + regions = [x['RegionName'] for x in resp.get('Regions', [])] + except botocore.exceptions.NoRegionError: + # above seems to fail depending on boto3 version, ignore and lets try something else + pass # fallback to local list hardcoded in boto3 if still no regions if not regions: