Skip to content

multi: add HashiCorp Vault KV v2 secret support#92

Open
Roasbeef wants to merge 2 commits into
mainfrom
vault-kv2-support
Open

multi: add HashiCorp Vault KV v2 secret support#92
Roasbeef wants to merge 2 commits into
mainfrom
vault-kv2-support

Conversation

@Roasbeef

@Roasbeef Roasbeef commented Jul 1, 2026

Copy link
Copy Markdown
Member

In this PR, we add vault as a third secret source and target alongside the existing file and k8s backends, wired into the init-wallet, store-secret and load-secret commands. This lets an lnd deployment keep its wallet seed and password in HashiCorp Vault directly, so the secrets never need to be materialized as a Kubernetes Secret in etcd.

This supersedes #62, which was a straight port of an older lnd-fork branch written against a KV v1 Vault with a hand-rolled Kubernetes login. Our production Vault targets the KV v2 secrets engine, so that version wouldn't work as-is: a KV v2 read comes back with the values nested under data, which the KV v1 Logical().Read path doesn't unwrap.

What's here

  • KV v2 via the official helper. Reads and writes go through client.KVv2(mount), which handles the nested data/ path shaping KV v2 requires. Writes are read-modify-write merges, so storing one entry (e.g. the seed) never clobbers a sibling entry (e.g. the password) in the same secret. Using Put on a merged map (rather than Patch) keeps the required policy to just create/read/update.
  • Idempotency preserved. The errTargetExists sentinel is kept on the write path, so --error-on-existing keeps working across restarts. This matters: we never want to silently rotate a seed out from under an already-initialized wallet.
  • Kubernetes auth. Authentication uses the Kubernetes auth method via the official vault/api/auth/kubernetes login helper. The pod's projected ServiceAccount token is exchanged for a Vault token bound to a role and policy. The auth mount, role and token path are configurable; the server address comes from VAULT_ADDR or --vault.addr.
  • Docs + example + tests. A README section, an example-init-wallet-vault.sh startup script, and a vault_test.go suite (a mock KV v2 + k8s-auth server covering round-trip, no-clobber merge, the overwrite guard, newline trimming, and the not-found/missing-key/empty-value error paths).

The docs/vault-integration-design.md file captures how our production Vault in lightning-infra is set up (KV v2, Kubernetes auth, VSO), the gap versus the KV v1 approach, and the companion infra wiring (an lnd policy scoped to secret/data/lnd/*, a k8s auth role, and the lnd chart init-script) that will follow in a separate lightning-infra PR.

Roasbeef added 2 commits July 1, 2026 13:05
In this commit, we add `vault` as a third secret source and target
alongside the existing `file` and `k8s` backends, wired into the
`init-wallet`, `store-secret` and `load-secret` commands. This lets an
lnd deployment keep its wallet seed and password in HashiCorp Vault
directly, so the secrets never need to be materialized as a Kubernetes
Secret in etcd.

The implementation targets the KV v2 secrets engine using the official
`vault/api` KV v2 helper: reads and writes go through
`client.KVv2(mount)`, which handles the nested `data/` path shaping that
KV v2 requires. Writes are read-modify-write merges so that storing one
entry (e.g. the seed) never clobbers a sibling entry (e.g. the password)
in the same secret. The `errTargetExists` sentinel is preserved on the
write path so the existing idempotency contract (`--error-on-existing`)
keeps working across restarts, which is important to make sure we never
silently rotate a seed out from under an initialized wallet.

Authentication uses the Kubernetes auth method via the official
`vault/api/auth/kubernetes` login helper. The pod's projected
ServiceAccount token is exchanged for a Vault token bound to a role and
policy. The auth mount, role and token path are all configurable; the
Vault server address is taken from the `VAULT_ADDR` environment variable
or the `--vault.addr` flag.

A companion `example-init-wallet-vault.sh` and a README section round out
the change.
In this commit, we add the design doc that motivates the KV v2 Vault
variant: how our production Vault in lightning-infra is actually set up
(KV v2, Kubernetes auth, VSO), the gap versus the earlier KV v1 approach,
the locked design decisions, and the companion infra wiring needed to
roll it out.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant