aws-vault¶
Project URL¶
Use case¶
I serve static content from the domain static.manselmi.com
. Objects reside in a bucket in
us-east-1
named static.manselmi.com
, and objects within that bucket are accessible only via a
CloudFront distribution.
I would like to be able to do the following programatically:
-
get, put and delete objects within the
static.manselmi.com
bucket -
invalidate the CloudFront cache (e.g. I just overwrote an object and want to ensure CloudFront doesn't serve a previously cached object)
-
rotate long-term credentials
Configuration¶
-
Create IAM user
manselmi-work-sts
. The user is so named because it's for my occasional use at work, and will only be able to do anything useful by assuming a privileged role via STS. -
Create IAM user group
work
, and assign the usermanselmi-work-sts
to the group. -
Create IAM permission policy
static.manselmi.com
that allows the required S3 and CloudFront actions.{ "Version": "2012-10-17", "Statement": [ { "Sid": "ManselmiAllowS3BucketStaticManselmiCom", "Effect": "Allow", "Action": [ "s3:GetBucketPolicy", "s3:GetBucketPolicyStatus", "s3:GetBucketPublicAccessBlock", "s3:GetEncryptionConfiguration", "s3:ListBucket", "s3:ListBucketMultipartUploads" ], "Resource": [ "arn:aws:s3:::static.manselmi.com" ] }, { "Sid": "ManselmiAllowS3ObjectStaticManselmiCom", "Effect": "Allow", "Action": [ "s3:AbortMultipartUpload", "s3:DeleteObject", "s3:GetObject", "s3:GetObjectAttributes", "s3:ListMultipartUploadParts", "s3:PutObject" ], "Resource": [ "arn:aws:s3:::static.manselmi.com/*" ] }, { "Sid": "ManselmiAllowCloudfrontStaticManselmiCom", "Effect": "Allow", "Action": [ "cloudfront:CreateInvalidation", "cloudfront:GetInvalidation", "cloudfront:ListInvalidations" ], "Resource": [ "arn:aws:cloudfront::123456789012:distribution/ABCDEFGHIJKLMN" ] } ] }
-
Create IAM role
static.manselmi.com
and attach to it the previous permission policy. Edit the role's trust policy so that any user within my AWS account may assume the role, but require that the role's session name equal the username of the user assuming the role, and also require multi-factor authentication: -
Create IAM permission policy
assume-role-static.manselmi.com
that allows assuming the previous role: -
Create IAM permission policy
credential-rotation
that allows the required IAM actions: -
Attach IAM permission policies
assume-role-static.manselmi.com
andcredential-rotation
to the IAM user groupwork
. -
Generate long-term credentials for IAM user
manselmi-work-sts
and assign to the user one or more MFA devices. -
Add long-term credentials to aws-vault's storage backend:
-
Update file
~/.aws/config
:[profile manselmi] credential_process = /Users/manselmi/.prefix/sw/homebrew/bin/aws-vault export --format=json -- manselmi region = us-east-1 [profile static.manselmi.com] duration_seconds = 1800 mfa_process = /Users/manselmi/.prefix/sw/homebrew/bin/op read --no-newline op://<vault-name>/<item-name>/[section-name/]<field-name>?attribute=otp mfa_serial = arn:aws:iam::123456789012:mfa/1password-work region = us-east-1 role_arn = arn:aws:iam::123456789012:role/static.manselmi.com role_session_name = manselmi-work-sts source_profile = manselmi
Example usage¶
2023-10-19 11:48:04 4369 security/gnupg/B397CE8214A7D51C1349384B140ABA5A34E6AB23.pub
2023-10-16 23:53:53 1870 security/index.html
2023-01-28 22:43:43 131 security/style.css
Profile Credentials Sessions
======= =========== ========
manselmi manselmi -
static.manselmi.com - sts.AssumeRole:11m35s
DISTRIBUTION_ID='ABCDEFGHIJKLMN'
PROFILE='static.manselmi.com'
aws-vault exec "${PROFILE}" -- aws cloudfront create-invalidation \
--distribution-id "${DISTRIBUTION_ID}" \
--paths '/foo' '/bar/*'
{
"Location": "https://cloudfront.amazonaws.com/2020-05-31/distribution/ABCDEFGHIJKLMN/invalidation/I1PPLLBTK6DB2HF1HJMQEYO5CC",
"Invalidation": {
"Id": "I1PPLLBTK6DB2HF1HJMQEYO5CC",
"Status": "InProgress",
"CreateTime": "2023-06-26T20:22:17.518000+00:00",
"InvalidationBatch": {
"Paths": {
"Quantity": 2,
"Items": [
"/foo",
"/bar/*"
]
},
"CallerReference": "cli-1687810937-602265"
}
}
}
INVALIDATION_ID='I1PPLLBTK6DB2HF1HJMQEYO5CC'
aws-vault exec "${PROFILE}" -- aws cloudfront get-invalidation \
--distribution-id "${DISTRIBUTION_ID}" \
--id "${INVALIDATION_ID}"
{
"Invalidation": {
"Id": "I1PPLLBTK6DB2HF1HJMQEYO5CC",
"Status": "Completed",
"CreateTime": "2023-06-26T20:22:17.518000+00:00",
"InvalidationBatch": {
"Paths": {
"Quantity": 2,
"Items": [
"/foo",
"/bar/*"
]
},
"CallerReference": "cli-1687810937-602265"
}
}
}
# OOPS I just went out of my way to expose my long-term credentials!
aws-vault export --no-session -- manselmi