Bo Qiang
Bo Qiang

Reputation: 789

are there any boto3 + MFA examples out there?

I found an example for boto + MFA:

http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_sample-code.html

But I cannot find an example of how to do it with boto3. Any equivalent boto3 examples?

Thanks!

Upvotes: 9

Views: 14724

Answers (6)

Effie
Effie

Reputation: 233

Trying to understand better how to use Session in different cases, I've written the following example:

Considering the Config and Credentials files are set under ~.aws/config.

Config file looks similar to the following:

[profile mfa]
mfa_serial = arn:aws:iam::ACCOUNT_ID:mfa/MFA_DEVICE_NAME
region=us-east-1

[profile non-mfa]
region=us-east-1

the python file:

import os
import boto3
from botocore.session import Session


def get_profile_name():
    profile_name = input(
        "Which AWS account do you want to use to connect to? \n "
        "Choose Profile: \n0. default profile\n1. profile with mfa\n2. profile without mfa\n"
        "Please enter either 0 or 1 or 2: ")
    return profile_name


def init_aws_session():
    profiles = Session().available_profiles  # profiles = {0: 'default', 1: 'mfa', 2: 'non-mfa'}
    profile_name = get_profile_name()

    if profile_name == "1":
        # profile with mfa
        # get the mfa device
        mfa_serial = Session().get_scoped_config().get('mfa_serial')
        sts = boto3.client('sts')
        # get mfa code from user
        mfa_code = input("Enter the MFA code: ")
        mfa_token = sts.get_session_token(
            SerialNumber=mfa_serial,
            TokenCode=mfa_code
        )
        profile_session = boto3.Session(profile_name=profiles[int(profile_name)],
                                        aws_session_token=mfa_token["Credentials"]["SessionToken"],
                                        aws_secret_access_key=mfa_token["Credentials"]["SecretAccessKey"],
                                        aws_access_key_id=mfa_token["Credentials"]["AccessKeyId"]
                                        )
        return profile_session

    elif profile_name == "2":
        # profile without mfa
        profile_session = boto3.Session(profile_name=profiles[int(profile_name)])
        credentials = profile_session.get_credentials().get_frozen_credentials()
        profile_session = boto3.Session(profile_name=profiles[int(profile_name)],
                                        aws_access_key_id=credentials.access_key,
                                        aws_secret_access_key=credentials.secret_key)
        profile_session.get_credentials()
        return profile_session
    elif profile_name == "0":
        # default profile
        # act according to your needs
        pass
    else:
        print("Not valid option entered")


if __name__ == "__main__":
    # get session
    session = init_aws_session()

    # Use the session to create a client
    ec2 = session.client("ec2", region_name='us-east-1',
                         verify=os.getenv("CA_BUNDLE"))
    # get instances using client
    resources = ec2.describe_instances()
    print(resources)

    # Use the session to create a resource
    instance_id = 'i-012345678901'
    ec2 = session.resource('ec2')
    instance = ec2.Instance(instance_id)
    print(instance)

Another nice article with code example for MFA only: medium.com/Charles Victus

Upvotes: 0

Ilia S.
Ilia S.

Reputation: 887

A simple example of creating Virtual MFA and assigning it to a user:

import pyotp as pyotp
from datetime import datetime, timedelta  

iam = boto3.client("iam")

user = iam.create_user(user_name="some_user_name")
mfa = iam.create_virtual_mfa_device(virtual_mfa_device_name="some_virtual_mfa_name")

totp = pyotp.TOTP(mfa['VirtualMFADevice']['Base32StringSeed'])
code_1 = totp.generate_otp(totp.timecode(datetime.now() - timedelta(seconds=30)))
code_2 = totp.generate_otp(totp.timecode(datetime.now()))

iam.enable_mfa_device(
        user_name=user["UserName"],
        serial_number=mfa["SerialNumber"],
        authentication_code1=code_1,
        authentication_code2=code_2,
    )

Upvotes: 1

Zoltan Szabo
Zoltan Szabo

Reputation: 85

The code below works but you have to use ~/.boto file with the correct credentials. SerialNumber is your MFA device serial or the full AWS ARN of it

#!/usr/bin/env python

import boto3

mfa_TOTP = input("Enter the MFA code: ")

client=boto3.client('sts')

response = client.assume_role(
    RoleArn='arn:aws:iam::123456789:role/admin_full',
    RoleSessionName='mysession',
    DurationSeconds=3600,
    SerialNumber='arn:aws:iam::987654321:mfa/myaccount',
    TokenCode=mfa_TOTP,
)

Upvotes: 9

Ganesh Satpute
Ganesh Satpute

Reputation: 3941

In addition to answers by Zoltan, and Fauxsys, this could be another way to create AWS client

import boto3

mfa_otp = raw_input("Enter the MFA code: ")

client = boto3.client('sts')

mfa_creds = client.get_session_token(
    DurationSeconds=36000,
    SerialNumber='<MFA serial number>',
    TokenCode=mfa_otp
)


boto3 \
    .client(service_name="<service name e.g. secretsmanager>",
            region_name='us-west-2',
            aws_access_key_id=mfa_creds['Credentials']['AccessKeyId'],
            aws_secret_access_key=mfa_creds['Credentials']['SecretAccessKey'],
            aws_session_token=mfa_creds['Credentials']['SessionToken'])
        

If you're not using MFA, you can omit those parts and it'll still work.

Upvotes: 4

Fauxsys
Fauxsys

Reputation: 51

The MFA method described below can be used for boto3 as well as the AWS CLI:

~/.aws/credentials:

[local-keys]
aws_access_key_id = ABCDEFG
aws_secret_access_key = HIJKLMNOP

[stackoverflow]
role_arn = arn:aws:iam::123456789:role/RoleName
source_profile = local-keys
mfa_serial = arn:aws:iam:987654321:mfa/UserName

~/.aws/config:

[profile stackoverflow]
region = us-east-1

Here is an example of how to use this in Python:

aws_MFA.py:

#!/usr/bin/env python3
import boto3

session = boto3.Session(profile_name='stackoverflow')
ec2client = session.client('ec2')

Upvotes: 2

Arora20
Arora20

Reputation: 1063

You can use sts and get_session_token method to call use MFA with boto3. For this pre requirements is you should create a client object of sts and then call the function with mfa token. This will give you temporary credentials which you can use and these credentials are valid for 36 hours Code -

sts = boto3.client('sts')
response = sts.get_session_token(DurationSeconds=<time>, SerialNumber='string',TokenCode='string')

http://boto3.readthedocs.io/en/latest/reference/services/sts.html#STS.Client.get_session_token

Upvotes: 6

Related Questions