diff --git a/botocore/credentials.py b/botocore/credentials.py index 19b12b327b..51e301f0bc 100644 --- a/botocore/credentials.py +++ b/botocore/credentials.py @@ -921,7 +921,10 @@ def load(self): """ Search for credentials in explicit environment variables. """ - if self._mapping['access_key'] in self.environ: + + access_key_var = self._mapping['access_key'] + + if access_key_var in self.environ and not self.environ.get(access_key_var) == '': logger.info('Found credentials in environment variables.') fetcher = self._create_credentials_fetcher() credentials = fetcher(require_expiry=False) @@ -951,20 +954,20 @@ def fetch_credentials(require_expiry=True): credentials = {} access_key = environ.get(mapping['access_key']) - if access_key is None: + if access_key is None or access_key == '': raise PartialCredentialsError( provider=method, cred_var=mapping['access_key']) credentials['access_key'] = access_key secret_key = environ.get(mapping['secret_key']) - if secret_key is None: + if secret_key is None or secret_key == '': raise PartialCredentialsError( provider=method, cred_var=mapping['secret_key']) credentials['secret_key'] = secret_key token = None for token_env_var in mapping['token']: - if token_env_var in environ: + if token_env_var in environ and not environ[token_env_var] == '': token = environ[token_env_var] break credentials['token'] = token diff --git a/tests/unit/test_credentials.py b/tests/unit/test_credentials.py index 12caa4b09f..796cdab9ae 100644 --- a/tests/unit/test_credentials.py +++ b/tests/unit/test_credentials.py @@ -691,6 +691,16 @@ def test_envvars_not_found(self): creds = provider.load() self.assertIsNone(creds) + def test_envvars_empty_string(self): + environ = { + 'AWS_ACCESS_KEY_ID': '', + 'AWS_SECRET_ACCESS_KEY': '', + 'AWS_SECURITY_TOKEN': '', + } + provider = credentials.EnvProvider(environ) + creds = provider.load() + self.assertIsNone(creds) + def test_can_override_env_var_mapping(self): # We can change the env var provider to # use our specified env var names. @@ -765,6 +775,18 @@ def test_partial_creds_is_an_error(self): with self.assertRaises(botocore.exceptions.PartialCredentialsError): provider.load() + def test_partial_creds_is_an_error_empty_string(self): + # If the user provides an access key, they must also + # provide a secret key. Not doing so will generate an + # error. + environ = { + 'AWS_ACCESS_KEY_ID': 'foo', + 'AWS_SECRET_ACCESS_KEY': '', + } + provider = credentials.EnvProvider(environ) + with self.assertRaises(botocore.exceptions.PartialCredentialsError): + provider.load() + def test_missing_access_key_id_raises_error(self): expiry_time = datetime.now(tzlocal()) - timedelta(hours=1) environ = {