I have a requirement where I need to start couple of EC2 VMs when it is requested. I can use AWS CLI but I would have to provide MFA code each time I run the aws query. So, using the following code I wanted to automate this import boto3 from botocore.exceptions import ClientError MFA_ARN = "arn:aws:iam::6963451289992:mfa/User.Name" ROLE_ARN = "arn:aws:iam::196354236187:role/high-access" SESSION_NAME = "EC2StartInstanceSession" def get_user_session(): """ Create a boto3 session using the default profile. """ try: session = boto3.Session(profile_name='default') return session except Exception as e: print(f"Error getting user session: {e}") exit(1) def assume_role_with_mfa(user_session, region): """ Assume a role using MFA and return a new boto3 session with the temporary credentials. """ sts_client = user_session.client('sts') mfa_code = input("Enter MFA code: ") try: response = sts_client.assume_role( RoleArn=ROLE_ARN, RoleSessionName=SESSION_NAME, SerialNumber=MFA_ARN, TokenCode=mfa_code, DurationSeconds=3600 # 1 hour; adjust as needed ) credentials = response['Credentials'] print("Assumed credentials:", credentials) # Debug print of temporary credentials # Create a new session explicitly with the temporary credentials and region session = boto3.Session( region_name=region, aws_access_key_id=credentials['AccessKeyId'], aws_secret_access_key=credentials['SecretAccessKey'], aws_session_token=credentials['SessionToken'] ) return session except ClientError as e: print(f"Error assuming role: {e}") exit(1) def print_assumed_identity(session, region): """ Explicitly create an STS client using the temporary credentials and print the assumed identity. """ creds = session.get_credentials().get_frozen_credentials() print("Using temporary credentials:", creds) sts_client = boto3.client( 'sts', region_name=region, aws_access_key_id=creds.access_key, aws_secret_access_key=creds.secret_key, aws_session_token=creds.token ) try: identity = sts_client.get_caller_identity() print("Assumed identity:", identity) except ClientError as e: print(f"Error getting caller identity: {e}") def start_ec2_instance(session, instance_id, region): """ Start the specified EC2 instance using the provided session. """ ec2 = session.client('ec2', region_name=region) try: ec2.start_instances(InstanceIds=[instance_id]) print(f"Instance {instance_id} in {region} is starting...") except ClientError as e: print(f"Error starting instance {instance_id} in {region}: {e}") def main(): user_session = get_user_session() region = input("Enter the AWS Region (e.g., ap-south-1): ") or "us-east-1" session = assume_role_with_mfa(user_session, region) # Verify that the assumed credentials are active by printing the identity print_assumed_identity(session, region) instance_id = input("Enter the Instance ID: ") start_ec2_instance(session, instance_id, region) if __name__ == "__main__": main()` But when I run the above code, I get the following error Error starting instance in ap-south-2: An error occurred (AuthFailure) when calling the StartInstances operation: AWS was not able to validate the provided access credentials. But when I run python code with profiles I setup for aws cli it works fine. If the above code works my next step was to enter the secret key for AWS MFA in code and use pyotp so that MFA process can be automated. Since, I would be executing the code from my local machine it should not be a problem to hardcode it is what I thought. Continue reading...