We've already seen the basics of Vault and wrote some code to access it in the last posts, this time we'll focus on two aspects that allow us to have more control over who can do what with our vault. Let's dive into it.

Managing tokens

As you can remember, in the first post of the series, when we initialized our Vault instance, apart from sealing keys we received one root token, that allowed us to perform all operations on the storage. That would be awful, however, if we were to be limited to that one token, right? Fortunately, we can create additional ones pretty easily:

$ VAULT_ADDR='http://127.0.0.1:8888' vault token create       
Key                Value
---                -----
token              f76b3273-f7e4-8718-f16a-8dc4868cb959
token_accessor     fbd8553b-437d-a41e-3725-ee0083a83b44
token_duration     ∞
token_renewable    false
token_policies     [root]

Simple command allowed us to get another token, with root permissions as well. This is because by default when we create a token it has the same permissions as its parent, that is the token which is in use when token create command is called.

We can see the details describing the token with token lookup <TOKEN> command:

$ VAULT_ADDR='http://127.0.0.1:8888' vault token lookup 5778006b-b064-ad1d-e924-5906338d8026
Key                 Value
---                 -----
accessor            758aeb74-c73c-d86b-7a7e-736596b688c1
creation_time       1516827727
creation_ttl        0
display_name        token
entity_id           n/a
expire_time         <nil>
explicit_max_ttl    0
id                  5778006b-b064-ad1d-e924-5906338d8026
issue_time          2018-01-24T22:02:07.100201594+01:00
meta                <nil>
num_uses            0
orphan              false
path                auth/token/create
policies            [root]
renewable           false
ttl                 0

We can also, obviously, delete the token using token revoke, after which we can check that it is indeed, not available any more:

$ VAULT_ADDR='http://127.0.0.1:8888' vault token revoke 5778006b-b064-ad1d-e924-5906338d8026 
Success! Revoked token (if it existed)
$ VAULT_ADDR='http://127.0.0.1:8888' vault token lookup 5778006b-b064-ad1d-e924-5906338d8026
Error looking up token: Error making API request.

URL: POST http://127.0.0.1:8888/v1/auth/token/lookup
Code: 403. Errors:

* bad token

Limited access

While you may be fine with generating tokens with root access rights while you are playing around with Vault, but using it in real life requires putting some restrictions. You can do that using policies, where you can define what can, and cannot be done, and then use that policy when creating a token.

We start with creating an HCL file with policy details. Its structure is simple to follow, as you need to define path elements and actions that can be done with keys that match that path:

# policy.hcl
path "secret/foo" {
    capabilities = ["read"]
}

path "secret/*" {
    capabilities = ["create", "read", "update", "delete", "list"]
}

In the policy stated above, the users will be able to do everything with all keys under secret/ path, except for secret/foo which can only be read. Next step will be to write that policy to the Vault:

$ VAULT_ADDR='http://127.0.0.1:8888' vault policy write policy1 policy.hcl      
Success! Uploaded policy: policy1

Now we can create a token using -policy parameter and the name we used for our policy:

$ VAULT_ADDR='http://127.0.0.1:8888' vault token create -policy=policy1        
Key                Value
---                -----
token              61fa3497-820d-85f5-271d-f20ec6f6c39e
token_accessor     37f91273-721d-b0f6-b8b4-59c8eff93b9a
token_duration     768h
token_renewable    true
token_policies     [default policy1]

Let's first create a secret/foo key with a root token, then we can login using the newly created token and see what we can and cannot do:

$ VAULT_ADDR='http://127.0.0.1:8888' vault login 61fa3497-820d-85f5-271d-f20ec6f6c39e
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.

Key                Value
---                -----
token              61fa3497-820d-85f5-271d-f20ec6f6c39e
token_accessor     37f91273-721d-b0f6-b8b4-59c8eff93b9a
token_duration     767h59m52s
token_renewable    true
token_policies     [default policy1]

We can list all secrets...

$ VAULT_ADDR='http://127.0.0.1:8888' vault list secret                               
Keys
----
foo

...create a new one...

$ VAULT_ADDR='http://127.0.0.1:8888' vault write secret/hello value=world
Success! Data written to: secret/hello

...alter it...

$ VAULT_ADDR='http://127.0.0.1:8888' vault write secret/hello value=friend
Success! Data written to: secret/hello

...read it...

$ VAULT_ADDR='http://127.0.0.1:8888' vault read secret/hello         
Key                 Value
---                 -----
refresh_interval    768h
value               friend

...and delete:

$ VAULT_ADDR='http://127.0.0.1:8888' vault delete secret/hello
Success! Data deleted (if it existed) at: secret/hello

What about secret/foo? We can read it...

$ VAULT_ADDR='http://127.0.0.1:8888' vault read secret/foo                
Key                 Value
---                 -----
refresh_interval    768h
value               bar

...but cannot alter it, nor delete:

$ VAULT_ADDR='http://127.0.0.1:8888' vault write secret/foo value=newbar
Error writing data to secret/foo: Error making API request.

URL: PUT http://127.0.0.1:8888/v1/secret/foo
Code: 403. Errors:

* permission denied
$ VAULT_ADDR='http://127.0.0.1:8888' vault delete secret/foo       
Error deleting secret/foo: Error making API request.

URL: DELETE http://127.0.0.1:8888/v1/secret/foo
Code: 403. Errors:

* permission denied

This confirms that our policy works just like we wanted. More on policies can be found in the docs.