AWS PowerShell with AsumeRole and MFA

0

So, I have been working on a script to assist in documentation of our environments, but I am running into some trouble with authentication. I have authentication working but MFA seems to be coming up too often.

So currently my credential file looks something like the below:

[default]
region=us-east-1
output=json

[root]
aws_access_key_id = AKIAWMOJ************
aws_secret_access_key = 4Ezy8DcZAVY11N***********************

[staging]
role_arn=arn:aws:iam::363*******614:role/MyRoleName
source_profile=root
role_session_name=Staging
mfa_serial=arn:aws:iam::439*******561:mfa/MyUserName

[production]
role_arn=arn:aws:iam::658*******771:role/MyRoleName
source_profile=root
role_session_name=Production
mfa_serial=arn:aws:iam::439*******561:mfa/MyUserName

When I run something like "Get-S3Bucket -Profile production", I am prompted for my MFA. Again, if I run "Get-S3Bucket -Profile staging" I am again prompted for my MFA. We have many accounts, why, if my MFA is based on the root account, am I forced to MFA again for each of the accounts?

Would this not make more sense?

[root]
aws_access_key_id = AKIAWMOJ************
aws_secret_access_key = 4Ezy8DcZAVY11N***********************
mfa_serial=arn:aws:iam::439*******561:mfa/MyUserName

Then I would MFA for my initial authentication and be done with it until it expires. Am I missing a step? Do I have my setup incorrect? The process for authentication within PowerShell seems overly complicated and troublesome trying to run large scale scripts on a multi-account setup.

Any help would be appreciated.

2 Answers
0

You can't use the mfa_serial parameter with permanent IAM credentials.

If you use profiles to authenticate commands using the AWS CLI, specify the --profile option followed by the profile name. This is done to verify that the calls authenticate using MFA.

Run the sts get-session-token AWS CLI command, replacing the variables with information from your account, resources, and MFA device:

$ aws sts get-session-token --serial-number arn-of-the-mfa-device --token-code code-from- token

You receive an output with temporary credentials and an expiration time (by default, 12 hours) similar to the following:

{ "Credentials": { "SecretAccessKey": "secret-access-key", "SessionToken": "temporary-session-token", "Expiration": "expiration-date-time", "AccessKeyId": "access-key-id" } }

You can specify an expiration duration (in seconds) using the --duration-seconds option in the sts get-session-token command. The value can range from 900 seconds (15 minutes) to 129600 seconds (36 hours). If you are using root user credentials, then the range is from 900 seconds (15 minutes) to 3600 seconds (1 hour).

Using temporary credentials with named profiles You can also use named profiles to specify the commands that require MFA authentication. To do so, edit the credentials file in the .aws folder in the home directory of the user. In the credentials file, add a new profile configuration for issuing MFA-authenticated commands. Here's an example profile configuration:

[mfa] aws_access_key_id = example-access-key-as-in-returned-output aws_secret_access_key = example-secret-access-key-as-in-returned-output aws_session_token = example-session-Token-as-in-returned-output

After the credentials expire, run the get-session-token command again, and then export the returned values to the environment variables or to the profile configuration.

profile pictureAWS
answered 9 months ago
  • OK, but that is still not really addressing the issue that I can see.

    Lets say I have 3 accounts.

    1. Root Account - Only has users accounts with MFA and roles setup which assume on separate accounts.
    2. Staging Account - This has a role on it which my root account has permissions to assume.
    3. Production Account - Same as staging.

    If I use:

    aws sts get-session-token --serial-number arn-of-the-mfa-device --token-code code-from- token
    

    This gives me an access key, secret key, and session token. How do I use this to assume the role on any of the other accounts?

    I am tired of trying to decipher if it is a aws cli profile, it is a just PowerShell profile. I have account configuration data in a shared configuration file and in a net sdk configuration file, they don't communicate with each other and I never know what it is trying to authenticate with or how. Every answer I get is a small part of the answer with lots of non-essential information in it like adding an expiration time. If you had the configuration I am speaking about with 3 separate AWS account, one main account in the root with MFA and a role to assume to the other accounts how would you set it up as a whole?

0

What you would have to do is not to use profiles and to assume the role in each account. You could script this. I have a similar script that I run when using CLI and MFA.

This should work for you. Its designed for linux but you could use and make it into a script you pass parameters into it so that you can have switch which assumes the role in a different account.

When you run the script, you pass environment name in with a swich..i.e.

-t = MFA TOKEN NUMBER -e = ENVIRONMENT NAME

log-into-aws.sh -t 123456 -e production

After it assumes the role in the account you do not need to specify a profile. You are logged into the account in question. If you want to switch accounts, you just run the script again.

log-into-aws.sh

#!/bin/bash
# User configurable variables. Fill in these 2 lines
export AWS_ACCESS_KEY_ID="XXXXXXXXXXXXX"
export AWS_SECRET_ACCESS_KEY="XXXXXXXXXXXXXXXXXXXXXXXXXX"
mymfatokenarn=arn:aws:iam::111111111111:mfa/iphone
# Only change these ^^

export AWS_SESSION_TOKEN=""
export AWS_DEFAULT_REGION="eu-west-2"

token=
while getopts t:e: flag
do
    case "${flag}" in
        t) token=${OPTARG};;
        e) env=${OPTARG};;
    esac
done

if [[ $(expr length "$token") != 6 ]]
then
        echo 'Please supply token code'
        read token
fi

sts=$(aws sts get-session-token  --serial-number $mymfatokenarn --token-code $token)
var=( $(echo $sts | jq '.[] | .AccessKeyId, .SecretAccessKey, .SessionToken') )
export AWS_ACCESS_KEY_ID=$(echo ${var[0]} | tr -d '"')
export AWS_SECRET_ACCESS_KEY=$(echo ${var[1]} | tr -d '"')
export AWS_SESSION_TOKEN=$(echo ${var[2]} | tr -d '"')

# Set up all your accounts/environments below
if [[ $env == "staging" ]]
then
    #Assume the org role in staging.
    assumedrole=$(aws sts assume-role --role-arn arn:aws:iam::222222222222:role/OrganizationAccountAccessRole --role-session-name staging)
    var=( $(echo $assumedrole | jq '.[] | .AccessKeyId, .SecretAccessKey, .SessionToken') )
    export AWS_ACCESS_KEY_ID=$(echo ${var[0]} | tr -d '"')
    export AWS_SECRET_ACCESS_KEY=$(echo ${var[1]} | tr -d '"')
    export AWS_SESSION_TOKEN=$(echo ${var[2]} | tr -d '"')

elif [[ $env == "production" ]]
    #Assume the org role in production.
    assumedrole=$(aws sts assume-role --role-arn arn:aws:iam::33333333333:role/OrganizationAccountAccessRole --role-session-name production)
    var=( $(echo $assumedrole | jq '.[] | .AccessKeyId, .SecretAccessKey, .SessionToken') )
    export AWS_ACCESS_KEY_ID=$(echo ${var[0]} | tr -d '"')
    export AWS_SECRET_ACCESS_KEY=$(echo ${var[1]} | tr -d '"')
    export AWS_SESSION_TOKEN=$(echo ${var[2]} | tr -d '"')
fi
profile picture
EXPERT
answered 9 months ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions