From 64a2077787904f144f77839660071f35f25d181f Mon Sep 17 00:00:00 2001 From: Mick Bass Date: Wed, 24 Dec 2014 17:04:25 -0700 Subject: [PATCH] Add support for AWS Security Token Service (temporary credentials) to all AWS cloud modules. --- cloud/amazon/cloudformation.py | 31 +++++-------------------- cloud/amazon/ec2_vpc.py | 40 +++++++++++++------------------- cloud/amazon/elasticache.py | 38 +++++++++++------------------- cloud/amazon/rds_param_group.py | 23 +++++------------- cloud/amazon/rds_subnet_group.py | 23 +++++------------- cloud/amazon/route53.py | 18 ++++---------- cloud/amazon/s3.py | 27 +++++++-------------- 7 files changed, 59 insertions(+), 141 deletions(-) diff --git a/cloud/amazon/cloudformation.py b/cloud/amazon/cloudformation.py index 1da173e0a39..e1a16b99620 100644 --- a/cloud/amazon/cloudformation.py +++ b/cloud/amazon/cloudformation.py @@ -41,12 +41,6 @@ options: required: false default: {} aliases: [] - region: - description: - - The AWS region to use. If not specified then the value of the EC2_REGION environment variable, if any, is used. - required: true - default: null - aliases: ['aws_region', 'ec2_region'] state: description: - If state is "present", stack will be created. If state is "present" and if stack exists and template has changed, it will be updated. @@ -75,29 +69,17 @@ options: default: null aliases: [] version_added: "1.4" - aws_secret_key: - description: - - AWS secret key. If not set then the value of the AWS_SECRET_KEY environment variable is used. - required: false - default: null - aliases: [ 'ec2_secret_key', 'secret_key' ] - version_added: "1.5" - aws_access_key: - description: - - AWS access key. If not set then the value of the AWS_ACCESS_KEY environment variable is used. - required: false - default: null - aliases: [ 'ec2_access_key', 'access_key' ] - version_added: "1.5" region: description: - - The AWS region to use. If not specified then the value of the EC2_REGION environment variable, if any, is used. - required: false + - The AWS region to use. If not specified then the value of the AWS_REGION or EC2_REGION environment variable, if any, is used. + required: true + default: null aliases: ['aws_region', 'ec2_region'] version_added: "1.5" requirements: [ "boto" ] author: James S. Martin +extends_documentation_fragment: aws ''' EXAMPLES = ''' @@ -220,7 +202,7 @@ def main(): template_parameters = module.params['template_parameters'] tags = module.params['tags'] - ec2_url, aws_access_key, aws_secret_key, region = get_ec2_creds(module) + region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module) kwargs = dict() if tags is not None: @@ -236,8 +218,7 @@ def main(): try: cfn = boto.cloudformation.connect_to_region( region, - aws_access_key_id=aws_access_key, - aws_secret_access_key=aws_secret_key, + **aws_connect_kwargs ) except boto.exception.NoAuthHandlerFound, e: module.fail_json(msg=str(e)) diff --git a/cloud/amazon/ec2_vpc.py b/cloud/amazon/ec2_vpc.py index 486cd0d38a9..ede2834e44f 100644 --- a/cloud/amazon/ec2_vpc.py +++ b/cloud/amazon/ec2_vpc.py @@ -96,33 +96,13 @@ options: aliases: [] region: description: - - region in which the resource exists. - required: false + - The AWS region to use. If not specified then the value of the AWS_REGION or EC2_REGION environment variable, if any, is used. + required: true default: null aliases: ['aws_region', 'ec2_region'] - aws_secret_key: - description: - - AWS secret key. If not set then the value of the AWS_SECRET_KEY environment variable is used. - required: false - default: None - aliases: ['ec2_secret_key', 'secret_key' ] - aws_access_key: - description: - - AWS access key. If not set then the value of the AWS_ACCESS_KEY environment variable is used. - required: false - default: None - aliases: ['ec2_access_key', 'access_key' ] - validate_certs: - description: - - When set to "no", SSL certificates will not be validated for boto versions >= 2.6.0. - required: false - default: "yes" - choices: ["yes", "no"] - aliases: [] - version_added: "1.5" - requirements: [ "boto" ] author: Carson Gee +extends_documentation_fragment: aws ''' EXAMPLES = ''' @@ -599,7 +579,19 @@ def main(): state = module.params.get('state') - vpc_conn = ec2_connect(module) + region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module) + + # If we have a region specified, connect to its endpoint. + if region: + try: + vpc_conn = boto.vpc.connect_to_region( + region, + **aws_connect_kwargs + ) + except boto.exception.NoAuthHandlerFound, e: + module.fail_json(msg = str(e)) + else: + module.fail_json(msg="region must be specified") if module.params.get('state') == 'absent': vpc_id = module.params.get('vpc_id') diff --git a/cloud/amazon/elasticache.py b/cloud/amazon/elasticache.py index 18be34560a5..0840ee517a2 100644 --- a/cloud/amazon/elasticache.py +++ b/cloud/amazon/elasticache.py @@ -92,24 +92,13 @@ options: required: false default: no choices: [ "yes", "no" ] - aws_secret_key: - description: - - AWS secret key. If not set then the value of the AWS_SECRET_KEY environment variable is used. - required: false - default: None - aliases: ['ec2_secret_key', 'secret_key'] - aws_access_key: - description: - - AWS access key. If not set then the value of the AWS_ACCESS_KEY environment variable is used. - required: false - default: None - aliases: ['ec2_access_key', 'access_key'] region: description: - - The AWS region to use. If not specified then the value of the EC2_REGION environment variable, if any, is used. - required: false + - The AWS region to use. If not specified then the value of the AWS_REGION or EC2_REGION environment variable, if any, is used. + required: true + default: null aliases: ['aws_region', 'ec2_region'] - +extends_documentation_fragment: aws """ EXAMPLES = """ @@ -163,7 +152,7 @@ class ElastiCacheManager(object): def __init__(self, module, name, engine, cache_engine_version, node_type, num_nodes, cache_port, cache_subnet_group, cache_security_groups, security_group_ids, zone, wait, - hard_modify, aws_access_key, aws_secret_key, region): + hard_modify, region, **aws_connect_kwargs): self.module = module self.name = name self.engine = engine @@ -178,9 +167,8 @@ class ElastiCacheManager(object): self.wait = wait self.hard_modify = hard_modify - self.aws_access_key = aws_access_key - self.aws_secret_key = aws_secret_key self.region = region + self.aws_connect_kwargs = aws_connect_kwargs self.changed = False self.data = None @@ -433,9 +421,10 @@ class ElastiCacheManager(object): try: endpoint = "elasticache.%s.amazonaws.com" % self.region connect_region = RegionInfo(name=self.region, endpoint=endpoint) - return ElastiCacheConnection(aws_access_key_id=self.aws_access_key, - aws_secret_access_key=self.aws_secret_key, - region=connect_region) + return ElastiCacheConnection( + region=connect_region, + **self.aws_connect_kwargs + ) except boto.exception.NoAuthHandlerFound, e: self.module.fail_json(msg=e.message) @@ -509,7 +498,7 @@ def main(): argument_spec=argument_spec, ) - ec2_url, aws_access_key, aws_secret_key, region = get_ec2_creds(module) + region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module) name = module.params['name'] state = module.params['state'] @@ -537,7 +526,7 @@ def main(): module.fail_json(msg="'num_nodes' is a required parameter. Please specify num_nodes > 0") if not region: - module.fail_json(msg=str("Either region or EC2_REGION environment variable must be set.")) + module.fail_json(msg=str("Either region or AWS_REGION or EC2_REGION environment variable or boto config aws_region or ec2_region must be set.")) elasticache_manager = ElastiCacheManager(module, name, engine, cache_engine_version, node_type, @@ -545,8 +534,7 @@ def main(): cache_subnet_group, cache_security_groups, security_group_ids, zone, wait, - hard_modify, aws_access_key, - aws_secret_key, region) + hard_modify, region, **aws_connect_kwargs) if state == 'present': elasticache_manager.ensure_present() diff --git a/cloud/amazon/rds_param_group.py b/cloud/amazon/rds_param_group.py index d1559ac78ae..8653f04f7e8 100644 --- a/cloud/amazon/rds_param_group.py +++ b/cloud/amazon/rds_param_group.py @@ -63,24 +63,13 @@ options: choices: [ 'mysql5.1', 'mysql5.5', 'mysql5.6', 'oracle-ee-11.2', 'oracle-se-11.2', 'oracle-se1-11.2', 'postgres9.3', 'sqlserver-ee-10.5', 'sqlserver-ee-11.0', 'sqlserver-ex-10.5', 'sqlserver-ex-11.0', 'sqlserver-se-10.5', 'sqlserver-se-11.0', 'sqlserver-web-10.5', 'sqlserver-web-11.0'] region: description: - - The AWS region to use. If not specified then the value of the EC2_REGION environment variable, if any, is used. + - The AWS region to use. If not specified then the value of the AWS_REGION or EC2_REGION environment variable, if any, is used. required: true default: null - aliases: [ 'aws_region', 'ec2_region' ] - aws_access_key: - description: - - AWS access key. If not set then the value of the AWS_ACCESS_KEY environment variable is used. - required: false - default: null - aliases: [ 'ec2_access_key', 'access_key' ] - aws_secret_key: - description: - - AWS secret key. If not set then the value of the AWS_SECRET_KEY environment variable is used. - required: false - default: null - aliases: [ 'ec2_secret_key', 'secret_key' ] + aliases: ['aws_region', 'ec2_region'] requirements: [ "boto" ] author: Scott Anderson +extends_documentation_fragment: aws ''' EXAMPLES = ''' @@ -248,13 +237,13 @@ def main(): module.fail_json(msg = str("Parameter %s not allowed for state='absent'" % not_allowed)) # Retrieve any AWS settings from the environment. - ec2_url, aws_access_key, aws_secret_key, region = get_ec2_creds(module) + region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module) if not region: - module.fail_json(msg = str("region not specified and unable to determine region from EC2_REGION.")) + module.fail_json(msg = str("Either region or AWS_REGION or EC2_REGION environment variable or boto config aws_region or ec2_region must be set.")) try: - conn = boto.rds.connect_to_region(region, aws_access_key_id=aws_access_key, aws_secret_access_key=aws_secret_key) + conn = boto.rds.connect_to_region(region, **aws_connect_kwargs) except boto.exception.BotoServerError, e: module.fail_json(msg = e.error_message) diff --git a/cloud/amazon/rds_subnet_group.py b/cloud/amazon/rds_subnet_group.py index 40170ba5f4b..0ff41496792 100644 --- a/cloud/amazon/rds_subnet_group.py +++ b/cloud/amazon/rds_subnet_group.py @@ -49,24 +49,13 @@ options: aliases: [] region: description: - - The AWS region to use. If not specified then the value of the EC2_REGION environment variable, if any, is used. + - The AWS region to use. If not specified then the value of the AWS_REGION or EC2_REGION environment variable, if any, is used. required: true default: null - aliases: [ 'aws_region', 'ec2_region' ] - aws_access_key: - description: - - AWS access key. If not set then the value of the AWS_ACCESS_KEY environment variable is used. - required: false - default: null - aliases: [ 'ec2_access_key', 'access_key' ] - aws_secret_key: - description: - - AWS secret key. If not set then the value of the AWS_SECRET_KEY environment variable is used. - required: false - default: null - aliases: [ 'ec2_secret_key', 'secret_key' ] + aliases: ['aws_region', 'ec2_region'] requirements: [ "boto" ] author: Scott Anderson +extends_documentation_fragment: aws ''' EXAMPLES = ''' @@ -121,13 +110,13 @@ def main(): module.fail_json(msg = str("Parameter %s not allowed for state='absent'" % not_allowed)) # Retrieve any AWS settings from the environment. - region, ec2_url, aws_connect_params = get_aws_connection_info(module) + region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module) if not region: - module.fail_json(msg = str("region not specified and unable to determine region from EC2_REGION.")) + module.fail_json(msg = str("Either region or AWS_REGION or EC2_REGION environment variable or boto config aws_region or ec2_region must be set.")) try: - conn = boto.rds.connect_to_region(region, **aws_connect_params) + conn = boto.rds.connect_to_region(region, **aws_connection_kwargs) except boto.exception.BotoServerError, e: module.fail_json(msg = e.error_message) diff --git a/cloud/amazon/route53.py b/cloud/amazon/route53.py index 6778870ad75..97689a985b4 100644 --- a/cloud/amazon/route53.py +++ b/cloud/amazon/route53.py @@ -74,18 +74,6 @@ options: required: false default: null aliases: [] - aws_secret_key: - description: - - AWS secret key. - required: false - default: null - aliases: ['ec2_secret_key', 'secret_key'] - aws_access_key: - description: - - AWS access key. - required: false - default: null - aliases: ['ec2_access_key', 'access_key'] overwrite: description: - Whether an existing record should be overwritten on create if values do not match @@ -106,6 +94,7 @@ options: version_added: "1.9" requirements: [ "boto" ] author: Bruce Pennypacker +extends_documentation_fragment: aws ''' # FIXME: the command stuff should have a more state like configuration alias -- MPD @@ -177,6 +166,7 @@ try: import boto import boto.ec2 from boto import route53 + from boto.route53 import Route53Connection from boto.route53.record import ResourceRecordSets except ImportError: print "failed=True msg='boto required for this module'" @@ -225,7 +215,7 @@ def main(): retry_interval_in = module.params.get('retry_interval') private_zone_in = module.params.get('private_zone') - region, ec2_url, aws_connect_params = get_aws_connection_info(module) + region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module) value_list = () @@ -252,7 +242,7 @@ def main(): # connect to the route53 endpoint try: - conn = boto.route53.Route53Connection(**aws_connect_params) + conn = Route53Connection(**aws_connect_kwargs) except boto.exception.BotoServerError, e: module.fail_json(msg = e.error_message) diff --git a/cloud/amazon/s3.py b/cloud/amazon/s3.py index ad8ed0d028c..d6ff9602fc0 100644 --- a/cloud/amazon/s3.py +++ b/cloud/amazon/s3.py @@ -71,18 +71,6 @@ options: - "S3 URL endpoint for usage with Eucalypus, fakes3, etc. Otherwise assumes AWS" default: null aliases: [ S3_URL ] - aws_secret_key: - description: - - AWS secret key. If not set then the value of the AWS_SECRET_KEY environment variable is used. - required: false - default: null - aliases: ['ec2_secret_key', 'secret_key'] - aws_access_key: - description: - - AWS access key. If not set then the value of the AWS_ACCESS_KEY environment variable is used. - required: false - default: null - aliases: [ 'ec2_access_key', 'access_key' ] metadata: description: - Metadata for PUT operation, as a dictionary of 'key=value' and 'key=value,key=value'. @@ -91,13 +79,13 @@ options: version_added: "1.6" region: description: - - "AWS region to create the bucket in. If not set then the value of the EC2_REGION and AWS_REGION environment variables are checked, followed by the aws_region and ec2_region settings in the Boto config file. If none of those are set the region defaults to the S3 Location: US Standard. Prior to ansible 1.8 this parameter could be specified but had no effect." + - "AWS region to create the bucket in. If not set then the value of the AWS_REGION and EC2_REGION environment variables are checked, followed by the aws_region and ec2_region settings in the Boto config file. If none of those are set the region defaults to the S3 Location: US Standard. Prior to ansible 1.8 this parameter could be specified but had no effect." required: false default: null version_added: "1.8" - requirements: [ "boto" ] author: Lester Wade, Ralph Tice +extends_documentation_fragment: aws ''' EXAMPLES = ''' @@ -130,6 +118,7 @@ from boto.s3.connection import OrdinaryCallingFormat try: import boto from boto.s3.connection import Location + from boto.s3.connection import S3Connection except ImportError: print "failed=True msg='boto required for this module'" sys.exit(1) @@ -301,7 +290,7 @@ def main(): overwrite = module.params.get('overwrite') metadata = module.params.get('metadata') - ec2_url, aws_access_key, aws_secret_key, region = get_ec2_creds(module) + region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module) if region in ('us-east-1', '', None): # S3ism for the US Standard region @@ -323,13 +312,13 @@ def main(): try: if is_fakes3(s3_url): fakes3 = urlparse.urlparse(s3_url) - s3 = boto.connect_s3( - aws_access_key, - aws_secret_key, + s3 = S3Connection( is_secure=False, host=fakes3.hostname, port=fakes3.port, - calling_format=OrdinaryCallingFormat()) + calling_format=OrdinaryCallingFormat(), + **aws_connect_kwargs + ) elif is_walrus(s3_url): walrus = urlparse.urlparse(s3_url).hostname s3 = boto.connect_walrus(walrus, aws_access_key, aws_secret_key)