Skip to main content

AWS Credentials Manager - Pull temporary credentials for an IAM user with optional SSH-key encryption

Project description

iam-sorry

PyPI Downloads License Python Version Build Status

A powerful Python CLI utility for managing temporary AWS credentials with optional SSH-key based encryption. Generate temporary IAM credentials, protect manager profiles with AES-256 encryption, and inject credentials into batch operations.

Key Features:

  • ✅ Generate temporary AWS credentials (max 36 hours)
  • ✅ SSH-key based AES-256 encryption for powerful profiles
  • ✅ Automatic encryption validation (ED25519, password-protected)
  • ✅ Batch operation support with environment injection
  • ✅ Lazy decryption: credentials stay encrypted on disk
  • ✅ Support for permanent and temporary profiles

Quick Start

Prerequisites

# Python 3.6+
python3 --version

# AWS credentials for a manager IAM user (temporary profile)
# A password-protected ED25519 SSH key (~/.ssh/id_ed25519)

# Install dependencies
pip install boto3 botocore cryptography

Basic Usage

# 1. Store your manager profile (one-time)
# Edit ~/.aws/credentials with your manager IAM credentials:
[usermanager]
aws_access_key_id = AKIA...
aws_secret_access_key = ...

# 2. Encrypt the manager profile (one-time)
iam-sorry --profile usermanager --encrypt
# ✓ Manager profile 'usermanager' encrypted with SSH key

# 3. Generate temporary credentials
iam-sorry --profile usermanager admin
# ✓ Successfully updated profile 'admin'
# ✓ Credentials expire at: 2025-10-26T12:00:00

# 4. Run batch operations
eval $(iam-sorry --eval usermanager)

for user in user1 user2 user3; do
  aws iam create-user --user-name $user
done

# 5. Cleanup
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN

Vision & Architecture

Use Case Coverage

This tool is pragmatically designed to handle three distinct credential management scenarios:

  1. Broad Temporary Access (most common)

    • Short-lived credentials for batch operations
    • Limited to specific duration (1-36 hours)
    • Auto-expiration provides security boundary
    • Ideal for: HPC jobs, data processing, CI/CD pipelines
  2. Narrow Permanent Access (low-risk services)

    • Long-lived credentials for specific services
    • Limited permissions per service role
    • Examples: bedrock, analytics, logging services
    • Ideal for: Service-to-service authentication
  3. Powerful IAM Access (critical, encrypted)

    • Full IAM management capabilities
    • High privilege, sensitive credentials
    • Protected with SSH-key encryption
    • Ideal for: Infrastructure automation, user provisioning

Current Implementation: SSH-Key Based (Pragmatic)

This interim solution leverages existing security infrastructure already in place at most organizations:

Why SSH Keys?

  • Most HPC users, AI researchers, and developers already have password-protected SSH keys
  • SSH keys commonly used for GitHub, GitLab, and other critical services
  • SSH-agent caching eliminates repeated passphrase entry
  • No additional credential management required
  • Works in headless environments (HPC nodes, servers) without browser interaction

Pragmatic Benefits:

  • Zero additional setup for users with existing SSH infrastructure
  • Leverages familiar SSH passphrase protection
  • Compatible with existing ssh-agent workflows
  • No new password requirements
  • Works offline and in air-gapped environments

Future Vision: Department-Level Service (Long-Term)

The longer-term architectural vision is a centralized, auditable system:

┌─────────────────────────────────────────────────────────────┐
│                                                             │
│  User Authentication                                       │
│  ├─ Active Directory / LDAP                               │
│  ├─ SAML / OAuth                                          │
│  └─ Browser-based SSO                                     │
│         ↓                                                  │
│  Department IAM Service                                    │
│  ├─ Service runs with high-privilege IAM role             │
│  ├─ Receives delegated requests from users                │
│  ├─ All actions logged with user identity                 │
│  ├─ Audit trail for compliance                            │
│  └─ Permission model based on user group                  │
│         ↓                                                  │
│  AWS IAM Actions                                           │
│  ├─ create-user, delete-user                              │
│  ├─ attach-policy, detach-policy                          │
│  ├─ create-access-key, rotate-key                         │
│  └─ All traceable to user who initiated action            │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Benefits:
  ✓ Single point of IAM access (easier to audit)
  ✓ All actions logged with user identity
  ✓ Centralized permission model
  ✓ No credential distribution needed
  ✓ Reduces credential loss risk
  ✓ Prevents unauthorized IAM abuse
  ✓ Department-wide credential management

Why This is Better for Production:

  • Single high-privilege credential (service identity) instead of many
  • All IAM actions attributed to specific users
  • Centralized audit trail for compliance
  • Fine-grained permission delegation
  • Browser-based authentication (AD/SAML)
  • No credentials stored on individual machines

Current vs. Future Tradeoffs

Aspect Current (SSH-Key) Future (Service)
Setup Per-user (self-service) Per-department (IT-managed)
Auth SSH passphrase Active Directory / SSO
Credentials Distributed (each user) Centralized (service only)
Audit Trail Limited (per-machine logs) Complete (all via service)
Offline Access ✓ Yes ✗ No (requires network)
Headless Systems ✓ Excellent ✗ Needs browser
Security Model Good (encrypted at-rest) Excellent (centralized)
Compliance Medium (per-machine audit) High (centralized logging)

Why SSH-Key Approach Now?

The interim SSH-key solution is chosen because:

  1. Existing Infrastructure: Most users already have password-protected SSH keys
  2. Headless Compatibility: Works on HPC nodes, servers without browser
  3. No Additional Setup: Leverages existing ssh-agent workflows
  4. Quick Deployment: Can be deployed immediately to self-sufficient users
  5. Low Friction: Minimal learning curve for technical users
  6. Offline Capable: Works in air-gapped environments

This allows departments to:

  • Protect credentials immediately
  • Give users self-service temporary credential generation
  • Maintain audit logs at system level
  • Plan for centralized service later without user disruption

Target Users

This Tool is Best For:

  • Self-sufficient technical users (DevOps, HPC, AI researchers)
  • Organizations with existing SSH key infrastructure
  • Teams using headless systems (no browser)
  • Users needing on-demand temporary credentials
  • Environments without centralized SSO/AD integration

This Tool is NOT For:

  • Organizations with strong centralized IT governance
  • Non-technical end users
  • Systems requiring browser-based authentication
  • Highly regulated environments (use service approach)

Installation

1. Download

pip install iam-sorry

Or from source:

git clone https://github.com/dirkpetersen/iam-sorry
cd iam-sorry
pip install -e .

2. Prepare SSH Key

Your ED25519 SSH key must be password-protected:

# Check if your key is protected
ssh-keygen -l -f ~/.ssh/id_ed25519

# Add passphrase if not protected
ssh-keygen -p -f ~/.ssh/id_ed25519

3. Setup Manager Profile

Add your IAM manager credentials to ~/.aws/credentials:

[usermanager]
aws_access_key_id = AKIA...
aws_secret_access_key = ...

Usage Guide

Encrypt Manager Profile

# One-time: Encrypt your powerful manager credentials
iam-sorry --profile usermanager --encrypt

# Verify encryption
iam-sorry --show-encrypted usermanager

Result:

[usermanager]
aws_access_key_id = __encrypted__:pdZLbbMlei28ZA0vhsT6gesOG6BLB...
aws_secret_access_key = __encrypted__:1vYfR8x2kjhsRR0vhsT6gesOG6B...

Generate Temporary Credentials

# Generate temporary credentials for a specific IAM user
iam-sorry --profile usermanager admin

# Specify duration (1-36 hours, default: 36)
iam-sorry --profile usermanager --duration 12 admin

# Using environment variable instead of --profile
AWS_PROFILE=usermanager iam-sorry admin

Output:

✓ Successfully updated profile 'admin'
✓ IAM user: admin
✓ Credentials expire at: 2025-10-26T12:00:00

Batch Operations with Encryption

# Inject encrypted manager credentials into environment
eval $(iam-sorry --eval usermanager)

# Now run batch IAM operations
for user in user1 user2 user3; do
  aws iam create-user --user-name $user
  aws iam attach-user-policy --user-name $user \
    --policy-arn arn:aws:iam::aws:policy/ReadOnlyAccess
done

# Cleanup
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN

Batch Operations with Permanent Credentials

# For low-risk permanent credentials (bedrock service)
eval $(./aws-creds --eval bedrock)

# Run bulk operations
aws bedrock list-foundation-models
aws bedrock create-evaluation-job --config file://config.json

# Cleanup
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN

View Credentials

# View encrypted credentials (ciphertext, no decryption)
./aws-creds --show-encrypted usermanager

# View decrypted credentials (requires SSH passphrase)
./aws-creds --show-decrypted usermanager

# View plaintext credentials (for unencrypted profiles)
./aws-creds --show-decrypted bedrock

Command Reference

Global Flags

--profile PROFILE           Manager profile (defaults to AWS_PROFILE env var)
--duration HOURS            Credential duration: 1-36 hours (default: 36)

Main Commands

# Generate temporary credentials
./aws-creds --profile usermanager admin
./aws-creds --profile usermanager --duration 12 admin

# Encrypt manager profile (one-time)
./aws-creds --profile usermanager --encrypt

# Show encrypted credentials
./aws-creds --show-encrypted usermanager

# Show decrypted credentials
./aws-creds --show-decrypted usermanager

# Output environment export statements
./aws-creds --eval usermanager

# Refresh default profile (prompts for confirmation)
AWS_PROFILE=usermanager ./aws-creds

Security Architecture

Credential Types

Profile Type Encryption Risk Usage
usermanager Permanent ✓ Encrypted HIGH Manager only
bedrock Permanent ✗ Plaintext LOW Direct service
admin Temporary ✗ Plaintext LOW Batch ops

Encryption Details

Key Validation:

  • SSH key must be ED25519 (256-bit)
  • SSH key must be password-protected
  • Script validates automatically before encryption

Encryption Process:

SSH Private Key
    ↓ (HKDF-SHA256)
AES-256 Encryption Key (32 bytes)
    ↓
Credential Value + Random Nonce
    ↓ (AES-256-GCM)
__encrypted__:<base64>
    ↓
~/.aws/credentials (at-rest encrypted)
    ↓ (eval $(./aws-creds --eval usermanager))
Memory only (never on disk)
    ↓ (eval injects into environment)
AWS SDK access

Security Guarantees

  • No unprotected keys: SSH key must be password-protected
  • No plaintext on disk: Manager credentials stored encrypted
  • No disk persistence: Credentials only in memory during batch ops
  • Passphrase protected: SSH passphrase required each time
  • Random nonces: Different ciphertext each encryption
  • Lazy decryption: Only decrypt when needed
  • Auto-cleanup: Session tokens auto-expire (max 36 hours)

Configuration

SSH Key Requirements

Current System:

Key Type:     ED25519 (256-bit) ✓ EXCELLENT
Protection:   AES-256-CTR ✓ EXCELLENT
Permissions:  600 ✓ CORRECT

If Your Key is Unprotected:

ssh-keygen -p -f ~/.ssh/id_ed25519
# Enter old passphrase: [press Enter if none]
# Enter new passphrase: [type strong passphrase]
# Confirm new passphrase: [re-type]

Using ssh-agent for Passphrase Caching

# Start ssh-agent
eval $(ssh-agent -s)

# Add your key (you'll be prompted once for passphrase)
ssh-add ~/.ssh/id_ed25519

# Now encryption/decryption won't prompt for passphrase
./aws-creds --profile usermanager --encrypt
eval $(./aws-creds --eval usermanager)

# Kill agent when done
ssh-agent -k

Custom SSH Key Path

To use a different SSH key, modify the script:

# In aws-creds, change:
def get_ssh_key_path():
    return os.path.expanduser("~/.ssh/id_ed25519")

# To:
def get_ssh_key_path():
    return os.path.expanduser("~/.ssh/my-custom-key")

Troubleshooting

"SSH key is not password protected"

Error: SSH key '/home/user/.ssh/id_ed25519' is not password protected.
For security, only password-protected SSH keys can be used for encryption.
Add a passphrase: ssh-keygen -p -f /home/user/.ssh/id_ed25519

Solution:

ssh-keygen -p -f ~/.ssh/id_ed25519
# Add a strong passphrase

"Cannot encrypt 'default' profile"

Error: Cannot encrypt 'default' profile. Use --profile or AWS_PROFILE
to specify an explicit profile name.

Solution: Always use an explicit profile name:

./aws-creds --profile usermanager --encrypt

"Could not determine IAM user"

Error: Could not determine IAM user for profile 'admin'

Solution: Create the profile first:

./aws-creds --profile usermanager admin

"Profile does not exist"

Error: Manager profile 'usermanager' not found in credentials file

Solution: Add the profile to ~/.aws/credentials:

[usermanager]
aws_access_key_id = AKIA...
aws_secret_access_key = ...

SSH Agent Not Available

⚠ ssh-agent not available or not running

Solution: Start ssh-agent:

eval $(ssh-agent -s)
ssh-add ~/.ssh/id_ed25519

Examples

Example 1: Setup & Encrypt

# 1. Install
pip install boto3 botocore cryptography

# 2. Add manager profile to ~/.aws/credentials
cat >> ~/.aws/credentials << 'EOF'
[usermanager]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
EOF

# 3. Encrypt
./aws-creds --profile usermanager --encrypt

# 4. Verify
./aws-creds --show-encrypted usermanager

Example 2: Batch IAM Provisioning

#!/bin/bash
# provision-users.sh

eval $(./aws-creds --eval usermanager)

for username in alice bob charlie; do
  echo "Creating user: $username"
  aws iam create-user --user-name $username

  echo "Creating access key for: $username"
  KEY=$(aws iam create-access-key --user-name $username \
    --query 'AccessKey.[AccessKeyId,SecretAccessKey]' --output text)

  echo "AccessKeyId: $(echo $KEY | cut -f1)"
  echo "SecretAccessKey: $(echo $KEY | cut -f2)"
done

unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN

Example 3: Batch CloudFormation

#!/bin/bash
# deploy-stacks.sh

eval $(./aws-creds --eval usermanager)

REGIONS=("us-east-1" "us-west-2" "eu-west-1")
STACK_NAME="my-infrastructure"

for region in "${REGIONS[@]}"; do
  echo "Deploying to: $region"
  aws cloudformation create-stack \
    --region $region \
    --stack-name $STACK_NAME \
    --template-body file://template.yaml \
    --capabilities CAPABILITY_IAM
done

unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN

Performance

  • Credential Generation: ~2-5 seconds (depends on IAM lookup)
  • Encryption: <100ms per credential
  • Decryption: <100ms per credential
  • Batch Operations: No overhead beyond normal AWS CLI/SDK

Compatibility

  • Python: 3.6+
  • OS: Linux, macOS, WSL2
  • AWS SDK: Works with any tool using AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN

Security Considerations

Best Practices

  1. Keep SSH Key Secure

    • Never share your SSH key
    • Use strong passphrase (20+ characters)
    • Store on secure hardware if possible
  2. Use SSH-Agent

    • Cache SSH passphrase with ssh-agent
    • Avoid typing passphrase repeatedly
    • Clear agent after batch operations
  3. Temporary Credentials Only

    • Rotate temporary credentials regularly
    • Use maximum practical duration
    • Let credentials auto-expire
  4. Batch Operations

    • Run in isolated bash sessions
    • Always unset environment variables after
    • Avoid storing credentials in scripts
  5. Monitoring

    • Enable CloudTrail for audit
    • Monitor credential usage
    • Alert on unusual activity

What This Tool DOES Protect

  • ✅ Manager credentials encrypted at-rest
  • ✅ Encryption key never stored (derived from SSH key)
  • ✅ Passphrase-protected SSH key required
  • ✅ Random nonces per encryption
  • ✅ Auto-expiring temporary credentials

What This Tool DOESN'T Protect

  • ❌ Shell history (credentials visible in ~/.bash_history)
  • ❌ Process listing (credentials visible in ps during execution)
  • ❌ SSH key compromise (if attacker gets SSH key, they get credentials)
  • ❌ Unencrypted profiles (bedrock, admin remain plaintext)

Contributing

Report issues or suggest improvements by opening a GitHub issue.

License

Specify your license here (MIT, Apache 2.0, etc.)

Author

Created with focus on practical AWS credential security for DevOps and infrastructure automation workflows.

Related Tools

  • aws-vault: Alternative credential encryption tool (uses OS keyring)
  • aws-cli: Official AWS command-line interface
  • aws-iam: AWS IAM management tool
  • aws-sso: AWS Identity Center for organizations

FAQ

Q: Why ED25519 instead of RSA?

A: ED25519 is modern, provides 256-bit security, and has better performance than RSA 4096-bit.

Q: Can I use multiple SSH keys?

A: Currently the tool uses ~/.ssh/id_ed25519. You can modify the script to support custom paths.

Q: What if I forget my SSH passphrase?

A: You'll need to reset it with ssh-keygen -p. You may need to re-encrypt credentials with the new passphrase.

Q: Can I use this with AWS SSO?

A: No, this tool requires IAM user credentials. For organizations, AWS SSO is recommended instead.

Q: What happens if AWS STS is down?

A: Credential generation will fail. You can use cached temporary credentials or permanent credentials.

Q: Can I automate without passphrase prompts?

A: Yes, use ssh-agent to cache the passphrase. See "Using ssh-agent" section.

Q: Is this production-ready?

A: Yes, but test thoroughly in your environment. The encryption is solid, but credential management should always be tested carefully.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

iam_sorry-0.1.0.tar.gz (17.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

iam_sorry-0.1.0-py3-none-any.whl (16.6 kB view details)

Uploaded Python 3

File details

Details for the file iam_sorry-0.1.0.tar.gz.

File metadata

  • Download URL: iam_sorry-0.1.0.tar.gz
  • Upload date:
  • Size: 17.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for iam_sorry-0.1.0.tar.gz
Algorithm Hash digest
SHA256 a9d1cc6b28310231ba6122dac73af59ff2c4e06a2e10213f4e9db580cf30cbf5
MD5 1c09dbac57d2931c06949e6f4c62c252
BLAKE2b-256 e969be0c3ee4424f4d7e3a627f185a5f2ad7260f8f40d583d89fd4869e2ce12f

See more details on using hashes here.

Provenance

The following attestation bundles were made for iam_sorry-0.1.0.tar.gz:

Publisher: publish-pypi.yml on dirkpetersen/iam-sorry

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file iam_sorry-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: iam_sorry-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 16.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for iam_sorry-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 438e21b0cab2e1b7bf60aaaf9eb1d55567dde74101f72592509e918c11e9b2f8
MD5 feeeb971c71fb737c3cdfa9387b49fe0
BLAKE2b-256 175bc704e396ad3e993609002451f20fddd28151582c526cd427bda2d5dd1352

See more details on using hashes here.

Provenance

The following attestation bundles were made for iam_sorry-0.1.0-py3-none-any.whl:

Publisher: publish-pypi.yml on dirkpetersen/iam-sorry

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page