AWS Identity and Access Management
Using IAM (API Version 2010-05-08)
Did this page help you?  Yes | No |  Tell us about it...
« PreviousNext »
View the PDF for this guide.Go to the AWS Discussion Forum for this product.Go to the Kindle Store to download this guide in Kindle format.

Configuring MFA-Protected API Access

IAM policies let you specify which APIs a user is allowed to call. In some cases, you might want the additional security of requiring a user to be authenticated with AWS multi-factor authentication (MFA) before the user is allowed to perform particularly sensitive actions.

For example, you might have a policy that allows users to perform the Amazon EC2 RunInstances, DescribeInstances, and StopInstances actions. But you might want to restrict a destructive action like TerminateInstances and make sure that users can perform that action only if they have been authenticated with an AWS MFA device.

Overview

Adding MFA protection to APIs involves these tasks:

  • An administrator configures an AWS MFA device for each user who will make API requests that require MFA authentication. This process is described at Setting Up an MFA Device.

  • An administrator creates policies that include a condition that checks whether the user has been authenticated using an AWS MFA device.

  • The user calls one of the AWS Security Token Service APIs that support MFA parameters: AssumeRole or GetSessionToken, depending on the scenario for MFA protection, as explained later. As part of the call, the user includes the device identifier for the device that's associated with the user, as well as the time-based one-time password (TOTP) that is generated by the device. In each case, the user gets back temporary security credentials that the user then uses to make additional requests to AWS.

    Note

    MFA protection for an AWS service's APIs is available only if the service supports temporary security credentials. For a list of these services, see Using Temporary Security Credentials to Access AWS.

If the user is denied access to APIs because of an authorization failure, AWS returns an "Access Denied" error message (as it does for any unauthorized access). With MFA-protected API policies in place, AWS denies access to the APIs specified in the policies if the user attempts to use the APIs without valid MFA authentication, or if the time of the request for the APIs is beyond the duration specified in the policy. The user must re-authenticate with MFA by requesting new temporary security credentials using an MFA code and device serial number.

IAM Policies with MFA Conditions

Policies with MFA conditions can be attached to the following:

  • An IAM user or group.

  • A resource such as an Amazon S3 bucket, Amazon SQS queue, or Amazon SNS topic.

  • The trust policy of an IAM role that will be assumed by a user.

An MFA condition in a policy can be used to check the following properties:

  • Existence—To simply verify that the user has been authenticated with MFA, check that the aws:MultiFactorAuthPresent key True in a bool condition.

  • Duration—If you want to grant access only within a specified time after MFA authentication, use a numeric condition type to compare the aws:MultiFactorAuthAge key's age to a value (such as 3600 seconds). Note that the aws:MultiFactorAuthAge key is not present if MFA was not used.

The following example shows the trust policy of an IAM role that includes an MFA condition that tests for the existence of MFA authentication. This policy lets users from the AWS account specified in the Principal element (replace ACCOUNT-B-ID with a valid AWS account ID) assume the role that this policy is attached to, but only if the user has been MFA authenticated.

{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Principal": {"AWS": "ACCOUNT-B-ID"},
    "Action": "sts:AssumeRole",
    "Condition": {"Bool": {"aws:MultiFactorAuthPresent": "true"}}
  }
}

For more information on the condition types for MFA, see Available Keys for Conditions, Numeric Conditions, and Existence of Condition Keys

Choosing Between GetSessionToken and AssumeRole

AWS STS provides two APIs that let users pass MFA information: GetSessionToken and AssumeRole. The API that the user calls to get temporary security credentials depends on which of the following scenarios applies.

You use GetSessionToken for these scenarios:

  • Access to APIs in the current account, except for IAM and AWS STS APIs. (If you need access to those APIs with MFA protection, you can use AssumeRole).

  • Access to resources that are protected with resource-based policies that include an MFA condition.

You use AssumeRole for these scenarios:

  • Cross-account delegation. You can add MFA protection to the process of assuming a role in another account.

  • Access to APIs in the current account, including IAM and AWS STS.

Details about how to implement these scenarios are provided later in this document.

Important Points About MFA-Protected API Access

It's important to understand the following aspects of MFA protection for APIs:

  • MFA protection is available only by using temporary security credentials, which in turn must be obtained using AssumeRole or GetSessionToken.

  • You cannot use MFA-protected API access with root account credentials.

  • Federated users cannot be assigned an MFA device for use with AWS services, so they cannot access AWS resources controlled by MFA. (See next point.)

  • Other AWS STS APIs that return temporary credentials do not support MFA authentication. For AssumeRoleWithWebIdentity and AssumeRoleWithSAML, the user is authenticated using an external provider and AWS cannot determine whether that provider required MFA. For GetFederationToken, MFA authentication is not necessarily associated with a specific user.

  • Similarly, long-term credentials (IAM user access keys and root account access keys) do not support MFA authentication because these don't expire.

  • AssumeRole and GetSessionToken can also be called without MFA authentication information. In that case, the caller gets back temporary security credentials, but the session information for those temporary credentials does not indicate that the user authenticated using MFA.

  • You establish MFA protection for APIs by adding MFA conditions to policies. If a policy doesn't include the condition for MFAs, the policy does not enforce MFA authentication. For cross-account delegation, if the role's trust policy doesn’t include an MFA condition, there is no MFA protection for the API calls made using the role's temporary security credentials.

  • When you allow users from another AWS account to access resources in your account, even when you require multi-factor authentication, the security of your resources depends on the configuration of the other (or trusted) account. Any identity within the trusted account that has permission to create virtual MFA devices can construct an MFA claim to satisfy that part of your role's trust policy. Before you make another account's access to your AWS resources conditional upon multi-factor authentication, ensure that the trusted account's owner follows best practices and restricts access to MFA device-management APIs to specific, trusted administrators.

  • If a policy includes an MFA condition, a request is denied if users have not been MFA authenticated, or if they provide an invalid MFA device identifier or invalid TOTP.

Scenario: MFA Protection for Cross-Account Delegation

In this scenario, you want to delegate access to IAM users in another account, but only if the users have been authenticated using an AWS MFA device. (For more information about cross-account delegation, see Cross-Account API Access Using IAM Roles.

Imagine that you have Account A (the trusting account), with the IAM user Alice, who has administrator permission. She wants to grant access to user Bob in Account B (the trusted account), but wants to make sure that Bob had been authenticated with MFA before he assumes the role.

  1. In Account A, Alice creates an IAM role named CrossAccountRole and sets the principal in the role's trust policy to the account ID of Account B. The trust policy grants permission to the AWS STS AssumeRole action.

    Alice also adds an MFA condition to the trust policy, as in the following example.

    {
      "Version": "2012-10-17",
      "Statement": {
        "Effect": "Allow",
        "Principal": {"AWS": "ACCOUNT-B-ID"},
        "Action": "sts:AssumeRole",
        "Condition": {"Bool": {"aws:MultiFactorAuthPresent": "true"}}
      }
    }
  2. Alice adds an access policy to the role that specifies what the role is allowed to do. The access policy for a role with MFA protection is no different than any other role access policy. The following example shows the policy that Alice adds to the role; it allows Bob to perform any DynamoDB action on the table Books in Account A.

    Note

    The access policy does not include an MFA condition. It is important to understand that the MFA authentication is used only to determine whether a user can assume the role. Once the user has assumed the role, no further MFA checks are made.

    {
      "Version": "2012-10-17",
      "Statement": [{
        "Effect": "Allow",
        "Action": ["dynamodb:*"],
        "Resource": ["arn:aws:dynamodb:region:ACCOUNT-A-ID:table/Books"]
      }]
    }
  3. In Account B, an administrator makes sure that user Bob has been configured with an AWS MFA device and that he knows the ID of the device—that is, the serial number if it's a hardware MFA device, or the device's ARN if it's a virtual MFA device.

  4. In Account B, the administrator attaches the following policy to user Bob that allows him to call the AssumeRole action. The resource is set to the ARN of the role that Alice created in step 1. Notice that this policy does not contain an MFA condition.

    {
      "Version": "2012-10-17",
      "Statement": [{
        "Effect": "Allow",
        "Action": ["sts:AssumeRole"],
        "Resource": ["arn:aws:iam::ACCOUNT-A-ID:role/CrossAccountRole"]
      }]
    }
  5. In Account B, Bob (or an application that Bob is running) calls AssumeRole. The call includes the ARN of the role to assume (arn:aws:iam::Account-A-ID:role/CrossAccountRole), the ID of the MFA device, and the current TOTP that Bob gets from his device.

    When Bob calls AssumeRole, AWS determines whether he has valid credentials, including MFA authentication. If so, Bob can perform any DynamoDB action on the table named Books in Account A.

    For an example of a program that calls AssumeRole, see Code Example: Calling AssumeRole with MFA Authentication (Python) later in this document.

Scenario: MFA Protection for Access to APIs in the Current Account

In this scenario, you want to make sure that a user in an account who requests access to sensitive actions has been authenticated using an AWS MFA device.

Imagine that you have Account A that contains a group of developers who need to work with Amazon EC2 instances. Ordinary developers can work with the instances, but they are not granted permissions for the ec2:StopInstances or ec2:TerminateInstances actions. You want to limit those privileged actions to just a few trusted users. To make absolutely sure that only your trusted users can stop or terminate instances—and not just anyone who might happen to get the access keys for one of those trusted users—you add MFA protection to a policy that allows these sensitive Amazon EC2 actions.

In this scenario, one of those trusted users is user Carol. User Alice is an administrator in Account A.

  1. Alice makes sure that Carol has been configured with an AWS MFA device and that Carol knows the ID of the device—the serial number if it's a hardware MFA device, or the device's ARN if it's a virtual MFA device.

  2. Alice creates a group named EC2-Admins and adds user Carol to the group.

  3. Alice attaches the following policy to the EC2-Admins group. This policy grants users permission to call the Amazon EC2 StopInstances and TerminateInstances actions, but only if the user has authenticated using MFA.

    {
      "Version": "2012-10-17",
      "Statement": [{
        "Effect": "Allow",
        "Action": [
          "ec2:StopInstances",
          "ec2:TerminateInstances"
        ],
        "Resource": ["*"],
        "Condition": {"Bool": {"aws:MultiFactorAuthPresent": "true"}}
      }]
    }
  4. If user Carol needs to stop or terminate an Amazon EC2 instance, she (or an application that she is running) calls GetSessionToken. The call includes the ID of the MFA device and the current TOTP that Carol gets from her device.

  5. User Carol (or an application that Carol is using) uses the temporary credentials returned by GetSessionToken to call the Amazon EC2 StopInstances or StopInstances action.

    For an example of a program that calls GetSessionToken, see Code Example: Calling GetSessionToken with MFA Authentication (Python and C#) later in this document.

Calling IAM or AWS STS APIs in the Same Account

In this scenario, you want to make sure that a user in an account who requests access to IAM and STS actions has been authenticated using an AWS MFA device. This scenario is similar to the previous one, except that the user also needs to be able to request IAM actions or STS actions.

This scenario requires a different approach, because the temporary security credentials returned by GetSessionToken are blocked from calling APIs in IAM or AWS STS. However, you can use AssumeRole to grant permissions for IAM and STS actions the same way you grant users cross-account access, except that you are granting them permissions to call actions in their own account.

In this scenario, user Alice is an administrator in the account, and can perform all actions including IAM and STS actions. Alice creates two IAM users, Bob and Mary. Both are power users—they can perform any action in Alice's account except IAM and STS actions. Alice also creates a role that gives a user permissions to perform IAM and STS actions. However, to assume the role, the user must be MFA-authenticated. Alice will give Mary—but not Bob—permission to assume the role.

  1. Alice creates an IAM group named Power Users and adds the following policy to the group. The policy allows members of the group to perform any actions in the account except IAM and STS actions.

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": ["*"],
          "Resource": ["*"]
        },
        {
          "Effect": "Deny",
          "Action": [
            "iam:*",
            "sts:*"
          ],
          "Resource": ["*"]
        }
      ]
    }
  2. Alice creates IAM users Bob and Mary and adds them to the Power Users group.

  3. Alice makes sure that Mary's IAM user is configured with an AWS MFA device and that she knows the ID of the device—that is, the serial number if it's a hardware MFA device, or the device's ARN if it's a virtual MFA device.

  4. Alice creates an IAM role named IAMAdminRole and adds the following trust policy to the role. The principal in the role's trust policy is set to the account ID of Account A—that is, Alice's own account. The policy grants permission for any IAM user in Account A to assume the role, but only if the user has been MFA authenticated.

    {
      "Version": "2012-10-17",
      "Statement": [{
        "Effect": "Allow",
        "Principal": {"AWS": "ACCOUNT-A-ID"},
        "Action": "sts:AssumeRole",
        "Condition": {"Bool": {"aws:MultiFactorAuthPresent": "true"}}
      }]
    }
  5. Alice adds an access policy to the role that specifies the permissions that will be granted to users who assume the role. For this scenario, the access policy allows the user who assumes the role to perform any IAM or STS action.

    {
      "Version": "2012-10-17",
      "Statement": [{
        "Effect": "Allow",
        "Action": [
          "iam:*",
          "sts:*"
        ],
        "Resource": ["*"]
      }]
    }
  6. Alice attaches the following user policy to user Mary (but not to user Bob). This policy allows Mary to assume the IAMAdminRole role if she has been MFA authenticated.

    {
      "Version": "2012-10-17",
      "Statement": [{
        "Effect": "Allow",
        "Action": ["sts:AssumeRole"],
        "Resource": ["arn:aws:iam::ACCOUNT-A-ID:role/IAMAdminRole"],
        "Condition": {"Bool": {"aws:MultiFactorAuthPresent": "true"}}
      }]
    }
  7. When Mary needs to administer IAM users in Account A, she calls AssumeRole. The call includes the ARN of the role to assume (arn:aws:iam::ACCOUNT-A-ID:role/IAMAdminRole), the ID of the MFA device, and the current TOTP that Mary gets from her device. She can then use the temporary security credentials returned by AssumeRole to perform IAM or STS tasks. Because he isn't MFA authenticated, Bob cannot assume the IAMAdminRole role, but because he's in the Power Users group, he can perform all other actions in the account.

    For an example of a program that calls AssumeRole, see Code Example: Calling AssumeRole with MFA Authentication (Python) later in this document.

Scenario: MFA Protection for Resources That Have Resource-Based Policies

In this scenario, you are the owner of an Amazon S3 bucket, an Amazon SQS queue, or an Amazon SNS topic and you want to make sure that any user who accesses the resource has been authenticated using an AWS MFA device.

This scenario illustrates a way to provide cross-account MFA protection without requiring users to assume a role first. If the user has authenticated using MFA and is able to get temporary security credentials using GetSessionToken, and if the user is in account that is trusted by the resource's policy, the user can access the resource.

Imagine that you are in Account A and create an S3 bucket. You want to grant access to this bucket to users who are in several different AWS accounts, but only if those users have MFA authentication.

In this scenario, user Alice is an administrator in Account A. User Charlie is an IAM user in Account C.

  1. In Account A, Alice creates a bucket named Account-A-bucket.

  2. Alice adds the bucket policy to the bucket. The policy allows any user in Account A, Account B, or Account C to perform the Amazon S3 PutObject and DeleteObject actions in the bucket. The policy includes an MFA condition.

    {
      "Version": "2012-10-17",
      "Statement": [{
        "Effect": "Allow",
        "Principal": {"AWS": [
          "ACCOUNT-A-ID",
          "ACCOUNT-B-ID",
          "ACCOUNT-C-ID"
        ]},
        "Action": [
          "s3:PutObject",
          "s3:DeleteObject"
        ],
        "Resource": ["arn:aws:s3:::ACCOUNT-A-BUCKET-NAME/*"],
        "Condition": {"Bool": {"aws:MultiFactorAuthPresent": "true"}}
      }]
    }

    Note

    Amazon S3 offers an MFA Delete feature for root account access (only). You can enable Amazon S3 MFA Delete when you set the versioning state of the bucket. Amazon S3 MFA Delete cannot be applied to an IAM user, and is managed independently from MFA-protected API access. An IAM user with permission to delete a bucket cannot delete a bucket with Amazon S3 MFA Delete enabled. For more information on Amazon S3 MFA Delete, see MFA Delete.

  3. In Account C, an administrator makes sure that user Charlie has been configured with an AWS MFA device and that he knows the ID of the device—the serial number if it's a hardware MFA device, or the device's ARN if it's a virtual MFA device.

  4. In Account C, Charlie (or an application that he is running) calls GetSessionToken. The call includes the ID or ARN of the MFA device and the current TOTP that Charlie gets from his device.

  5. Charlie (or an application that he is using) uses the temporary credentials returned by GetSessionToken to call the Amazon S3 PutObject action to upload a file to Account-A-bucket.

    For an example of a program that calls GetSessionToken, see Code Example: Calling GetSessionToken with MFA Authentication (Python and C#) later in this document.

    Note

    The temporary credentials returned by AssumeRole won't work in this case because although the user must have MFA authentication to assume a role, the temporary credentials returned by AssumeRole don't include the MFA information that is required in order to meet the MFA condition in the policy.

Additional Examples of Policies with MFA Conditions

The following examples show additional ways that MFA conditions can be added to policies.

Note

All of the following examples show policies attached directly to an IAM user or group in your own AWS account. To MFA-protect APIs across accounts, you use IAM roles and put the MFA condition check in the role trust policy, not in the role access policy. For more information, see Scenario: MFA Protection for Cross-Account Delegation.

Example 1: Granting access after recent MFA authentication (GetSessionToken)

The following example shows a policy attached to a user or group that grants Amazon EC2 access only if the user authenticated with MFA within the last hour (3600 seconds).

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": ["ec2:*"],
    "Resource": ["*"],
    "Condition": {"NumericLessThan": {"aws:MultiFactorAuthAge": "3600"}}
  }]
}

Example 2: Denying access to specific APIs without valid MFA authentication (GetSessionToken)

The following example shows a policy attached to a user or group that grants access to the entire Amazon EC2 API, but denies access to StopInstances and TerminateInstances if the user has not been MFA authenticated.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["ec2:*"],
      "Resource": ["*"]
    },
    {
      "Effect": "Deny",
      "Action": [
        "ec2:StopInstances",
        "ec2:TerminateInstances"
      ],
      "Resource": ["*"],
      "Condition": {"Bool": {"aws:MultiFactorAuthPresent": "true"}}
    }
  ]
}

Example 3: Denying access to specific APIs without recent valid MFA authentication (GetSessionToken)

The following example shows a policy attached to a user or group that grants access to the entire Amazon EC2 API, but denies access to StopInstances and TerminateInstances unless they authenticated using MFA authentication within the last hour.

Note

MFA-protected API policies using Deny statements that check for the numeric value of aws:MultiFactorAuthAge should include an existence check. AWS evaluates existence and duration independently; evaluating only for duration does not enforce a Deny condition if MFA has not been used at all.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["ec2:*"],
      "Resource": ["*"]
    },
    {
      "Effect": "Deny",
      "Action": [
        "ec2:StopInstances",
        "ec2:TerminateInstances"
      ],
      "Resource": ["*"],
      "Condition": {"Bool": {"aws:MultiFactorAuthPresent": "true"}}
    },
    {
      "Effect": "Deny",
      "Action": [
        "ec2:StopInstances",
        "ec2:TerminateInstances"
      ],
      "Resource": ["*"],
      "Condition": {"NumericGreaterThan": {"aws:MultiFactorAuthAge": "3600"}}
    }
  ]
}

Code Example: Calling GetSessionToken with MFA Authentication (Python and C#)

The following examples, written using the AWS SDK for Python (Boto) and AWS SDK for .NET, show how to call GetSessionToken and pass MFA authentication information. The temporary security credentials returned by GetSessionTokenRole are then used to list all Amazon S3 buckets in the account.

The policy attached to the user who runs this code (or to a group that the user is in) is assumed to include an MFA check. The policy also needs to grant the user permission to request the Amazon S3 ListBuckets action.

Example: Calling GetSessionToken with MFA Authentication Using Python

import boto
from boto.s3.connection import S3Connection
from boto.sts import STSConnection

# Prompt for MFA time-based one-time password (TOTP)
mfa_TOTP = raw_input("Enter the MFA code: ")

# The calls to AWS STS GetSessionToken must be signed using the access key ID and secret
# access key of an IAM user. The credentials can be in environment variables or in 
# a configuration file and will be discovered automatically
# by the STSConnection() function. For more information, see the Python SDK 
# documentation: http://boto.readthedocs.org/en/latest/boto_config_tut.html

sts_connection = STSConnection()

# Use the appropriate device ID (serial number for hardware device or ARN for virtual device). 
# Replace ACCOUNT-NUMBER-WITHOUT-HYPHENS and MFA-DEVICE-ID with appropriate values.

tempCredentials = sts_connection.get_session_token(
    duration=3600,
    mfa_serial_number="arn:aws:iam::ACCOUNT-NUMBER-WITHOUT-HYPHENS:mfa/MFA-DEVICE-ID",
    mfa_token=mfa_TOTP
)

# Use the temporary credentials to list the contents of an S3 bucket
s3_connection = S3Connection(
    aws_access_key_id=tempCredentials.access_key,
    aws_secret_access_key=tempCredentials.secret_key,
    security_token=tempCredentials.session_token
)

# Replace BUCKET-NAME with an appropriate value.
bucket = s3_connection.get_bucket(bucket_name="BUCKET-NAME")
objectlist = bucket.list()
for obj in objectlist:
    print obj.name

Example: Calling GetSessionToken with MFA Authentication Using C#

Console.Write("Enter MFA code: ");
string mfaTOTP = Console.ReadLine(); // Get string from user

/* The calls to AWS STS GetSessionToken must be signed using the access key ID and secret
   access key of an IAM user. The credentials can be in environment variables or in 
   a configuration file and will be discovered automatically
   by the AmazonSecurityTokenServiceClient constructor. For more information, see 
   http://docs.aws.amazon.com/AWSSdkDocsNET/latest/DeveloperGuide/net-dg-config-creds.html
*/
AmazonSecurityTokenServiceClient stsClient = 
    new AmazonSecurityTokenServiceClient();
GetSessionTokenRequest getSessionTokenRequest = new GetSessionTokenRequest();
getSessionTokenRequest.DurationSeconds = 3600;

// Replace ACCOUNT-NUMBER-WITHOUT-HYPHENS and MFA-DEVICE-ID with appropriate values
getSessionTokenRequest.SerialNumber = "arn:aws:iam::ACCOUNT-NUMBER-WITHOUT-HYPHENS:mfa/MFA-DEVICE-ID"; 
getSessionTokenRequest.TokenCode = mfaTOTP;

GetSessionTokenResponse getSessionTokenResponse = 
    stsClient.GetSessionToken(getSessionTokenRequest);

// Extract temporary credentials from result of GetSessionToken call
GetSessionTokenResult getSessionTokenResult = 
    getSessionTokenResponse.GetSessionTokenResult;
string tempAccessKeyId = getSessionTokenResult.Credentials.AccessKeyId;
string tempSessionToken = getSessionTokenResult.Credentials.SessionToken;
string tempSecretAccessKey = getSessionTokenResult.Credentials.SecretAccessKey;
SessionAWSCredentials tempCredentials = new SessionAWSCredentials(tempAccessKeyId, 
    tempSecretAccessKey, tempSessionToken);

// Use the temporary credentials to list the contents of an S3 bucket
// Replace BUCKET-NAME with an appropriate value
ListObjectsRequest S3ListObjectsRequest = new ListObjectsRequest();
S3ListObjectsRequest.BucketName = "BUCKET-NAME";
S3Client = AWSClientFactory.CreateAmazonS3Client(tempCredentials);
ListObjectsResponse S3ListObjectsResponse = 
    S3Client.ListObjects(S3ListObjectsRequest);
foreach (S3Object s3Object in S3ListObjectsResponse.S3Objects)
{
    Console.WriteLine(s3Object.Key);
}

Code Example: Calling AssumeRole with MFA Authentication (Python)

The following example, written using the AWS SDK for Python (Boto), shows how to call AssumeRole and pass MFA authentication information. The temporary security credentials returned by AssumeRole are then used to list all Amazon S3 buckets in the account.

For more information about this scenario, see Scenario: MFA Protection for Cross-Account Delegation.

import boto
from boto.s3.connection import S3Connection
from boto.sts import STSConnection

# Prompt for MFA time-based one-time password (TOTP)
mfa_TOTP = raw_input("Enter the MFA code: ")

# The calls to AWS STS AssumeRole must be signed using the access key ID and secret
# access key of an IAM user. (The AssumeRole API can also be called using temporary
# credentials, but this example does not show that scenario.) 
# The IAM user credentials can be in environment variables or in 
# a configuration file and will be discovered automatically
# by the STSConnection() function. For more information, see the Python SDK 
# documentation: http://boto.readthedocs.org/en/latest/boto_config_tut.html

sts_connection = STSConnection()

# Use appropriate device ID (serial number for hardware device or ARN for virtual device)
# Replace ACCOUNT-NUMBER-WITHOUT-HYPHENS, ROLE-NAME, and MFA-DEVICE-ID with appropriate values
tempCredentials = sts_connection.assume_role(
    role_arn="arn:aws:iam::ACCOUNT-NUMBER-WITHOUT-HYPHENS:role/ROLE-NAME",
    role_session_name="AssumeRoleSession1",
    mfa_serial_number="arn:aws:iam::ACCOUNT-NUMBER-WITHOUT-HYPHENS:mfa/MFA-DEVICE-ID",
    mfa_token=mfa_TOTP
)

# Use the temporary credentials to list the contents of an S3 bucket
s3_connection = S3Connection(
    aws_access_key_id=tempCredentials.credentials.access_key,
    aws_secret_access_key=tempCredentials.credentials.secret_key,
    security_token=tempCredentials.credentials.session_token
)

# Replace BUCKET-NAME with a real bucket name
bucket = s3_connection.get_bucket(bucket_name="BUCKET-NAME")
objectlist = bucket.list()
for obj in objectlist:
    print obj.name