I am trying to use the Boto3 library to sequentially and independently authenticate my Python application so that it can pull secrets from the AWS secrets manager on aws-account-1 and query AWS Athena on aws-account-2 from my local development machine.
Authenticating from the command line through account-1 using this command aws sso login—-profile aws-account-1
, the Secret Manager's client code pulls the secrets correctly. However, the Athena query fails because it is not authenticated to the correct user/profile.
Executing aws sso login—-profile aws-account-2
will allow me to execute the Athena queries but pulling the secrets will fail due to insufficient permissions.
One undesirable approach to authenticating from a single account is to create an AWS role that assumes aws-account-1 from aws-account-2.
So far, the code looks something similar to this:
def __local_authentication(self, account, resource):
try:
session = boto3.Session(profile_name=account)
client = self.__session.client(resource, region_name = self.__region)
return (session, client)
except Exception as e:
raise "Authentication error."
. . .
session, client = __local_authentication(self,'aws-account-1', 'secretmanager')
response = client.get_secret_value(SecretId=secret_name)
. . .
session, client = __local_authentication(self,'aws-account-2', 'athena')
resultset = wr.athena.query("", session=session)
Is there a better approach to authenticating my code to pull secrets from AWS Secret Manager and then authenticating again to execute Athena queries without using the assumeRole approach?
The best way to handle this scenario is to create separate AWS sessions for each account. This lets your code authenticate independently to each account while still keeping things clean and manageable.
The idea is to use separate AWS sessions for each account. Each session will handle authentication and permissions independently. To make this work, you’ll need:
SSO profiles for each account in your ~/.aws/config file.
A small Python utility to switch profiles and work with the appropriate services.
This is a code example:
class MultiAccountAWSClient:
def __init__(self, region):
self.region = region
def authenticate(self, account_profile, service_name):
try:
# Create a session for the specific profile
session = boto3.Session(profile_name=account_profile)
client = session.client(service_name, region_name=self.region)
return session, client
except Exception as e:
raise RuntimeError(f"Error authenticating with profile '{account_profile}': {e}")
then just:
aws_client = MultiAccountAWSClient(region="us-east-1")
session_account1, secrets_client = aws_client.authenticate('aws-account-1', 'secretsmanager')
session_account2, athena_client = aws_client.authenticate('aws-account-2', 'athena')