Allow standalone Redis in auth server storage#4994
Conversation
Add Addr field to RedisConfig for standalone mode (e.g., GCP Memorystore, AWS ElastiCache), making it mutually exclusive with SentinelConfig. Update validateConfig to enforce the mutual exclusion and require exactly one connection mode. Update NewRedisStorage to branch between redis.NewClient (standalone) and redis.NewFailoverClient (sentinel). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…te converter Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add an Addr field for standalone Redis mode and make SentinelConfig optional. A CEL XValidation rule enforces that exactly one of addr (standalone) or sentinelConfig (Sentinel) is set. Regenerate deepcopy, CRD manifests, and API reference docs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nConfig Replace the Sentinel-only requirement with support for either a standalone addr or a SentinelConfig, matching the new RedisStorageConfig.Addr field added to the CRD in earlier tasks. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix CEL XValidation rule Unicode curly quote bug in RedisStorageConfig (replaced U+201D right double quotation mark with ASCII single quotes) - Add mutual exclusivity guard when both addr and sentinelConfig are set in buildStorageRunConfig - Add test case covering the addr+sentinelConfig conflict error path - Update RedisStorage doc comment to describe both standalone and Sentinel modes - Use t.Cleanup instead of defer in withRedisStorage parallel test helper - Use non-default ACL username in TestNewRedisStorage_Standalone_WithMiniredis - Regenerate CRD manifests and API docs Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…d, tests - Fix CEL XValidation rule: replace string literal comparison with size() > 0 to avoid gci formatter rewriting quote characters - Add mutual-exclusivity guard in buildStorageRunConfig for both addr AND sentinelConfig set - Add test case for "both addr and sentinelConfig set" error in buildStorageRunConfig - Fix doc comment on RedisStorage to mention both standalone and Sentinel modes - Switch withRedisStorage cleanup from defer to t.Cleanup for parallel test safety - Use non-default username in standalone miniredis test - Regenerate CRD manifests and API docs Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #4994 +/- ##
==========================================
+ Coverage 69.76% 69.78% +0.01%
==========================================
Files 560 560
Lines 56475 56513 +38
==========================================
+ Hits 39399 39436 +37
Misses 14053 14053
- Partials 3023 3024 +1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
@jhrozek comment addressed |
|
I think you forgot to push the new code @reyortiz3 ? I only see main merges. |
Redis services such as GCP Memorystore Basic/Standard HA and Azure Cache for Redis use password-only AUTH and do not expose ACL users. The previous implementation required a non-empty username, which forced go-redis to send AUTH <username> <password> and caused authentication failures on those tiers. When username is omitted, go-redis v9 sends HELLO with "default" as the username (falling back to legacy AUTH <password> for servers that predate HELLO), which is the correct form for password-only managed Redis. - Remove the empty-username validation in storage.validateConfig - Skip username env var resolution in convertRedisACLConfig when UsernameEnvVar is empty, producing an empty ACLUserConfig.Username - Mark UsernameSecretRef optional in RedisACLUserConfig CRD type and only populate UsernameEnvVar in the RunConfig when the ref is present - Update docs to reflect standalone mode support, optional username, TLS CA cert guidance for managed services, and note that Redis Cluster mode (GCP Memorystore Cluster, ElastiCache Serverless) is not supported Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
@jhrozek ya, sorry the changes were not pushed, should be updated now/ |
Runs task operator-manifests and task crdref-gen to pick up the optional-username changes: removes usernameSecretRef from the required list in MCPExternalAuthConfig and VirtualMCPServer CRDs, updates the field description, and refreshes crd-api.md accordingly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
jhrozek
left a comment
There was a problem hiding this comment.
One small item worth a follow-up: the default timeouts (3s read/write, 5s dial) are likely too short for managed-service failover windows — Memorystore and ElastiCache typically take 15–30s to complete a failover, so in-flight ops will error during that window. Worth either raising the defaults or adding a note in the user guide recommending higher values for managed deployments.
Summary
Addrfield (standalone mode) alongside the existingSentinelConfig(Sentinel mode). Exactly one must be set. Mirrors the pattern already used inpkg/transport/session/redis_config.go.RedisConfig/RedisRunConfigin storage,convertRedisRunConfigin the embedded auth server runner,RedisStorageConfigCRD type with CEL XValidation, andbuildStorageRunConfigin the operator controller.usernameSecretRefoptional in the CRD and removes the empty-username validation invalidateConfig. When username is omitted, go-redis v9 sendsHELLOwith"default"as the username and falls back to legacyAUTH <password>for servers that predate HELLO. This is required for managed Redis tiers that do not expose ACL users (GCP Memorystore Basic/Standard HA, Azure Cache for Redis).docs/redis-storage.mdanddocs/arch/11-auth-server-storage.mdto document both connection modes, the optional username, TLS CA cert guidance for managed services (e.g.gcloud redis instances get-server-ca-certs), and the known limitation that Redis Cluster mode is not supported (tracked in Add Redis Cluster mode support to auth server storage #5010).Fixes #4990
Type of change
Test plan
task test)task lint-fix)New tests added in the standalone addr PR:
TestRedisConfig_Validationextended with standalone/conflict/neither casesTestNewRedisStorage_Standalone_ConnectionFailure— unreachable addr returns errorTestNewRedisStorage_Standalone_WithMiniredis— successful standalone connection via miniredisTestConvertRedisRunConfigextended with standalone happy path, both-set, neither-set casesTestBuildStorageRunConfigextended with standalone addr case and both-set error caseNew tests added in the optional-username commit:
TestConvertRedisRunConfig_WithEnvVars: "empty UsernameEnvVar uses legacy password-only auth" — verifies emptyUsernameEnvVarresolves to empty username without errorTestBuildStorageRunConfig: "Redis standalone with password-only auth omits UsernameEnvVar" — verifies operator omitsUsernameEnvVarfrom RunConfig whenusernameSecretRefis absentAPI Compatibility
This PR adds an optional
addrfield toRedisStorageConfig, makessentinelConfigoptional (it was previously implicitly required), and makesusernameSecretRefoptional inRedisACLUserConfig. All changes are additive and backward compatible — existing Sentinel-basedEmbeddedAuthServerConfigresources with a username are unchanged.v1beta1API, OR theapi-break-allowedlabel is applied and the migration guidance is described above.Changes
pkg/authserver/storage/redis.goAddrtoRedisConfig; updatevalidateConfig(XOR, drop empty-username check); branchNewRedisStorageon standalone vs Sentinelpkg/authserver/storage/config.goAddrtoRedisRunConfigpkg/authserver/runner/embeddedauthserver.goconvertRedisRunConfigto handleAddrXORSentinelConfig; makeconvertRedisACLConfigskip username resolution whenUsernameEnvVaris emptycmd/thv-operator/api/v1beta1/mcpexternalauthconfig_types.goAddrtoRedisStorageConfig; makeSentinelConfigoptional; add CEL XValidation; makeusernameSecretRefoptionalcmd/thv-operator/pkg/controllerutil/authserver.gobuildStorageRunConfigto handle standalone path; only populateUsernameEnvVarwhenusernameSecretRefis presentdocs/redis-storage.mddocs/arch/11-auth-server-storage.mddocs/server/swagger.json/yamladdrfieldcrd-api.mdDoes this introduce a user-facing change?
Yes. Two user-facing changes:
addr: "host:port"field instead of requiring a Sentinel deployment. Existing Sentinel configurations are unchanged.usernameSecretRefis now optional. Operators targeting managed Redis tiers without ACL support (GCP Memorystore Basic/Standard HA, Azure Cache for Redis) can omit it and rely on password-only AUTH.Implementation plan
Approved implementation plan
See
docs/superpowers/plans/2026-04-21-authserver-standalone-redis.md.Special notes for reviewers
self.addr.size() > 0rather thanself.addr != ''because thegciformatter in golangci-lint converts single-quoted CEL string literals to Unicode curly quotes, which corrupts the generated CRD YAML. Thesize() > 0form is semantically equivalent and linter-safe.SentinelTLSis only populated whenSentinelConfigis non-nil, matching the standalone path that has no separate dialer TLS config.Hello()substitutes"default"for an empty username (seecommands.go:363), soHELLO 2 AUTH default <password>is sent for password-only connections. Servers that reject HELLO fall back to legacyAUTH <password>automatically.Generated with Claude Code