fix(tenant-manager/redis): add CACertBase64 to TenantPubSubRedisConfig#491
Conversation
Adds an OPTIONAL CACertBase64 field on TenantPubSubRedisConfig so callers
can supply a base64-encoded PEM bundle that populates tls.Config.RootCAs
when TLS is enabled. Mirrors the pattern already used by commons/redis
and the tenant-manager Mongo client.
Why: on macOS the system trust path uses the Security Framework, which
rejects valid Amazon-issued ElastiCache/Valkey certificates as
"certificate is not standards compliant" — a strictness mismatch with
Go's pure-Go verifier. openssl s_client -CAfile amazon-root-ca-1.pem
verifies the same cluster successfully, and Go tls.Dial with an
explicit RootCAs pool (Amazon Root CA 1 PEM) handshakes cleanly. The
plugin needs a way to inject that CA without falling back to the
permissive InsecureSkipVerify path.
Default behavior preserved (backward-compatible):
- Empty CACertBase64 with TLS=true leaves tls.Config.RootCAs nil so
the Go runtime continues to use the system trust pool, exactly as
today. No existing caller breaks.
- CACertBase64 set with TLS=false is silently ignored.
- Invalid base64 returns a wrapped decode error.
- Valid base64 but no PEM blocks returns "no PEM blocks found".
Downstream consumers typically wire the new field from a
MULTI_TENANT_REDIS_CA_CERT environment variable.
Tests: table-driven unit tests in client_cacert_test.go cover all six
matrix cells (TLS x CACertBase64 presence/validity) including the
explicit regression assertion that empty CACertBase64 + TLS=true keeps
RootCAs nil. A small self-signed CA is generated in-test (ECDSA P-256)
so the suite stays deterministic and free of public CA bundles. The
four pre-existing tests in client_test.go and coverage_boost_test.go
are unchanged and still pass.
X-Lerian-Ref: 0x1
|
Caution Review failedPull request was closed or merged during review No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
WalkthroughThis PR extends Redis TLS configuration to support custom CA certificates through a base64-encoded PEM field. The implementation refactors TLS option building into a dedicated helper function, handles base64 decoding and certificate pool creation, and includes comprehensive test coverage for all configuration paths. ChangesCustom CA Certificate Support for Redis TLS
Comment |
🔍 PR Validation Summary🚫 PR Blocked — 1 blocking failure
|
🔒 Security Scan Results —
|
| Stage | Status | Blocking? |
|---|---|---|
| Filesystem Scan | ✅ Clean | — |
| Docker Image Scan | ➖ Skipped | — |
| Docker Hub Health Score | ➖ Skipped | — |
| Pre-release Version Check | ✅ Clean | — |
Trivy
Filesystem Scan
✅ No vulnerabilities or secrets found.
Pre-release Version Check
✅ No unstable version pins found.
📊 Unit Test Coverage Report:
|
| Metric | Value |
|---|---|
| Overall Coverage | 87.0% ✅ PASS |
| Threshold | 80% |
Coverage by Package
| Package | Coverage |
|---|---|
github.com/LerianStudio/lib-commons/v5/commons/backoff |
91.1% |
github.com/LerianStudio/lib-commons/v5/commons/certificate |
88.8% |
github.com/LerianStudio/lib-commons/v5/commons/circuitbreaker |
86.8% |
github.com/LerianStudio/lib-commons/v5/commons/cron |
94.2% |
github.com/LerianStudio/lib-commons/v5/commons/crypto |
95.6% |
github.com/LerianStudio/lib-commons/v5/commons/dlq |
81.0% |
github.com/LerianStudio/lib-commons/v5/commons/errgroup |
86.1% |
github.com/LerianStudio/lib-commons/v5/commons/internal/nilcheck |
100.0% |
github.com/LerianStudio/lib-commons/v5/commons/jwt |
89.4% |
github.com/LerianStudio/lib-commons/v5/commons/license |
96.9% |
github.com/LerianStudio/lib-commons/v5/commons/mongo |
89.0% |
github.com/LerianStudio/lib-commons/v5/commons/net/http/idempotency |
93.0% |
github.com/LerianStudio/lib-commons/v5/commons/net/http/ratelimit |
90.8% |
github.com/LerianStudio/lib-commons/v5/commons/net/http |
96.1% |
github.com/LerianStudio/lib-commons/v5/commons/outbox |
91.9% |
github.com/LerianStudio/lib-commons/v5/commons/pointers |
100.0% |
github.com/LerianStudio/lib-commons/v5/commons/postgres |
84.6% |
github.com/LerianStudio/lib-commons/v5/commons/rabbitmq |
89.3% |
github.com/LerianStudio/lib-commons/v5/commons/redis |
89.5% |
github.com/LerianStudio/lib-commons/v5/commons/safe |
99.6% |
github.com/LerianStudio/lib-commons/v5/commons/secretsmanager |
98.7% |
github.com/LerianStudio/lib-commons/v5/commons/security/ssrf |
95.9% |
github.com/LerianStudio/lib-commons/v5/commons/security |
100.0% |
github.com/LerianStudio/lib-commons/v5/commons/server |
88.0% |
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/cache |
97.9% |
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/client |
93.5% |
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/consumer |
87.9% |
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/core |
99.0% |
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/event |
95.7% |
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/internal/eviction |
100.0% |
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/log |
100.0% |
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/middleware |
92.3% |
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/mongo |
76.3% |
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/postgres |
86.8% |
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/rabbitmq |
82.6% |
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/redis |
95.8% |
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/s3 |
96.3% |
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/tenantcache |
98.4% |
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/valkey |
100.0% |
github.com/LerianStudio/lib-commons/v5/commons/transaction |
95.1% |
github.com/LerianStudio/lib-commons/v5/commons/webhook |
91.5% |
github.com/LerianStudio/lib-commons/v5/commons |
96.4% |
Generated by Go PR Analysis workflow
Bug
commons/tenant-manager/redis/client.go(v5.3.1) builds atls.Configwith noRootCAswhencfg.TLS=true, so Go falls back to the system trust pool. On macOS the system trust path uses Apple's Security Framework, which rejects valid Amazon-issued ElastiCache/Valkey certs as"certificate is not standards compliant"— a strictness mismatch with Go's pure-Go verifier when the same chain is supplied via an explicitRootCAspool.Empirical evidence (Valkey 7.2.4 / ElastiCache, TLS-required, default-user auth)
Cluster sample:
master.tenant-manager-devops-valkey.1tj5cc.sae1.cache.amazonaws.com:6379openssl s_client -CAfile amazon-root-ca-1.pemVerify return code: 0 (ok)✅tls.DialwithRootCAs: poolFromAmazonRootCA1tls.DialwithoutRootCAs(system trust)Change
Adds an OPTIONAL
CACertBase64field toTenantPubSubRedisConfig. When set and TLS is enabled, the decoded PEM bundle populatestls.Config.RootCAs. Mirrors the pattern already used bycommons/redis(TLSConfig.CACertBase64) and the tenant-manager Mongo client.Backward compatibility (hard guarantee)
The field is additive and optional. No existing caller breaks.
CACertBase64TLS""(zero value)false""(zero value)trueRootCAsleft nil → system trust fallback — identical to todaytrueRootCAspopulated from decoded PEM (the new behavior)falsetruetrue"no PEM blocks found"errorA regression test explicitly asserts the empty-CA + TLS-on path keeps
RootCAsnil, so future refactors can't silently break system-trust callers.Test matrix
All in
commons/tenant-manager/redis/client_cacert_test.go, build tag//go:build unit, deterministic (self-signed ECDSA P-256 CA generated in-test — no public CA bundle embedded):TestBuildOptions_CACertBase64_EmptyWithTLS_PreservesSystemTrust— regression guard for the backward-compat invariant.TestBuildOptions_CACertBase64_ValidPEM_PopulatesRootCAs— happy path,RootCAs.Equal()against the supplied cert.TestBuildOptions_CACertBase64_InvalidBase64_ReturnsWrappedError— fail-fast decode error.TestBuildOptions_CACertBase64_ValidBase64_NotPEM_ReturnsError— fail-fast PEM error.TestBuildOptions_CACertBase64_IgnoredWhenTLSDisabled— TLS off is honored.TestBuildOptions_CACertBase64_TableDriven— full 6-case matrix.The 4 pre-existing tests in
client_test.goandcoverage_boost_test.gopass unchanged.Verification
Downstream impact
plugin-br-bank-transfer(and any other consumer with the same macOS-vs-AWS-CA pain) will:lib-commonsto the new patch tag once released frommain.MULTI_TENANT_REDIS_CA_CERTenv var (base64-encoded Amazon Root CA 1 PEM).CACertBase64when buildingTenantPubSubRedisConfig.The new field's GoDoc explicitly names
MULTI_TENANT_REDIS_CA_CERTas the canonical downstream env to keep wiring consistent.Hotfix logistics
main(hotfix), patch bump expected via semantic-release onfix:commit type → next tag should bev5.3.2.semantic-releaseregenerates it post-merge per.releaserc.yml.develop: required as a follow-up so the field reaches the next minor pre-release. The repo's standarddevelop-backmerge workflow (chore(changelog): backmerge main into develop) should handle it; if not, a follow-up PRmain → developis needed. Not part of this PR.Constraints respected
%werror wrapping;ctx-first preserved on theNewTenantPubSubRedisClientsignature.TenantPubSubRedisConfigshape).-S) with trailerX-Lerian-Ref: 0x1.