mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Fetch AWS region from EC2 instance metadata
sig4() and query() upon getting a location set to None will attempt to fetch it from EC2 instance metadata before falling back to us-east-1. get_region_from_metadata() uses caching just like creds() does. If it can't connect to the metadata service, it does not try again. If a value is successfully retrieved, it is cached so that future calls are faster. get_location() will call get_region_from_metadata() if location is not explicitly set in config. If sig4() receives an empty location value, it tries to fetch it using get_region_from_metadata()
This commit is contained in:
parent
612e342c70
commit
57943ff4f7
1 changed files with 53 additions and 6 deletions
|
@ -51,6 +51,7 @@ __AccessKeyId__ = ''
|
|||
__SecretAccessKey__ = ''
|
||||
__Token__ = ''
|
||||
__Expiration__ = ''
|
||||
__Location__ = ''
|
||||
|
||||
|
||||
def creds(provider):
|
||||
|
@ -140,7 +141,7 @@ def sig2(method, endpoint, params, provider, aws_api_version):
|
|||
|
||||
|
||||
def sig4(method, endpoint, params, prov_dict,
|
||||
aws_api_version=DEFAULT_AWS_API_VERSION, location=DEFAULT_LOCATION,
|
||||
aws_api_version=DEFAULT_AWS_API_VERSION, location=None,
|
||||
product='ec2', uri='/', requesturl=None, data=''):
|
||||
'''
|
||||
Sign a query against AWS services using Signature Version 4 Signing
|
||||
|
@ -155,6 +156,11 @@ def sig4(method, endpoint, params, prov_dict,
|
|||
# Retrieve access credentials from meta-data, or use provided
|
||||
access_key_id, secret_access_key, token = creds(prov_dict)
|
||||
|
||||
if location is None:
|
||||
location = get_region_from_metadata()
|
||||
if location is None:
|
||||
location = DEFAULT_LOCATION
|
||||
|
||||
params_with_headers = params.copy()
|
||||
if product != 's3':
|
||||
params_with_headers['Version'] = aws_api_version
|
||||
|
@ -442,15 +448,56 @@ def query(params=None, setname=None, requesturl=None, location=None,
|
|||
return ret
|
||||
|
||||
|
||||
def get_region_from_metadata():
|
||||
'''
|
||||
Try to get region from instance identity document and cache it
|
||||
|
||||
.. versionadded:: 2015.5.6
|
||||
'''
|
||||
global __Location__
|
||||
|
||||
if __Location__ == 'do-not-get-from-metadata':
|
||||
LOG.debug('Previously failed to get AWS region from metadata. Not trying again.')
|
||||
return None
|
||||
|
||||
# Cached region
|
||||
if __Location__ != '':
|
||||
return __Location__
|
||||
|
||||
try:
|
||||
# Connections to instance meta-data must never be proxied
|
||||
result = requests.get(
|
||||
"http://169.254.169.254/latest/dynamic/instance-identity/document",
|
||||
proxies={'http': ''},
|
||||
)
|
||||
except requests.exceptions.RequestException:
|
||||
LOG.warning('Failed to get AWS region from instance metadata.', exc_info=True)
|
||||
# Do not try again
|
||||
__Location__ = 'do-not-get-from-metadata'
|
||||
return None
|
||||
|
||||
try:
|
||||
region = result.json()['region']
|
||||
__Location__ = region
|
||||
return __Location__
|
||||
except (ValueError, KeyError):
|
||||
LOG.warning('Failed to decode JSON from instance metadata.')
|
||||
return None
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def get_location(opts, provider=None):
|
||||
'''
|
||||
Return the region to use, in this order:
|
||||
opts['location']
|
||||
provider['location']
|
||||
get_region_from_metadata()
|
||||
DEFAULT_LOCATION
|
||||
'''
|
||||
return opts.get(
|
||||
'location', provider.get(
|
||||
'location', DEFAULT_LOCATION
|
||||
)
|
||||
)
|
||||
ret = opts.get('location', provider.get('location'))
|
||||
if ret is None:
|
||||
ret = get_region_from_metadata()
|
||||
if ret is None:
|
||||
ret = DEFAULT_LOCATION
|
||||
return ret
|
||||
|
|
Loading…
Add table
Reference in a new issue