For security, all users with AWS access console should enable MFA. To ensure this we can use aws:MultiFactorAuthPresent
to force that, but we need to understand that key correctly
Whatβs In This Document
- Understand Some Items
- Force Enabling MFA
- MFA Test Access Console
- MFA Test AWS API/CLI
- Create Temporary Credential With MFA
π Understand Some Items
Ref: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html
1. aws:MultiFactorAuthPresent Works with Boolean operators.
- Use this key to check whether multi-factor authentication (MFA) was used to validate the temporary security credentials that made the request.
- Availability β This key is included in the request context only when the principal uses temporary credentials to make the request. The key is not present in AWS CLI, AWS API, or AWS SDK requests that are made using long-term credentials.
2. Temporary credentials Are used to authenticate IAM roles, federated users, IAM users with temporary tokens from sts:GetSessionToken, and users of the AWS Management Console. IAM user access keys are long-term credentials, but in some cases, AWS creates temporary credentials on behalf of IAM users to perform operations. There are two common cases:
- IAM users in the AWS Management Console unknowingly use temporary credentials. Users sign into the console using their user name and password, which are long-term credentials. However, in the background, the console generates temporary credentials on behalf of the user.
- If an IAM user makes a call to an AWS service, the service re-uses the user's credentials to make another request to a different service. For example, when calling Athena to access an Amazon S3 bucket, or when using AWS CloudFormation to create an Amazon EC2 instance. For the subsequent request, AWS uses temporary credentials.
π Force Enabling MFA
There are two ways of combination in IAM policy to do this task for considering
1. Require MFA only for AWS access console which generates temporary credential in background and all AWS API/ CLI which using temporary credential for their subsequent requests
"Effect" : "Deny",
"Condition" : { "Bool" : { "aws:MultiFactorAuthPresent" : "false" } }
2. Require MFA for AWS access console either all AWS API/CLI.
"Effect" : "Deny",
"Condition" : { "BoolIfExists" : { "aws:MultiFactorAuthPresent" : "false" } }
- Due to the key
MultiFactorAuthPresent
is not included in long-term credential so the above condition receive valueNull
for the check of key existence and then applyDeny
effect.
3. Create IAM group which attach MFA policy and then assign to all IAM users
{
"Version": "2012-10-17",
"Statement": [
{
"Condition": {
"BoolIfExists": {
"aws:MultiFactorAuthPresent": "false"
}
},
"Resource": "*",
"NotAction": [
"iam:CreateVirtualMFADevice",
"iam:DeleteVirtualMFADevice",
"iam:ListVirtualMFADevices",
"iam:EnableMFADevice",
"iam:ResyncMFADevice",
"iam:ListAccountAliases",
"iam:ListUsers",
"iam:ListSSHPublicKeys",
"iam:ListAccessKeys",
"iam:ListServiceSpecificCredentials",
"iam:ListMFADevices",
"iam:GetAccountSummary",
"sts:GetSessionToken",
"kms:*",
"codecommit:*"
],
"Effect": "Deny",
"Sid": "DenyAllExceptListedIfNoMFA"
}
]
}
- Only the last items should be considered. Here it require MFA only for temporary credential (of course include AWS access console)
π MFA Test Access Console
1. Create IAM group FroceMFA with attach MFA present policy
With this policy, all AWS services are denied except the listed actions so users can enable MFA themselves
"NotAction": [
"iam:CreateVirtualMFADevice",
"iam:EnableMFADevice",
"iam:GetUser",
"iam:ListMFADevices",
"iam:ListVirtualMFADevices",
"iam:ResyncMFADevice",
"sts:GetSessionToken"
],
3. User have no permission except enable MFA if not enable yet
4. After enable MFA, signout and then login again
π MFA Test AWS API/CLI
1. Test AWS CLI
β‘ $ aws s3 ls --profile jack-test | wc -l
141
2. Test AWS API
β‘ $ aws elbv2 describe-target-groups --region ap-northeast-1 --profile jack-test | grep TargetGroupArn | wc -l
35
3. Test API with subsequent request
I use cdk to create stacks with subsequent requests to cloudformation
β‘ $ cdk deploy Route53dev1Stack --profile jack-test
4:27:32 PM | UPDATE_ROLLBACK_IN_P | AWS::CloudFormation::Stack | Env-dev-alb
AccessDenied. User doesn't have permission to call elasticloadbalancingv2:DescribeLoadBalancers
β Env-dev-alb failed: Error: The stack named Env-dev-alb failed to deploy: UPDATE_ROLLBACK_COMPLETE
π Create Temporary Credential With MFA
To overcome this, we create temporary credential with MFA
Ref: https://aws.amazon.com/premiumsupport/knowledge-center/authenticate-mfa-cli/
1. Create temporary credential
β‘ $ aws sts get-session-token --serial-number arn:aws:iam::123456789012:mfa/jack-test --token-code 892857 --profile jack-test
{
"Credentials": {
"AccessKeyId": "example-access-key-as-in-previous-output",
"SecretAccessKey": "example-secret-access-key-as-in-previous-output",
"SessionToken": "example-session-token-as-in-previous-output",
"Expiration": "2021-03-06T21:32:52Z"
}
}
2. Create Environment file
β‘ $ cat temp_env
export AWS_ACCESS_KEY_ID=example-access-key-as-in-previous-output
export AWS_SECRET_ACCESS_KEY=example-secret-access-key-as-in-previous-output
export AWS_SESSION_TOKEN=example-session-token-as-in-previous-output
3. Source temp_env and then run cdk again **without profile to use AWS Acess Key from env**
β‘ $ source temp_env
β‘ $ cdk deploy Route53dev1Stack
β
Env-dev-alb
Route53devStack: deploying...
Route53devStack: creating CloudFormation changeset...
[ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ] (3/3)
β
Route53devStack
Top comments (2)
Short-lived protected credentials are essential to protect a well-architected AWS environment.
Your use case works perfectly in Leapp, where you can set up MFA users, and automatically the credentials are rotated by the open-source App
github.com/Noovolari/leapp
Thanks for your sharing!