mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Work to allow security tokens and profiles to work with Ansible
Allow security tokens and profiles to be used as arguments to the 'common' ec2 modules Mostly refactoring to provide two new methods, `get_aws_connection_info`, which results in a dict that can be passed through to the boto `connect_to_region` calls, and `connect_to_aws` that can pass that dict through to the `connect_to_region` method of the appropriate module. Tidied up some variable names Works around boto/boto#2100 profiles don't work with boto < 2.24, but this detects for that and fails with an appropriate message. It is designed to work if profile is not passed but boto < 2.24 is installed. Modifications to allow empty aws auth variables to be passed (this is useful if wanting to have the keys as an optional parameter in ec2 calls - if set, use this value, if not set, use boto config or env variables) Reworked validate_certs improvements to work with refactoring Added documentation for profile and security_token to affected modules
This commit is contained in:
parent
372ae072fd
commit
b9a7352e0a
9 changed files with 198 additions and 32 deletions
|
@ -14,33 +14,44 @@ AWS_REGIONS = ['ap-northeast-1',
|
|||
'us-west-2']
|
||||
|
||||
|
||||
def ec2_argument_keys_spec():
|
||||
def aws_common_argument_spec():
|
||||
return dict(
|
||||
ec2_url=dict(),
|
||||
aws_secret_key=dict(aliases=['ec2_secret_key', 'secret_key'], no_log=True),
|
||||
aws_access_key=dict(aliases=['ec2_access_key', 'access_key']),
|
||||
validate_certs=dict(default=True, type='bool'),
|
||||
security_token=dict(no_log=True),
|
||||
profile=dict(),
|
||||
)
|
||||
return spec
|
||||
|
||||
|
||||
def ec2_argument_spec():
|
||||
spec = ec2_argument_keys_spec()
|
||||
spec = aws_common_argument_spec()
|
||||
spec.update(
|
||||
dict(
|
||||
region=dict(aliases=['aws_region', 'ec2_region'], choices=AWS_REGIONS),
|
||||
validate_certs=dict(default=True, type='bool'),
|
||||
ec2_url=dict(),
|
||||
)
|
||||
)
|
||||
return spec
|
||||
|
||||
|
||||
def get_ec2_creds(module):
|
||||
def boto_supports_profile_name():
|
||||
return hasattr(boto.ec2.EC2Connection, 'profile_name')
|
||||
|
||||
|
||||
def get_aws_connection_info(module):
|
||||
|
||||
# Check module args for credentials, then check environment vars
|
||||
# access_key
|
||||
|
||||
ec2_url = module.params.get('ec2_url')
|
||||
ec2_secret_key = module.params.get('aws_secret_key')
|
||||
ec2_access_key = module.params.get('aws_access_key')
|
||||
access_key = module.params.get('aws_access_key')
|
||||
secret_key = module.params.get('aws_secret_key')
|
||||
security_token = module.params.get('security_token')
|
||||
region = module.params.get('region')
|
||||
profile_name = module.params.get('profile')
|
||||
validate_certs = module.params.get('validate_certs')
|
||||
|
||||
if not ec2_url:
|
||||
if 'EC2_URL' in os.environ:
|
||||
|
@ -48,21 +59,27 @@ def get_ec2_creds(module):
|
|||
elif 'AWS_URL' in os.environ:
|
||||
ec2_url = os.environ['AWS_URL']
|
||||
|
||||
if not ec2_access_key:
|
||||
if not access_key:
|
||||
if 'EC2_ACCESS_KEY' in os.environ:
|
||||
ec2_access_key = os.environ['EC2_ACCESS_KEY']
|
||||
access_key = os.environ['EC2_ACCESS_KEY']
|
||||
elif 'AWS_ACCESS_KEY_ID' in os.environ:
|
||||
ec2_access_key = os.environ['AWS_ACCESS_KEY_ID']
|
||||
access_key = os.environ['AWS_ACCESS_KEY_ID']
|
||||
elif 'AWS_ACCESS_KEY' in os.environ:
|
||||
ec2_access_key = os.environ['AWS_ACCESS_KEY']
|
||||
access_key = os.environ['AWS_ACCESS_KEY']
|
||||
else:
|
||||
# in case access_key came in as empty string
|
||||
access_key = None
|
||||
|
||||
if not ec2_secret_key:
|
||||
if not secret_key:
|
||||
if 'EC2_SECRET_KEY' in os.environ:
|
||||
ec2_secret_key = os.environ['EC2_SECRET_KEY']
|
||||
secret_key = os.environ['EC2_SECRET_KEY']
|
||||
elif 'AWS_SECRET_ACCESS_KEY' in os.environ:
|
||||
ec2_secret_key = os.environ['AWS_SECRET_ACCESS_KEY']
|
||||
secret_key = os.environ['AWS_SECRET_ACCESS_KEY']
|
||||
elif 'AWS_SECRET_KEY' in os.environ:
|
||||
ec2_secret_key = os.environ['AWS_SECRET_KEY']
|
||||
secret_key = os.environ['AWS_SECRET_KEY']
|
||||
else:
|
||||
# in case secret_key came in as empty string
|
||||
secret_key = None
|
||||
|
||||
if not region:
|
||||
if 'EC2_REGION' in os.environ:
|
||||
|
@ -71,39 +88,75 @@ def get_ec2_creds(module):
|
|||
region = os.environ['AWS_REGION']
|
||||
else:
|
||||
# boto.config.get returns None if config not found
|
||||
region = boto.config.get('Boto', 'aws_region')
|
||||
region = boto.config.get('Boto', 'aws_region')
|
||||
if not region:
|
||||
region = boto.config.get('Boto', 'ec2_region')
|
||||
|
||||
return ec2_url, ec2_access_key, ec2_secret_key, region
|
||||
if not security_token:
|
||||
if 'AWS_SECURITY_TOKEN' in os.environ:
|
||||
security_token = os.environ['AWS_SECURITY_TOKEN']
|
||||
else:
|
||||
# in case security_token came in as empty string
|
||||
security_token = None
|
||||
|
||||
boto_params = dict(aws_access_key_id=access_key,
|
||||
aws_secret_access_key=secret_key,
|
||||
security_token=security_token)
|
||||
|
||||
# profile_name only works as a key in boto >= 2.24
|
||||
# so only set profile_name if passed as an argument
|
||||
if profile_name:
|
||||
if not boto_supports_profile_name():
|
||||
module.fail_json("boto does not support profile_name before 2.24")
|
||||
boto_params['profile_name'] = profile_name
|
||||
|
||||
if validate_certs and HAS_LOOSE_VERSION and LooseVersion(boto.Version) >= LooseVersion("2.6.0"):
|
||||
boto_params['validate_certs'] = validate_certs
|
||||
|
||||
return region, ec2_url, boto_params
|
||||
|
||||
|
||||
def get_ec2_creds(module):
|
||||
''' for compatibility mode with old modules that don't/can't yet
|
||||
use ec2_connect method '''
|
||||
region, ec2_url, boto_params = get_aws_connection_info(module)
|
||||
return ec2_url, boto_params['aws_access_key_id'], boto_params['aws_secret_access_key'], region
|
||||
|
||||
|
||||
def boto_fix_security_token_in_profile(conn, profile_name):
|
||||
''' monkey patch for boto issue boto/boto#2100 '''
|
||||
profile = 'profile ' + profile_name
|
||||
if boto.config.has_option(profile, 'aws_security_token'):
|
||||
conn.provider.set_security_token(boto.config.get(profile, 'aws_security_token'))
|
||||
return conn
|
||||
|
||||
|
||||
def connect_to_aws(aws_module, region, **params):
|
||||
conn = aws_module.connect_to_region(region, **params)
|
||||
if params.get('profile_name'):
|
||||
conn = boto_fix_security_token_in_profile(conn, params['profile_name'])
|
||||
return conn
|
||||
|
||||
|
||||
def ec2_connect(module):
|
||||
|
||||
""" Return an ec2 connection"""
|
||||
|
||||
ec2_url, aws_access_key, aws_secret_key, region = get_ec2_creds(module)
|
||||
validate_certs = module.params.get('validate_certs', True)
|
||||
region, ec2_url, boto_params = get_aws_connection_info(module)
|
||||
|
||||
# If we have a region specified, connect to its endpoint.
|
||||
if region:
|
||||
try:
|
||||
if HAS_LOOSE_VERSION and LooseVersion(boto.Version) >= LooseVersion("2.6.0"):
|
||||
ec2 = boto.ec2.connect_to_region(region, aws_access_key_id=aws_access_key, aws_secret_access_key=aws_secret_key, validate_certs=validate_certs)
|
||||
else:
|
||||
ec2 = boto.ec2.connect_to_region(region, aws_access_key_id=aws_access_key, aws_secret_access_key=aws_secret_key)
|
||||
ec2 = connect_to_aws(boto.ec2, region, **boto_params)
|
||||
except boto.exception.NoAuthHandlerFound, e:
|
||||
module.fail_json(msg = str(e))
|
||||
module.fail_json(msg=str(e))
|
||||
# Otherwise, no region so we fallback to the old connection method
|
||||
elif ec2_url:
|
||||
try:
|
||||
if HAS_LOOSE_VERSION and LooseVersion(boto.Version) >= LooseVersion("2.6.0"):
|
||||
ec2 = boto.connect_ec2_endpoint(ec2_url, aws_access_key, aws_secret_key, validate_certs=validate_certs)
|
||||
else:
|
||||
ec2 = boto.connect_ec2_endpoint(ec2_url, aws_access_key, aws_secret_key)
|
||||
ec2 = boto.connect_ec2_endpoint(ec2_url, **boto_params)
|
||||
except boto.exception.NoAuthHandlerFound, e:
|
||||
module.fail_json(msg = str(e))
|
||||
module.fail_json(msg=str(e))
|
||||
else:
|
||||
module.fail_json(msg="Either region or ec2_url must be specified")
|
||||
return ec2
|
||||
|
||||
return ec2
|
||||
|
|
|
@ -220,6 +220,20 @@ options:
|
|||
choices: ["yes", "no"]
|
||||
aliases: []
|
||||
version_added: "1.5"
|
||||
profile:
|
||||
description:
|
||||
- uses a boto profile. Only works with boto >= 2.24.0
|
||||
required: false
|
||||
default: null
|
||||
aliases: []
|
||||
version_added: "1.5"
|
||||
security_token:
|
||||
description:
|
||||
- security token to authenticate against AWS
|
||||
required: false
|
||||
default: null
|
||||
aliases: []
|
||||
version_added: "1.5"
|
||||
|
||||
requirements: [ "boto" ]
|
||||
author: Seth Vidal, Tim Gerla, Lester Wade
|
||||
|
|
|
@ -109,6 +109,20 @@ options:
|
|||
choices: ["yes", "no"]
|
||||
aliases: []
|
||||
version_added: "1.5"
|
||||
profile:
|
||||
description:
|
||||
- uses a boto profile. Only works with boto >= 2.24.0
|
||||
required: false
|
||||
default: null
|
||||
aliases: []
|
||||
version_added: "1.5"
|
||||
security_token:
|
||||
description:
|
||||
- security token to authenticate against AWS
|
||||
required: false
|
||||
default: null
|
||||
aliases: []
|
||||
version_added: "1.5"
|
||||
|
||||
requirements: [ "boto" ]
|
||||
author: Evan Duffield <eduffield@iacquire.com>
|
||||
|
|
|
@ -61,6 +61,20 @@ options:
|
|||
choices: ["yes", "no"]
|
||||
aliases: []
|
||||
version_added: "1.5"
|
||||
profile:
|
||||
description:
|
||||
- uses a boto profile. Only works with boto >= 2.24.0
|
||||
required: false
|
||||
default: null
|
||||
aliases: []
|
||||
version_added: "1.5"
|
||||
security_token:
|
||||
description:
|
||||
- security token to authenticate against AWS
|
||||
required: false
|
||||
default: null
|
||||
aliases: []
|
||||
version_added: "1.5"
|
||||
|
||||
requirements: [ "boto" ]
|
||||
author: Lorin Hochstein <lorin@nimbisservices.com>
|
||||
|
|
|
@ -65,6 +65,20 @@ options:
|
|||
choices: ["yes", "no"]
|
||||
aliases: []
|
||||
version_added: "1.5"
|
||||
profile:
|
||||
description:
|
||||
- uses a boto profile. Only works with boto >= 2.24.0
|
||||
required: false
|
||||
default: null
|
||||
aliases: []
|
||||
version_added: "1.5"
|
||||
security_token:
|
||||
description:
|
||||
- security token to authenticate against AWS
|
||||
required: false
|
||||
default: null
|
||||
aliases: []
|
||||
version_added: "1.5"
|
||||
|
||||
requirements: [ "boto" ]
|
||||
'''
|
||||
|
|
|
@ -56,6 +56,20 @@ options:
|
|||
choices: ["yes", "no"]
|
||||
aliases: []
|
||||
version_added: "1.5"
|
||||
profile:
|
||||
description:
|
||||
- uses a boto profile. Only works with boto >= 2.24.0
|
||||
required: false
|
||||
default: null
|
||||
aliases: []
|
||||
version_added: "1.5"
|
||||
security_token:
|
||||
description:
|
||||
- security token to authenticate against AWS
|
||||
required: false
|
||||
default: null
|
||||
aliases: []
|
||||
version_added: "1.5"
|
||||
|
||||
requirements: [ "boto" ]
|
||||
author: Vincent Viallet
|
||||
|
|
|
@ -59,17 +59,32 @@ options:
|
|||
default: null
|
||||
aliases: []
|
||||
instance_id:
|
||||
description:
|
||||
description:
|
||||
- instance that has a the required volume to snapshot mounted
|
||||
required: false
|
||||
default: null
|
||||
aliases: []
|
||||
device_name:
|
||||
description:
|
||||
description:
|
||||
- device name of a mounted volume to be snapshotted
|
||||
required: false
|
||||
default: null
|
||||
aliases: []
|
||||
profile:
|
||||
description:
|
||||
- uses a boto profile. Only works with boto >= 2.24.0
|
||||
required: false
|
||||
default: null
|
||||
aliases: []
|
||||
version_added: "1.5"
|
||||
security_token:
|
||||
description:
|
||||
- security token to authenticate against AWS
|
||||
required: false
|
||||
default: null
|
||||
aliases: []
|
||||
version_added: "1.5"
|
||||
|
||||
requirements: [ "boto" ]
|
||||
author: Will Thames
|
||||
'''
|
||||
|
|
|
@ -67,6 +67,20 @@ options:
|
|||
choices: ["yes", "no"]
|
||||
aliases: []
|
||||
version_added: "1.5"
|
||||
profile:
|
||||
description:
|
||||
- uses a boto profile. Only works with boto >= 2.24.0
|
||||
required: false
|
||||
default: null
|
||||
aliases: []
|
||||
version_added: "1.5"
|
||||
security_token:
|
||||
description:
|
||||
- security token to authenticate against AWS
|
||||
required: false
|
||||
default: null
|
||||
aliases: []
|
||||
version_added: "1.5"
|
||||
|
||||
requirements: [ "boto" ]
|
||||
author: Lester Wade
|
||||
|
|
|
@ -90,6 +90,20 @@ options:
|
|||
choices: ["yes", "no"]
|
||||
aliases: []
|
||||
version_added: "1.5"
|
||||
profile:
|
||||
description:
|
||||
- uses a boto profile. Only works with boto >= 2.24.0
|
||||
required: false
|
||||
default: null
|
||||
aliases: []
|
||||
version_added: "1.5"
|
||||
security_token:
|
||||
description:
|
||||
- security token to authenticate against AWS
|
||||
required: false
|
||||
default: null
|
||||
aliases: []
|
||||
version_added: "1.5"
|
||||
|
||||
requirements: [ "boto" ]
|
||||
author: Lester Wade
|
||||
|
|
Loading…
Reference in a new issue