feat: runtime credential rotation for AMQP, Redis, and TLS#59
Open
markusnissl wants to merge 1 commit intomainfrom
Open
feat: runtime credential rotation for AMQP, Redis, and TLS#59markusnissl wants to merge 1 commit intomainfrom
markusnissl wants to merge 1 commit intomainfrom
Conversation
Add infrastructure for detecting and reacting to secret file changes at runtime, enabling zero-downtime credential rotation in Kubernetes and Docker environments. Core: - Add config.GetSecretPath to expose _FILE env var paths - Add config.SecretWatcher that watches _FILE paths via fsnotify and updates a Watchable[string] when content changes AMQP: - Add Connection.UpdateURL that stores new URL and triggers reconnect - Add Connection.UpdateTLS for certificate rotation - Protect dial() reads with RLock for concurrent UpdateURL safety Redis: - Add Connection.SwapClient that creates new client with updated credentials, validates via ping, atomically swaps, closes old client - Protect c.client reads in Client(), checkHealth(), Close() - Fire onReconnect after swap so subscribers refresh references Database: - Add gormdb.SwappablePool — sits between GORM and *sql.DB, allows atomic pool swap without changing the *gorm.DB pointer - PostgreSQL driver stores SwappablePool for credential rotation - New queries immediately use new pool; old pool drains via grace period - No code changes needed in repositories TLS: - Add netutil.TLSReloader that watches cert/key/CA files via fsnotify - Provides dynamic GetCertificate/GetClientCertificate callbacks - Atomically reloads all three files together with debounce Builder: - Add WithSecretRotation() that enables all watchers with single toggle - Wire SecretWatcher into messaging and redis modules - AMQP watches RABBITMQ_URL_FILE or RABBITMQ_PASSWORD_FILE - Redis watches REDIS_PASSWORD_FILE
b9500c9 to
a961e22
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
config.SecretWatcher— watches_FILEenv var paths via fsnotify, updatesWatchable[string]on content change (Kubernetes symlink-swap pattern)UpdateURL/UpdateTLS— stores new credentials and triggers reconnect;dial()reads under RLock for thread safetySwapClient— creates new client, validates via ping, atomically swaps, closes old client; firesonReconnectfor subscriber refreshTLSReloader— watches cert/key/CA files, provides dynamicGetCertificate/GetClientCertificatecallbacks; debounced reloadWithSecretRotation()on Builder — single toggle that enables file watchers for all configured infrastructuredatabase/sqlpool); recommends Kubernetes rolling restartHow It Works
Usage
What Rotates vs What Doesn't
UpdateURL→ reconnect loopUpdateTLS→ reconnect loopSwapClient→ new client + ping validationTLSReloader→GetCertificatecallbacksdatabase/sqlpool can't swap credentialsTest plan
SecretWatcher: file change detection, atomic file replace, bad file keeps old value, no-op when no_FILEsetTLSReloader: initial load, cert rotation detection, bad cert keeps oldUpdateURLbuilds/tests pass,dial()reads under lockSwapClientbuilds/tests pass,Client()reads under lockWithSecretRotationwiring