Skip to content

feat: pluggable secret management and remote signing-key custody (#120) - #159

Merged
dami-005 merged 2 commits into
Zenith-options:mainfrom
Whiznificent:feat/secrets-management-issue-120
Sep 30, 2026
Merged

dami-005 merged 2 commits into
Zenith-options:mainfrom
Whiznificent:feat/secrets-management-issue-120

Conversation

@Whiznificent

Copy link
Copy Markdown

Closes #120.

What

Introduces a SecretProvider abstraction for every secret and a Signer abstraction for Stellar ed25519 keys, so the fund-controlling hot keys never live in a container spec or in process memory.

Secret retrieval

  • SecretProvider (async) with three real backends:
    • EnvSecretProvider — dev/default, one env var per secret.
    • SopsFileSecretProvider — SOPS-encrypted file, decrypted on demand via the sops binary (plaintext never hits disk); injectable binary path for tests.
    • VaultSecretProvider — HashiCorp Vault KV v2, plus auth/token/renew-self lease renewal.
  • SecretStore caches values in Arc<SecretString>: fail fast at startup (load errors if any secret is missing) and fail soft on refresh (refresh_loop keeps serving the last good values and logs if the backend blips).
  • Backend selected by ZENITH_SECRET_BACKEND (env/sops/vault) via provider_from_env().
  • All values are secrecy::SecretString — redacted in Debug, zeroised on drop, exposed only at the point of use.

Key rotation

  • HmacKeyRing signs with the current key and verifies with the current or previous key, so rotating cursors/idempotency/webhook keys has no invalid-signature window. has_previous() signals an open rotation window; dropping the previous key completes it.

Remote signing

  • Signer trait + LocalEd25519Signer (dev/tests), VaultTransitSigner (Vault Transit ed25519), and AwsKmsSigner (AWS KMS ED25519_SHA_512, requests SigV4-signed by a small in-repo implementation). The private key never enters process memory for the remote signers.

Docs

  • docs/secrets-rotation.md — runbook for each secret class (HMAC rings, DB credentials, Stellar signing keys, Vault token).
  • .env.example lists the secret-related configuration.

Testing

Every provider and signer path is unit-tested against a scripted HTTP transport (200/404/5xx/malformed JSON), plus: HMAC ring round-trip and rotation-window behaviour, SOPS success/failure via a stub binary, Vault KV v2 parsing and lease renewal, AWS KMS SigV4 request shape + SPKI public-key extraction, and a SecretString Debug-redaction test. The SigV4 implementation is validated against the canonical example from the AWS documentation.

The provider trait is deliberately injected into Vault/KMS clients so a full Vault integration test (testcontainers) can be run out-of-band without making CI depend on Docker; see the runbook's Testing section.

Test evidence

fmt, clippy -D warnings, and test pass on the branch (fork CI run).

The on-chain work brings hot signing keys that control protocol funds, and a
plaintext env var is not acceptable custody for them. Introduce a SecretProvider
abstraction (env, SOPS-encrypted files, HashiCorp Vault KV v2 with lease
renewal) behind a caching SecretStore that fails fast at startup and fails soft
on refresh; wrap every value in secrecy::SecretString so it is redacted in
Debug and zeroised on drop. Add HMAC key rings that sign with the current key
and verify with the current or previous one for zero-downtime rotation, and a
Signer abstraction with Vault Transit and AWS KMS (SigV4) backends so Stellar
keys never enter process memory. Includes a rotation runbook and unit tests
covering every provider/signer path against a scripted HTTP transport.
@drips-wave

drips-wave Bot commented Sep 30, 2026

Copy link
Copy Markdown

@Whiznificent Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

…ment-issue-120

# Conflicts:
#	.env.example
#	README.md
#	src/signing.rs
@dami-005
dami-005 merged commit 2f3afb4 into Zenith-options:main Sep 30, 2026
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.

[High] Secrets Management and Signing-Key Rotation

2 participants