operator: user adoption and add credential sync for externally-managed secrets#1438
Draft
operator: user adoption and add credential sync for externally-managed secrets#1438
Conversation
…naged secrets Fixes #1354. The User controller previously only created SCRAM credentials when the user did not already exist in Redpanda, which meant applying a User CR for a pre-existing user left it permanently unmanaged (status.managedUser=false). This also meant password rotation via Secret updates was never reconciled. Phase 1 — Adoption: Remove the !hasUser gate so that UpsertSCRAM (which is idempotent) handles both new and existing users whenever spec.authentication is declared. Phase 2 — Credential sync: Add spec.authentication.syncCredentials (opt-in bool). When enabled, each reconciliation cycle re-reads the password from the referenced Secret and upserts it to Redpanda, enabling external rotation via ESO or similar tools. Phase 3 — Secret watch: Index Users by their referenced password Secret and add a Watches handler so that external Secret changes (e.g. from ESO) trigger immediate reconciliation instead of waiting for the 5-minute periodic cycle. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…dentials field Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
This PR is stale because it has been open 5 days with no activity. Remove stale label or comment or this will be closed in 5 days. |
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.
Closes #1354
Summary
The User controller has two related issues that prevent importing existing Redpanda users and block credential rotation via external secret management systems (like ESO + Azure Key Vault):
SyncResourceonly callsCreatewhen!hasUser, so applying a User CR for a pre-existing Redpanda user leaves it permanently atstatus.managedUser=falseThis PR fixes both issues across three phases:
Phase 1: Fix user adoption
Changed:
SyncResourcebranching logic inuser_controller.goThe old code had a
!hasUser && shouldManageUsergate that prevented adoption of existing users. The fix changes this toshouldManageUser && !hasManagedUser, which triggers theCreate/upsert path regardless of whether the user already exists in Redpanda. This works because the underlyingAlterUserSCRAMswithUpsertSCRAMis idempotent — it handles both create and update.No opt-in needed — declaring
spec.authenticationis already the signal that the operator should manage the user.Phase 2: Ongoing credential sync (opt-in)
New field:
spec.authentication.syncCredentials(bool, defaultfalse)When enabled, each reconciliation cycle re-reads the password from the referenced Secret and upserts credentials to Redpanda. This enables password rotation via external systems like ESO.
New method:
users.Client.Update()— reads the current password from the Secret viaPassword.Fetch()(no generation or Secret creation) and upserts to Redpanda.Phase 3: Immediate reconciliation on Secret changes
New index: Users are indexed by the password Secret they reference (
spec.authentication.password.valueFrom.secretKeyRef.name)New watch: A
Watches(&corev1.Secret{}, ...)handler maps Secret changes to referencing User CRs and enqueues them. This means ESO-driven Secret updates trigger immediate reconciliation instead of waiting up to 5 minutes.How to migrate existing users to operator management
Step-by-step: ESO + Azure Key Vault workflow
Ensure credentials exist in Azure Key Vault — the username/password pair must already be provisioned
Configure ESO to sync to a K8s Secret:
Apply the User CR referencing the ESO-managed Secret:
Verify adoption:
To rotate credentials: Update the secret in Azure Key Vault. ESO will sync the new value to the K8s Secret, the operator will detect the Secret change (via the new watch) and immediately reconcile, pushing the new password to Redpanda.
Step-by-step: Manual migration (no ESO)
Create a K8s Secret with the current password:
kubectl create secret generic my-user-password \ --from-literal=password='current-password'Apply the User CR (same as step 3 above, but
syncCredentialsis optional since you're managing the Secret manually)To rotate: Update the Secret, then either wait for the 5-minute periodic reconcile or trigger a manual reconcile by annotating the User CR
Key flags
password.noGenerate: trueauthentication.syncCredentials: trueFiles changed
operator/api/redpanda/v1alpha2/user_types.go— addSyncCredentialsfield,ShouldSyncCredentials(),GetPasswordSecretName()helpersoperator/internal/controller/redpanda/user_controller.go— fix adoption logic, add credential sync branch, add Secret index + watchoperator/pkg/client/users/client.go— addUpdate()methodoperator/internal/controller/redpanda/user_controller_test.go— addTestUserAdoptExistingandTestUserCredentialSynctestsTODO
make generateto regenerate apply configurations for the newSyncCredentialsfieldTest plan
TestUserAdoptExisting— pre-creates a user via Kafka admin API, then applies a User CR and verifiesmanagedUser=trueand the new password worksTestUserCredentialSync— creates a user withsyncCredentials: true, rotates the password Secret, reconciles, and verifies the new password authenticatesTestUserReconciletable tests continue to pass (adoption case added to table)🤖 Generated with Claude Code