Skip to content

[FEATURE]: Secret management plugin (Vault / Infisical) #139

Description

@araujof

Summary

Let CPEX components and authentication flows resolve secrets from an external secret manager. Ship Vault support, but behind a provider-agnostic abstraction so we are not coupled to Vault and can add Infisical (and others) without touching consumers. Not a default builtin or core dependency.

Motivation

Today secret material (e.g. JWT decoding keys) is inline or file-based in config. Operators want to source it from their secret manager. We want to offer that without forcing every deployment to carry the dependency — and without licensing obligations leaking into integrations that don't use it.

Scope

  • A SecretProvider abstraction (fetch a secret by reference, with caching/TTL and refresh). Vault and Infisical are implementations behind it; consumers depend only on the trait.
  • A secret-reference indirection usable anywhere config takes secret material, so a value can say "resolve this from the provider" instead of holding the literal.
  • First consumer: the JWT identity plugin — add a provider-backed variant to DecodingKeySource (today: Pem, PemFile, Jwk, JwksUrl, Secret), so signing/verification keys can come from Vault/Infisical.
  • Optional wiring: gate providers behind Cargo features and keep them out of the default builtin set, mirroring how valkey is opt-in (full only, not default). A build with no secrets feature pulls none of it.

Licensing (must resolve in design)

The deny.toml allow list is strictly permissive (Apache-2.0, MIT, BSD, MPL, ISC, …). Pulling a copyleft/BUSL-licensed Vault client into the runtime graph would taint deployments that don't even use the feature.

  • Prefer talking to Vault/Infisical over their HTTP APIs with a permissively licensed HTTP client, rather than adopting a vendor SDK whose license isn't on the allow list.
  • Vet each provider crate against deny.toml before adding it; if it needs a new license entry, that is a deliberate decision to call out in review.
  • Keep provider crates optional so cargo deny on the default graph stays clean and non-users take on no new obligations.

Acceptance Criteria

Scenario: JWT key sourced from a secret provider
  Given a JWT issuer configured with a provider-backed decoding key
  When the plugin initializes
  Then the key is fetched via the SecretProvider and used to verify tokens

Scenario: no secrets feature, no dependency
  Given CPEX built without any secrets provider feature
  Then no Vault/Infisical crates appear in the dependency graph

Scenario: swapping providers requires no consumer changes
  Given a component that resolves a secret reference
  When the configured provider changes from Vault to Infisical
  Then the component code is unchanged

Design Sketch

config (secret reference) ──► SecretProvider (trait) ──► VaultProvider
                                                    └──► InfisicalProvider
        consumers: JWT decoding key, other CPEX components

Alternatives Considered

  • Vendor SDK per provider — rejected as the default path over licensing and coupling; revisit only if the HTTP API is insufficient for a given provider.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status
    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions