Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@benkehoe
Last active January 27, 2022 22:03
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save benkehoe/b4ae80789add308ec446a1c5760ccdea to your computer and use it in GitHub Desktop.
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
# 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