HashiCorp Vault — Paths & Mount Points

3 minute read

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/myapp won’t work for KV v2. You need secret/data/myapp for read/write and secret/metadata/myapp for 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