home / writing / hashicorp-vault-essentials

HashiCorp Vault Essentials

Vault centralises secrets and encryption behind an API. This guide explains its architecture, the seal model, authentication, policies, secrets engines, dynamic credentials and HA setup.

What Vault is and how it is built

Vault is a secrets management and data protection service. Applications and people authenticate to it, and in return receive short-lived access to secrets, encryption services or generated credentials. Everything is accessed through an HTTP API; the CLI and web UI are clients of that API.

The main components are:

  • Storage backend: where Vault persists data. Everything written there is encrypted first, so the backend itself is untrusted.
  • Barrier: the encryption layer between Vault's logic and storage.
  • Auth methods: verify an identity and issue a token.
  • Secrets engines: components mounted at paths that store, generate or encrypt data.
  • Audit devices: log every request and response (with sensitive values hashed).
  • Policies: path-based rules that decide what a token may do.

Everything in Vault is a path. Secrets engines are mounted at paths like secret/ or database/, auth methods live under auth/, and system configuration under sys/. A dev-mode server (vault server -dev) is handy for learning, but it keeps data in memory, starts unsealed and must never be used in production.

Initialization, seal and unseal

A new server must be initialized once with vault operator init. This generates the encryption key that protects data and a root key that protects that key, splits the root key into shares (with the default Shamir seal), and returns an initial root token. Give the shares to separate trusted people and never store them in tickets, chat or repositories.

A sealed Vault knows where its data is but cannot decrypt it. To unseal, a threshold of key shares (for example 3 of 5) is provided with vault operator unseal. The server re-seals on restart or when you run vault operator seal, which is also an emergency brake.

MethodHow it works
Shamir sharesHumans supply a threshold of key shares after each start
Cloud KMS auto-unsealA cloud key service protects the root key; nodes unseal themselves on boot
Transit auto-unsealAnother Vault cluster's transit engine wraps the root key

Auto-unseal removes manual unsealing at the cost of a dependency on the external service, so protect and monitor it. Revoke and stop using the initial root token once other admin access is configured; a new one can be generated when needed with vault operator generate-root.

Authentication methods and tokens

Auth methods are enabled per path and fall into two broad groups. Human methods include userpass, LDAP and OIDC/SSO. Machine methods include AppRole, Kubernetes service accounts, and cloud identity methods (AWS, Azure, GCP). Prefer a method based on an identity the client already has, to avoid distributing another long-lived secret.

vault auth enable approle
vault write auth/approle/role/web token_policies="web-read" token_ttl=1h token_max_ttl=4h
vault read auth/approle/role/web/role-id

Every successful login produces a token, and tokens are what policies attach to. Key facts:

  • Service tokens are the default: renewable, revocable, with child tokens and leases tracked in storage.
  • Batch tokens are lightweight, not stored, and not renewable; useful for high-volume short tasks.
  • Tokens have a TTL and a max TTL; periodic tokens can be renewed indefinitely, and orphan tokens have no parent, so revoking a parent does not revoke them.
  • Revoking a token revokes its children and associated leases.
  • Token accessors let you look up or revoke a token without knowing its value.

Entities and groups unify several logins (for example the same person via LDAP and OIDC) under one identity for policy assignment.

Policies

Vault is deny-by-default. A policy lists paths and the capabilities allowed on each: create, read, update, delete, list, plus special ones such as sudo and deny.

path "secret/data/web/*" {
  capabilities = ["read", "list"]
}

path "secret/data/{{identity.entity.name}}/*" {
  capabilities = ["create", "read", "update"]
}

path "sys/*" {
  capabilities = ["deny"]
}

* matches a trailing wildcard and + matches exactly one path segment. Templated paths use identity values so one policy can serve many users. Load policies with vault policy write web-read web-read.hcl. Two built-ins exist: default, attached to tokens unless explicitly excluded, and root, which allows everything. Note that for the KV version 2 engine the API paths include data/ and metadata/, a frequent source of "permission denied" errors.

Secrets engines

Enable an engine at a path with vault secrets enable.

  • KV stores arbitrary key-value data. Version 2 adds versioning, soft delete and custom metadata.
  • Transit provides encryption as a service: apps send plaintext and receive ciphertext, and keys never leave Vault. Keys can be rotated, and old ciphertext can be rewrapped to a newer key version.
  • PKI issues X.509 certificates on demand with short lifetimes.
  • Database, AWS and others generate credentials dynamically.
  • TOTP generates and validates one-time codes.
  • Cubbyhole is a per-token private store, used for response wrapping.
vault secrets enable -path=secret kv-v2
vault kv put secret/web/config api_key=changeme
vault kv get -field=api_key secret/web/config

vault secrets enable transit
vault write -f transit/keys/orders
vault write transit/encrypt/orders plaintext=$(base64 <<< "hello")

Dynamic secrets and leases

Static secrets are shared and long-lived. With dynamic secrets, Vault creates a unique credential when a client asks, for example a database user with specific grants, and deletes it when its lease ends. Compromise of one credential has a small blast radius, and every credential is traceable to a requester.

Each dynamic secret comes with a lease: an ID, a duration, and a renewable flag. Clients renew leases while still working, or let them expire. Operators can revoke one lease, or a whole prefix with vault lease revoke -prefix, to cut access immediately. Set default and maximum lease TTLs per engine.

Short TTLs only help if applications cope with rotation. Make clients renew leases or re-fetch credentials, and keep connection pools able to pick up new database users.

Vault Agent

Vault Agent runs next to an application and handles the Vault-specific work for it. It performs auto-auth (logging in with a configured method and keeping the token renewed), optional caching of tokens and leases, and templating that renders secrets into files such as config or environment files and re-renders them when values change. A sink can also write the token to a file for other processes. On Kubernetes, an injector can add the agent as a sidecar based on pod annotations.

Storage and high availability

Vault's recommended storage is integrated storage (Raft), which keeps data on each node's disk and replicates it with consensus, so no separate database is needed. Use three or five nodes. One node is the active leader that serves writes; the others are standbys that forward or redirect requests and take over if the leader fails. Consul and other external backends are also supported, but add another system to operate.

  • Take regular snapshots with vault operator raft snapshot save and test restores.
  • Enable at least one audit device before serving traffic; Vault refuses requests if all audit devices fail.
  • Use TLS everywhere and restrict network access to the API port.
  • Enterprise features add namespaces for multi-tenancy and performance or disaster-recovery replication across clusters.