Files
vault-tools/docs/vcm.md
T
unkin-agent ddc25139f7
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Support OIDC form_post, require loopback listener, redact request URLs in errors
2026-10-23 22:01:42 +11:00

162 lines
5.5 KiB
Markdown

# vcm
`vcm` manages Vault tokens for multiple vault instances ("contexts"). It logs
in to (or renews tokens for) one or all configured contexts and caches each
resulting token under `~/.cache/vcm/<context>` for use by
[`vctx`](vctx.md) and other tooling.
## Synopsis
```
vcm login <context> # log in to one context
vcm login --all # log in to every configured context
vcm renew <context> # renew one context's cached token
vcm renew --all # renew every context that has a cached token
vcm list # show contexts + cached-token status
vcm version
```
## Flags
Both `login` and `renew` accept:
| Flag | Default | Description |
| -------------- | -------------------------------- | -------------------------------------------------- |
| `--all` | `false` | Operate on every configured context. |
| `--method <m>` | context/config, else `ldap` | Override the auth method (`ldap`, `userpass`, `okta`, `radius`, `token`, `oidc`). |
| `--user <u>` | context/config, else `$USER` | Override the login username. |
`login` also accepts:
| Flag | Default | Description |
| -------------- | -------------------------------- | -------------------------------------------------- |
| `--role <r>` | context `role`, else mount default | OIDC role to log in with. |
| `--listen <a>` | context `oidc_listen`, else `localhost:8250` | OIDC callback listen address. |
A context name or `--all` is required (but not both).
## Configuration
`vcm` reads `~/.config/vcm/config.yaml` (`$XDG_CONFIG_HOME` is honoured in
place of `~/.config`).
```yaml
# ~/.config/vcm/config.yaml
defaults:
method: ldap # applied to any context that doesn't set its own
user: ben
namespace: ""
contexts:
sydney:
address: https://vault.syd1.au.unkin.net
staging/sydney: # slashes are allowed; they nest on disk
address: https://vault-staging.syd1.au.unkin.net
namespace: staging
user: svc-ben # per-context override
legacy:
address: https://vault-legacy.example.net
method: userpass
path: userpass2 # override the auth mount path (default = method)
sydney/admin: # OIDC: one context per role
address: https://vault.syd1.au.unkin.net
method: oidc
role: admin
```
### Field resolution
For each context, every field is resolved with the chain
**context value → file `defaults` → built-in default**:
- `method` — built-in default `ldap`.
- `user` — built-in default `$USER`.
- `namespace` — no built-in default (unset means the root namespace).
- `path` — the auth mount path; defaults to the resolved `method`.
- `role` — OIDC role; unset uses the mount's `default_role`.
- `oidc_listen` — OIDC callback listener on a loopback host (`localhost`,
`127.0.0.1` or `[::1]`); defaults to `localhost:8250`.
`--method` / `--user` on the command line override the resolved values. When
`--method` changes the method and the context did not pin an explicit `path`,
the auth path follows the new method.
## Auth methods
- **Password methods** (`ldap`, `userpass`, `okta`, `radius`): `vcm` prompts
for a password (no echo) and POSTs to `auth/<path>/login/<user>`.
- **`token`**: `vcm` prompts for a raw Vault token (no echo), verifies it with
`auth/token/lookup-self`, and caches its details.
- **`oidc`**: the same flow as `vault login -method=oidc`. `vcm` listens on
`oidc_listen`, requests `auth/<path>/oidc/auth_url` with
`redirect_uri=http://<oidc_listen>/oidc/callback`, opens the URL with
`xdg-open` (printing it too), and exchanges the returned code via
`auth/<path>/oidc/callback`. It gives up after 2 minutes. The redirect URI
must be in the role's `allowed_redirect_uris`. `--all` runs each OIDC
context's browser login in turn.
## Token cache
Tokens are written to `~/.cache/vcm/<context>` (honouring `$XDG_CACHE_HOME`)
as JSON. Slash contexts nest: `staging/sydney` →
`~/.cache/vcm/staging/sydney`. Parent directories are created `0700` and token
files are written `0600`.
Each file stores enough to inspect and later revoke the token:
```json
{
"context": "staging/sydney",
"address": "https://vault-staging.syd1.au.unkin.net",
"namespace": "staging",
"token": "s....",
"accessor": "hmac-...",
"policies": ["default", "kv-read"],
"renewable": true,
"lease_duration_seconds": 3600,
"issued_at": "2026-07-26T12:00:00Z",
"expires_at": "2026-07-26T13:00:00Z"
}
```
The `accessor` lets you revoke the token later without exposing the secret
(`vault token revoke -accessor <accessor>`).
## Examples
```bash
# Log in to one context (prompts for password)
vcm login sydney
# Log in everywhere at once
vcm login --all
# Log in to a context overriding the method + user
vcm login sydney --method okta --user someone.else
# OIDC login with a different role than the context's
vcm login sydney/admin --role readonly
# Renew a slash-named context
vcm renew staging/sydney
# Renew everything that currently has a cached token
vcm renew --all
# See what is configured and which tokens are still valid
vcm list
```
## Shell completion
```bash
vcm completion bash > /etc/bash_completion.d/vcm
vcm completion zsh > ~/.zsh/completions/_vcm
```
Context names complete dynamically from the config file (the RPM installs these
completions automatically).