From 7c63d7b790de4baedac0b3b02a78f2f65306362b Mon Sep 17 00:00:00 2001 From: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com> Date: Fri, 6 Jun 2025 15:19:18 -0400 Subject: [PATCH] fix(server): race condition in revoked token logic (#23311) Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com> --- server/server.go | 6 ++++-- util/session/state.go | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/server/server.go b/server/server.go index 4a341a38a282b..c47bc383d5c29 100644 --- a/server/server.go +++ b/server/server.go @@ -561,13 +561,15 @@ func (server *ArgoCDServer) Run(ctx context.Context, listeners *Listeners) { } }() - server.userStateStorage.Init(ctx) - metricsServ := metrics.NewMetricsServer(server.MetricsHost, server.MetricsPort) if server.RedisClient != nil { cacheutil.CollectMetrics(server.RedisClient, metricsServ, server.userStateStorage.GetLockObject()) } + // Don't init storage until after CollectMetrics. CollectMetrics adds hooks to the Redis client, and Init + // reads those hooks. If this is called first, there may be a data race. + server.userStateStorage.Init(ctx) + svcSet := newArgoCDServiceSet(server) server.serviceSet = svcSet grpcS, appResourceTreeFn := server.newGRPCServer() diff --git a/util/session/state.go b/util/session/state.go index ff121733b6b04..f3346cafbc121 100644 --- a/util/session/state.go +++ b/util/session/state.go @@ -38,6 +38,8 @@ func NewUserStateStorage(redis *redis.Client) *userStateStorage { } } +// Init sets up watches on the revoked tokens and starts a ticker to periodically resync the revoked tokens from Redis. +// Don't call this until after setting up all hooks on the Redis client, or you might encounter race conditions. func (storage *userStateStorage) Init(ctx context.Context) { go storage.watchRevokedTokens(ctx) ticker := time.NewTicker(storage.resyncDuration)