search by tags

for the user

adventures into the land of the command line

chickens & eggs & hashicorp vault

I wanted to learn how to do secret storage, never having done so before, so I tried out the hashicorp vault mostly because I like their website. So how did it go? Well I ended up thinking…

“But where do I store the secret that gives me access to the vault? And what if I lose it?”

Anyway…

Download the installation package for your distribution. At the time of writing this is the latest linux 64 bit one.

$ [email protected]:~# wget https://releases.hashicorp.com/vault/0.9.1/vault_0.9.1_linux_amd64.zip

Unzip it and add the binary to your path

$ [email protected]:~# unzip vault_0.9.1_linux_amd64.zip
$ [email protected]:~# ls -l
total 91960
-rwxr-xr-x 1 root root 76376780 Dec 21 13:43 vault
-rw-r--r-- 1 root root 17784524 Dec 21 13:45 vault_0.9.1_linux_amd64.zip

$ [email protected]:~# mv vault /usr/bin/vault

$ [email protected]:~# vault
usage: vault [-version] [-help]  [args]

Common commands:
    delete           Delete operation on secrets in Vault
    path-help        Look up the help for a path
    read             Read data or secrets from Vault
    renew            Renew the lease of a secret
    revoke           Revoke a secret.
    server           Start a Vault server
    status           Outputs status of whether Vault is sealed and if HA mode is enabled
    unwrap           Unwrap a wrapped secret
    write            Write secrets or configuration into Vault

All other commands:
    audit-disable    Disable an audit backend
    audit-enable     Enable an audit backend
    audit-list       Lists enabled audit backends in Vault
    auth             Prints information about how to authenticate with Vault
    auth-disable     Disable an auth provider
    auth-enable      Enable a new auth provider
    capabilities     Fetch the capabilities of a token on a given path
    generate-root    Generates a new root token
    init             Initialize a new Vault server
    key-status       Provides information about the active encryption key
    list             List data or secrets in Vault
    mount            Mount a logical backend
    mount-tune       Tune mount configuration parameters
    mounts           Lists mounted backends in Vault
    policies         List the policies on the server
    policy-delete    Delete a policy from the server
    policy-write     Write a policy to the server
    rekey            Rekeys Vault to generate new unseal keys
    remount          Remount a secret backend to a new path
    rotate           Rotates the backend encryption key used to persist data
    seal             Seals the Vault server
    ssh              Initiate an SSH session
    step-down        Force the Vault node to give up active duty
    token-create     Create a new auth token
    token-lookup     Display information about the specified token
    token-renew      Renew an auth token if there is an associated lease
    token-revoke     Revoke one or more auth tokens
    unmount          Unmount a secret backend
    unseal           Unseals the Vault server
    version          Prints the Vault version

Start a dev server for some devving, it won’t fork, so you’ll have to open another terminal session or use the linux process manager.

[email protected]:~# vault server -dev > vault.log 2>&1 &

[email protected]:~# cat vault.log

==> Vault server configuration:

                     Cgo: disabled
         Cluster Address: https://127.0.0.1:8201
              Listener 1: tcp (addr: "127.0.0.1:8200", cluster address: "127.0.0.1:8201", tls: "disabled")
               Log Level:
                   Mlock: supported: true, enabled: false
        Redirect Address: http://127.0.0.1:8200
                 Storage: inmem
                 Version: Vault v0.9.1
             Version Sha: 87b6919dea55da61d7cd444b2442cabb8ede8ab1

==> WARNING: Dev mode is enabled!

In this mode, Vault is completely in-memory and unsealed.
Vault is configured to only have a single unseal key. The root
token has already been authenticated with the CLI, so you can
immediately begin using the Vault CLI.

The only step you need to take is to set the following
environment variables:

    export VAULT_ADDR='http://127.0.0.1:8200'

The unseal key and root token are reproduced below in case you
want to seal/unseal the Vault or play with authentication.

Unseal Key: r3DZ0KUChnyMrcS4V/mYd7TS6hbMCQ5XLuSiAOMAU9A=
Root Token: 542af63a-22cc-e5b7-24d8-7aa553348190

Vault says to set an env var and also tells you the unseal key and root token:

[email protected]:~# export VAULT_ADDR='http://127.0.0.1:8200'

[email protected]:~# vault status
Seal Type: shamir
Sealed: false
Key Shares: 1
Key Threshold: 1
Unseal Progress: 0
Unseal Nonce:
Version: 0.9.1
Cluster Name: vault-cluster-260ea1c4
Cluster ID: 17c1608b-08c4-6eb6-ed3f-6793f5696f65

High-Availability Enabled: false

ok… now some terminology…

Vault Backends

There are many available “backend” types in vault, which are organised into four groups: secret, auth, audit and plugin. The default backend is the secret type backend called key/value or “kv”.

For a full list of backends: https://www.vaultproject.io/docs/secrets/index.html and https://www.vaultproject.io/docs/auth/index.html

You can have multiple backends of the same type running at the same time in a vault server.

Inspect our vault mounts:

[email protected]:~# vault mounts
Path        Type       Accessor            Plugin  Default TTL  Max TTL  Force No Cache  Replication Behavior  Seal Wrap  Description
cubbyhole/  cubbyhole  cubbyhole_f5d60677  n/a     n/a          n/a      false           local                 false      per-token private secret storage
identity/   identity   identity_aac92a1d   n/a     n/a          n/a      false           replicated            false      identity store
secret/     kv         kv_ea250776         n/a     system       system   false           replicated            false      key/value secret storage
sys/        system     system_4eb47ada     n/a     n/a          n/a      false           replicated            false      system endpoints used for control, policy and debugging

Mount another kv backend:

[email protected]:~# vault mount kv
Successfully mounted 'kv' at 'kv'!

The mount point will be the same name as the backend.

[email protected]:~# vault mounts
Path        Type       Accessor            Plugin  Default TTL  Max TTL  Force No Cache  Replication Behavior  Seal Wrap  Description
cubbyhole/  cubbyhole  cubbyhole_f5d60677  n/a     n/a          n/a      false           local                 false      per-token private secret storage
identity/   identity   identity_aac92a1d   n/a     n/a          n/a      false           replicated            false      identity store
kv/         kv         kv_afeb2d17         n/a     system       system   false           replicated            false
secret/     kv         kv_ea250776         n/a     system       system   false           replicated            false      key/value secret storage
sys/        system     system_4eb47ada     n/a     n/a          n/a      false           replicated            false      system endpoints used for control, policy and debugging

Unmount it:

[email protected]:~# vault unmount kv
Successfully unmounted 'kv' if it was mounted

[email protected]:~# vault mounts
Path        Type       Accessor            Plugin  Default TTL  Max TTL  Force No Cache  Replication Behavior  Seal Wrap  Description
cubbyhole/  cubbyhole  cubbyhole_f5d60677  n/a     n/a          n/a      false           local                 false      per-token private secret storage
identity/   identity   identity_aac92a1d   n/a     n/a          n/a      false           replicated            false      identity store
secret/     kv         kv_ea250776         n/a     system       system   false           replicated            false      key/value secret storage
sys/        system     system_4eb47ada     n/a     n/a          n/a      false           replicated            false      system endpoints used for control, policy and debugging

Static Secrets

Write a secret:

[email protected]:~# vault write secret/hello value=world
Success! Data written to: secret/hello

Write multiple secrets:

[email protected]:~# vault write secret/hello value=world excited=yes
Success! Data written to: secret/hello

Read a secret:

[email protected]:~# vault read secret/hello
Key                 Value
---                 -----
refresh_interval    768h0m0s
excited             yes
value               world

Read with JSON formatting and find a value:

[email protected]:~# vault read -format=json secret/hello
{
    "request_id": "cf927d61-ee12-7b74-ba6e-603ac9ead38c",
    "lease_id": "",
    "lease_duration": 2764800,
    "renewable": false,
    "data": {
        "excited": "yes",
        "value": "world"
    },
    "warnings": null
}

[email protected]:~# vault read -format=json secret/hello | jq -r .data.value
world

Delete a secret:

[email protected]:~# vault delete secret/hello
Success! Deleted 'secret/hello' if it existed.

[email protected]:~# vault read secret/hello
No value found at secret/hello

Dynamic Secrets

Unlike the static stuff we did before, vault can also generate secrets dynamically, and let you revoke them any time after they’ve been created. There are several backends for dynamic secrets, generally to do with authentication and security. Some examples: aws backend, consul backend, pki backend, rabbitmq backend, etc.

Paths

Help with checking what is stored in what paths in your backend(s):

[email protected]:~# vault path-help secret
.
.
.
## PATHS

The following paths are supported by this backend. To view help for
any of the paths below, use the help command with any route matching
the path pattern. Note that depending on the policy of your auth token,
you may or may not be able to access certain paths.

    ^.*$
        Pass-through secret storage to the storage backend, allowing you to
        read/write arbitrary data into secret storage.

Authentication & Authorisation

[email protected]:~# vault token-create
Key             Value
---             -----
token           57820f37-3ef2-9620-1305-6f5c966b3629
token_accessor  0e4d46b8-0c7f-5c0a-d991-40e16d3c0890
token_duration  0s
token_renewable false
token_policies  [root]

[email protected]:~# vault auth 57820f37-3ef2-9620-1305-6f5c966b3629
Successfully authenticated! You are now logged in.
token: 57820f37-3ef2-9620-1305-6f5c966b3629
token_duration: 0
token_policies: [root]

[email protected]:~# vault token-revoke 57820f37-3ef2-9620-1305-6f5c966b3629
Success! Token revoked if it existed.

[email protected]:~# vault auth 57820f37-3ef2-9620-1305-6f5c966b3629
Error validating token: Error making API request.

URL: GET http://127.0.0.1:8200/v1/auth/token/lookup-self
Code: 403. Errors:

* permission denied

NON DEV (PROPER USE)

[email protected]:~# cat config.hcl
storage "inmem" {
  path = "vault"
}

listener "tcp" {
 address = "127.0.0.1:8200"
 tls_disable = 1
}

[email protected]:~# vault server -config=config.hcl > vault.log 2>&1 &
[1] 2737

[email protected]:~# vim vault.log

==> Vault server configuration:

                     Cgo: disabled
              Listener 1: tcp (addr: "127.0.0.1:8200", cluster address: "127.0.0.1:8201", tls: "disabled")
               Log Level:
                   Mlock: supported: true, enabled: true
                 Storage: inmem
                 Version: Vault v0.9.1
             Version Sha: 87b6919dea55da61d7cd444b2442cabb8ede8ab1

==> Vault server started! Log data will stream in below:


[email protected]:~# vault init
Unseal Key 1: h/EPkFa6FQJhW/h3fcYD+/My/OLNEnQ5k9p09mvMxF8x
Unseal Key 2: BJZjV8bAYfs+kMm0ROh2HU8oJPrf8uhs6xlo8Ul8xKLk
Unseal Key 3: /S+mjD4KjmX1IALoxi1zAFz8P8Qnaafq+esSoLvJ08ld
Unseal Key 4: W0o8OK3dOtgKiFhF9E50+h64rG7n6Yw/yJU/Ap6WSBrM
Unseal Key 5: lcliNRNqErh9a0XJ0heB6Pm2OSlkB0LJW7SvHAv3zcjx
Initial Root Token: c3105fc5-4294-132f-aed1-309d5b2d886b

Vault initialized with 5 keys and a key threshold of 3. Please
securely distribute the above keys. When the vault is re-sealed,
restarted, or stopped, you must provide at least 3 of these keys
to unseal it again.

Vault does not store the master key. Without at least 3 keys,
your vault will remain permanently sealed.


[email protected]:~# vault unseal
Key (will be hidden):
Sealed: true
Key Shares: 5
Key Threshold: 3
Unseal Progress: 1
Unseal Nonce: e6a46572-7021-0c91-5863-8f9db83b8700
[email protected]:~# vault unseal BJZjV8bAYfs+kMm0ROh2HU8oJPrf8uhs6xlo8Ul8xKLk
Sealed: true
Key Shares: 5
Key Threshold: 3
Unseal Progress: 2
Unseal Nonce: e6a46572-7021-0c91-5863-8f9db83b8700
[email protected]:~# vault unseal /S+mjD4KjmX1IALoxi1zAFz8P8Qnaafq+esSoLvJ08ld
Sealed: false
Key Shares: 5
Key Threshold: 3
Unseal Progress: 0


[email protected]:~# vault auth c3105fc5-4294-132f-aed1-309d5b2d886b
Successfully authenticated! You are now logged in.
token: c3105fc5-4294-132f-aed1-309d5b2d886b
token_duration: 0
token_policies: [root]


[email protected]:~# vault write secret/hello value=world
Success! Data written to: secret/hello

USING THE HTTP API

[email protected]:~# curl -X GET -H "X-Vault-Token:c3105fc5-4294-132f-aed1-309d5b2d886b" http://127.0.0.1:8200/v1/secret/hello
{"request_id":"74f1745d-ff57-c550-100f-24cac65b0c68","lease_id":"","renewable":false,"lease_duration":2764800,"data":{"value":"world"},"wrap_info":null,"warnings":null,"auth":null}


[email protected]:~# vault seal
Vault is now sealed.


[email protected]:~# curl -X GET -H "X-Vault-Token:c3105fc5-4294-132f-aed1-309d5b2d886b" http://127.0.0.1:8200/v1/secret/hello
{"errors":["Vault is sealed"]}


[email protected]:~# curl -X PUT -d '{"key": "W0o8OK3dOtgKiFhF9E50+h64rG7n6Yw/yJU/Ap6WSBrM"}' http://127.0.0.1:8200/v1/sys/unseal
{"type":"shamir","sealed":true,"t":3,"n":5,"progress":1,"nonce":"603fde4e-2d29-d59b-a6c8-7eaa301fc0f8","version":"0.9.1"}
[email protected]:~# curl -X PUT -d '{"key": "lcliNRNqErh9a0XJ0heB6Pm2OSlkB0LJW7SvHAv3zcjx"}' http://127.0.0.1:8200/v1/sys/unseal
{"type":"shamir","sealed":true,"t":3,"n":5,"progress":2,"nonce":"603fde4e-2d29-d59b-a6c8-7eaa301fc0f8","version":"0.9.1"}
[email protected]:~# curl -X PUT -d '{"key": "BJZjV8bAYfs+kMm0ROh2HU8oJPrf8uhs6xlo8Ul8xKLk"}' http://127.0.0.1:8200/v1/sys/unseal
{"type":"shamir","sealed":false,"t":3,"n":5,"progress":0,"nonce":"","version":"0.9.1","cluster_name":"vault-cluster-bc281258","cluster_id":"46188469-2e4d-70f4-90fe-d06e77b6b3ca"}


[email protected]:~# curl -X GET -H "X-Vault-Token:c3105fc5-4294-132f-aed1-309d5b2d886b" http://127.0.0.1:8200/v1/secret/hello
{"request_id":"cf8fc6d6-b269-9aa8-abaa-9ed7531a408a","lease_id":"","renewable":false,"lease_duration":2764800,"data":{"value":"world"},"wrap_info":null,"warnings":null,"auth":null}

Chicken first or the egg? I still don’t know…