Vault is a secret management tool, and you can interact with it through its HTTP API, which is incredibly powerful for automation.
Let’s see how we can use curl to perform common operations.
First, we need a running Vault instance and a token with sufficient permissions. For these examples, we’ll assume Vault is running on http://127.0.0.1:8200 and we have a token stored in an environment variable VAULT_TOKEN.
export VAULT_TOKEN="s.xxxxxxxxxxxxxxxxxxxx" # Replace with your actual token
export VAULT_ADDR="http://127.0.0.1:8200"
Reading a Secret
Reading a secret from the KV v2 store is a fundamental operation.
curl --header "X-Vault-Token: $VAULT_TOKEN" \
--request GET \
"$VAULT_ADDR/v1/secret/data/myapp/config"
This command sends a GET request to the /v1/secret/data/myapp/config endpoint. The X-Vault-Token header authenticates the request. The response will be a JSON object containing the secret data under the data.data field.
Writing a Secret
To write a secret, we use a POST request to the same endpoint, but with the data payload.
curl --header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{"data":{"username":"admin","password":"supersecretpassword"}}' \
"$VAULT_ADDR/v1/secret/data/myapp/config"
The --data flag carries the JSON payload. Vault will then store this under the myapp/config path. If the secret already exists, this operation will create a new version.
Deleting a Secret
Deleting a secret is straightforward with a DELETE request.
curl --header "X-Vault-Token: $VAULT_TOKEN" \
--request DELETE \
"$VAULT_ADDR/v1/secret/data/myapp/config"
This removes the latest version of the secret at myapp/config. For KV v2, this usually means soft deletion (moving to a recycle bin), which can be configured.
Listing Secrets
To see what secrets are available at a given path, we use a LIST request.
curl --header "X-Vault-Token: $VAULT_TOKEN" \
--request LIST \
"$VAULT_ADDR/v1/secret/metadata/myapp/"
This will return a JSON object with a keys array, listing all the secret paths directly under /myapp/. For example, it might return {"request_id": "...", "lease_id": "", "renewable": false, "lease_duration": 0, "data": {"keys": ["config"]}}.
Enabling a New Secret Engine
You can enable new secret engines dynamically. Let’s enable the KV v2 engine at a custom path.
curl --header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{"type": "kv", "options": {"version": 2}}' \
"$VAULT_ADDR/v1/sys/mounts/kv2_custom"
This POST request to /v1/sys/mounts/kv2_custom tells Vault to create a new mount point for the KV v2 engine. The type parameter specifies the engine, and options.version ensures it’s version 2.
Disabling a Secret Engine
Similarly, you can disable a mounted secret engine.
curl --header "X-Vault-Token: $VAULT_TOKEN" \
--request DELETE \
"$VAULT_ADDR/v1/sys/mounts/kv2_custom"
This DELETE request to /v1/sys/mounts/kv2_custom will unmount the KV v2 engine from the kv2_custom path. All secrets stored within that engine become inaccessible.
Reading Secret Engine Configuration
To inspect the configuration of a mounted secret engine, you can use a GET request.
curl --header "X-Vault-Token: $VAULT_TOKEN" \
--request GET \
"$VAULT_ADDR/v1/sys/mounts/secret"
This fetches the configuration details for the secret engine (which is typically KV v1 by default). The response will include type, description, and any specific options for that engine.
Authenticating with AppRole
AppRole authentication is a common way for applications to get Vault tokens. First, you need to configure an AppRole.
# Create an AppRole
curl --header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{"token_policies": "myapp-policy"}' \
"$VAULT_ADDR/v1/auth/approle/role/my-app-role"
# Get the RoleID
curl --header "X-Vault-Token: $VAULT_TOKEN" \
"$VAULT_ADDR/v1/auth/approle/role/my-app-role/role-id"
# Get the SecretID (you'd typically do this once and store it securely)
curl --header "X-Vault-Token: $VAULT_TOKEN" \
"$VAULT_ADDR/v1/auth/approle/role/my-app-role/secret-id"
Once you have the role_id and secret_id, your application can authenticate:
ROLE_ID="your-role-id" # Replace with actual RoleID
SECRET_ID="your-secret-id" # Replace with actual SecretID
curl --request POST \
--data "{\"role_id\": \"$ROLE_ID\", \"secret_id\": \"$SECRET_ID\"}" \
"$VAULT_ADDR/v1/auth/approle/login"
This POST request to the /v1/auth/approle/login endpoint will return a Vault token in the auth.client_token field of the JSON response, which your application can then use for subsequent API calls.
The most counterintuitive aspect of Vault’s API, especially with KV v2, is that the "data" endpoint is where you write secrets, but the "metadata" endpoint is used for listing and deleting them. This separation is crucial for versioning and auditing.
Once you’ve mastered these fundamental API operations, the next logical step is to explore managing Vault’s dynamic secrets, such as database credentials or cloud provider access, which are generated on-demand.