Skip to content

mvisonneau/vac

Repository files navigation

vac | AWS credentials management leveraging Vault

PkgGoDev Go Report Card test Coverage Status release

vac is a wrapper to manage AWS credentials dynamically using Hashicorp Vault.

It is heavily inspired from jantman/vault-aws-creds and ahmetb/kubectx.

Written in golang, it can work on most common platforms (Linux, MacOS, Windows).

It leverages the external process sourcing capabilities of the AWS CLI config definition.

asciicast

Install

Have a look onto the latest release page and pick your flavor.

Checksums are signed with the following GPG key: C09C A9F7 1C5C 988E 65E3  E5FC ADEA 38ED C46F 25BE

Go

~$ go install github.com/mvisonneau/vac/cmd/vac@latest

Homebrew

~$ brew install mvisonneau/tap/vac

Docker

~$ docker run -it --rm docker.io/mvisonneau/vac
~$ docker run -it --rm ghcr.io/mvisonneau/vac
~$ docker run -it --rm quay.io/mvisonneau/vac

Scoop

~$ scoop bucket add https://github.com/mvisonneau/scoops
~$ scoop install vac

asdf

~$ asdf plugin add vac https://github.com/bodgit/asdf-vac.git
~$ asdf install vac latest
~$ asdf global vac latest

Binaries, DEB and RPM packages

Have a look onto the latest release page to pick your flavor and version. Here is an helper to fetch the most recent one:

~$ export VAC_VERSION=$(curl -s "https://api.github.com/repos/mvisonneau/vac/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
# Binary (eg: linux/amd64)
~$ wget https://github.com/mvisonneau/vac/releases/download/${VAC_VERSION}/vac_${VAC_VERSION}_linux_amd64.tar.gz
~$ tar zxvf vac_${VAC_VERSION}_linux_amd64.tar.gz -C /usr/local/bin

# DEB package (eg: linux/386)
~$ wget https://github.com/mvisonneau/vac/releases/download/${VAC_VERSION}/vac_${VAC_VERSION}_linux_386.deb
~$ dpkg -i vac_${VAC_VERSION}_linux_386.deb

# RPM package (eg: linux/arm64)
~$ wget https://github.com/mvisonneau/vac/releases/download/${VAC_VERSION}/vac_${VAC_VERSION}_linux_arm64.rpm
~$ rpm -ivh vac_${VAC_VERSION}_linux_arm64.rpm

Quickstart

  • Once you have installed it, create a new profile in your ~/.aws/credentials file:
~$ cat - <<EOF >> ~/.aws/credentials

[vac]
credential_process = $(which vac) get
EOF
  • You will need to set the following env variable to use this profile
~$ export AWS_PROFILE=vac

(you can omit this part by using it as your default profile instead)

  • Finally assuming that you have sorted out your Vault accesses already, you need to chose which engine/role to use:
~$ vac
[follow prompt]

Advanced usage

~$ vac --help
NAME:
   vac - Manage AWS credentials dynamically using Vault

USAGE:
   vac [global options] command [command options] [arguments...]

COMMANDS:
   get      get the creds in credential_process format (json)
   status   returns some info about the current context, cached credentials and Vault server connectivity
   help, h  Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --engine path, -e path  engine path [$VAC_ENGINE]
   --role name, -r name    role name [$VAC_ROLE]
   --state path, -s path   state path (default: "~/.vac_state") [$VAC_STATE_PATH]
   --log-level level       log level (debug,info,warn,fatal,panic) (default: "info") [$VAC_LOG_LEVEL]
   --log-format format     log format (json,text) (default: "text") [$VAC_LOG_FORMAT]
   --help, -h              show help

Static configuration

You are forced to use the fuzzyfinding capabilities. This is particularily useful in a non-TTY usage scenario. eg:

# ~/.aws/credentials
[default]
credential_process = /usr/local/bin/vac get
[dev-admin]
credential_process = /usr/local/bin/vac -e dev -r admin get
[staging-admin]
credential_process = /usr/local/bin/vac -e staging -r admin get

You can also dynamically switch your context without a prompt by doing the following:

# only prompt for chosing a role in the "dev" engine
~$ vac -e dev

# no prompt, automatically switch to "admin" role in the "dev" engine
~$ vac -e dev -r admin

TTL and cache bypass

The get command can take various flags in order to manage the credentials TTLs but also when to refresh them:

~$ vac get --help
NAME:
   vac get - get the creds in credential_process format (json)

USAGE:
   vac get [command options] [arguments...]

OPTIONS:
   --min-ttl duration           min-ttl duration (default: 0s) [$VAC_MIN_TTL]
   --ttl duration, -t duration  ttl duration (default: 0s) [$VAC_TTL]
   --force-generate, -f         bypass currently cached creds and generate new ones [$VAC_FORCE_GENERATE]

Examples

# Generate credentials valid for 1h
~$ vac get --ttl 1h

# Generate credentials valid for 1h but replace them if existing ones expire in less than 30m
~$ vac get --ttl 1h --min-ttl 30m

# Generate credentials valid for 2h, indepently if some valid ones are still present in the cache
~$ vac get --ttl 2 -f

you can of course define them in your ~/.aws/credentials profiles as well

~$ cat - <<EOF >> ~/.aws/credentials
[vac-4h]
credential_process = $(which vac) get --ttl 4h
[vac-no-cache]
credential_process = $(which vac) get -f
EOF

Get information about current configuration

You can use the status command in order to retrieve some info about:

  • Current context (selected engine/role)
  • Cached credentials
  • Vault server connectivity details
~$ vac status
+----------------+---------------------+
|  LOCAL STATE   |                     |
+----------------+---------------------+
| Current Engine | dev                 |
| Current Role   | admin               |
+----------------+---------------------+
+-----------+--------+---------------+
|  ENGINE   |  ROLE  |  EXPIRATION   |
+-----------+--------+---------------+
| dev       | admin  | in 2 hours    |
| prod      | admin  | 2 days ago    |
| staging   | admin  | 2 days ago    |
+-----------+--------+---------------+
+-------------+--------------------------------------+
|    VAULT    |                                      |
+-------------+--------------------------------------+
| ClusterID   | 0e6b2fcd-e84b-a7cd-f84d-6b31947a8d73 |
| ClusterName | vault-cluster-90f72c95               |
| Initialized | true                                 |
| Sealed      | false                                |
| Version     | 1.5.3                                |
+-------------+--------------------------------------+

Required Vault policies

To be able to use all the lookup features, you will need some

# List available AWS engines
path "sys/mounts" {
  capabilities = ["read"]
}

# List all the roles for each <engine_path>
# path "<engine_path>/roles" {
#  capabilities = ["list"]
# }
# eg:
path "dev/roles" {
 capabilities = ["list"]
}

path "staging/roles" {
 capabilities = ["list"]
}

# Assume the role
# path "<engine_path>/sts/<role>" {
#  capabilities = ["update"]
# }
# eg:

path "dev/sts/admin" {
  capabilities = ["update"]
}

path "staging/sts/admin" {
  capabilities = ["update"]
}

Limitations

  • It currently only supports authenticating using STS assumed_role or federation_tokens methods.
  • It will list all available engines and roles according to the defined policies. This result may not be relevant to what an user can actually assume.

Contribute

Contributions are more than welcome! Feel free to submit a PR.