rotate: nine rotation drivers + verify-before-revoke execute spine

Implements the Rotator interface across all four rotation patterns, each a
self-contained one-file driver self-registering via init():

  in-place DB password   postgres, mysql (3-stmt unprivileged fallback), redis
  local keypair + propagate  sshkey (ed25519), wireguard (clamped curve25519)
  provider-API token         gitea PAT, mullvad device key
  cloud-key self-identifying  aws IAM access key (hand-rolled SigV4, no SDK dep)

Spine (execute.go) enforces Hard Rule #2: backup -> rotate -> verify(new) ->
store -> re-read+verify -> revoke-old; dryrun.go keeps --execute gated. Each
driver ships a table-driven test proving real cutover (old secret stops
authenticating) and asserting no secret substring leaks to argv/Meta/errors.
Promotes golang.org/x/crypto to a direct dependency.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
leetcrypt
2026-06-18 14:48:24 -07:00
parent 71a74e7166
commit 59af53dcc0
25 changed files with 4116 additions and 3 deletions
+5 -2
View File
@@ -31,8 +31,11 @@ type Rotator interface {
Rotate(ctx context.Context, c discover.Credential, v *vault.Vault) (*vault.Handle, error)
// Verify proves the newly minted secret actually authenticates.
Verify(ctx context.Context, newSecret *vault.Handle, v *vault.Vault) error
// RevokeOld retires the previous credential — only after verify + store.
RevokeOld(ctx context.Context, c discover.Credential) error
// RevokeOld retires the previous credential — only after verify + store. It
// receives the vault so a driver can read the OLD secret (c.Secret) when
// revocation needs it (e.g. SSH: derive the old public key to remove from
// authorized_keys). In-place engines (postgres) ignore it.
RevokeOld(ctx context.Context, c discover.Credential, v *vault.Vault) error
}
var (