Force an IAM User to use MFA authentication
If you are dealing with your personal AWS account, permissions are not a big concern. That single IAM user (you!) will have all necessary permissions, probably will have AdministratorAccess
and the job is almost done. Probably, since you are a shrewd person, you have enabled the Multi Factor Authentication (MFA) so, along with username and password, you have to provide a six-digits random code.
But what if you had to manage an enterprise account with multiple IAM users? What tools do we have to force every user in the account to enable the MFA?
A real life scenario
Alice is responsible for her company’s AWS account and today she needs to create an IAM user for John Doe: her new colleague. John needs AWS Management Console access and PowerUser
privileges. In itself, the creation of IAM user is really a simple task and Alice will need few minutes to create one.
She is savvy enough, so for security sake she had already set a Password policy so, during the first login, John needs to type a new password that meets the specific criteria, like a minimum length or the presence of numbers and special characters.
Note — when you check “User must crete a new passoword at next sign-in” AWS will automatically attach
IAMUserChangePassword
policy to the user.
Going better!
The above solution surely reduce the risk of weak passwords and since she is smart, she asks John to set Multi Factor Authentication. But…
How can Alice be sure that Joe activates MFA?
How can she easily apply these rules for each new colleague?
Using policy
A first important thing to notice is related to the PowerUserAccess
and its lack of IAM related permissions. Due to this restriction, Joe can't activate MFA, even if he wants to. To solve the issue Alice needs to create a new custom policy that looks like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowListUsers",
"Effect": "Allow",
"Action": [
"iam:ListUsers"
],
"Resource": "arn:aws:iam::*:user/"
},
{
"Sid": "AllowMFAHandling",
"Effect": "Allow",
"Action": [
"iam:CreateVirtualMFADevice",
"iam:DeleteVirtualMFADevice",
"iam:EnableMFADevice",
"iam:ListMFADevices",
"iam:ListVirtualMFADevices"
],
"Resource": [
"arn:aws:iam::*:mfa/*",
"arn:aws:iam::*:user/${aws:username}"
]
},
{
"Sid": "BlockEverythingUnlessSignedInWithMFA",
"Effect": "Deny",
"NotAction": [
"iam:ChangePassword",
"iam:CreateVirtualMFADevice",
"iam:DeleteVirtualMFADevice",
"iam:EnableMFADevice",
"iam:ListMFADevices",
"iam:ListUsers",
"iam:ListVirtualMFADevices"
],
"Resource": "*",
"Condition": {
"BoolIfExists": {
"aws:MultiFactorAuthPresent": "false"
}
}
}
]
}
This policy is quite simple. The statement BlockEverythingUnlessSignedInWithMFA
deny almost every possible action if MFA is not present (this check is performed using Condition
and Not
in combo). By the way, some other actions needs to be performed when MFA is not yet active. For instance, John needs to change password as soon as he do sign-in, so Alice can't explicitly deny iam:ChangePassword
, even if MFA is not yet present. Clearly, the same is for iam:CreateVirtualMFADevice
, iam:EnableMFADevice
and so on. The property NotAction
is gold in situations like this.
The lack of an explicit deny doesn’t imply an implicit allow, so the statement AllowListUsers
and AllowMFAHandling
are necessary.
The only action that doesn’t have an explicit allow is
iam:ChangePassword
can you guess why? :)
Wrap everything up
At this point Alice can create a new IAM group (for instance PowerConsultants
) attaching both PowerUserAccess
and the policy just created. In this way as soon as a new collegue step into the office, she only needs to create a user and put him or her into that group.