fix AWS plugin credential precedence for environment variables (#52945)

* fix AWS plugin credential precedence for environment variables

* Allow aliases in direct plugins options

Consolidate precedence fix just in the doc fragment using aliases for mismatched options

* Access options with the option name rather than alias

* fix indentation

* update unit tests

* Improve readability
pull/54355/head
Sloane Hertel 6 years ago committed by Brian Coca
parent 4fac91bed5
commit 54be769e8d

@ -0,0 +1,2 @@
bugfixes:
- AWS plugins - before 2.8 the environment variable precedence was incorrectly reversed.

@ -399,9 +399,15 @@ class ConfigManager(object):
if config in defs: if config in defs:
# direct setting via plugin arguments, can set to None so we bypass rest of processing/defaults # direct setting via plugin arguments, can set to None so we bypass rest of processing/defaults
direct_aliases = []
if direct:
direct_aliases = [direct[alias] for alias in defs[config].get('aliases', []) if alias in direct]
if direct and config in direct: if direct and config in direct:
value = direct[config] value = direct[config]
origin = 'Direct' origin = 'Direct'
elif direct and direct_aliases:
value = direct_aliases[0]
origin = 'Direct'
else: else:
# Use 'variable overrides' if present, highest precedence, but only present when querying running play # Use 'variable overrides' if present, highest precedence, but only present when querying running play

@ -6,7 +6,7 @@
class ModuleDocFragment(object): class ModuleDocFragment(object):
# inventory cache # Plugin options for AWS credentials
DOCUMENTATION = r''' DOCUMENTATION = r'''
options: options:
aws_profile: aws_profile:
@ -14,33 +14,29 @@ options:
type: str type: str
aliases: [ boto_profile ] aliases: [ boto_profile ]
env: env:
- name: AWS_PROFILE
- name: AWS_DEFAULT_PROFILE - name: AWS_DEFAULT_PROFILE
- name: AWS_PROFILE
aws_access_key: aws_access_key:
description: The AWS access key to use. description: The AWS access key to use.
type: str type: str
aliases: [ aws_access_key_id ]
env: env:
- name: AWS_ACCESS_KEY_ID
- name: AWS_ACCESS_KEY
- name: EC2_ACCESS_KEY - name: EC2_ACCESS_KEY
- name: AWS_ACCESS_KEY
- name: AWS_ACCESS_KEY_ID
aws_secret_key: aws_secret_key:
description: The AWS secret key that corresponds to the access key. description: The AWS secret key that corresponds to the access key.
type: str type: str
aliases: [ aws_secret_access_key ]
env: env:
- name: AWS_SECRET_ACCESS_KEY
- name: AWS_SECRET_KEY
- name: EC2_SECRET_KEY - name: EC2_SECRET_KEY
- name: AWS_SECRET_KEY
- name: AWS_SECRET_ACCESS_KEY
aws_security_token: aws_security_token:
description: The AWS security token if using temporary access and secret keys. description: The AWS security token if using temporary access and secret keys.
type: str type: str
env: env:
- name: AWS_SECURITY_TOKEN
- name: AWS_SESSION_TOKEN
- name: EC2_SECURITY_TOKEN - name: EC2_SECURITY_TOKEN
region: - name: AWS_SESSION_TOKEN
description: The region for which to create the connection. - name: AWS_SECURITY_TOKEN
type: str
env:
- name: AWS_REGION
- name: EC2_REGION
''' '''

@ -0,0 +1,18 @@
# -*- 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)
class ModuleDocFragment(object):
# Plugin option for AWS region
DOCUMENTATION = r'''
options:
region:
description: The region for which to create the connection.
type: str
env:
- name: EC2_REGION
- name: AWS_REGION
'''

@ -14,6 +14,7 @@ DOCUMENTATION = '''
extends_documentation_fragment: extends_documentation_fragment:
- inventory_cache - inventory_cache
- constructed - constructed
- aws_credentials
description: description:
- Get inventory hosts from Amazon Web Services EC2. - Get inventory hosts from Amazon Web Services EC2.
- Uses a YAML configuration file that ends with aws_ec2.(yml|yaml). - Uses a YAML configuration file that ends with aws_ec2.(yml|yaml).
@ -25,34 +26,6 @@ DOCUMENTATION = '''
description: token that ensures this is a source file for the 'aws_ec2' plugin. description: token that ensures this is a source file for the 'aws_ec2' plugin.
required: True required: True
choices: ['aws_ec2'] choices: ['aws_ec2']
boto_profile:
description:
- The boto profile to use.
- This plugin supports boto3-style credentials, so the profile may be sourced from ~/.aws/config for assuming an IAM role.
- See U(https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html) for details.
env:
- name: AWS_PROFILE
- name: AWS_DEFAULT_PROFILE
aws_access_key_id:
description: The AWS access key to use. If you have specified a profile, you don't need to provide
an access key/secret key/session token.
env:
- name: AWS_ACCESS_KEY_ID
- name: AWS_ACCESS_KEY
- name: EC2_ACCESS_KEY
aws_secret_access_key:
description: The AWS secret key that corresponds to the access key. If you have specified a profile,
you don't need to provide an access key/secret key/session token.
env:
- name: AWS_SECRET_ACCESS_KEY
- name: AWS_SECRET_KEY
- name: EC2_SECRET_KEY
aws_security_token:
description: The AWS security token if using temporary access and secret keys.
env:
- name: AWS_SECURITY_TOKEN
- name: AWS_SESSION_TOKEN
- name: EC2_SECURITY_TOKEN
regions: regions:
description: description:
- A list of regions in which to describe EC2 instances. - A list of regions in which to describe EC2 instances.
@ -555,9 +528,9 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
:param config_data: contents of the inventory config file :param config_data: contents of the inventory config file
''' '''
self.boto_profile = self.get_option('boto_profile') self.boto_profile = self.get_option('aws_profile')
self.aws_access_key_id = self.get_option('aws_access_key_id') self.aws_access_key_id = self.get_option('aws_access_key')
self.aws_secret_access_key = self.get_option('aws_secret_access_key') self.aws_secret_access_key = self.get_option('aws_secret_key')
self.aws_security_token = self.get_option('aws_security_token') self.aws_security_token = self.get_option('aws_security_token')
if not self.boto_profile and not (self.aws_access_key_id and self.aws_secret_access_key): if not self.boto_profile and not (self.aws_access_key_id and self.aws_secret_access_key):

@ -12,32 +12,6 @@ DOCUMENTATION = '''
- Get instances and clusters from Amazon Web Services RDS. - Get instances and clusters from Amazon Web Services RDS.
- Uses a YAML configuration file that ends with aws_rds.(yml|yaml). - Uses a YAML configuration file that ends with aws_rds.(yml|yaml).
options: options:
boto_profile:
description: The boto profile to use. The plugin will look for an instance role if no credentials
are provided.
env:
- name: AWS_PROFILE
- name: AWS_DEFAULT_PROFILE
aws_access_key_id:
description: The AWS access key to use. If you have specified a profile, you don't need to provide
an access key/secret key/session token.
env:
- name: AWS_ACCESS_KEY_ID
- name: AWS_ACCESS_KEY
- name: EC2_ACCESS_KEY
aws_secret_access_key:
description: The AWS secret key that corresponds to the access key. If you have specified a profile,
you don't need to provide an access key/secret key/session token.
env:
- name: AWS_SECRET_ACCESS_KEY
- name: AWS_SECRET_KEY
- name: EC2_SECRET_KEY
aws_security_token:
description: The AWS security token if using temporary access and secret keys.
env:
- name: AWS_SECURITY_TOKEN
- name: AWS_SESSION_TOKEN
- name: EC2_SECURITY_TOKEN
regions: regions:
description: A list of regions in which to describe RDS instances and clusters. Available regions are listed here description: A list of regions in which to describe RDS instances and clusters. Available regions are listed here
U(https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.RegionsAndAvailabilityZones.html) U(https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.RegionsAndAvailabilityZones.html)
@ -65,6 +39,7 @@ DOCUMENTATION = '''
extends_documentation_fragment: extends_documentation_fragment:
- inventory_cache - inventory_cache
- constructed - constructed
- aws_credentials
requirements: requirements:
- boto3 - boto3
- botocore - botocore
@ -271,9 +246,9 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
''' '''
:param config_data: contents of the inventory config file :param config_data: contents of the inventory config file
''' '''
self.boto_profile = self.get_option('boto_profile') self.boto_profile = self.get_option('aws_profile')
aws_access_key_id = self.get_option('aws_access_key_id') aws_access_key_id = self.get_option('aws_access_key')
aws_secret_access_key = self.get_option('aws_secret_access_key') aws_secret_access_key = self.get_option('aws_secret_key')
aws_security_token = self.get_option('aws_security_token') aws_security_token = self.get_option('aws_security_token')
if not self.boto_profile and not (aws_access_key_id and aws_secret_access_key): if not self.boto_profile and not (aws_access_key_id and aws_secret_access_key):

@ -13,6 +13,7 @@ requirements:
- botocore - botocore
extends_documentation_fragment: extends_documentation_fragment:
- aws_credentials - aws_credentials
- aws_region
short_description: Look up AWS account attributes. short_description: Look up AWS account attributes.
description: description:
- Describes attributes of your AWS account. You can specify one of the listed - Describes attributes of your AWS account. You can specify one of the listed

@ -129,9 +129,9 @@ def test_get_boto_attr_chain(inventory):
def test_boto3_conn(inventory): def test_boto3_conn(inventory):
inventory._options = {"boto_profile": "first_precedence", inventory._options = {"aws_profile": "first_precedence",
"aws_access_key_id": "test_access_key", "aws_access_key": "test_access_key",
"aws_secret_access_key": "test_secret_key", "aws_secret_key": "test_secret_key",
"aws_security_token": "test_security_token"} "aws_security_token": "test_security_token"}
inventory._set_credentials() inventory._set_credentials()
with pytest.raises(AnsibleError) as error_message: with pytest.raises(AnsibleError) as error_message:
@ -151,10 +151,10 @@ def test_get_hostname(inventory):
def test_set_credentials(inventory): def test_set_credentials(inventory):
inventory._options = {'aws_access_key_id': 'test_access_key', inventory._options = {'aws_access_key': 'test_access_key',
'aws_secret_access_key': 'test_secret_key', 'aws_secret_key': 'test_secret_key',
'aws_security_token': 'test_security_token', 'aws_security_token': 'test_security_token',
'boto_profile': 'test_profile'} 'aws_profile': 'test_profile'}
inventory._set_credentials() inventory._set_credentials()
assert inventory.boto_profile == "test_profile" assert inventory.boto_profile == "test_profile"
@ -165,10 +165,10 @@ def test_set_credentials(inventory):
def test_insufficient_credentials(inventory): def test_insufficient_credentials(inventory):
inventory._options = { inventory._options = {
'aws_access_key_id': None, 'aws_access_key': None,
'aws_secret_access_key': None, 'aws_secret_key': None,
'aws_security_token': None, 'aws_security_token': None,
'boto_profile': None 'aws_profile': None
} }
with pytest.raises(AnsibleError) as error_message: with pytest.raises(AnsibleError) as error_message:
inventory._set_credentials() inventory._set_credentials()

Loading…
Cancel
Save