Skip to content

Instantly share code, notes, and snippets.

@mounirmesselmeni
Last active February 20, 2025 20:35
Show Gist options
  • Select an option

  • Save mounirmesselmeni/09ede1d1ee47b92dcfed6b32002e4c9a to your computer and use it in GitHub Desktop.

Select an option

Save mounirmesselmeni/09ede1d1ee47b92dcfed6b32002e4c9a to your computer and use it in GitHub Desktop.
AWS MFA Credential Updater
import configparser
import datetime
import json
import os
import subprocess
from pathlib import Path
import zoneinfo
# Define AWS credentials file path
credentials_file = Path.home() / ".aws/credentials"
print("πŸ” Checking AWS credentials file...")
# Read and update the credentials file
config = configparser.ConfigParser()
config.read(credentials_file)
if "backup" in config:
print("♻️ Restoring backup credentials...")
config["default"] = config["backup"]
with open(credentials_file, "w") as file:
config.write(file)
print("βœ… Backup restored.")
# Get ARN from environment variable
mfa_arn = os.getenv("AWS_MFA_ARN")
if not mfa_arn:
print("❌ Error: AWS_MFA_ARN environment variable is missing.")
exit(1)
# Get MFA token code from user input
token_code = input("πŸ”‘ Enter MFA token code: ")
print("⏳ Requesting temporary credentials from AWS...")
# Get session token using AWS CLI
try:
result = subprocess.run(
[
"aws",
"sts",
"get-session-token",
"--serial-number",
mfa_arn,
"--token-code",
token_code,
"--duration-seconds",
"43200",
],
capture_output=True,
text=True,
check=True,
)
output = result.stdout
except subprocess.CalledProcessError as e:
print(f"❌ Failed to retrieve AWS session token:\n{e.stderr}")
exit(1)
# Extract credentials from JSON output
try:
credentials = json.loads(output)["Credentials"]
session_token = credentials["SessionToken"]
access_key_id = credentials["AccessKeyId"]
secret_access_key = credentials["SecretAccessKey"]
expiration_utc = credentials[
"Expiration"
] # Expiration timestamp with timezone offset
except (json.JSONDecodeError, KeyError):
print("❌ Error: Failed to parse AWS CLI output.")
exit(1)
# Convert expiration time to user's local time
expiration_time_utc = datetime.datetime.fromisoformat(
expiration_utc
) # Handles both Z and +00:00 formats
local_timezone = zoneinfo.ZoneInfo(
datetime.datetime.now().astimezone().tzname()
) # Get local timezone
expiration_time_local = expiration_time_utc.astimezone(local_timezone)
# Backup the existing profile
if "default" in config:
print("πŸ“‚ Backing up existing AWS credentials...")
config["backup"] = config["default"]
# Update the credentials file
config["default"] = {
"aws_access_key_id": access_key_id,
"aws_secret_access_key": secret_access_key,
"aws_session_token": session_token,
}
with open(credentials_file, "w") as file:
config.write(file)
print("πŸŽ‰ AWS session token updated successfully!")
print(
f"πŸ” New credentials are valid until: **{expiration_time_local.strftime('%Y-%m-%d %H:%M:%S %Z')}**"
)
@mounirmesselmeni
Copy link
Author

How to run it:
AWS_MFA_ARN=arn:aws:iam::xxxxxx:mfa/xxxxx python3 aws_token.py
Where AWS_MFA_ARN is the ARN for your MFA which you can get from AWS Console, this could be set as env var in your .bashrc or .zschrc to avoid defining it every time.

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