Introduces the vault-tools monorepo: two Go CLIs that share a config file (~/.config/vault) and token cache (~/.cache/vault) for working with multiple Vault instances (contexts). - add shared/ library: config parsing (vctl.yaml/config.yaml, per-context overrides, slash contexts), token cache (0600/0700, atomic writes, path- traversal guards), and a small hand-rolled Vault HTTP client (login/renew) - add vctl: login/renew (single or --all), list, --method/--user overrides, no-echo password/token prompts, dynamic context completion - add vctx: resolve a context, set VAULT_ADDR/VAULT_TOKEN/VAULT_NAMESPACE and exec the vault CLI, passing remaining args through untouched - add unit tests across shared/, vctl and vctx command layers (config resolution, cache paths, vault client, --all iteration + error aggregation, vctx arg pass-through and env construction via fakeable exec/prompt seams) - add Makefile (build/test/completions/rpm, patch|minor|major version bumps), nfpm RPM packaging bundling bash/zsh/fish completions for both binaries - add Woodpecker pipelines: build/test/pre-commit on PRs, and a tag release that cross-compiles, builds+uploads the RPM to artifactapi, and cuts a Gitea release (serviceAccountName default, k8s resources on every step) - add README, per-command docs (docs/vctl.md, docs/vctx.md), AGENTS.md and an example config Claude-Session: https://claude.ai/code/session_015ur3i7D2azsMAWTSVABApv
4.3 KiB
vctl
vctl 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/vault/<context> for use by
vctx and other tooling.
Synopsis
vctl login <context> # log in to one context
vctl login --all # log in to every configured context
vctl renew <context> # renew one context's cached token
vctl renew --all # renew every context that has a cached token
vctl list # show contexts + cached-token status
vctl 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). |
--user <u> |
context/config, else $USER |
Override the login username. |
A context name or --all is required (but not both).
Configuration
vctl reads the first of these files that exists:
~/.config/vault/vctl.yaml~/.config/vault/config.yaml
($XDG_CONFIG_HOME is honoured in place of ~/.config.)
# ~/.config/vault/vctl.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)
Field resolution
For each context, every field is resolved with the chain
context value → file defaults → built-in default:
method— built-in defaultldap.user— built-in default$USER.namespace— no built-in default (unset means the root namespace).path— the auth mount path; defaults to the resolvedmethod.
--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):vctlprompts for a password (no echo) and POSTs toauth/<path>/login/<user>. token:vctlprompts for a raw Vault token (no echo), verifies it withauth/token/lookup-self, and caches its details.
Token cache
Tokens are written to ~/.cache/vault/<context> (honouring $XDG_CACHE_HOME)
as JSON. Slash contexts nest: staging/sydney →
~/.cache/vault/staging/sydney. Parent directories are created 0700 and token
files are written 0600.
Each file stores enough to inspect and later revoke the token:
{
"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
# Log in to one context (prompts for password)
vctl login sydney
# Log in everywhere at once
vctl login --all
# Log in to a context overriding the method + user
vctl login sydney --method okta --user someone.else
# Renew a slash-named context
vctl renew staging/sydney
# Renew everything that currently has a cached token
vctl renew --all
# See what is configured and which tokens are still valid
vctl list
Shell completion
vctl completion bash > /etc/bash_completion.d/vctl
vctl completion zsh > ~/.zsh/completions/_vctl
Context names complete dynamically from the config file (the RPM installs these completions automatically).