enforce MFA for AWS console login, but not for API

2019-03-14 21:49发布

问题:

I am looking to enforce all IAM users(local and remote) to enable and activate their MFA devices. I want them all to enable MFA to do their respective tasks.

I am trying with the following policy

{
      "Effect": "Allow",
      "Action": "*",
      "Resource": "*",
      "Condition": {"Bool": {"aws:MultiFactorAuthPresent": "true"}}
}

However; this policy applies irrespective of how you are accessing the services, through console or through APIs

There is a lot of automation done by all users and their automation breaks as MFA authentication was not implied.

As a first step, we wish everybody to atleast enables MFA for console login; but the same should not enforce them to use MFA for API calls used in automation.

Is this achievable through IAM policy?

Thanks

回答1:

The trick is to reverse the check...rather than only allowing if aws:MultiFactorAuthPresent is true, deny if it's false.

Here's the doc on self-service MFA management: http://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_users-self-manage-mfa-and-creds.html

The full policy suggested in there is:

{
    "Version": "2012-10-17",
    "Statement":[
        {
            "Sid": "AllowAllUsersToListAccounts",
            "Effect": "Allow",
            "Action":[
                "iam:ListAccountAliases",
                "iam:ListUsers",
                "iam:GetAccountSummary"
            ],
            "Resource": "*"
        },
        {
            "Sid": "AllowIndividualUserToSeeAndManageTheirOwnAccountInformation",
            "Effect": "Allow",
            "Action":[
                "iam:ChangePassword",
                "iam:CreateAccessKey",
                "iam:CreateLoginProfile",
                "iam:DeleteAccessKey",
                "iam:DeleteLoginProfile",
                "iam:GetAccountPasswordPolicy",
                "iam:GetLoginProfile",
                "iam:ListAccessKeys",
                "iam:UpdateAccessKey",
                "iam:UpdateLoginProfile",
                "iam:ListSigningCertificates",
                "iam:DeleteSigningCertificate",
                "iam:UpdateSigningCertificate",
                "iam:UploadSigningCertificate",
                "iam:ListSSHPublicKeys",
                "iam:GetSSHPublicKey",
                "iam:DeleteSSHPublicKey",
                "iam:UpdateSSHPublicKey",
                "iam:UploadSSHPublicKey"
            ],
            "Resource": "arn:aws:iam::accountid:user/${aws:username}"
        },
        {
            "Sid": "AllowIndividualUserToListTheirOwnMFA",
            "Effect": "Allow",
            "Action":[
                "iam:ListVirtualMFADevices",
                "iam:ListMFADevices"
            ],
            "Resource":[
                "arn:aws:iam::accountid:mfa/*",
                "arn:aws:iam::accountid:user/${aws:username}"
            ]
        },
        {
            "Sid": "AllowIndividualUserToManageTheirOwnMFA",
            "Effect": "Allow",
            "Action":[
                "iam:CreateVirtualMFADevice",
                "iam:DeactivateMFADevice",
                "iam:DeleteVirtualMFADevice",
                "iam:RequestSmsMfaRegistration",
                "iam:FinalizeSmsMfaRegistration",
                "iam:EnableMFADevice",
                "iam:ResyncMFADevice"
            ],
            "Resource":[
                "arn:aws:iam::accountid:mfa/${aws:username}",
                "arn:aws:iam::accountid:user/${aws:username}"
            ]
        },
        {
            "Sid": "BlockAnyAccessOtherThanAboveUnlessSignedInWithMFA",
            "Effect": "Deny",
            "NotAction": "iam:*",
            "Resource": "*",
            "Condition":{
                "BoolIfExists":{ "aws:MultiFactorAuthPresent": "false"}
            }
        }
    ]
}

The most important part is the last statement, which does the deny. If you change it to this:

{
    "Sid": "BlockAnyAccessOtherThanAboveUnlessSignedInWithMFA",
    "Effect": "Deny",
    "NotAction": "iam:*",
    "Resource": "*",
    "Condition":{
        "Bool":{ "aws:MultiFactorAuthPresent": "false"}
    }
}

(BoolIfExists changed to Bool) it will allow IAM access keys to bypass the requirement of MFA, while still requiring you to use MFA when logging in through the AWS Console.

Be careful if you decide to use that full policy from the docs. Note that it allows a user to create access keys and change their password, and the deny clause only blocks non-IAM actions...this means that, if MFA gets disabled on an account, a user's password could be changed or new access keys could be provisioned without an MFA check, and if you've made the Bool change, those new access keys would be able to access anything that the user has permissions for, without MFA. I.E., all of the security vulnerabilities of unsecured keys, with some potential for account hijacking on top.

I would suggest using a policy similar to this instead:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowAllUsersToListAccounts",
            "Effect": "Allow",
            "Action": [
                "iam:ListAccountAliases",
                "iam:ListUsers"
            ],
            "Resource": [
                "arn:aws:iam::accountid:user/*"
            ]
        },
        {
            "Sid": "AllowIndividualUserToSeeTheirAccountInformation",
            "Effect": "Allow",
            "Action": [
                "iam:GetAccountPasswordPolicy",
                "iam:GetAccountSummary",
                "iam:GetLoginProfile"
            ],
            "Resource": [
                "arn:aws:iam::accountid:user/${aws:username}"
            ]
        },
        {
            "Sid": "AllowIndividualUserToListTheirMFA",
            "Effect": "Allow",
            "Action": [
                "iam:ListVirtualMFADevices",
                "iam:ListMFADevices"
            ],
            "Resource": [
                "arn:aws:iam::accountid:mfa/*",
                "arn:aws:iam::accountid:user/${aws:username}"
            ]
        },
        {
            "Sid": "AllowIndividualUserToManageThierMFA",
            "Effect": "Allow",
            "Action": [
                "iam:CreateVirtualMFADevice",
                "iam:DeactivateMFADevice",
                "iam:DeleteVirtualMFADevice",
                "iam:EnableMFADevice",
                "iam:ResyncMFADevice"
            ],
            "Resource": [
                "arn:aws:iam::accountid:mfa/${aws:username}",
                "arn:aws:iam::accountid:user/${aws:username}"
            ]
        },
        {
            "Sid": "DoNotAllowAnythingOtherThanAboveUnlessMFAd",
            "Effect": "Deny",
            "NotAction": "iam:*",
            "Resource": "*",
            "Condition": {
                "Bool": {
                    "aws:MultiFactorAuthPresent": "false"
                }
            }
        }
    ]
}


回答2:

Create 2 IAM users for each person:

  1. one for AWS Console sign-in which enforces MFA, and
  2. one for API usage that doesn't have a password and that does not enforce MFA


回答3:

Posting for posterity. I tried using the methods posted by Josh Hancock but the api calls from enforced console MFA accounts fail for some AWS services like elastic filesystem and some s3 api calls. When raised a support ticket, the response from AWS was that, "There is a feature request for this precise issue as there is currently no reliable mechanism to enforce MFA for the console only. I have added your account to the list of requesting accounts for this feature request. Unfortunately, I do not have a reliable workaround other than enable MFA everywhere, or only apply the IAM MFA policy to users that are console only."



回答4:

For your use case, it's sufficient to just activate an MFA device for the IAM user. This will require the user to provide an MFA code whenever they sign into the AWS Management Console, but not for AWS API calls.

Writing an IAM policy using the "MultiFactorAuthPresent" condition is only needed if you also want to enforce MFA for API calls.

Btw, posting AWS-related questions on the AWS forums (https://forums.aws.amazon.com/index.jspa) is a great way to get responses.



回答5:

I'm sure you probably found the solution to this already, but here's an official guide from the AWS Security team on setting up MFA on login for IAM users if anyone is struggling with this too:

https://blogs.aws.amazon.com/security/post/Tx2SJJYE082KBUK/How-to-Delegate-Management-of-Multi-Factor-Authentication-to-AWS-IAM-Users

Basically, this can be achieved by creating a few User Groups and doing checks on whether MFA is set or not upon login.