I'd like to require the usage of MFA to IAM users when they log into the AWS Console. I know that's possible to do that for API access, but not sure whether is possible to achieve the same when logging into the Console.
To configure MFA device enforcement for your users Open the IAM Identity Center console . In the left navigation pane, choose Settings. On the Settings page, choose the Network & security tab, and then choose Configure.
To the right of the table of users, click the “Enable” option that appears. On the confirmation screen, click “Enable Multi-Factor Authentication.” This will enable MFA for the user, and the next time they login to Office 365 on the web, they'll have to go through a process of setting up MFA.
Enable the MFA device. IAM users with virtual or hardware MFA devices: Enable from the AWS Management Console, AWS CLI, or the IAM API. IAM users with FIDO security keys: Enable from the AWS Management Console only. AWS account root users with any type of MFA device: Enable from the AWS Management Console only.
You can enforce your requirement with an IAM Policy based on an IAM condition that specifies the aws:MultiFactorAuthAge key as outlined in section IAM Policies with MFA Conditions within Configuring MFA-Protected API Access - you can enforce this at two levels:
- Existence — To simply verify that the user has been authenticated with MFA, check that the aws:MultiFactorAuthAge key is not null. (If the user has not been authenticated with MFA, this key doesn't exist and therefore is null.)
- Duration — If you want to grant access only within a specified time after MFA authentication, use a numeric condition type to compare the key's age to a value (such as 3600 seconds).
Accordingly, a generic IAM policy for all AWS actions that simply tests for the existence of MFA authentication might look as follows:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*",
"Condition":
{
"Null":{"aws:MultiFactorAuthAge":"false"}
}
}
]
}
This is a case of 'it just works', i.e. there's nothing to be done regarding MFA-Protected Access for the AWS Management Console specifically, insofar the console uses the API in turn and calls every API action with the logged in user's IAM credentials accordingly (once a user has configured and enabled an MFA device, the login page will require entering the MFA token automatically) - see also section Using MFA-Protected APIs Through the Console within Configuring MFA-Protected API Access:
AWS evaluates MFA-protected API policies for actions in the console, such as terminating an Amazon EC2 instance. Set up the IAM user with an MFA device and enable an MFA-protected API policy. The user can then simply log into the console with MFA authentication and is subject to the policies for MFA-protected APIs. For users who already have an assigned MFA device, the console experience doesn't change (except for optional time limits on certain MFA-protected APIs that require more frequent re-authentication). For more information on setting up an IAM user with an MFA device, see Setting Up an MFA Device.
The IAM policy listed here will do the following:
It is best to create this as an IAM policy, and then attach it to the user groups that have console users. You can also attach the policy to a user directly, but that's harder to manage.
Note that adding an MFA device to your account is insufficient to be able to access AWS resources; you need to have logged in with that MFA device for it to work. Thus, to get set up with MFA, you need to do the following steps:
The IAM policy is the following:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iam:ChangePassword",
"iam:CreateVirtualMFADevice",
"iam:EnableMFADevice",
"iam:ResyncMFADevice",
"iam:DeleteVirtualMFADevice",
"iam:DeactivateMFADevice",
"iam:ListMFADevices",
"iam:ListVirtualMFADevices",
"iam:ListAccessKeys",
"iam:GetAccessKeyLastUsed",
"iam:GetUser"
],
"Resource": [
"arn:aws:iam::*:mfa/${aws:username}",
"arn:aws:iam::*:user/${aws:username}"
]
},
{
"Sid": "BlockMostAccessUnlessSignedInWithMFA",
"Effect": "Deny",
"NotAction": [
"iam:CreateVirtualMFADevice",
"iam:ListVirtualMFADevices",
"iam:EnableMFADevice",
"iam:ResyncMFADevice",
"iam:DeleteVirtualMFADevice",
"iam:DeactivateMFADevice",
"iam:ListAccountAliases",
"iam:ListUsers",
"iam:ListSSHPublicKeys",
"iam:ListAccessKeys",
"iam:GetAccessKeyLastUsed",
"iam:ListServiceSpecificCredentials",
"iam:ListMFADevices",
"iam:GetAccountSummary",
"iam:ChangePassword",
"iam:GetUser",
"sts:GetSessionToken"
],
"Resource": "*",
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "false"
}
}
}
]
}
Note that while this allows use of most of the AWS API without needing MFA, some API calls won't work. In particular, any calls that use temporary AWS authentication credentials will fail. For example:
In order to do these things, you need to get MFA API credentials (see below). The other option (especially good for ECR login) is to create a less privileged user in a group that doesn't have the MFA Required policy to use for making the API calls in question.
For enhanced security, you can require MFA access for both the web console and the API. To do this, change the condition
in the above policy to be the following:
"Condition": {
"BoolIfExists": {
"aws:MultiFactorAuthPresent": "false"
}
}
The reason that this works is that API calls with permanent credentials don't pass the MultiFactorAuthPresent key at all, whereas console requests always do. Changing this condition from Bool
to BoolIfExists
changes the condition to resolve to true if the MultiFactorAuthPresent key does not exist, which in turn blocks the requests.
To use the API with MFA, you need to use the sts get-session-token
command. For example, with the AWS CLI:
# Get the serial number of your MFA device
aws --profile <PROFILE_NAME> iam list-mfa-devices --user-name <IAM_USER_NAME>
# Get temporary API keys that will pass MFA verification
aws --profile <PROFILE_NAME> sts get-session-token --serial-number <MFA_SERIAL_NUMBER> --token-code <MFA_TOKEN>
# Export the temporary credentials for use in subsequent calls
export AWS_ACCESS_KEY_ID=<KEY>
export AWS_SECRET_ACCESS_KEY=<SECRET>
export AWS_SESSION_TOKEN=<SESSION_TOKEN>
If you prefer a script that manages the credential acquisition process, use the command-line tool iam-mfa
: https://github.com/zagaran/iam-mfa. (Disclaimer: I am the primary author of this tool.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With