01 · Vault, declared
One repo. CI applies it. Nobody clicks.
Policies live under policies/, auth roles under
roles/, and auth methods and secret engines are declared
next to them. A pipeline plans on every merge request and applies on
the default branch, with a short-lived token from your own CI.
The assistant never applies anything. It reads the repo like any
other reviewer and proposes changes through the same merge requests
your team uses.
02 · Read it exactly
A small parser for a small grammar.
Vault policies are flat: a path and a list of
capabilities. The assistant parses them with a focused,
dependency-free reader that copes with either brace style, and loads
role JSON alongside, so every later check works on structure, not on
text matching.
On a real 14-policy, 4-role estate this reader and the rules below
produced zero findings. That clean baseline is the point: it
only speaks when something is actually wrong.
03 · Capability hygiene
Write or sudo on an escalation surface.
A grant is flagged when it gives sudo, or
create / update / delete, on a
path that controls Vault itself:
- near-root wildcards:
*, sys/*, auth/*
- the control-plane engines:
sys/, auth/, identity/
- audit devices
- CA and key management on
pki/, transit/, ssh/
A companion check catches broad read/list reach on those same wildcard surfaces.
04 · Don't cry wolf
Least-privilege consumer paths are exempt, by name.
A service that issues certificates needs update on
pki/issue/<role>. That is a correctly scoped grant,
not a finding. So the check fires on everything under the
consumer engines except a curated list of consumer leaves:
issue, sign, encrypt, decrypt, creds, and the public read endpoints.
Anything not on that list keeps firing, including management verbs
nobody thought to enumerate. Key export and verbatim signing stay
out of the list on purpose.
05 · Cross-reference integrity
A role that grants a policy that does not exist.
An auth role lists the policies its tokens receive. If one of them is
missing from policies/, the role mints tokens bound to
nothing: today that is a silent no-op, and the day someone creates a
policy with that name it becomes an unreviewed grant.
06 · Findings go out as issues
Named path, named capability, "N of M paths".
Each finding says which file, which path, which capability, and how
much of the policy it concerns. It passes the same fail-closed safety
layer as the audit story: the protected root policy is never
flagged or edited, and nothing touching an audit device is ever
proposed.
Lint findings are issue-only today. The one path that already
produces draft MRs against this repo is the audit-driven policy widen
from the previous story.
07 · Consistent with its consumers Roadmap
Planned: check Vault against the workloads that use it.
Planned: join the Vault repo to the cluster side. Every
ExternalSecret or agent-injected path should be readable
by the policy its ServiceAccount's Kubernetes auth role grants, and
every role should point at a ServiceAccount and namespace that still
exist.
Today the assistant sees Vault on the cluster side only as an External
Secrets backend, so this join is not built yet.
08 · Declared vs live Roadmap
Planned: compare git with what Vault actually runs.
With a read-only Vault token (list and read on policies, auth methods
and mounts), the assistant could flag policies, roles or engines that
exist in Vault but not in git, the classic "someone fixed it in the
UI" drift. This needs an operator-provisioned token and is not
built.