Vault expresses everything as HTTP paths. Secret engines and auth methods are "mounted," and requests are routed by longest-prefix match. Getting the path design wrong leads to authorization and compatibility pain, so it pays to nail down the fundamentals.
This article walks through how path resolution works, the differences between KV v1 and v2, the login paths used by auth methods, the sys/ administrative API, and the key points for path-based policies — including the pitfalls that show up frequently on the exam.
Vault's HTTP API is rooted under /v1/, and the leading segment splits into roughly three families: sys/ for administration, auth/ for auth methods, and everything else for user-mounted secret engines. The actual routing is resolved by longest-prefix matching the request path against the mount table.
Even on identical-looking paths, the sub-path layout differs by engine. KV v2 uses data/ and metadata/ sub-paths, while Transit uses encrypt/ and decrypt/. The HTTP verb convention is: GET for reads, POST for writes, LIST for listing (or GET with the list=true query parameter).
| Path type | Example | Resolves to | Authorization anchor |
|---|---|---|---|
| Secret engine | /v1/secret/data/app | KV v2 on the secret/ mount | path "secret/data/*" |
| Auth method | /v1/auth/approle/login | login on auth/approle/ | path "auth/approle/login" |
| System administration | /v1/sys/mounts | Mount listing/management API | path "sys/mounts" |
| Identity | /v1/identity/entity | Entity management API | path "identity/*" |
Vault routing resolution (conceptual diagram)
Sanity check: inspect the mount table and routing
export VAULT_ADDR=http://127.0.0.1:8200
export VAULT_TOKEN=<root-or-suitable-token>
# マウント一覧
curl -sH "X-Vault-Token: $VAULT_TOKEN" \
$VAULT_ADDR/v1/sys/mounts | jq .
# LISTが通らない場合の一覧取得(例: KV v2のトップ階層)
curl -sH "X-Vault-Token: $VAULT_TOKEN" \
"$VAULT_ADDR/v1/secret/metadata?list=true" | jq .Mount names become part of the API path itself, so settle on vocabulary for environments and domains up front, and pick a hierarchy that anticipates future expansion and migration. KV v2 in particular carries data/ and metadata/ sub-paths and is not wire-compatible with v1.
Transit is an encryption service, with a different API and a different responsibility than a storage-backed KV. Trying to retrofit one into the other quickly creates path and permission mismatches, so use separate mounts and separate policies per purpose.
| Engine | Example data path | Versioning | Main auxiliary paths |
|---|---|---|---|
| KV v1 | /v1/kv/app/config | None | n/a |
| KV v2 | /v1/secret/data/app/config | Yes (version selectable) | /v1/secret/metadata/app/config, /v1/secret/destroy/... |
| Transit | /v1/transit/encrypt/orders | N/A | /v1/transit/decrypt/<key>, /v1/transit/rotate/<key> |
KV v2 sub-path layout
secret/ (mount)
|
+-- data/<name> (値の読み書き: GET/POST)
+-- metadata/<name> (メタ情報・バージョン管理)
+-- destroy/<name> (特定versionの完全削除)
+-- delete/<name> (論理削除: version無効化)
Mount KV v2 at secret/ and read/write a value
# KV v2を有効化(既にあれば不要)
curl -sX POST -H "X-Vault-Token: $VAULT_TOKEN" \
-d '{"type":"kv","options":{"version":"2"}}' \
$VAULT_ADDR/v1/sys/mounts/secret
# 書き込み(KV v2は data/ サブパス)
curl -sX POST -H "X-Vault-Token: $VAULT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"data":{"username":"app","password":"s3cr3t"}}' \
$VAULT_ADDR/v1/secret/data/app/config | jq .
# 読み取り(最新版)
curl -sH "X-Vault-Token: $VAULT_TOKEN" \
$VAULT_ADDR/v1/secret/data/app/config | jq .
# バージョン指定の読み取り(例: version=2)
curl -sH "X-Vault-Token: $VAULT_TOKEN" \
"$VAULT_ADDR/v1/secret/data/app/config?version=2" | jq .Auth methods are mounted under auth/<method>/, and the entry point for token issuance is the login endpoint. Applications call login to obtain a Vault token, then make ordinary API calls against secret engine paths.
You can mount the same method twice under different paths and use them side by side (for example, auth/approle/ and auth/approle-ci/). Since changing the path changes the login endpoint, the mount name has to line up in both the client config and the policy.
| Method | Login path | Main request fields | Notes |
|---|---|---|---|
| AppRole | /v1/auth/approle/login | role_id, secret_id | Watch for alias mounts (for example, approle-ci) |
| Kubernetes | /v1/auth/kubernetes/login | jwt, role | Map K8s ServiceAccount JWTs to role names |
| Userpass | /v1/auth/userpass/login/<user> | password | Username in the path, password in the body |
From authentication to reading a secret
App -> POST /v1/auth/<method>/login -> Token
Token -> GET /v1/<mount>/... -> Secret
^ |
|---- Policy ----------|
Example: AppRole login followed by a read
# AppRoleでlogin
curl -sX POST -H "X-Vault-Token: $VAULT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"role_id":"<ROLE_ID>","secret_id":"<SECRET_ID>"}' \
$VAULT_ADDR/v1/auth/approle/login | jq .
# 取得した client_token を使ってKV v2を読む
APP_TOKEN=<client_token_from_response>
curl -sH "X-Vault-Token: $APP_TOKEN" \
$VAULT_ADDR/v1/secret/data/app/config | jq .sys/ is Vault's administrative API surface, handling enabling and configuring mounts and auth methods, health checks, policies, and token inspection. Application code rarely calls it directly; it shows up heavily in operations and automation (Terraform, CI).
These permissions are powerful, so restrict them to the minimum paths necessary. As a rule, grant sys/mounts/* and sys/auth/* only to administrative roles, never to applications.
| Endpoint | Purpose | Typical verbs | Caveats |
|---|---|---|---|
| /v1/sys/mounts | List/create mounts | GET, POST | Specify type at creation time |
| /v1/sys/mounts/<path>/tune | Tuning (description, version count, etc.) | POST | For example, max_versions on KV v2 |
| /v1/sys/auth | Auth method management | GET, POST | Keep the method type aligned with the path |
| /v1/sys/health | Health check | GET | Used by UIs and load balancers |
| /v1/sys/capabilities-self | Check your own capabilities | POST | Handy for debugging policies |
How sys/ APIs are organized
Typical sys/ operations
# Transitエンジンを有効化
curl -sX POST -H "X-Vault-Token: $VAULT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"type":"transit"}' \
$VAULT_ADDR/v1/sys/mounts/transit
# KV v2のmax_versionsを10に設定
data='{"options":{"version":"2"},"description":"App secrets","max_versions":10}'
curl -sX POST -H "X-Vault-Token: $VAULT_TOKEN" \
-H "Content-Type: application/json" \
-d "$data" \
$VAULT_ADDR/v1/sys/mounts/secret/tune
# 自トークンの権限を確認
curl -sX POST -H "X-Vault-Token: $VAULT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"paths":["secret/data/app/*","sys/mounts"]}' \
$VAULT_ADDR/v1/sys/capabilities-self | jq .Vault ACL policies grant capabilities per path. Because KV v2 treats data/ and metadata/ separately, granting read-only access usually means at least reading data/ and considering list on metadata/. Also distinguish destroy from delete.
Because routing uses longest-prefix match, mixing broad allows with narrow denies makes things complicated fast. As a rule, allow only what is necessary, and avoid wildcards you do not actually need.
| Purpose | Example target path | Required capabilities | Notes |
|---|---|---|---|
| KV v2 read-only | secret/data/app/* | read | Add list on metadata if you need to enumerate |
| KV v2 write | secret/data/app/* | create, update | Initial creation needs create; updates need update |
| KV v2 logical delete | secret/delete/app/* | update | Disables the specified version |
| KV v2 physical delete | secret/destroy/app/* | delete | Irreversible; enforce least privilege strictly |
How a request is evaluated against policy
Request: GET /v1/secret/data/app/config
|
v
[ポリシー集合]
- path "secret/data/app/*" { capabilities = ["read"] }
- path "secret/metadata/*" { capabilities = ["list"] }
|
v
判定: 許可(readが一致)Example least-privilege policy and how to verify it
# ポリシー定義(HCL)
cat > app-readonly.hcl <<'EOF'
path "secret/data/app/*" {
capabilities = ["read"]
}
path "secret/metadata/app" {
capabilities = ["list"]
}
EOF
# ポリシー作成
curl -sX PUT -H "X-Vault-Token: $VAULT_TOKEN" \
-H "Content-Type: application/json" \
-d @- $VAULT_ADDR/v1/sys/policies/acl/app-readonly <<'JSON'
{"policy": "$(sed 's/"/\\"/g' app-readonly.hcl)"}
JSON
# 自トークンのcapabilitiesを自己診断
curl -sX POST -H "X-Vault-Token: $VAULT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"paths":["secret/data/app/config","secret/metadata/app"]}' \
$VAULT_ADDR/v1/sys/capabilities-self | jq .Associate
問題 1
In an environment where KV v2 is mounted at secret/, an application calls GET /v1/secret/app/config and receives a 404. What is the most likely cause?
正解: A
KV v2 reads use /v1/<mount>/data/<name>. /v1/secret/app/config is the KV v1 shape and will return 404 on v2. The correct path is /v1/secret/data/app/config.
Is it safe to rename a mount?
It can affect running applications, so plan it carefully. The common approach is to create a new mount, migrate the data (for example, with the kv migrate tool or dual read/write), and then cut over. During migration it is safest to temporarily grant a policy that allows both paths.
The LIST method is being blocked by my proxy. What should I do?
There is an alternative: pass the list=true query parameter on a GET request. For example, /v1/secret/metadata?list=true. The response format is equivalent to LIST.
I granted only read on KV v2 but my app still cannot list keys.
Listing on KV v2 requires list capability on metadata/. For example, add capabilities=["list"] on path "secret/metadata/app". Reading the actual values still requires read on path "secret/data/app/*".
Practice with certification-focused question sets
無料で問題を解いてみるNicheeLab Editorial Team
NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.
Vault Core Concepts: Sealed/Unsealed, Auth, Secrets (2026)
Vault fundamentals — sealed/unsealed state, auth methods, se...
Vault Operations Professional (VOP-003): Complete Guide (2026)
Pass the Vault Operations Professional exam — enterprise pat...
Vault Path-Based Routing: API URL Structure (2026)
How Vault's path-based routing works — mount points, sub-pat...
Vault Tokens: Auth Token Mechanics (2026)
Token fundamentals — service vs. batch tokens, accessor, ren...
Vault Token Types: Service, Batch, Periodic (2026)
Service vs. batch tokens compared — performance, ACL behavio...