Last active
September 26, 2024 01:02
-
-
Save benkehoe/b4ae80789add308ec446a1c5760ccdea to your computer and use it in GitHub Desktop.
A drop-in replacement for relying on well-known profiles in ~/.aws/config
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Copyright 2020 Ben Kehoe | |
# | |
# Permission is hereby granted, free of charge, to any person obtaining a copy of this | |
# software and associated documentation files (the "Software"), to deal in the Software | |
# without restriction, including without limitation the rights to use, copy, modify, | |
# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to | |
# permit persons to whom the Software is furnished to do so. | |
# | |
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, | |
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | |
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
# This code is intended provide a drop-in replacement for programs relying on | |
# well-known profiles in ~/.aws/config on the system they're running on. | |
# | |
# Programs that know the AWS configuration they need should have that config | |
# contained in themselves, not force users to configure their system a particular way. | |
# | |
# If you're not familiar with boto3 sessions, here's an explainer: | |
# https://ben11kehoe.medium.com/boto3-sessions-and-why-you-should-use-them-9b094eb5ca8e | |
# | |
# If you're looking to create boto3 sessions with AWS SSO config, consider | |
# aws_sso_lib.get_boto3_session(), which is more comprehensive: | |
# https://github.com/benkehoe/aws-sso-util/blob/master/lib/README.md#get_boto3_session | |
# | |
# If you need to assume a role based on another session, consider aws-assume-role-lib: | |
# https://github.com/benkehoe/aws-assume-role-lib | |
# | |
# If you have a shell script, consider using a temporary config file: | |
""" | |
# make sure no profile is set first | |
export -n AWS_PROFILE= AWS_DEFAULT_PROFILE= | |
export AWS_CONFIG_FILE=$(mktemp --suffix .aws-config) | |
cat <<EOF > $AWS_CONFIG_FILE | |
[default] | |
sso_start_url = https://example.awsapps.com/start | |
sso_region = us-east-2 | |
sso_account_id = 123456789012 | |
sso_role_name = MyRole | |
region = us-east-1 | |
EOF | |
aws sts get-caller-identity | |
aws s3 cp s3://some-bucket/some-key ./my-file | |
rm -f $AWS_CONFIG_FILE | |
export -n AWS_CONFIG_FILE= | |
""" | |
# If none of the above solutions work, here's the function: | |
def get_boto3_session_with_config(config, region_name=None, extra_profiles=None): | |
"""Get a boto3 session with the given configuration. | |
Other profiles can be given with extra_profiles as a dictionary | |
with profile names as the keys and profile config as the values, | |
and then these profiles can be referenced in the config and by | |
each other. This is primarily useful if the config is assuming | |
a role with role_arn and source_profile. | |
Note providing region_name in the config will get overridden by | |
the AWS_DEFAULT_REGION environment variable, but providing | |
region_name directly as an argument will not be overridden. | |
""" | |
import uuid, boto3, botocore | |
profile_name = "anonymous_" + uuid.uuid4().hex[:8] | |
session_config = { | |
"profiles": {} | |
} | |
if extra_profiles: | |
session_config["profiles"].update(extra_profiles) | |
session_config["profiles"][profile_name] = config | |
botocore_session = botocore.session.Session( | |
profile=profile_name, | |
session_vars={'profile': (None, None, None, None),} # ignore AWS_PROFILE | |
) | |
botocore_session._config = session_config | |
session = boto3.Session(botocore_session=botocore_session, region_name=region_name) | |
return session | |
#################### | |
# EXAMPLES # | |
#################### | |
# These examples use AWS SSO and assumed-role configuration just to demonstrate. | |
# | |
# But as mentioned above, with AWS SSO consider using aws_sso_lib.get_boto3_session(): | |
# https://github.com/benkehoe/aws-sso-util/blob/master/lib/README.md#get_boto3_session | |
# | |
# And use aws-assume-role-lib for role assumption: | |
# https://github.com/benkehoe/aws-assume-role-lib | |
session = get_boto3_session_with_config( | |
config={ | |
"sso_start_url": "https://example.awsapps.com/start", | |
"sso_region": "us-east-2", | |
"sso_account_id": "123456789012", | |
"sso_role_name": "MyRole" | |
}, | |
region_name="us-east-2" | |
) | |
# an assumed role profile | |
session = get_boto3_session_with_config( | |
config={ | |
"role_arn": "arn:aws:iam::123456789012:role/MyAssumedRole", | |
"source_profile": "sso_profile" | |
}, | |
region_name="us-east-2", | |
extra_profiles={ | |
"sso_profile": { | |
"sso_start_url": "https://example.awsapps.com/start", | |
"sso_region": "us-east-2", | |
"sso_account_id": "123456789012", | |
"sso_role_name": "MyRole" | |
} | |
} | |
) | |
# even if you rely on them setting an environment variable (or a command-line flag) to select from profiles, you can use this: | |
profiles = { | |
"my_role": { | |
"sso_start_url": "https://example.awsapps.com/start", | |
"sso_region": "us-east-2", | |
"sso_account_id": "123456789012", | |
"sso_role_name": "MyRole" | |
}, | |
"my_other_role": { | |
"sso_start_url": "https://example.awsapps.com/start", | |
"sso_region": "us-east-2", | |
"sso_account_id": "123456789012", | |
"sso_role_name": "MyRole" | |
} | |
} | |
import os | |
profile_name = os.environ.get("AWS_PROFILE", os.environ.get("AWS_DEFAULT_PROFILE")) | |
session = session = get_boto3_session_with_config(profiles[profile_name]) | |
# use like a normal boto3 Session | |
session.client("sts").get_caller_identity() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment