🚧 🚧 🚧 Work-in-Progress | 🚀 |
---|---|
Things may break without any prior notice at any given v0.x version: So do not use this for anything critical, but feel free to test this out and give feedback! |
After some testing, depending on the amount of bugs/issues/feedback, I'm hoping to release v1.0.0 during November 2021. No commitments though! |
Much like going to AWS re:Invent in Las Vegas, using various AWS tools (SDKs, CLI, CDK, Terraform, etc) via command-line to assume IAM roles in different accounts with Multi-Factor Authentication can be an exhausting experience: vegas-credentials
aims to simplify the credential process!
It's an utility that plugs into AWS credential_process
to assume IAM Roles with TOPT MFA (with optional Yubikey Touch support) to fetch, cache and refresh assumed temporary session credentials.
Features | Overview | Get Started | Yubikeys | Configure | Examples | Why? | Design |
---|
-
Plugs into AWS
credential_process
: If you're unfamiliar with AWScredential_process
, this AWS re:Invent video explains it very well -
Supports automatic temporary session credential refreshing for tools that understand session credential expiration
-
Supports Role Chaining
-
Works out-of-the-box with most tools such as AWS CLI, most AWS SDKs, AWS CDK, Terraform...
-
Encrypted Caching of session credentials to speed things up & to avoid having to input MFA token code for each operation
-
Supports both Yubikey Touch or Authenticator App TOPT MFA simultaneously:
- For example you can default to using Yubikey, but if don't have the Yubikey with you all the time and also have MFA codes in an Authenticator App (such as Authy for example)
- You may just touch the Yubikey or manually type the token code (via GUI Prompt Dialog or CLI
stdin
) – which ever input is given first will be used
-
Smooth Yubikey integration:
- Just tap your physical key: No need to manually type or copy-paste MFA token code
- Supports multiple Yubikey devices
-
Fast & Cross-Platform: Built with Go and supports macOS, Linux and Windows operating systems with
x86_64
&arm64
(e.g. Apple M1) architectures
-
AWS SSO
→ See
benkehoe/aws-sso-util
for that -
Encrypting of master/source (long-term user) credentials in
~/.aws/credentials
→ You may implement this quite easily with few lines of bash &
credential_process
→ … or use a tool such as
99designs/aws-vault
-
SAML or OpenID Connect federated authentication
-
Acting as a credential source in EC2 – i.e.
vegas-credentials
is meant for local development usage
-
Install
vegas-credentials
via one of the following:Homebrew (MacOS/Linux)
- Requires
brew
-command - Install:
brew tap aripalo/tap brew install vegas-credentials # Verify installation vegas-credentials --version
Scoop (Windows)
- Requires
scoop
-command - Install:
scoop bucket add aripalo https://github.com/aripalo/scoops.git scoop install aripalo/vegas-credentials # Verify installation vegas-credentials --version
NPM (MacOS/Linux/Windows)
- Requires
node
-command (v14+
) - Install:
npm install -g vegas-credentials # Verify installation vegas-credentials --version
Go (MacOS/Linux/Windows)
- Requires
Go
-command (v1.17+
) - Perform the installation outside of any Go Module
- Install:
go install github.com/aripalo/vegas-credentials # Verify installation vegas-credentials --version
- Requires
-
Configure you source profile and its credentials, most often it's the
default
one which you configure into~/.aws/credentials
:# ~/.aws/credentials [default] aws_access_key_id = AKIAIOSFODNN7EXAMPLE aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
-
TODO
# ~/.aws/config [default] mfa_serial = arn:aws:iam::111111111111:mfa/FrankSinatra
-
Configure your target profile with
credential_process
into~/.aws/config
:# ~/.aws/config [profile frank@concerts] credential_process = vegas-credentials assume --profile=frank@concerts vegas_role_arn=arn:aws:iam::222222222222:role/SingerRole vegas_source_profile=default # You may also provide any other additional standard AWS configuration, such as: region = us-west-1 duration_seconds = 4383 role_session_name = SinatraAtTheSands external_id = 0093624694724
Note:
role_arn
&source_profile
must be prefixed withvegas_
to prevent AWS tooling to ignorecredential_process
setting and to prevent Terraform failing. -
Use any AWS tooling that support ini-based configuration with
credential_process
, like AWS CLI v2:aws sts get-caller-identity --profile frank@concerts
To use Yubikeys:
-
You must have at least one Yubikey Touch device with OATH TOPT support (Yubikey 5 or 5C recommended).
-
Install
ykman
CLI -
Set up Yubikey as
Virtual MFA device
in AWS IAM - Not!U2F MFA
-
Think of backup strategy in case you lose your Yubikey device, you should do at least one of the following:
- During
Virtual MFA device
setup also assign Authenticator App such as Authy for backup - If you own multiple Yubikey devices, during
Virtual MFA device
setup also configure the second Yubikey and once done, store it securely - Print the QR-code (and store & lock it very securely)
- Save the QR-code or secret key in some secure & encrypted location
- During
-
When configuring your Yubikey, use
arn:aws:iam::<ACCOUNT_ID>:mfa/<IAM_USERNAME>
(i.e. MFA device ARN) as the Yubikey OATH account label:ykman oath accounts add -t arn:aws:iam::<ACCOUNT_ID>:mfa/<IAM_USERNAME>
-
Configure
vegas_yubikey_serial
into~/.aws/config
:# ~/.aws/config [default] mfa_serial = arn:aws:iam::111111111111:mfa/FrankSinatra vegas_yubikey_serial = 12345678
Optionally you may configure
vegas_yubikey_label
if you used something else thanarn:aws:iam::<ACCOUNT_ID>:mfa/<IAM_USERNAME>
as the OATH account label (though not recommended).
Configuration for the most part happens in ~/.aws/config
ini-file, but there are some command-line flags and environment variables that you may want to use sometimes.
Option | Description |
---|---|
mfa_serial |
Required: The ARN of the Virtual (OATH TOPT) MFA device used in Multi-Factor Authentication. |
vegas_yubikey_serial |
Required if using Yubikey: Yubikey Device Serial to use. You can see the serial(s) with ykman list command. This enforces the use of a specific Yubikey and also enables the support for using multiple Yubikeys (for different profiles)! |
vegas_yubikey_label |
Use only if you have any other value than the AWS MFA Device ARN as oath account label! Yubikey oath Account Label to use. You can see the available accounts with ykman oath accounts list command. Set the account label which you have configured your AWS TOPT MFA! |
Example:
# ~/.aws/config
[default]
mfa_serial = arn:aws:iam::111111111111:mfa/FrankSinatra
vegas_yubikey_serial = 12345678
Option | Description |
---|---|
credential_process |
Required: To enable this tool, set the value as vegas-credentials assume --profile <my-profile> . Value of my-profile must match the profile name in ini -section title, e.g. [profile my-profile] . |
vegas_role_arn |
Required: The target IAM Role ARN to be assumed. |
vegas_source_profile |
Required: Which credentials (profile) are to be used as a source for assuming the target role. |
Example:
# ~/.aws/config
[profile frank@concerts]
credential_process = vegas-credentials assume --profile=frank@concerts
vegas_role_arn=arn:aws:iam::222222222222:role/SingerRole
vegas_source_profile=default
# You may also provide any other additional standard AWS configuration, such as:
region = us-west-1
duration_seconds = 4383
role_session_name = SinatraAtTheSands
external_id = 0093624694724
Flag | Description |
---|---|
--help |
Prints help text |
--profile |
Required: Which AWS Profile to use from ~/.aws/config : Value (for example my-profile ) must match the profile name in ini -section title, e.g. [profile my-profile] |
--disable-dialog |
Disable GUI Dialog Prompt |
--disable-mandatory-refresh |
Disable Session Credentials refreshing if expiration within 10 minutes (as defined in Botocore) |
--hide-arns |
Hide IAM Role & MFA Serial ARNS from output (even on verbose mode) |
--verbose |
Verbose output |
--debug |
Prints out various debugging information |
--no-color |
Disable colorful fancy output |
Example:
vegas-credentials assume --profile=frank@concerts --verbose --no-color
... though you shouldn't really call this tool directly yourself, but instead configure it as credential_process
in ~/.aws/config
.
Option | Description |
---|---|
NO_COLOR |
Disable colorful fancy output, see also --no-color CLI flag |
VEGAS_CREDENTIALS_NO_COLOR |
Disable color only for this tool (not for your whole environment ) |
TERM=dumb |
Another way to disable colorful fancy output |
This tool also supports role chaining - given that the specific AWS tool your using supports it - which means assuming an initial role and then using it to assume another role. An example with 3 different AWS accounts would look like:
Assuming correct IAM roles exists with valid permissions and trust policies:
-
Assuming you have the following configuration already:
# ~/.aws/credentials [default] aws_access_key_id = AKIAIOSFODNN7EXAMPLE aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
# ~/.aws/config [default] aws_mfa_device = arn:aws:iam::111111111111:mfa/FrankSinatra [profile frank@concerts] credential_process = vegas-credentials assume --profile=frank@concerts vegas_role_arn=arn:aws:iam::222222222222:role/SingerRole vegas_source_profile=default
-
Configure another role with standard
role_arn
andsource_profile
:# ~/.aws/config [profile frank@movies] role_arn=arn:aws:iam::333333333333:role/ActorRole # Important: NO prefix here! source_profile=frank@concerts # Important: NO prefix here!
-
Do some chaining:
aws sts get-caller-identity --profile frank@movies
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.27"
}
}
required_version = ">= 0.14.9"
}
# Again, nothing special here, just normal profile configuration…
provider "aws" {
profile = "frank@concerts"
region = "eu-west-3"
}
data "aws_region" "current" {}
output "album_name" {
value = "Sinatra & Sextet: Live in ${
replace(
regex("[a-zA-Z]+\\)$", data.aws_region.current.description),
")",
""
)
}"
}
There are already a bazillion ways to assume an IAM Role with MFA, but most existing open source tools in this scene either:
- export the temporary session credentials to environment variables (
AWS_ACCESS_KEY_ID
,AWS_SECRET_ACCESS_KEY
,AWS_SESSION_TOKEN
) - write new sections for “short-term” credentials into
~/.aws/credentials
(for example likeaws-mfa
does)
The downside with those approaches is that using most of these tools (especially the ones that export environment variables) means you lose the built-in ability to automatically refresh the temporary credentials and/or the temporary credentials are “cached” in some custom location or saved into ~/.aws/credentials
.
This tool follows the concept that you should never put temporary credentials into ~/.aws/credentials
and also provides a mechanism to automatically refresh session credentials (if the AWS tool you use supports that).
Most AWS provided tools & SDKs already support MFA & assuming a role out of the box, but what they lack is a nice integration with Yubikey Touch, requiring you to manually type in or copy-paste the MFA TOPT token code: This utility instead integrates with ykman
Yubikey CLI so just a quick touch is enough!
Also with this tool, even if you use Yubikey Touch, you still get the possibility to input MFA TOPT token code manually from an Authenticator App (for example if you don't have your Yubikey on your person).
Then there's tools such as AWS CDK that does not support caching of assumed temporary credentials, requiring the user to input the MFA TOPT token code for every operation with cdk
CLI – which makes the developer experience really cumbersome.
To recap, most existing solutions (I've seen so far) to these challenges either lack support for automatic temporary session credential refreshing, cache/write temporary session credentials to suboptimal locations and/or don't work that well with AWS tooling (i.e. requiring one to create “wrappers”):
This vegas-credentials
is yet another tool, but it plugs into the standard credential_process
AWS configuration so most of AWS tooling (CLI v2, SDKs and CDK) will work out-of-the-box with it and also support automatic temporary session credential refreshing.
There are many great existing solutions out there that solve similar problems and I've tried to learn from them as much as I can. This tool that I've built is definitely not better than for example 99designs/aws-vault
in many scenarios as it has a lot more features, more contributors and been around some time. Instead the comparison below focuses on the specific use case this tool tries to solve (i.e. providing a nice UX for assuming a role with MFA using credential_process
to support as many AWS tools as possible without having to use wrapper scripts).
Feature/Info | aripalo/vegas-credentials |
99designs/aws-vault |
broamski/aws-mfa |
meeuw/aws-credential-process |
---|---|---|---|---|
Github Info | TODO |
|
|
|
credential_process with MFA + Assume Role |
✅ | ❌ [*2] | ❌ [*4] | ✅ |
Automatic Temporary Session Credential Refresh | ✅ | ❌ [*3] | ❌ [*5] | ✅ |
Yubikey | ✅ ✅ [*1] | ✅ [*1] | ❌ [*6] | ✅ [*10] |
Cache Encryption | ✅ | ✅ | ❌ [*7] | ✅ |
Cache Invalidation on config change | ✅ | ✅ ? | ✅ [*8] | ✅ |
Cached Performance | ⚡️ <100ms [*11] |
⚡️ <50ms |
⚡️ [*9] |
🐢>400ms [*11] |
Comprehensively Unit Tested | ✅ | ? | ❌ | ✅ |
Installation methods | brew , scoop , npm , go |
brew , port , choco , scoop , pacman , pkg , zypper , nix-env , asdf |
pip |
brew , pip |
Please, correct me if I'm wrong above or there's any other good alternatives!
-
Yubikey support in
99designs/aws-vault
is not perfect:- Using multiple Yubikeys is cumbersome due to having to pass in Yubikey device serial as environment variable for each command – vs. this tool allows setting device serial via configuration per profile (no need to remember the serial for each Yubikey).
- Uses deprecated
ykman
commands. - See also point 2 about
credential_process
, assumed roles and Yubikeys.
-
Does not seem to play well with
credential_process
:-
At least I haven't figured out how to succesfully configure it to use
credential_process
, assume a role, use Yubikey for MFA and to provide temporary session credentials. -
They themselves claim that “
credential_process
is designed for retrieving master credentials” - which is NOT true since this tool does work with temporary credentials viacredential_process
just fine and even the AWS docs oncredential_process
showSessionToken
andExpiration
on the expected output from the credentials program. -
There's further indication that
99designs/aws-vault
is not designed forcredential_process
:Using credentials_process isn't the way I use aws-vault, it was a contributed addition, so feels like we should emphasise this is not the recommended path.
– Michael Tibben, VP Technology, 99designs
-
-
This pretty much relates to point 1: For AWS tools to automatically request refreshed credentials, the credentials need to be provided via either the multiple standard methods or via
credential_process
.
-
Works differently by writing temporary session credentials into
~/.aws/credentials
, so therefore nocredential_process
support at all. -
If temporary session credentials written into
~/.aws/credentials
bybroamski/aws-mfa
are expired, AWS tools will fail and you must invokeaws-mfa
command manually to fetch new session credentials. There is no (automatic) way for AWS tools to triggeraws-mfa
command. -
You may use Yubikey, but it requires you to manually copy-paste the value from
ykman
or Yubikey Manager GUI. No "touch integration". -
Temporary session credentials are written in plaintext into
~/aws/credentials
. Besides being available as plaintext, it pollutes the credentials file. -
Configuration is only provided via flags to
aws-mfa
CLI command, so each time you executeaws-mfa
it will use the flags provided. But, the gotcha is that again you need to executeaws-mfa
manually always. -
As temporary session credentials (or "short-term" as
aws-mfa
calls them) are stored as plaintext into~/aws/credentials
, there is no delay since AWS tools can directly read them from that file.
-
Hyperfine benchmark for retrieving cached temporary session credentials:
This tool caches temporary session credentials to disk. In the background it uses dgraph-io/badger
which is a fast SSD-optimized key-value store for Go and importantly supports Time-to-Live attributes for data (useful for temporary session credential expiration).
The data is stored into the key-value store with AES-256-CTR
encryption. The encryption secret is derived from the environment (system boot time, hostname and user UID). So this is not a 100% secure setup, but it's slightly “better” compared to what broamski/aws-mfa
does or how AWS CLI caches to ~/.aws/cli/cache
: At least it provides “security by obscurity” solution against rogue scripts that might try to steal your credentials. And then again, it's only caching temporary session credentials – which you should aim to keep short-lived!
Reason why it caches temporary session credentials in the first place is to create a better user experience with AWS tools that don't support temporary session credential caching with assumed roles.
By default, the cached data is invalidated if the environment changes (system boot time, hostname and user UID), but this is okay since this tool will then query STS for new temporary session credentials and add them to cache.
Also this tool invalidates cached credentials if their expiration time is within 10 minutes and retrieves new ones. This functionality matches to botocore
. You may disable this with --disable-mandatory-refresh
CLI flag.
TODO
TODO