Skip to content

Instantly share code, notes, and snippets.

@ashishjullia
Forked from geekgunda/aws-mfa-access.sh
Last active September 21, 2024 09:01
Show Gist options
  • Save ashishjullia/c188cdf6107d0b348e9baa8f01ca6919 to your computer and use it in GitHub Desktop.
Save ashishjullia/c188cdf6107d0b348e9baa8f01ca6919 to your computer and use it in GitHub Desktop.
aws-cli MFA access via assume role
#!/bin/bash
if [ "$1" == "" ]; then
echo "Usage: $(basename "$0") <MFA-TOKEN>"
exit 1
fi
session_duration=129600 # 36 hours
mfa_device_code=$(aws iam list-mfa-devices | jq -r .MFADevices[0].SerialNumber)
if [ -z "$mfa_device_code" ]; then
echo "Failed to retrieve MFA device code. Make sure you have configured your AWS CLI correctly."
exit 1
fi
mfa_code=$1
tmp_creds_file="$HOME/.aws/tempcreds"
aws_creds_file="$HOME/.aws/credentials"
orig_creds_file="$HOME/.aws/origcreds"
if [ ! -f "$orig_creds_file" ]; then
echo "Original credentials file not found at $orig_creds_file"
echo "Backing up current credentials to $orig_creds_file"
cp $aws_creds_file $orig_creds_file
fi
cp $orig_creds_file $aws_creds_file
cmd="aws sts get-session-token --duration-seconds ${session_duration} --serial-number ${mfa_device_code} --token-code ${mfa_code}"
echo "$cmd"
$cmd > ${tmp_creds_file}
new_creds=$(cat ${tmp_creds_file})
if [ -z "$new_creds" ]; then
echo "Request failed"
exit 1
fi
access_key_id=$(echo ${new_creds} | jq -r ".Credentials.AccessKeyId")
secret_access_key=$(echo ${new_creds} | jq -r ".Credentials.SecretAccessKey")
session_token=$(echo ${new_creds} | jq -r ".Credentials.SessionToken")
expiry=$(echo ${new_creds} | jq -r ".Credentials.Expiration")
printf "[default]\naws_access_key_id = ${access_key_id}\naws_secret_access_key = ${secret_access_key}\naws_session_token = ${session_token}" > ${aws_creds_file}
# Export the new environment variables
export AWS_ACCESS_KEY_ID=${access_key_id}
export AWS_SECRET_ACCESS_KEY=${secret_access_key}
export AWS_SESSION_TOKEN=${session_token}
echo "All set. Expiry at: $(date -d ${expiry})"
echo "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}"
echo "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}"
echo "AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN}"
echo "Contents of ${aws_creds_file}:"
cat ${aws_creds_file}
@ashishjullia
Copy link
Author

chmod +x aws-mfa-access.sh

source ./aws-mfa-access.sh <mfa_token_code_from_app>

@KrisCowie
Copy link

KrisCowie commented Sep 21, 2024

Here's what I came up with for Windows powershell:

param (
    [string]$mfa_token_code
)

if (-not $mfa_token_code) {
    Write-Host "Usage: .\aws-mfa-access.ps1 <MFA-TOKEN>"
    exit 1
}

$session_duration = 129600 # 36 hours
$mfa_device_code = # your MFA device ARN here

if (-not $mfa_device_code) {
    Write-Host "Failed to retrieve MFA device code. Make sure you have configured your AWS CLI correctly."
    exit 1
}


if ($env:AWS_ACCESS_KEY_ID -and $env:AWS_SECRET_ACCESS_KEY -and $env:AWS_SESSION_TOKEN) {
    Write-Host "Clearing current AWS session credentials..."
    Remove-Item Env:AWS_ACCESS_KEY_ID
    Remove-Item Env:AWS_SECRET_ACCESS_KEY
    Remove-Item Env:AWS_SESSION_TOKEN
}

$tmp_creds_file = "$HOME\.aws\tempcreds"
$aws_creds_file = "$HOME\.aws\credentials"
$orig_creds_file = "$HOME\.aws\origcreds"

# Backup original credentials and preserve MFA serial
if (-not (Test-Path $orig_creds_file)) {
    Write-Host "Original credentials file not found at $orig_creds_file"
    Write-Host "Backing up current credentials to $orig_creds_file"
    Copy-Item $aws_creds_file $orig_creds_file
}

# Read and preserve the original MFA serial from the original credentials file
$mfa_serial = ""
if (Test-Path $orig_creds_file) {
    $orig_creds_content = Get-Content $orig_creds_file
    foreach ($line in $orig_creds_content) {
        if ($line -like "*mfa_serial*") {
            $mfa_serial = $line.Trim()  # Keep the format intact
        }
    }
}

# Overwrite credentials with original credentials
Copy-Item $orig_creds_file $aws_creds_file

$cmd = "aws sts get-session-token --duration-seconds $session_duration --serial-number $mfa_device_code --token-code $mfa_token_code"
Write-Host "Executing: $cmd"
$session_data = Invoke-Expression $cmd

if (-not $session_data) {
    Write-Host "Request failed."
    exit 1
}

$new_creds = $session_data | ConvertFrom-Json
$access_key_id = $new_creds.Credentials.AccessKeyId
$secret_access_key = $new_creds.Credentials.SecretAccessKey
$session_token = $new_creds.Credentials.SessionToken
$expiry = $new_creds.Credentials.Expiration

# Write new credentials to the file, preserving the MFA serial
$creds_content = @"
[default]
aws_access_key_id = $access_key_id
aws_secret_access_key = $secret_access_key
aws_session_token = $session_token
"@

# If MFA serial was found, add it back to the credentials file
if ($mfa_serial -ne "") {
    $creds_content += "`n$mfa_serial"
}

Set-Content $aws_creds_file $creds_content

# Export the new environment variables
$env:AWS_ACCESS_KEY_ID = $access_key_id
$env:AWS_SECRET_ACCESS_KEY = $secret_access_key
$env:AWS_SESSION_TOKEN = $session_token

Write-Host "All set. Expiry at: $(Get-Date $expiry)"
Write-Host "AWS_ACCESS_KEY_ID=$($env:AWS_ACCESS_KEY_ID)"
Write-Host "AWS_SECRET_ACCESS_KEY=$($env:AWS_SECRET_ACCESS_KEY)"
Write-Host "AWS_SESSION_TOKEN=$($env:AWS_SESSION_TOKEN)"
Write-Host "Contents of ${aws_creds_file}:"
Get-Content "${aws_creds_file}"

This allows a user to run it whenever they want - it will overwrite the existing temporary access codes if they exist, and generate new ones if they don't.
Also allows mfa codes with 0's at the front

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment