From 485d3a6f64572462757cdc8796bcc6d7eb4147d3 Mon Sep 17 00:00:00 2001 From: Jerry Ma Date: Tue, 7 Aug 2018 16:33:15 -0700 Subject: [PATCH] Enable AWS cred file to be read as long as .s3cfg auth fields are nonexistent or empty. This commit allows the credentials to be read from ~/.aws/credentials or user-specified (via envvar) file if .s3cfg exists but does not have authentication options. The previous behavior is that s3cmd will *not* read credentials from the above path as long as .s3cfg exists (even if it contains no authentication options). --- S3/Config.py | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/S3/Config.py b/S3/Config.py index 046c1f444..9e247019a 100644 --- a/S3/Config.py +++ b/S3/Config.py @@ -24,7 +24,7 @@ import http.client as httplib import locale -try: +try: from configparser import NoOptionError, NoSectionError, MissingSectionHeaderError, ConfigParser as PyConfigParser except ImportError: # Python2 fallback code @@ -217,8 +217,7 @@ def __init__(self, configfile = None, access_key=None, secret_key=None, access_t try: self.read_config_file(configfile) except IOError: - if 'AWS_CREDENTIAL_FILE' in os.environ or 'AWS_PROFILE' in os.environ: - self.aws_credential_file() + pass # override these if passed on the command-line if access_key and secret_key: @@ -229,7 +228,10 @@ def __init__(self, configfile = None, access_key=None, secret_key=None, access_t # Do not refresh the IAM role when an access token is provided. self._access_token_refresh = False - if len(self.access_key)==0: + # The next few clauses are in descending order of priority. + # That is, we will prefer key envvars, then AWS cred file, then IAM auth. + + if not self.is_option_nonempty('access_key'): env_access_key = os.getenv('AWS_ACCESS_KEY') or os.getenv('AWS_ACCESS_KEY_ID') env_secret_key = os.getenv('AWS_SECRET_KEY') or os.getenv('AWS_SECRET_ACCESS_KEY') env_access_token = os.getenv('AWS_SESSION_TOKEN') or os.getenv('AWS_SECURITY_TOKEN') @@ -241,8 +243,15 @@ def __init__(self, configfile = None, access_key=None, secret_key=None, access_t # Do not refresh the IAM role when an access token is provided. self._access_token_refresh = False self.access_token = config_unicodise(env_access_token) - else: - self.role_config() + + if not self.is_option_nonempty('access_key'): + self.aws_credential_file() + + if not self.is_option_nonempty('access_key'): + self.role_config() + + if not self.is_option_nonempty('access_key'): + raise Exception('There is no access key available!') #TODO check KMS key is valid if self.kms_key and self.server_side_encryption == True: @@ -250,6 +259,9 @@ def __init__(self, configfile = None, access_key=None, secret_key=None, access_t if self.kms_key and self.signature_v2 == True: raise Exception('KMS encryption requires signature v4. Please set signature_v2 to False') + def is_option_nonempty(self, option_name): + return hasattr(self, option_name) and bool(str(getattr(self, option_name))) + def role_config(self): """ Get credentials from IAM authentication @@ -268,10 +280,6 @@ def role_config(self): Config().update_option('access_key', config_unicodise(creds['AccessKeyId'])) Config().update_option('secret_key', config_unicodise(creds['SecretAccessKey'])) Config().update_option('access_token', config_unicodise(creds['Token'])) - else: - raise IOError - else: - raise IOError except: raise @@ -284,9 +292,11 @@ def role_refresh(self): def aws_credential_file(self): try: - aws_credential_file = os.path.expanduser('~/.aws/credentials') + aws_credential_file = os.path.expanduser('~/.aws/credentials') if 'AWS_CREDENTIAL_FILE' in os.environ and os.path.isfile(os.environ['AWS_CREDENTIAL_FILE']): aws_credential_file = config_unicodise(os.environ['AWS_CREDENTIAL_FILE']) + elif not os.path.isfile(aws_credential_file): + return config = PyConfigParser()