6
votes

I'm trying to setup my AWS CLI to assume a role using MFA and expiring the creds after 15 minutes (minimum duration_seconds allowed, apparently).

My IAM role policy is:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::XXXXXXXXXXXX:user/myuser"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "Bool": {
          "aws:MultiFactorAuthPresent": "true"
        },
        "NumericLessThan": {
          "aws:MultiFactorAuthAge": "900"
        }
      }
    }
  ]
}

My CLI config is setup as follows:

[profile xxx]
role_arn = arn:aws:iam::XXXXXXXXXXXX:role/mfa
mfa_serial = arn:aws:iam::XXXXXXXXXXXX:mfa/foobar
source_profile = mfa

When I run a command using the xxx profile above, MFA is asked the first time and remains valid for all the subsequent requests. However, after 15 minutes, the token is still valid and MFA isn't asked again.

$ aws s3 ls --profile xxx

I tried setting the duration_seconds parameter on my CLI as below:

[profile xxx]
role_arn = arn:aws:iam::XXXXXXXXXXXX:role/mfa
mfa_serial = arn:aws:iam::XXXXXXXXXXXX:mfa/foobar
source_profile = mfa
duration_seconds = 900

But now, I'm asked the MFA token for every command issued, even if the time difference is in the order of seconds.

Am I missing something here?

AWS CLI version: aws-cli/2.0.49 Python/3.7.4 Darwin/19.6.0 exe/x86_64

Appreciate any help.

Thanks in advance!

2
Have you try to clear the cache ? rm -r ~/.aws/cli/cacheBen
Yes, same problem. Also, the problem seems not to be the credentials returned, since the creds stored in ~/.aws/cli/cache are valid and the expiation time is correct (15 min from now). Seems like AWS CLI is losing track of the creds and re-asking for authentication.Mauricio Klein

2 Answers

3
votes

So, I discovered the reason for this behavior:

As described in this Github Issue, AWS CLI treats any session within 15min as expired, refreshing the creds automatically (or asking for a new one-time passcode, in case of MFA).

So, setting the session duration for 15min (900s) is basically the same as getting a one-time credential.

I just tested setting the session_duration to 930 (15min + 30s), and the session is indeed valid for 30 seconds.

0
votes

Seems that the issue is with your conditions.

"Bool": {
          "aws:MultiFactorAuthPresent": "true"
        },

This will always require the MFA

instead try something like that:

{
  "Version": "2012-10-17",
   "Statement":[
    {
            "Sid": "AllowActionsForEC2",
            "Effect": "Allow",
            "Action": ["ec2:RunInstances",
               "ec2:DescribeInstances",
               "ec2:StopInstances "],
            "Resource": "*"
    },
    {
           "Sid": "AllowActionsForEC2WhenMFAIsPresent",
           "Effect":"Allow",
           "Action":"ec2:TerminateInstances",
           "Resource":"*",
           "Condition":{
             "NumericLessThan ":{"aws:MultiFactorAuthAge":"300"}
    }
   }
  ]
}

The Users with short-term credentials older than 300 seconds must reauthenticate to gain access to this API.

So for your policy it will look like this:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::XXXXXXXXXXXX:user/myuser"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "NumericLessThan": {
          "aws:MultiFactorAuthAge": "900"
        }
      }
    }
  ]
}

The issue is that every conditions needs to be met in order for you to be able to assume the role. "aws:MultiFactorAuthPresent": "true" will always check if you used the MFA to login.