HashiCorp Vault concentrates an organisation's most valuable machine credentials in one place, so a weak auth method, a surviving root token or an unmonitored audit gap turns the secrets manager into the single best target in the estate. This guide covers identity, policies, tokens and leases, auth methods for workloads, dynamic secrets and PKI, and production operation of seal, audit and upgrades. It is for platform engineers and operators running Vault Community, Enterprise or HCP Vault Dedicated. HashiCorp became part of IBM in February 2025; new Vault releases have shipped under the Business Source License 1.1 since August 2023, and the OpenBao fork (an OpenSSF sandbox project) shares most concepts here.
Key takeaways
- Everything in Vault resolves to a token. Auth methods exchange an external identity (a Kubernetes service account, a cloud role, an OIDC login) for a Vault token carrying policies, a TTL and a parent, so token hygiene is identity hygiene.
- Deny is the default, and deny always wins. An empty policy grants nothing, the most specific path match applies, and a
denycapability overrides every other capability includingsudo. - Dynamic secrets beat stored secrets. Database, cloud and PKI engines issue leased, per-client credentials that Vault revokes on expiry or on demand, including by prefix during an incident.
- Root tokens are for setup and emergencies only. Revoke the initial root token after configuration, regenerate one with
vault operator generate-rootand a key-holder quorum when needed, and revoke it again afterwards. - Audit devices are a hard dependency. Vault refuses requests it cannot log to at least one enabled audit device, so run two or more devices and ship the logs off the host.
How identity and access work in HashiCorp Vault
Vault separates who you are (auth methods and the identity store) from what you may do (ACL policies attached to tokens, entities and groups). Every request after login carries a token, and the token's policies, plus any entity and group policies, decide the outcome.
Auth methods
Auth methods mount under auth/ (default path auth/<type>) and can be mounted more than once at different paths. Disabling a mount logs out every client that authenticated through it. For external methods such as LDAP, Okta or GitHub, Vault rechecks the external account at login and on token renewal, but tokens already issued stay valid for their grant period unless revoked in Vault, which is why short TTLs matter.
| Auth method | Typical client | What proves identity | Main caution |
|---|---|---|---|
| Kubernetes | Pods | Service account JWT checked through the Kubernetes TokenReview API | Bind roles to specific service account names and namespaces; Vault's reviewer needs the system:auth-delegator ClusterRole |
| JWT/OIDC | CI/CD jobs, humans through an IdP, Kubernetes via OIDC discovery | Signed JWT validated against issuer keys, with bound claims | JWTs cannot be revoked before expiry, so keep TTLs short and bind aud and sub |
| AWS, Azure, Google Cloud, OCI, AliCloud | Cloud workloads | Platform identity (IAM role, managed identity, service account) | Bind to specific role or principal IDs, not whole accounts or subscriptions |
| AppRole | Legacy apps, VMs, tooling without platform identity | role_id plus secret_id | The secret_id is a secret zero: deliver it response-wrapped through a trusted orchestrator |
| TLS certificates | Services with mTLS identity | Client certificate chained to a configured CA | Certificate lifecycle and revocation become part of Vault access |
| LDAP, Okta, userpass, OIDC, RADIUS, Kerberos, GitHub | Human operators | Directory or IdP credentials | Pair with Login MFA; prefer the corporate IdP over userpass |
| SAML, SCEP, SPIFFE, TPM | Enterprise-only scenarios | Assertion, device certificate, SPIFFE SVID, TPM attestation | Licence-dependent; check edition before designing around them |
Entities, aliases and groups
- Entity: a consolidated record of a client. An entity can hold aliases from several auth methods, but only one alias per auth mount.
- Alias: the link between an entity and one account on an auth mount (a username, a GitHub login, a Kubernetes service account UID). Mount accessor plus alias name uniquely identify it.
- Groups: internal groups are managed in Vault; external groups map to an LDAP group, GitHub team or IdP group and are refreshed only at login or token renewal, so a removal upstream does not take effect until then.
- Policy evaluation: entity and group policies are evaluated at request time and are additive to the token's own policies. Write access to identity endpoints is an escalation path, because anyone who can edit entities, aliases or group membership can grant themselves policies.
Policies
Policies are HCL or JSON path rules. Capabilities are create, read, update, patch, delete, list, sudo (needed for root-protected paths), deny, subscribe (events) and recover (restore from snapshot). Generating database credentials needs read on database/creds/<role>, because capabilities map to the HTTP verb. The * glob works only as the final character; + matches exactly one path segment. Templated policies insert identity values with {{identity.entity.id}} style placeholders; use IDs, not names, because names can be changed. required_parameters, allowed_parameters and denied_parameters constrain request bodies, but are not supported on KV version 2.
Admin roles and privileged access
Vault has no built-in "administrator" role. Privilege comes from the root policy, from sudo on root-protected paths, and from write access to sys/, auth/ and identity/. Design these as distinct, narrow personas.
| Persona | Typical paths | Control |
|---|---|---|
| Break-glass root | Everything (root policy) | No standing root token; generate with vault operator generate-root and a quorum of unseal or recovery key holders; revoke after use |
| Platform operator | sys/mounts, sys/auth, sys/policies/acl, sys/audit | Changes through Terraform or another config-as-code pipeline, not interactive CLI; Login MFA for humans |
| Identity administrator | identity/entity, identity/group | Separate from policy authors, since identity writes can grant policies |
| Secrets engine owner | One mount, for example database/ for a team | Scoped to one mount or namespace; cannot touch sys/ |
| Auditor | sys/audit-hash, read-only sys/ views | Read access to logs in the SIEM, not to secret paths |
- Root token lifecycle: the initial root token from
vault operator initshould be used for bootstrap and then revoked. Root tokens are the only tokens that can be created without an expiry. - Namespaces (Enterprise and HCP Vault Dedicated): do daily work in administrative namespaces and reserve the root namespace for tasks that strictly need it.
- Host access: anyone with shell on a node, or write access to the storage backend, can tamper with Vault data without a token.
- Emergency seal: sealing through the API discards the root key from memory (root privilege needed), a containment step during an intrusion. Document who may do it. See the Break-Glass Account Guide.
- Offboarding: removing a person from the IdP may not revoke Vault access. Remove the entity from groups, revoke its active leases and tokens, and delete the entity; disable rather than delete auth mounts you retire.
Integrations, API tokens and service accounts
Tokens, TTLs and leases
- Token types: service tokens (prefix
hvs.since Vault 1.10) support renewal, revocation and child tokens; batch tokens (hvb.) are lightweight encrypted blobs with no storage write, no renewal and no revocation of their own; recovery tokens usehvr.. The prefixes help secret scanners. - TTLs: every non-root token has a TTL. The system max TTL defaults to 32 days and can be lowered per mount. An explicit max TTL is a hard cap even for periodic tokens, which otherwise live for as long as they keep renewing.
- Hierarchy: revoking a parent token revokes its children and their leases. Orphan tokens escape that tree, so restrict
auth/token/create-orphanand token roles that create orphans. - Leases: dynamic secrets and service tokens carry leases with a lease ID that begins with the request path.
vault lease revoke -prefix aws/revokes every AWS credential Vault issued, the fastest containment lever Vault offers. KV secrets do not have leases.
Choosing a workload pattern
| Pattern | How secrets reach the app | Choose when | Trade-off |
|---|---|---|---|
| Direct API or SDK | App authenticates and calls Vault | Teams that can change code and want lease-aware renewal | Every app carries Vault logic |
| Vault Agent | Auto-auth, token sink, templates rendered to files, or env vars in process supervisor mode | VMs and containers that cannot be changed | Templates retry indefinitely unless exit_on_retry_failure is set; file sinks need tight permissions or wrap_ttl |
| Vault Proxy | Local API proxy with auto-auth and caching | Apps that already speak the Vault API; replaces the deprecated API proxy in Vault Agent | Another local process to run and patch |
| Vault Secrets Operator (Kubernetes) | Syncs Vault data into Kubernetes Secrets, remediates drift and can restart Deployments, ReplicaSets and StatefulSets on rotation | Kubernetes-native teams | Secrets land in etcd, so Kubernetes Secret encryption and RBAC become part of the control |
Kubernetes and AppRole specifics
- Kubernetes reviewer JWT: when Vault runs in the cluster, omit
token_reviewer_jwtso Vault uses and periodically re-reads its own short-lived service account token (Vault 1.9.3 or later). Using each client's JWT as the reviewer avoids storing any JWT but needssystem:auth-delegatorfor every client. Avoid long-lived reviewer token Secrets. See the Kubernetes NHI Security Guide. - Kubernetes roles: set
bound_service_account_namesandbound_service_account_namespacesto explicit values, never*for both, and keep the resulting token TTL short. - AppRole: keep
bind_secret_idenabled, setsecret_id_ttlandsecret_id_num_uses, restrict logins withsecret_id_bound_cidrsandtoken_bound_cidrs, and deliver the secret_id as a response-wrapped token from a trusted orchestrator (for example the CI system) so only the final client unwraps it. HashiCorp recommends batch tokens with AppRole. User lockout is on by default: 5 failed attempts lock the alias for 15 minutes. - CI/CD: prefer JWT/OIDC auth bound to the pipeline's identity token claims (repository, branch, environment) over a stored AppRole secret_id or a long-lived Vault token in a CI variable. See the CI/CD Pipeline Identity Security Guide.
Dynamic secrets and PKI
- Database engine: dynamic roles create a unique user per request via
creation_statements(for exampledefault_ttl="1h",max_ttl="24h"); static roles rotate the password of an existing account on arotation_periodorrotation_schedule. Immediately runvault write -force database/rotate-root/<connection>so only Vault knows the management credential, and never put that root user in a static role. - PKI: keep the root CA outside Vault where possible, issue from an intermediate on its own mount, use roughly 30 to 90 day leaf lifetimes, keep
allow_any_namefalse and scopeallowed_domains, enable auto-tidy and automatic CRL rebuilds, and setno_store=trueonly for very short-lived, high-volume certificates (serial-number revocation is then unavailable). Public ACME directories should enforceeab_policy=always-required. See the Machine Identity, PKI and Certificate Lifecycle Guide.
Logging and detection
Audit devices (file, syslog, socket) record every request and response. Most string values are written as keyed HMAC-SHA256 hashes, not plaintext; integers and booleans are not hashed. Use sys/audit-hash/<device> to hash a known value (a token or a leaked secret) and search for it. Setting hmac_accessor=false leaves token accessors readable so you can correlate a token's activity across events.
| Signal | Where to see it | Why it matters |
|---|---|---|
Any use of a token with the root policy | Audit log, auth.policies containing root | Should be rare and tied to a change ticket |
Writes to sys/audit, sys/auth, sys/policies/acl, sys/mounts | Audit log request path | Disabling audit or adding a permissive auth mount precedes most abuse |
Writes to identity/ entities, aliases, groups | Audit log | Self-granted policies through identity |
| Spikes of permission denied on secret paths | Audit log error field | Enumeration with a stolen token |
| Creation of orphan or periodic tokens | auth/token/create-orphan, token roles | Persistence that survives parent revocation |
| Logins from unexpected networks or new auth mounts | Audit log remote_address, mount accessor | Leaked secret_id, JWT or token replay |
Relevant ATT&CK techniques include T1555 Credentials from Password Stores, T1552.001 Credentials In Files (Agent sink files, unseal keys on disk) and T1528 Steal Application Access Token.
Metrics that show the programme is working:
- Dynamic share: percentage of secrets consumed as dynamic, leased credentials rather than KV values.
- Static age: maximum age of KV secrets and static role passwords against policy.
- Root token hours: time any root token existed per quarter (target: only during approved break-glass).
- Long TTL tokens: count of non-root tokens with TTL above 24 hours or no explicit max TTL.
- Audit coverage: number of healthy audit devices per cluster (target two or more) and log delivery lag to the SIEM.
Hardening baseline
- Host and process: run Vault as a dedicated unprivileged user that cannot modify its binary or configuration; one Vault process per host (bare metal, then VM, then container); disable SSH and remote desktop where you can; use the packaged systemd unit options such as
ProtectSystem=full,PrivateTmp=yes,NoNewPrivileges=yes; add SELinux or AppArmor. - Memory: disable swap, or keep mlock enabled, and if mlock is disabled with Integrated Storage, encrypt swap; disable core dumps (
LimitCORE=0in systemd orRLIMIT_CORE0). - Network: TLS end to end including load balancers and storage, TLS 1.3 where possible, HSTS through custom response headers; restrict the API listener (default port 8200) and cluster port (default 8201) to the clients and peers that need them; send outbound traffic through a proxy you can observe.
- Seal: choose auto-unseal (cloud KMS, HSM or Transit) for availability, and authenticate it with platform identity (instance profile, managed identity, service account) rather than keys in the
sealstanza; useVAULT_HSM_PINas an environment variable if an HSM PIN is unavoidable. Protect the KMS key from deletion: if it is permanently deleted the cluster cannot be recovered, even from backups. Recovery keys authorisegenerate-rootand rekey but cannot unseal. - Key custody: with Shamir unseal, distribute shares to separate named custodians, store them offline, pass them to
vault operator unsealon standard input rather than as arguments, and rehearse rekeying when a custodian leaves. - Storage: put Integrated Storage on its own partition, restrict access to the storage layer, and keep regular, encrypted snapshots with restore tests.
- Policies as code: manage auth mounts, policies and engines through a reviewed pipeline; keep globs and templates to a minimum and set
deny_slash_in_templated_paths=true. - Lifetimes: lower mount max TTLs, set explicit max TTLs on periodic tokens, and confirm user lockout thresholds for AppRole, LDAP and userpass.
- Audit: at least two audit devices, log rotation and central collection, restricted access to log files.
- Upgrades and plugins: follow the security announcement list, prefer immutable upgrades (new nodes on the new version join, unseal, then old nodes are destroyed), and vet every external plugin before registration.
Rollout and rollback: introduce a new auth method or tighter policy on a separate mount path first, migrate one application per ring, watch permission-denied counts in the audit log, then retire the old path. Rollback is a revert of the policy code; keep the old mount until the last client moves.
Small versus large estates: a single team can run one Integrated Storage cluster with auto-unseal, two audit devices and Vault Agent. Larger organisations add namespaces or separate clusters per trust boundary, performance and disaster recovery replication (Enterprise), seal high availability with two or three seals from different regions or providers. See the Secrets Management Guide and, for product selection, the Secrets Management Buyer's Guide.
Common misconfigurations
- Keeping the initial root token. A stored "just in case" root token is a non-expiring master key.
- Vault as a static KV store only. Long-lived database passwords and cloud keys copied into KV still leak and still need manual rotation; dynamic engines and leases are the reason to run Vault.
- Broad roles and globs.
path "secret/*" { capabilities = ["read","list"] }for every app, or Kubernetes roles bound to*service accounts in*namespaces, turn one compromised pod into access to every secret. - Secret zero in plain sight. AppRole secret_ids, Vault tokens or unseal keys stored in CI variables, images or scripts. Machine secrets that live with people are equally exposed: in the LastPass breach, a DevOps engineer's vault held the AWS and backup decryption keys that unlocked customer data.
- Signing and release keys in general pipelines. In the HashiCorp GPG key exposure, a tampered Codecov script in CI captured HashiCorp's own release signing key from the environment. Keep signing in Vault Transit or an HSM with a dedicated, isolated job.
- Single audit device or no off-host logs. One full disk can stop Vault serving requests, and local-only logs can be altered by anyone with shell access.
Framework mapping
| Vault control | NIST SP 800-53 Rev. 5 | NIST CSF 2.0 | ISO/IEC 27001:2022 Annex A | CIS Controls v8.1 |
|---|---|---|---|---|
| Auth methods, short TTLs, dynamic secrets, no embedded secrets | IA-5, IA-5(7), IA-4 | PR.AA-01 | A.5.17 | 5, 6 |
| Policies, namespaces, root token control | AC-6 | PR.AA-05 | A.8.2 | 6.8 |
| Seal, Transit, PKI, storage encryption | SC-12, SC-28 | PR.DS-01 | A.8.24 | 3.11 |
| Audit devices and central logging | AU-2, AU-9 | PR.PS-04, DE.CM-09 | A.8.15 | 8.2 |
| Config as code, hardening baseline | CM-2, CM-6, CM-3 | PR.PS-01 | A.8.9 | 4.1 |
Practitioner checklist
- Revoke the initial root token and document the
generate-rootquorum procedure and its custodians. - Enable at least two audit devices, forward to the SIEM, and alert on root policy use and writes to
sys/audit,sys/authandidentity/. - Move workloads to platform-identity auth (Kubernetes, cloud IAM, JWT/OIDC) and bind roles to explicit service accounts, namespaces and claims.
- Replace static database and cloud credentials with dynamic roles, run
rotate-rooton every connection, and lower mount max TTLs. - Deliver any remaining AppRole secret_ids response-wrapped, with TTL, use limits and CIDR bindings.
- Configure auto-unseal with platform identity, protect the KMS key from deletion, and test snapshot restore.
- Apply the host baseline: unprivileged user, no swap or mlock on, no core dumps, single tenancy, TLS 1.3.
- Manage policies, mounts and auth methods as reviewed code, and separate identity administration from policy authoring.
- Rehearse prefix revocation (
vault lease revoke -prefix) and emergency seal in an incident exercise.
Standards and references
- HashiCorp: Vault production hardening
- HashiCorp: Vault policies
- HashiCorp: Vault tokens
- HashiCorp: Vault seal and unseal
- HashiCorp: Vault audit devices
- HashiCorp: Vault Kubernetes auth method
- HashiCorp: PKI secrets engine considerations
- NIST: SP 800-53 Rev. 5
Related NHI Mgmt Group resources: Secrets Management Guide · Secrets Rotation Runbook Template · Terraform Cloud and HCP Security Guide · NHI Authentication Guide · Top 10 Secrets Management Mistakes