Codiwan.com

The blog for Design Patterns, Linux, HA and Myself!

Hashicorp Vault Installation, Userpass, KV Secrets and Policy Authorization

Vault installation with tutorial on Userpass authentication with Policy Authorization

This document presents the installation steps for Hashicorp Vault and then proceeds with an example scenario involving the userpass username password based authentication, KV Secrets engine and Policy Authorization. This document is divided into the following sections:

Hashicorp Vault Installation

In this section we will look into vault installation process. It requires downloading the gpg key, adding the repository and installing the vault.

$ curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead (see apt-key(8)).
OK
$ sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
Repository: 'deb [arch=amd64] https://apt.releases.hashicorp.com hirsute main'
:
Reading package lists... Done
$ sudo apt-get update && sudo apt-get install vault

Then update the vault configuration based on your preferences. I’ll be using the following configuration for vault:

$ cat /etc/vault/config.hcl
storage "file" {
  path = "/opt/vault/data"
}
listener "tcp" {
  address = "192.168.56.104:8200"
  tls_disable = 0
  tls_cert_file = "/etc/vault/certs/192.168.56.104.pem"
  tls_key_file = "/etc/vault/certs/192.168.56.104-key.pem"
}
ui = true

This config file is not the default one, so we will need to update the SystemD service file as well so that Vault picks up this configuration file. I’ve generated the certificates using mkcert. The service file is located at /usr/lib/systemd/system/vault.service. The ExecStart property needs to be updated here:

ExecStart=/usr/bin/vault server -config=/etc/vault/config.hcl

Once the file is changed, perform daemon reload and restart the Vault service:

$ systemctl daemon-reload
$ systemctl restart vault.service
$ systemctl status vault.service

Export the Vault URI so that we don’t have to pass it wth every command:

$ export VAULT_ADDR='https://192.168.56.104:8200'

Setup the Vault completion and update the .bashrc so that it is executed after starting shell next time onwards. I’m using .bashrc here but this file will different if you’re using ZSH or FISH.

$ vault -autocomplete-install
$ complete -C /usr/local/bin/vault vault
$ source ~/.bashrc

After the initial startup Vault will always be SEALED. We can check its status using:

$ vault status
Key                Value
---                -----
Seal Type          shamir
Initialized        false
Sealed             true
Total Shares       0
Threshold          0
Unseal Progress    0/0
Unseal Nonce       n/a
Version            1.7.3
Storage Type       file
HA Enabled         false

Let’s start the unseal process. After executing the operator init subcommand it will print out the list of all the unseal keys and the Root Token. These keys and tokens are important and must be copied to a different place so that we don’t lose them. The unsealing process will be done using the Unseal keys and the first time login will be done using the Root Token.

$ vault operator init
Unseal Key 1: XjGtrLO9NQxORIls6pqzFRFS1BN8K1atfbFTnS9SXk0t
Unseal Key 2: K9ujZAorX2IqU0I2zs0aFHhpcyvLbaCO/gPlO/YNKJgP
Unseal Key 3: otplWPfKoVtuq4q5ti8HZIQ+shzmp6fVSoAmnzIYsN+R
Unseal Key 4: xjQWO5vPYVUXZvRaFDYND2d5JU8iF/foCMkifsmxfR4U
Unseal Key 5: 2Ne5s0OHSJT6kUnfLde1E+GvObRj/h6ppbPJjBEZrQi1

Initial Root Token: s.tgisePwqWHIYDkVRZZtKa06m

Vault initialized with 5 key shares and a key threshold of 3. Please securely
distribute the key shares printed above. When the Vault is re-sealed,
restarted, or stopped, you must supply at least 3 of these keys to unseal it
before it can start servicing requests.

Vault does not store the generated master key. Without at least 3 key to
reconstruct the master key, Vault will remain permanently sealed!

It is possible to generate new unseal keys, provided you have a quorum of
existing unseal keys shares. See "vault operator rekey" for more information.

Vault listed all the 5 unseal keys, however, to unseal it we just need only 3 unseal keys. Their order do not matter. Execute vault operator unseal and pass the first unseal key. You’ll notice that the Unseal Progress has changed to 1/3. This way we need to pass all the 3 Unseal keys and finally the Sealed status vaule will change to false.

$ vault operator unseal
Unseal Key (will be hidden):
Key                Value
---                -----
Seal Type          shamir
Initialized        true
Sealed             true
Total Shares       5
Threshold          3
Unseal Progress    1/3
Unseal Nonce       2bf63b58-c4ee-e584-3ff5-20705bc01017
Version            1.7.3
Storage Type       file
HA Enabled         false
$ vault operator unseal
Unseal Key (will be hidden):
Key                Value
---                -----
Seal Type          shamir
Initialized        true
Sealed             true
Total Shares       5
Threshold          3
Unseal Progress    2/3
Unseal Nonce       2bf63b58-c4ee-e584-3ff5-20705bc01017
Version            1.7.3
Storage Type       file
HA Enabled         false
$ vault operator unseal
Unseal Key (will be hidden):
Key             Value
---             -----
Seal Type       shamir
Initialized     true
Sealed          false
Total Shares    5
Threshold       3
Version         1.7.3
Storage Type    file
Cluster Name    vault-cluster-43a0999e
Cluster ID      be8bfba1-72c5-743a-3458-a9d8932ce36c
HA Enabled      false

The Vault status can also be checked using the following command:

$ vault status
Key             Value
---             -----
Seal Type       shamir
Initialized     true
Sealed          false
Total Shares    5
Threshold       3
Version         1.7.3
Storage Type    file
Cluster Name    vault-cluster-43a0999e
Cluster ID      be8bfba1-72c5-743a-3458-a9d8932ce36c
HA Enabled      false

Let’s log in now using the Root Token:

$ vault login
Token (will be hidden):
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                s.tgisePwqWHIYDkVRZZtKa06m
token_accessor       VtYVHHlIpMWwZpR5gVauhLrQ
token_duration       ∞
token_renewable      false
token_policies       ["root"]
identity_policies    []
policies             ["root"]

Vault KV Secrets Engine

To store the Key Value config parameters we need to first enable the KV secrets engine using the following command:

$ vault secrets enable --path=servers kv
Success! Enabled the kv secrets engine at: servers/

Here the path is servers. This means that the all keys that we will save in this secrets engine will always be prepended by the servers/ path. This is where the secrets will be stored.

We can then find the path at which the secrets engines are mounted using the following command as well:

$ vault secrets list
Path          Type         Accessor              Description
----          ----         --------              -----------
cubbyhole/    cubbyhole    cubbyhole_7064544c    per-token private secret storage
identity/     identity     identity_7bac5daa     identity store
servers/      kv           kv_e047147c           n/a
sys/          system       system_875f4e5e       system endpoints used for control, policy and debugging

Let’s enter some secrets into the KV secrets engine:

$ vault kv put servers/us-west id=us-west location=california
Success! Data written to: servers/us-west
$ vault kv put servers/us-east id=us-east location=newyork
Success! Data written to: servers/us-west
$ vault kv put servers/in-east id=in-east location=kolkata
Success! Data written to: servers/us-west
$ vault kv put servers/in-west id=in-west location=mumbai
Success! Data written to: servers/us-west

Here we’ve inserted 4 keys. Then we can get the list of all the secrets present inside the servers path using the list sub command:

$ vault kv list servers
Keys
----
in-east
in-west
us-east
us-west

We can use get subcommand with kv to get the values:

$ vault kv get servers/in-west
====== Data ======
Key         Value
---         -----
id          in-west
location    mumbai
$ vault kv get servers/in-east
====== Data ======
Key         Value
---         -----
id          in-east
location    kolkata

Vault Policy Methods

In this section we will look into Vault Policies. We will create two policies:

  1. Admin
    • They can possibly perform any action, like, creating secrets or deleting them.
    path "*" {
        capabilities = ["create", "read", "update", "delete", "list", "sudo"]
    }
    
  2. Non Admin
    • They are less powerful than the Admins.
    • They can read all the secrets present inside the servers/ path.
    • They can modify the servers/in-east KV secret.
     path "servers/*" {
         capabilities = ["list", "read"]
     }
     path "servers/in-east" {
         capabilities = ["list", "read", "update"]
     }
    

Let’s write them:

$ vault policy write admin policies/admin.hcl
Success! Uploaded policy: admin
$ vault policy write nonadmin policies/nonadmin.hcl
Success! Uploaded policy: nonadmin

To list out the policy execute vault policy list:

$ vault policy list
admin
default
nonadmin
root

To read the policy execute:

$ vault policy read admin
path "*" {
    capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}
$ vault policy read nonadmin
path "servers/*" {
  capabilities = ["list", "read"]
}
path "servers/in-east" {
  capabilities = ["list", "read", "update"]
}

userpass Username Password Authentication and Authorization

To allow users to login and use Vault we need to enable the userpass authentication first:

$ vault auth enable userpass
Success! Enabled userpass auth method at: userpass/

With this method enabled we can create users with username and password and assign them policies while creation. In this example we will create two user: Admin and User1 and then assign them the admin and nonadmin policies respectively.

$ vault write auth/userpass/users/admin password=admin policies=admin
Success! Data written to: auth/userpass/users/admin
$ vault write auth/userpass/users/user1 password=user1 policies=nonadmin
Success! Data written to: auth/userpass/users/user1

Let’s log in using the admin user’s credentials and verify if the correct polices are mapped and granted.

$ vault login -method=userpass username=admin
Password (will be hidden):
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                  s.pe7gGITxX8hw1vRVAkxuoKEp
token_accessor         9QA0iDFsU6YYTZFHGCa0uHMD
token_duration         768h
token_renewable        true
token_policies         ["admin" "default"]
identity_policies      []
policies               ["admin" "default"]
token_meta_username    admin

In the token_policies section we can check that the token generated for the user has the admin policies. Since we’ve granted this user the permission to list all the secrets, it can perform that action:

$ vault secrets list
Path          Type         Accessor              Description
----          ----         --------              -----------
cubbyhole/    cubbyhole    cubbyhole_7064544c    per-token private secret storage
identity/     identity     identity_7bac5daa     identity store
servers/      kv           kv_e047147c           n/a
sys/          system       system_875f4e5e       system endpoints used for control, policy and debugging

Likewise it can access the secrets that we had created earlier using the Root user.

$ vault kv get servers/in-east
====== Data ======
Key         Value
---         -----
id          in-east
location    kolkata
$ vault kv get servers/in-west
====== Data ======
Key         Value
---         -----
id          in-west
location    mumbai

Along with accessing them, it can edit them as well.

$ vault kv put servers/in-east id=in-east location=shillong
Success! Data written to: servers/in-east
$ vault kv get servers/in-east
====== Data ======
Key         Value
---         -----
id          in-east
location    shillong

Let’s log in using the user User1.

$ vault login -method=userpass username=user1
Password (will be hidden):
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                  s.ihNHc7SH49UH46v2N4PpTJYb
token_accessor         h2SjkDcoZ56M2sasIX2J6DYI
token_duration         768h
token_renewable        true
token_policies         ["default" "nonadmin"]
identity_policies      []
policies               ["default" "nonadmin"]
token_meta_username    user1

Since we’ve only granted the user the permission to view the servers KV secrets, it cannot list the secrets:

$ vault secrets list
Error listing secrets engines: Error making API request.

URL: GET https://192.168.56.104:8200/v1/sys/mounts
Code: 403. Errors:

* 1 error occurred:
        * permission denied
$ vault kv list servers
Keys
----
in-east
in-west
us-east
us-west

Along with permission to view the secrets, we’ve granted the user the permission to update the in-east. Let’s test that. If the user tries to update us-east then it will get 403 Permission Denied error, however, if it can safely perform the same operation with the in-east key.

$ vault kv get servers/us-east
=== Data ===
Key    Value
---    -----
id     us-east
$ vault kv put servers/us-east location=123
Error writing data to servers/us-east: Error making API request.

URL: PUT https://192.168.56.104:8200/v1/servers/us-east
Code: 403. Errors:

* 1 error occurred:
        * permission denied


$ vault kv put servers/in-east id=in-east location=kolkata
Success! Data written to: servers/in-east
Loading Comments... Disqus Loader
comments powered by Disqus