Skip to content

Commit ada2bb0

Browse files
committed
feat: redis TLS encryption enabled by default for all connections
Assisted-by: Cursor Signed-off-by: Rizwana777 <[email protected]>
1 parent 74bcf0d commit ada2bb0

File tree

30 files changed

+1332
-448
lines changed

30 files changed

+1332
-448
lines changed

Makefile

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,23 @@ endif
5959
@echo ""
6060
@echo "Configuring Redis TLS (required for E2E)..."
6161
./hack/dev-env/gen-redis-tls-certs.sh
62-
@echo "Step 1: Enabling TLS on Redis servers (creates secrets)..."
62+
@echo ""
63+
@echo "Configuring each cluster for Redis TLS (Redis + ArgoCD components together)"
64+
@echo "Note: Redis and ArgoCD components are configured together per-cluster to avoid"
65+
@echo " connection errors during the transition period."
66+
@echo ""
67+
@echo "=== Control Plane ==="
6368
./hack/dev-env/configure-redis-tls.sh vcluster-control-plane
64-
./hack/dev-env/configure-redis-tls.sh vcluster-agent-managed
65-
./hack/dev-env/configure-redis-tls.sh vcluster-agent-autonomous
66-
@echo "Step 2: Configuring Argo CD components for Redis TLS..."
6769
./hack/dev-env/configure-argocd-redis-tls.sh vcluster-control-plane
70+
@echo ""
71+
@echo "=== Agent Managed ==="
72+
./hack/dev-env/configure-redis-tls.sh vcluster-agent-managed
6873
./hack/dev-env/configure-argocd-redis-tls.sh vcluster-agent-managed
74+
@echo ""
75+
@echo "=== Agent Autonomous ==="
76+
./hack/dev-env/configure-redis-tls.sh vcluster-agent-autonomous
6977
./hack/dev-env/configure-argocd-redis-tls.sh vcluster-agent-autonomous
78+
@echo ""
7079
@echo " E2E environment ready with Redis TLS enabled (required)"
7180

7281
.PHONY: teardown-e2e

agent/agent.go

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,11 @@ type AgentOption func(*Agent) error
142142
// options.
143143
func NewAgent(ctx context.Context, client *kube.KubernetesClient, namespace string, opts ...AgentOption) (*Agent, error) {
144144
a := &Agent{
145-
version: version.New("argocd-agent"),
146-
deletions: manager.NewDeletionTracker(),
147-
sourceCache: cache.NewSourceCache(),
148-
inflightLogs: make(map[string]struct{}),
145+
version: version.New("argocd-agent"),
146+
deletions: manager.NewDeletionTracker(),
147+
sourceCache: cache.NewSourceCache(),
148+
inflightLogs: make(map[string]struct{}),
149+
cacheRefreshInterval: 30 * time.Second, // Default interval, can be overridden via WithCacheRefreshInterval
149150
}
150151
a.infStopCh = make(chan struct{})
151152
a.namespace = namespace
@@ -331,6 +332,7 @@ func NewAgent(ctx context.Context, client *kube.KubernetesClient, namespace stri
331332
MinVersion: tls.VersionTLS12,
332333
}
333334
if a.redisProxyMsgHandler.redisTLSInsecure {
335+
log().Warn("INSECURE: Not verifying Redis TLS certificate for cluster cache")
334336
clusterCacheTLSConfig.InsecureSkipVerify = true
335337
} else if a.redisProxyMsgHandler.redisTLSCAPath != "" {
336338
caCertPEM, err := os.ReadFile(a.redisProxyMsgHandler.redisTLSCAPath)
@@ -445,20 +447,22 @@ func (a *Agent) Start(ctx context.Context) error {
445447

446448
// Start the background process of periodic sync of cluster cache info.
447449
// This will send periodic updates of Application, Resource and API counts to principal.
448-
if a.mode == types.AgentModeManaged {
449-
go func() {
450-
ticker := time.NewTicker(a.cacheRefreshInterval)
451-
defer ticker.Stop()
452-
for {
453-
select {
454-
case <-ticker.C:
455-
a.addClusterCacheInfoUpdateToQueue()
456-
case <-a.context.Done():
457-
return
458-
}
450+
// Both managed and autonomous agents need to send cluster cache info updates
451+
go func() {
452+
// Send initial update immediately on startup (don't wait for first ticker)
453+
a.addClusterCacheInfoUpdateToQueue()
454+
455+
ticker := time.NewTicker(a.cacheRefreshInterval)
456+
defer ticker.Stop()
457+
for {
458+
select {
459+
case <-ticker.C:
460+
a.addClusterCacheInfoUpdateToQueue()
461+
case <-a.context.Done():
462+
return
459463
}
460-
}()
461-
}
464+
}
465+
}()
462466

463467
if a.remote != nil {
464468
a.remote.SetClientMode(a.mode)

cmd/argocd-agent/agent.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,8 +240,8 @@ func NewAgentRunCommand() *cobra.Command {
240240

241241
// Redis TLS flags
242242
command.Flags().BoolVar(&redisTLSEnabled, "redis-tls-enabled",
243-
env.BoolWithDefault("ARGOCD_AGENT_REDIS_TLS_ENABLED", false),
244-
"Enable TLS for Redis connections")
243+
env.BoolWithDefault("ARGOCD_AGENT_REDIS_TLS_ENABLED", true),
244+
"Enable TLS for Redis connections (enabled by default for security)")
245245
command.Flags().StringVar(&redisTLSCAPath, "redis-tls-ca-path",
246246
env.StringWithDefault("ARGOCD_AGENT_REDIS_TLS_CA_PATH", nil, ""),
247247
"Path to CA certificate for Redis TLS")

cmd/argocd-agent/principal.go

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ func NewPrincipalRunCommand() *cobra.Command {
9595
redisUpstreamTLSCAPath string
9696
redisUpstreamTLSCASecretName string
9797
redisUpstreamTLSInsecure bool
98+
informerSyncTimeout time.Duration
9899
)
99100
var command = &cobra.Command{
100101
Use: "principal",
@@ -255,6 +256,10 @@ func NewPrincipalRunCommand() *cobra.Command {
255256
opts = append(opts, principal.WithRedis(redisAddress, redisPassword, redisCompressionType))
256257
opts = append(opts, principal.WithHealthzPort(healthzPort))
257258

259+
if informerSyncTimeout > 0 {
260+
opts = append(opts, principal.WithInformerSyncTimeout(informerSyncTimeout))
261+
}
262+
258263
// Configure Redis TLS
259264
opts = append(opts, principal.WithRedisTLSEnabled(redisTLSEnabled))
260265
if redisTLSEnabled {
@@ -269,9 +274,20 @@ func NewPrincipalRunCommand() *cobra.Command {
269274
opts = append(opts, principal.WithRedisServerTLSFromSecret(kubeConfig.Clientset, namespace, redisServerTLSSecretName))
270275
}
271276

272-
// Validate upstream TLS configuration - insecure and CA path are mutually exclusive
273-
if redisUpstreamTLSInsecure && redisUpstreamTLSCAPath != "" {
274-
cmdutil.Fatal("Cannot specify both --redis-upstream-tls-insecure and --redis-upstream-ca-path")
277+
// Validate upstream TLS configuration - only one mode can be specified
278+
modesSet := 0
279+
if redisUpstreamTLSInsecure {
280+
modesSet++
281+
}
282+
if redisUpstreamTLSCAPath != "" {
283+
modesSet++
284+
}
285+
// Only count non-default secret name to allow default value
286+
if redisUpstreamTLSCASecretName != "" && redisUpstreamTLSCASecretName != "argocd-redis-tls" {
287+
modesSet++
288+
}
289+
if modesSet > 1 {
290+
cmdutil.Fatal("Only one Redis upstream TLS mode can be specified: --redis-upstream-tls-insecure, --redis-upstream-ca-path, or --redis-upstream-ca-secret-name")
275291
}
276292

277293
// Redis upstream TLS (for connections to principal's argocd-redis)
@@ -415,11 +431,14 @@ func NewPrincipalRunCommand() *cobra.Command {
415431
command.Flags().IntVar(&healthzPort, "healthz-port",
416432
env.NumWithDefault("ARGOCD_PRINCIPAL_HEALTH_CHECK_PORT", cmdutil.ValidPort, 8003),
417433
"Port the health check server will listen on")
434+
command.Flags().DurationVar(&informerSyncTimeout, "informer-sync-timeout",
435+
env.DurationWithDefault("ARGOCD_PRINCIPAL_INFORMER_SYNC_TIMEOUT", nil, 0),
436+
"Timeout for waiting for informers to sync on startup (0 = use default of 60s, increase for slow environments)")
418437

419438
// Redis TLS flags
420439
command.Flags().BoolVar(&redisTLSEnabled, "redis-tls-enabled",
421-
env.BoolWithDefault("ARGOCD_PRINCIPAL_REDIS_TLS_ENABLED", false),
422-
"Enable TLS for Redis connections")
440+
env.BoolWithDefault("ARGOCD_PRINCIPAL_REDIS_TLS_ENABLED", true),
441+
"Enable TLS for Redis connections (enabled by default for security)")
423442
command.Flags().StringVar(&redisServerTLSCertPath, "redis-server-tls-cert",
424443
env.StringWithDefault("ARGOCD_PRINCIPAL_REDIS_SERVER_TLS_CERT_PATH", nil, ""),
425444
"Path to TLS certificate for Redis proxy server")
@@ -468,7 +487,7 @@ func observer(interval time.Duration) {
468487
// The secret names where the certificates are stored in are hard-coded at the
469488
// moment.
470489
func getResourceProxyTLSConfigFromKube(kubeClient *kube.KubernetesClient, namespace, certName, caName string) (*tls.Config, error) {
471-
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
490+
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
472491
defer cancel()
473492
proxyCert, err := tlsutil.TLSCertFromSecret(ctx, kubeClient.Clientset, namespace, certName)
474493
if err != nil {

docs/configuration/agent/configuration.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ The recommended approach for production deployments is to use ConfigMap entries
8080
- **Description**: Skip verification of remote TLS certificate (INSECURE)
8181
- **Type**: Boolean
8282
- **Default**: `false`
83-
- **Security Warning**: Only use for development purposes
83+
**Security Warning**: Only use for development purposes
8484
- **Example**: `"false"`
8585

8686
#### Root CA Secret Name

0 commit comments

Comments
 (0)