blob: ed895d61cfd558a4d129d5cd9c4a0dbb8cec30da [file] [log] [blame]
from __future__ import print_function
from __future__ import unicode_literals
import argparse
import os
from six.moves import configparser
def get_aws_credential_files_from_env():
"""Extract credential file paths from environment variables."""
files = set()
for env_var in {'AWS_CONFIG_FILE', 'AWS_CREDENTIAL_FILE',
'AWS_SHARED_CREDENTIALS_FILE', 'BOTO_CONFIG'}:
try:
files.add(os.environ[env_var])
except KeyError:
pass
return files
def get_aws_secrets_from_env():
"""Extract AWS secrets from environment variables."""
keys = set()
for env_var in {'AWS_SECRET_ACCESS_KEY', 'AWS_SECURITY_TOKEN',
'AWS_SESSION_TOKEN'}:
try:
keys.add(os.environ[env_var])
except KeyError:
pass
return keys
def get_aws_secrets_from_file(credentials_file):
"""Extract AWS secrets from configuration files.
Read an ini-style configuration file and return a set with all found AWS
secret access keys.
"""
aws_credentials_file_path = os.path.expanduser(credentials_file)
if not os.path.exists(aws_credentials_file_path):
return set()
parser = configparser.ConfigParser()
try:
parser.read(aws_credentials_file_path)
except configparser.MissingSectionHeaderError:
return set()
keys = set()
for section in parser.sections():
for var in {'aws_secret_access_key', 'aws_security_token',
'aws_session_token'}:
try:
keys.add(parser.get(section, var))
except configparser.NoOptionError:
pass
return keys
def check_file_for_aws_keys(filenames, keys):
"""Check if files contain AWS secrets.
Return a list of all files containing AWS secrets and keys found, with all
but the first four characters obfuscated to ease debugging.
"""
bad_files = []
for filename in filenames:
with open(filename, 'r') as content:
text_body = content.read()
for key in keys:
# naively match the entire file, low chance of incorrect
# collision
if key in text_body:
bad_files.append({'filename': filename,
'key': key[:4].ljust(32, str('*'))})
return bad_files
def main(argv=None):
parser = argparse.ArgumentParser()
parser.add_argument('filenames', nargs='+', help='Filenames to run')
parser.add_argument(
'--credentials-file',
dest='credential_files',
action='append',
default=['~/.aws/config', '~/.aws/credentials', '/etc/boto.cfg',
'~/.boto'],
help=(
'Location of additional AWS credential files from which to get '
'secret keys from'
)
)
args = parser.parse_args(argv)
credential_files = set(args.credential_files)
# Add the credentials files configured via environment variables to the set
# of files to to gather AWS secrets from.
credential_files |= get_aws_credential_files_from_env()
keys = set()
for credential_file in credential_files:
keys |= get_aws_secrets_from_file(credential_file)
# Secrets might be part of environment variables, so add such secrets to
# the set of keys.
keys |= get_aws_secrets_from_env()
if not keys:
print('No AWS keys were found in the configured credential files and '
'environment variables.\nPlease ensure you have the correct '
'setting for --credentials-file')
return 2
bad_filenames = check_file_for_aws_keys(args.filenames, keys)
if bad_filenames:
for bad_file in bad_filenames:
print('AWS secret found in {filename}: {key}'.format(
**bad_file))
return 1
else:
return 0
if __name__ == '__main__':
exit(main())