boto / botocore

The low-level, core functionality of boto3 and the AWS CLI.
Apache License 2.0
1.44k stars 1.06k forks source link

Allow $AWS_PROFILE to be blank #3110

Open bemoody opened 4 months ago

bemoody commented 4 months ago

Describe the bug

If the environment variable AWS_PROFILE is set to an empty string, then boto3.client raises an exception. It does so even if client credentials are explicitly specified by keyword arguments or other means.

Expected behavior

Setting AWS_PROFILE= should be treated the same way as having AWS_PROFILE unset (i.e., it should fall back to other methods for determining credentials.)

There's no rule or standard saying that you need to treat an empty environment variable the same as one that is undefined - it's just common practice and good if you want to avoid surprising people. In the case of boto3, it's impossible to have a profile with an empty name, so it doesn't make sense to try to search for one.

Current behavior

If AWS_PROFILE is set to an empty string, then boto3.client('s3') raises botocore.exceptions.ProfileNotFound, apparently regardless of what other arguments or environment variables are defined.

Reproduction Steps

rm -rf ~/.aws
pip install boto3
python3
>>> import os
>>> [os.environ.pop(v) for v in os.environ if v.startswith('AWS')]
>>> import boto3

This succeeds (and returns a client with no credentials):

>>> boto3.client('s3')
<botocore.client.S3 object at 0x7f6dfb706fd0>

This succeeds (and returns a client with credentials):

>>> boto3.client('s3', aws_access_key_id='AKIAZZ', aws_secret_access_key='xx')
<botocore.client.S3 object at 0x7f6dfb5abfd0>

This ought to succeed (and return a client with no credentials):

>>> os.environ['AWS_PROFILE'] = ''
>>> boto3.client('s3')
...
botocore.exceptions.ProfileNotFound: The config profile () could not be found

This ought to succeed (and return a client with credentials):

>>> os.environ['AWS_PROFILE'] = ''
>>> boto3.client('s3', aws_access_key_id='AKIAZZ', aws_secret_access_key='xx')
...
botocore.exceptions.ProfileNotFound: The config profile () could not be found

Possible Solution

In botocore.session.Session.get_scoped_config:

--- session.py.orig
+++ session.py
@@ -413,7 +413,7 @@
         # If a profile is not explicitly set return the default
         # profile config or an empty config dict if we don't have
         # a default profile.
-        if profile_name is None:
+        if not profile_name:
             return profile_map.get('default', {})
         elif profile_name not in profile_map:
             # Otherwise if they specified a profile, it has to

Additional Information/Context

For one example of where this issue is an annoyance: Python's unittest.mock.patch.dict provides an easy way to temporarily override environment variables for a unit test, but it doesn't let you undefine variables.

SDK version used

boto3 1.34.31 botocore 1.34.31

Environment details (OS name and version, etc.)

Debian 12, Python 3.11