AWS CLI MFA, how about that for title? It translates to Amazon Web Services Command Line Interface Multi Factor Authentication when all acronyms are spelled out. If you have enabled MFA for the AWS Console you may know that is fairly straight forward once you have created your IAM user, however it is a different story to configure MFA for the AWS CLI tool. This blog post will present a solution for this problem based on a CloudFormation Template and AWS CLI profiles.


If you are using the AWS platform from the command line you have configured your terminal for CLI access using an AWS Access Key ID and an AWS Secret Access Key. As a result, those values are saved in the ~/.aws/credentials file, i.e. there is a file in your computer in which the AWS account credentials are stored in plain text. Consequently, if your computer is stolen or hacked, a malicious user can use your credentials and then use the AWS CLI tool to do whatever you are privileged to do in your AWS account. Adding MFA to the CLI access will add a significant hurdle for the intruder since they also need your MFA device in addition to your AWS access keys before he or she can do any harm.


Currently, there is not easy way of mandating MFA for AWS CLI users. The trick that will be presented in this blog post is to limit the privileges for users that have not authenticated using MFA and then create a separate role with the desired privileges that requires MFA to be assumed. When the AWS CLI tool user switches to the role, the user is prompted for the TOTP (Time-based One-time Password, e.g. a six digit code that the MFA device presents) before the actual role switch occurs. As a result, the user receives temporary security credentials that are valid for 1 hour. Within that time frame multiple CLI commands can be executed without the need of re-authentication. By utilizing two different CLI profiles the role switch occurs if the user just provided the correct profile.

To summarize:

  • Create an IAM Role with the same privileges as the IAM Group. Make sure that the IAM Role requires MFA.
  • Create an IAM Group with admin privileges to which we can add users. Make sure that the IAM Group requires MFA.
  • Create a policy that allows users to manage their MFA configuration.
  • Create AWS CLI profiles that handle the role switch and MFA authentication for the user.

Before You Start

I advise that you create a temporary backup user with admin privileges (and verify that it works), before you try the proposed solution. Chances are that you accidentally screw up your own user role or privileges and lock yourself out from the account accordingly. If that happens, you can use the root credentials to restore your access, but it may be easier to have a dedicated temporary user that is deleted once you have completed your IAM configuration.

The source code has been published to the aws-cli-mfa repository in my GitHub account. There you will find two role / group pairs, one AdminMFARole/AdminMFAGroup with full admin privileges that I discuss in detail below. Similarly, there is one S3MFARole/S3MFaGroup that has full access to S3, but is prohibited from using other AWS services.

Admin Role

First, we need to create an AWS::IAM::Role. The privileges of this role will dictate what the AWS CLI user is allowed to do after the role switch.. In this blog post, the role will have admin privileges, but requires MFA ro be assumed, but you create other roles with more limited privileges according to your needs (the example in the GitHub repository also contains an S3 role). AWS comes with a predefined managed policy arn:aws:iam::aws:policy/AdministratorAccess that we can use, but we need to add an assume role policy document with a Condition that MFA is present using one of the AWS Global and IAM Condition Context Keys:

  Type: AWS::IAM::Role
      - arn:aws:iam::aws:policy/AdministratorAccess
    RoleName: AdminMFARole
      Version: 2012-10-17
        - Sid: AllowAssumeRoleIfMFAIsPresent
          # see
          Effect: Allow
            AWS: !Ref AWS::AccountId
          Action: sts:AssumeRole
              aws:MultiFactorAuthPresent: true

Admin Group

Next step is to create an AWS::IAM::Group. You can assign which of your IAM users will have admin access by adding them to or removing them from this group. The group is configured with two policies. The first policy allow users in the group to assume the AdminMFARole above. Note that this policy should be without MFA requirement. Why? If the user had already been MFA authenticated, there would be no need for the role switch since its sole purpose is to trigger the MFA authentication.

The second policy document has the same privileges as the previously mentioned arn:aws:iam::aws:policy/AdministratorAccess, but it adds MFA requirement. Regrettably, it is not possible to copy an existing policy and just add the MFA condition to it, hence we need to specify a full policy document. This second policy is what gives your AWS Console users administrator privileges if they use MFA as part of the login flow. If you only plan to cater for CLI users, this policy can be omitted.

  Type: AWS::IAM::Group
    GroupName: AdminMFAGroup

      - PolicyName: AllowAssumeAdminMFAPolicy
          Version: 2012-10-17
            Sid: AllowUserToAssumeAdminMFARole
            Effect: Allow
            Action: sts:AssumeRole
            Resource: !GetAtt AdminMFARole.Arn

      - PolicyName: AdminMFAPolicy
        # same privileges as the arn:aws:iam::aws:policy/AdministratorAccess, but with MFA requirement
          Version: 2012-10-17
            Sid: AllowAdminUserToDoAnythingIfMFAIsPresent
            Effect: Allow
            Action: '*'
            Resource: '*'
                aws:MultiFactorAuthPresent: true

Manage MFA Policy

The third step enables MFA self service for all users in the AdminMFAGroup. Basically, this policy allows the users to create their own MFA configuration without enforcing MFA in the first place, both using the AWS CLI as well as the AWS Console.

  Type: AWS::IAM::ManagedPolicy
    Description: A policy that allows users to manage their personal MFA configuration
      - !Ref AdminMFAGroup
      # add more groups that should have MFA requirement
    ManagedPolicyName: ManageMFAPolicy
      Version: 2012-10-17

      - Sid: AllowUsersToManageTheirOwnMFADevice
        Effect: Allow
        - iam:CreateVirtualMFADevice
        - iam:EnableMFADevice
        - iam:ResyncMFADevice
          # users should only manage their own resources
          - !Join ['', ['arn:aws:iam::', !Ref 'AWS::AccountId', ':mfa/${aws:username}']]
          - !Join ['', ['arn:aws:iam::', !Ref 'AWS::AccountId', ':user/${aws:username}']]

      - Sid: AllowUsersToListMFADevicesAndUsers
        Effect: Allow
        - iam:ListMFADevices
        - iam:ListVirtualMFADevices
        - iam:ListUsers
        Resource: "*"

Enforcing MFA

Now the infrastructure is setup, and you can start enforcing MFA for your users.

Warning This is the point where you should create a temporary admin user so that you can make corrections in case you lock yourself out from the account.

The result depend on whether or not the user already has an active MFA. Non-MFA users are now restricted to just enable MFA, both in the AWS Console and using the AWS CLI. As soon as they have an active MFA device (and have re-login), they will have admin privileges.

AWS CLI Profiles

All users of the account need to configure their AWS CLI environment with two profiles in order to facilitate the automatic role switch from the command line. Start by creating a named profile in your ~/.aws/credentials file in which you provide the AWS Access Key ID and the AWS Secret Access Key:


The second profile is created in the file in which you provide a reference to the profile to be use for authentication by using the source_profile, an ARN to the role which should be used for role switching and the ARN to your configured MFA device.

[profile my-project-mfa]
source_profile = my-project
role_arn = arn:aws:iam::123456789012:role/AdminMFARole
mfa_serial = arn:aws:iam::123456789012:mfa/my-user-name

Of course, you need to change the values of the profile names, AWS Access Key ID, AWS Secret Access Key, role ARN, and the MFA serial to whatever values are applicable for you. One way of getting the MFA serial is to go to the IAM Users and check in the Security Credentials. It will be presented there if the user has configured a MFA device.


Finally, all configuration is complete and you can start using your new, MFA enabled, CLI profile. To use a specific profile, you simply specify the profile name after using the --profile option.

Continuing with the example profile names above, you will find that the my-project profile (i.e. the profile without MFA) is no longer allowed to for example list S3 buckets:

$ aws s3 ls --profile my-project
An error occurred (AccessDenied) when calling the ListBuckets operation: Access Denied

Using the my-project-mfa profile on the other hand yields a different behavior:

$ aws s3 ls --profile my-project-mfa
Enter MFA code:
[user enters valid MFA token]
[a list of S3 buckets is presented]

Achievement unlocked, requiring MFA for the AWS CLI!

Many times you will execute multiple CLI commands to the same account. You can set the AWS_PROFILE environment variable to avoid to repeatedly key in the same profile over and over again, e.g.

$ export AWS_PROFILE=my-project-mfa


Do not forget to delete your temporary admin user.


One caveat to look out for is that you may have noticed that specified the AWS::AccountId as Principal in the AdminMFARole. As a consequence, all IAM users and roles in the acconut can assume this role (given that they satisfy the MFA condition). A much better approach would be to use the AdminMFAGroup as principal, regrettably AWS does not allow you to use IAM Group as a principal.

To mitigate this risk, you need to be very careful when you create policies for other groups, roles and users. For example you must make sure to restrict which roles they are allowed to switch to and they should be allowed to manage groups, roles or users. This should not be a surprise to you, if you have worked with AWS before you are probably already familiar with the principle of least privilege.

Mattias Severson

Mattias is a senior software engineer specialized in backend architecture and development with experience of cloud based applications and scalable solutions. He is a clean code proponent who appreciates Agile methodologies and pragmatic Test Driven Development. Mattias has experience from many different environments, including everything between big international projects that last for years and solo, single day jobs. He is open-minded and curious about new technologies. Mattias believes in continuous improvement on a personal level as well as in the projects that he is working on. Additionally, Mattias is a frequent speaker at user groups, companies and conferences.

This Post Has 6 Comments

  1. Adrian Ng

    Hi Matthias,
    Great article and great title; 3 TLAs (three letter acronyms). Yeh, I noticed that I was able to assume roles without specifying an MFA then I stumbled across this. I can see why they’ve done it like this though, because automated systems wouldn’t be able to assume the roles if MFA was enabled. Shame that you can’t enforce MFA on the IAM user level.

    1. Mattias Severson

      @Adrian: Thank you. By following the steps in the blog post, you are actually able to enforce MFA on IAM users. For other scenarios like the M2M flow that you describe where MFA is not applicable you should create separate IAM role(s). Adhering to the Principle of Least Privilege those roles should be as restrictive as possible. I advice against using the Admin Role mentioned in the blog post in let’s say a Lambda function that just makes calls to DynamoDB, because the arn:aws:iam::aws:policy/AdministratorAccess policy configured in the admin role is far to permissive.

  2. Josh

    For me; i could only get this to work when i included the region in [profile my-profile] inside ~/.aws/config

  3. Indranil

    I tried this tutorial but I am facing weird issue where by when I add user to the AdminMFA group and the when I use Cli with profile set like “–profile my-project”. I am getting positive results

  4. cionsystems

    Thanks for sharing Multi Factor Authentication tips. for more info i rfer cion systems Multi Factor Authentication in USA.

Leave a Reply