HashiCorp Vault β€” AWS Secrets Engine

1 minute read

The AWS secrets engine generates dynamic IAM credentials β€” IAM users, assumed roles, or federation tokens β€” on demand.


Credential Types

Type Creates Lifetime Use Case
IAM User New IAM user + access keys Until lease expires (Vault deletes user) Long-running tasks
Assumed Role STS AssumeRole credentials 15min to 12h (AWS limit) Cross-account, temporary
Federation Token STS GetFederationToken 15min to 36h (AWS limit) Console access, broad temp creds

Setup

Enable the Engine

vault secrets enable aws

Configure Root Credentials

vault write aws/config/root \
    access_key="AKIAIOSFODNN7EXAMPLE" \
    secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" \
    region="us-east-1"

πŸ’‘ Best practice: Use an IAM role for Vault itself instead of static keys. If Vault runs on EC2, use an instance profile.

Configure Lease Defaults

vault write aws/config/lease \
    lease="30m" \
    lease_max="1h"

IAM User Credentials

# Create a role that generates IAM users
vault write aws/roles/s3-readonly \
    credential_type="iam_user" \
    policy_document=-<<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::my-bucket",
        "arn:aws:s3:::my-bucket/*"
      ]
    }
  ]
}
EOF

Generate Credentials

vault read aws/creds/s3-readonly

Expected output:

Key                Value
---                -----
lease_id           aws/creds/s3-readonly/abc123
lease_duration     30m
lease_renewable    true
access_key         AKIAIOSFODNN7EXAMPLE
secret_key         wJalrXUtnFEMI/K7MDENG/bPxRfi...
security_token     <empty for IAM users>
# Use the credentials
export AWS_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE"
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI..."
aws s3 ls s3://my-bucket/

Assumed Role Credentials

# Create a role that assumes an existing IAM role
vault write aws/roles/deploy-role \
    credential_type="assumed_role" \
    role_arns="arn:aws:iam::123456789012:role/deploy-role" \
    default_sts_ttl="1h" \
    max_sts_ttl="4h"
vault read aws/creds/deploy-role

Expected output:

Key                Value
---                -----
lease_id           aws/creds/deploy-role/abc123
lease_duration     1h
access_key         ASIAIOSFODNN7EXAMPLE
secret_key         wJalrXUtnFEMI/K7MDENG/bPxRfi...
security_token     FwoGZXIvYXdz...

⚠️ Assumed role credentials include a security_token that must be used with the access/secret keys.


Using Existing IAM Policies

Instead of inline policies, reference existing AWS-managed or customer-managed policies:

vault write aws/roles/ec2-admin \
    credential_type="iam_user" \
    policy_arns="arn:aws:iam::aws:policy/AmazonEC2FullAccess,arn:aws:iam::123456789012:policy/custom-policy"

Rotate Root Credentials

vault write -f aws/config/rotate-root

After rotation, only Vault knows the new root credentials.


Quick Reference

Command Description
vault secrets enable aws Enable AWS engine
vault write aws/config/root ... Configure root creds
vault write aws/roles/NAME credential_type=iam_user ... IAM user role
vault write aws/roles/NAME credential_type=assumed_role ... Assumed role
vault read aws/creds/NAME Generate credentials
vault write -f aws/config/rotate-root Rotate root creds
vault lease revoke aws/creds/NAME/LEASE Revoke credentials

Next: Azure & GCP Secrets