HashiCorp Vault — Paths & Mount Points
Every operation in Vault is a path-based API request. Understanding how paths, mount points, and routing work is essential for writing policies and building integrations.
How Vault Routing Works
When Vault receives a request, it uses the path to determine which secrets engine handles it:
Request: GET /v1/secret/data/myapp
Vault Router:
"secret/" → KV v2 engine
"data/myapp" → passed to the engine as the sub-path
┌─────────────────────────────────────────────────┐
│ Vault Router │
│ │
│ Path Prefix → Engine │
│ ──────────── ────── │
│ secret/ → KV v2 │
│ database/ → Database │
│ transit/ → Transit │
│ pki/ → PKI │
│ aws/ → AWS Secrets │
│ auth/userpass/ → Userpass Auth │
│ sys/ → System Backend │
│ cubbyhole/ → Cubbyhole │
└─────────────────────────────────────────────────┘
Path Anatomy
/v1/secret/data/team-a/production/database
│ │ │ │ │ │
│ │ │ └─────────┴─────────┘
│ │ │ Sub-path
│ │ │ (passed to engine)
│ │ │
│ │ └── KV v2 prefix
│ │ (data/, metadata/)
│ │
│ └── Mount point
│ (routes to KV v2 engine)
│
└── API version prefix
System Paths
The sys/ path provides access to Vault configuration:
# Health check (no auth required)
vault read sys/health
# List mounted secrets engines
vault read sys/mounts
# List auth methods
vault read sys/auth
# View policies
vault read sys/policy
# Server configuration (sanitized)
vault read sys/config/state/sanitized
# Seal status
vault read sys/seal-status
# Generate random bytes
vault write sys/tools/random bytes=32 format=hex
Auth Paths
Auth methods are mounted under auth/:
# Default token auth
# auth/token/...
# Userpass auth
vault auth enable userpass
# Now available at: auth/userpass/
# AppRole auth
vault auth enable approle
# Now available at: auth/approle/
# Custom path
vault auth enable -path=corp-sso oidc
# Now available at: auth/corp-sso/
Policy Paths
Policies reference paths to control access:
# Allow read access to team-a's secrets
path "secret/data/team-a/*" {
capabilities = ["read", "list"]
}
# Allow managing database credentials
path "database/creds/readonly" {
capabilities = ["read"]
}
# Deny access to admin secrets
path "secret/data/admin/*" {
capabilities = ["deny"]
}
Path Wildcards
| Pattern | Matches |
|---|---|
secret/data/myapp |
Exact path only |
secret/data/myapp/* |
All sub-paths under myapp |
secret/data/+/database |
Single directory wildcard (e.g., secret/data/team-a/database) |
secret/* |
Everything under secret/ |
# Glob wildcard — matches everything after
path "secret/data/team-a/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
# Single segment wildcard — matches one path segment
path "secret/data/+/database" {
capabilities = ["read"]
}
# Matches: secret/data/team-a/database
# Matches: secret/data/team-b/database
# Does NOT match: secret/data/team-a/sub/database
KV v2 Path Prefixes
KV v2 adds internal path prefixes that you must know for API calls and policies:
| Operation | CLI Path | API Path | Policy Path |
|---|---|---|---|
| Read/Write | secret/myapp |
secret/data/myapp |
secret/data/myapp |
| List | secret/ |
secret/metadata/ |
secret/metadata/* |
| Delete | secret/myapp |
secret/data/myapp |
secret/data/myapp |
| Undelete | N/A | secret/undelete/myapp |
secret/undelete/myapp |
| Destroy | secret/myapp |
secret/destroy/myapp |
secret/destroy/myapp |
| Metadata | secret/myapp |
secret/metadata/myapp |
secret/metadata/myapp |
⚠️ Common mistake: Writing a policy for
secret/myappwon’t work for KV v2. You needsecret/data/myappfor read/write andsecret/metadata/myappfor list/metadata.
Organizing Secrets by Path
A common convention for organizing secrets:
secret/
├── data/
│ ├── team-a/
│ │ ├── dev/
│ │ │ ├── database (DB credentials)
│ │ │ └── api-keys (API keys)
│ │ ├── staging/
│ │ │ ├── database
│ │ │ └── api-keys
│ │ └── prod/
│ │ ├── database
│ │ └── api-keys
│ └── team-b/
│ └── ...
# Policy: team-a can access all their secrets
path "secret/data/team-a/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
path "secret/metadata/team-a/*" {
capabilities = ["list", "read"]
}
# Policy: team-a can only read prod secrets (no write)
path "secret/data/team-a/prod/*" {
capabilities = ["read", "list"]
}
Quick Reference
| Path Type | Example | Description |
|---|---|---|
| Secrets | secret/data/myapp |
KV v2 secret data |
| Metadata | secret/metadata/myapp |
KV v2 metadata |
| Auth | auth/userpass/login/admin |
Auth method operations |
| System | sys/mounts |
System configuration |
| Cubbyhole | cubbyhole/my-temp-data |
Per-token private storage |
| Glob | path/* |
Match all sub-paths |
| Segment | path/+/sub |
Match one path segment |
Next: Metadata & Versioning