Skip to content

secret_store: HashiCorp Vault KV2 backend (covers OVHcloud Secret Manager, Vault, OpenBao) #170

Description

@fheikens

Summary

Add a HashiCorp Vault KV2 backend to the secret_store credential provider. Because KV2 is a de-facto standard wire protocol, one backend covers three targets at once:

  • OVHcloud Secret Manager — GA (2026), exposes a HashiCorp Vault KV2-compatible API; relevant to growing European adoption.
  • HashiCorp Vault — the KV2 secrets engine itself (widely used in EU on-prem / regulated environments).
  • OpenBao — the open-source Vault fork (same KV2 API).

Inherits decisions from the credential-provider epic #92; extends the secret_store provider (#97), sibling to the AWS Parameter Store backend (#157). Frame this as "KV2 protocol backend", not "OVH support" — OVH is one consumer of the same interface.

Do we support it today? No. Current secret_store backends: AWS Secrets Manager, AWS Systems Manager Parameter Store, Azure Key Vault, GCP Secret Manager.

Cross-cutting decision for the epic/keystone (#92 / #93) — read first

This backend departs from a core epic principle and that decision must be made at the umbrella, not silently here:

Open design decisions (resolve in the spec, before code)

  1. Reference disambiguation. A KV2 secret is an HTTPS URL like https://vault.example.com/v1/<mount>/data/<path>, which structurally overlaps the Azure Key Vault form (https://<vault>.vault.azure.net/secrets/<name>). Backend routing currently infers from secret_ref shape, so KV2 needs a clean discriminator — candidates: a vault+kv2:// scheme, or requiring the /v1/.../data/ path marker. (Note: internal/config/secretref_test.go already rejects a bare vault:// scheme — the namespace was anticipated.)
  2. Auth method + where its credential lives. Decide which Vault auth methods to support first (token via VAULT_TOKEN / token file? AppRole? Kubernetes auth?) and how that credential is supplied without putting a long-lived secret in signals.yaml (env/file/mounted, parallel to how the DB password is kept out of config today).
  3. KV2 payload mapping. KV2 returns a versioned JSON object of key/value pairs under data.data. Map onto the existing secret_json_key extraction; decide version selection (latest vs pinned) and how it interacts with the cache/TTL model (KV2 has lease/version semantics).
  4. Transport / topology. Vault CA trust, Vault namespace (Enterprise / HCP), and OVHcloud-specific endpoint/region details.

Scope (STDD — spec first)

  1. Spec: a KV2 sub-spec (or an extension of credential-provider-secret-store.md) covering the ref form, the new auth model + its invariants/failure modes, payload mapping, and NFRs — plus the keystone note on the stored-auth-credential trade-off.
  2. Acceptance cases (normal / boundary / invalid / failure), each referencing a spec ID.
  3. Failing tests with an injected fake KV2 client (no live network, per NFR003).
  4. Implementation: SecretBackendHashiCorpVaultKV2 enum, ref parsing/disambiguation, a hashicorpVaultKV2Fetcher implementing secretFetcher, the Vault auth wiring, config + validation, failure taxonomy, guidance text.
  5. Live smoke (env-gated) against a real Vault/OpenBao and against OVHcloud Secret Manager's KV2 endpoint.
  6. Docs: a per-target recipe in docs/database-connections.md (Vault / OpenBao / OVHcloud), with auth setup and least-privilege policy.

Acceptance criteria

  • A secret_store target with a KV2 reference fetches the DB password from Vault/OpenBao/OVHcloud and connects, with no DB password in config.
  • The KV2 reference is routed unambiguously (no collision with the Azure Key Vault form).
  • The Vault auth credential is supplied out-of-config (env/file/mounted), never inline in signals.yaml.
  • secret_json_key extraction works against the KV2 data.data object.
  • Secret values are never logged/persisted; only metadata.
  • Unit tests pass with a fake KV2 client; live smoke passes against Vault/OpenBao and OVHcloud.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:collectorArq Signals collectors and pipelinearea:securitySecurity hardening, AppSec, compliance controlseffort:LLarge effort (24-80 hours)enhancementNew feature or requestpriority:P2Nice-to-have / can be deferred

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions