vault-config

Example config for a single-node experimental HashiCorp Vault instance

Get started

Make sure Vault has access to:

  • /vault/file: storage location for the file backend
  • /vault/logs: storage location for audit logs
  • /vault/config: storage location for config file

Run Vault as:

vault server -config=/vault/config/vault.hcl

Refer to config/vault.hcl for content.

Configure

Once Vault's initialized and with your root token in hand log in via the token auth method, make the following changes:

  • Add policies from policies/role-administrator subdirectory into Vault
  • Create group administrators
  • Assign policies administrator and auditor to that group
  • Create one entity to represent yourself as an administrator
  • Create one alias assigned to that entity for you to use as a username
  • Enable auth method userpass
  • Create one userpass username named like your alias, define your own password
  • Add your own entity to group administrators

Log out. Never again use the root token unless there's a good reason.

Get the Vault command-line client via vaultproject.io/downloads. It'll install the Vault service itself along with the command-line client. Just ignore the service or keep it disabled via systemctl disable --now vault.service. You only need the vault binary.

  • Authenticate against Vault:

    export VAULT_ADDR='https://fully.qualified.domain.name/'
    vault login
    
    # Which will prompt for:
    Token (will be hidden): 
    

    Enter your personal alias' token, do not ever again use the root token.

  • Enable audit file device (in non-Vault-speak "the audit log file"):

    # Enable
    vault audit enable file file_path=/vault/logs/audit.log
    
    # Expected output:
    Success! Enabled the file audit device at: file/
    

    Confirm:

    # Confirm
    vault audit list
    
    # Expected output
    Path     Type    Description
    ----     ----    -----------
    file/    file    n/a
    
  • We're going to allow all human users to change their own userpass password. The policy to do so is at policies/role-human/change-own-password.hcl. For a hands-on example of an actual password change via HTTP API see Hands-on but first:

    • Before you can load the policy into Vault you need to replace the string ACCESSOR in it with your particular userpass accessor. Get it like so:

      # List auth methods
      vault auth list
      
      # Expected result similar to:
      Path         Type        Accessor                  Description
      ----         ----        --------                  -----------
      token/       token       auth_token_d3aad127       token based credentials
      userpass/    userpass    auth_userpass_6671d643    n/a
      

      Over in policies/role-human/change-own-password.hcl replace ACCESSOR with what you're seeing here in the Accessor column. Feel free to read up on templated policies for more info.

    • Load the policy

    • Create a group for humans and assign the policy change-own-password to it.

      # Create group
      vault write identity/group name="humans" policies="change-own-password"
      
      # Expected output:
      Success! Data written to: identity/group/name/humans
      

      Adding member entities to your group may be best done via Vault's UI. If we're just talking about a few member entities then the CLI does it like so:

      # Create group
      vault write identity/group name="humans" policies="change-own-password" member_entity_ids="<uuid>,<uuid>,<uuid>"
      
      # Expected output:
      Success! Data written to: identity/group/name/humans
      

      Entity IDs are coming from vault list identity/entity/id and/or vault read identity/entity/name/<name>.

  • Optionally policies/role-cfgmgmt/cfgmgmt.hcl gets you started with read-only secrets access for example for a config management tool like Ansible.

    You'll want to create an Ansible entity with an alias and create both a token and a userpass alias. Lastly within the userpass auth method create a user of the same name used for both the entity and its aliases and use that user to authenticate against Vault. Retrieve a token. You'll likely want a distinct group where your Ansible entity becomes a member and which uses a policy such as the example at policies/role-cfgmgmt/cfgmgmt.hcl.

    From here on out it's just more of what you already did, feel free to make this fit your own approach.

  • Optionally from policies/role-kv-writer/kv-writer.hcl load a policy that allows affected entities to create kv secrets, create new versions for existing secrets and to traverse the UI directory structure of secrets. Entities with this policy will not be able to read secrets nor see if versions exist at a given location.

    Permission to also read/view secrets is commented out in the policy file in case you do need this feature.

    Assign the policy to a group as needed.

  • As a similar narrowly scoped use case consider a Zabbix monitoring instance that may need access to credentials, session IDs, tokens or other forms of authentication to monitor machines and services.

    Here's one suggestion to set up the basics for Zabbix.

    In Vault with a user that has sufficient permissions:

    • Create an entity zabbix without a policy.
    • Add an alias of type userpass to the entity.
    • Within the userpass auth method create a user (an account if you will) with the same name as the alias you just created so in this case zabbix, set a password for the account

    Now tie it all together by creating a group named rbacgroup_zabbix. Add the zabbix entity to it and make it use the policy role-zabbix. At this point the policy does not yet exist which is fine, you can set a policy name and Vault will offer to Add new policy. Don't worry, this will not actually add a new policy - empty, broken or otherwise. Vault will simply link your group to the policy role-zabbix which does not exist. You'll get to that in a minute.

    Like so: Vault 1.11.3 Create Group menu

    Next up check out policies/role-zabbix/role-zabbix.hcl. Do some light replacement before importing it into Vault. The policy file contains a few occurrences of the string GROUPID, replace them with the group ID of rbacgroup_zabbix.

    • Via Vault's UI you can get the group ID at Access > Groups > rbacgroup_zabbix.
    • Via the vault command-line client you can do it like so where the id value is what you're after:
      # Get 'rbacgroup_zabbix' group metadata
      vault kv get /identity/group/name/rbacgroup_zabbix
      
      # Expected output similar to:
      == Metadata ==
      
      ========== Data ==========
      Key                  Value
      ---                  -----
      alias                map[]
      creation_time        2022-09-22T21:47:57.720309362Z
      id                   88560da7-e180-3d2e-9053-dc0ee4ba7fbe
      ...
      

    With your ID in hand and policies/role-zabbix/role-zabbix.hcl updated import it as a new policy. You're going to want to save it with the same policy name you assigned earlier to rbacgroup_zabbix which was role-zabbix. This role will grant read-only access to secrets underneath a folder for_rbacgroup_zabbix which in our example lives inside a kv version 2 secrets engine mounted at its default location kv.

    So whenever your Zabbix instance needs access to something store secrets underneath kv/for_rbacgroup_zabbix. The policy will make sure only the group with correct ID will have access to secrets.

    Log in to Vault with userpass and the zabbix account from above, get the account's token and lastly double-check that zabbix with its token can read a secret:

    curl --silent --location --header 'X-Vault-Token: <token>' \
        "${VAULT_ADDR}"'v1/kv/data/for_rbacgroup_zabbix/some/secret' \
        | jq '.data.data'
    

    Configure Zabbix with its own Vault token and enjoy no longer having to store any secrets in Zabbix itself.

    Side note, if your token regularly expires you may want to store the token itself in Vault and let Zabbix monitor token expiry via the Zabbix equivalent of:

    # Look up a token's own attributes
    curl --silent --location --header 'X-Vault-Token: <token>' \
        "${VAULT_ADDR}"'v1/auth/token/lookup-self' \
        | jq '.data.ttl'
    
    # .data.ttl will show remaining validity in secs:
    2754536
    

    Users wishing to browse the rbacgroup_zabbix directory structure via Vault's UI will need to manually begin their browsing at kv/list/for_rbacgroup_zabbix. Users with higher privileges such as administrators will be able to list all directories underneath the root kv object in Vault's web UI. This will include not only zabbix-specific data but also directories intended for other users which is why kv/list access is not granted to rbacgroup_zabbix.

    Their list permission only begins one lever deeper at kv/list/for_rbacgroup_zabbix. It may make sense to communicate an entrypoint link to end users that - in this case - will look like:

    "${VAULT_ADDR}"'/ui/vault/secrets/kv/list/for_rbacgroup_zabbix/'
    

Clean-up

If during any of the above steps you've used the Vault command-line client to authenticate against Vault with your root token make sure that client's ~/.vault-token file is deleted. It contains the verbatim root token.

Hands-on

How to change a password via API call, see docs at vaultproject.io:

curl \ 
    --header 'X-Vault-Token: '"${vaultToken}" \ 
    --request POST \ 
    --data '{"password": "'"${newPassword}"'"}' \ 
    'https://f.q.d.n/v1/auth/userpass/users/'"${username}"'/password'

If successful Vault will not return data. You may want to make response headers visible via curl --include. A successful password change results in an HTTP status code 204.

Description
Example config for a single-node experimental HashiCorp Vault instance
Readme 188 KiB
Languages
HCL 100%