@@ -76,8 +76,27 @@ func needsDexTokenRenewal(secret *corev1.Secret) bool {
7676 return time .Until (expiry ) < dexServerTokenRenewalThreshold ()
7777}
7878
79+ // isDexTokenExpiryFeatureEnabled returns true if Dex token renewal expiry is enabled.
80+ // Users can set enableDexTokenExpiry: false (default) in the ArgoCD CR to use the legacy non-expiring token approach.
81+ func isDexTokenExpiryFeatureEnabled (cr * argoproj.ArgoCD ) bool {
82+ if cr .Spec .EnableDexTokenExpiry == nil {
83+ return false // Enabled by default (old behavior with non-expiring tokens)
84+ }
85+ return * cr .Spec .EnableDexTokenExpiry
86+ }
87+
7988// getDexOAuthClientSecret returns a time-limited Dex OAuth client token via the TokenRequest API.
89+ // If token renewal is disabled via the feature flag, it falls back to the legacy approach.
8090func (r * ReconcileArgoCD ) getDexOAuthClientSecret (cr * argoproj.ArgoCD ) (* string , error ) {
91+ // Check if token expiry feature is enabled, by default it is false, so we use the non-expiry legacy approach
92+ if ! isDexTokenExpiryFeatureEnabled (cr ) {
93+ // Use legacy approach (non-expiring tokens)
94+ log .Info ("Dex token renewal feature is disabled, using legacy non-expiring token approach" )
95+ return r .getDexOAuthClientSecretLegacy (cr )
96+ }
97+
98+ // Use new TokenRequest API approach (PR #2163)
99+ log .Info ("Dex token renewal feature is enabled, using TokenRequest API for short-lived tokens" )
81100 sa := newServiceAccountWithName (common .ArgoCDDefaultDexServiceAccountName , cr )
82101 if err := argoutil .FetchObject (r .Client , cr .Namespace , sa .Name , sa ); err != nil {
83102 return nil , err
@@ -159,6 +178,76 @@ func (r *ReconcileArgoCD) getDexOAuthClientSecret(cr *argoproj.ArgoCD) (*string,
159178 return & token , nil
160179}
161180
181+ // getDexOAuthClientSecretLegacy returns the legacy non-expiring Dex OAuth client secret.
182+ // This is the original implementation before PR #2163.
183+ // It uses persistent service account token secrets without automatic renewal.
184+ func (r * ReconcileArgoCD ) getDexOAuthClientSecretLegacy (cr * argoproj.ArgoCD ) (* string , error ) {
185+ sa := newServiceAccountWithName (common .ArgoCDDefaultDexServiceAccountName , cr )
186+ if err := argoutil .FetchObject (r .Client , cr .Namespace , sa .Name , sa ); err != nil {
187+ return nil , err
188+ }
189+
190+ // Find the token secret
191+ var tokenSecret * corev1.ObjectReference
192+ for _ , saSecret := range sa .Secrets {
193+ if strings .Contains (saSecret .Name , "token" ) {
194+ tokenSecret = & saSecret
195+ break
196+ }
197+ }
198+
199+ if tokenSecret == nil {
200+ // This change of creating secret for dex service account is due to
201+ // the change in Kubernetes v1.24 that reduces secret-based service account tokens.
202+ // From k8s v1.24 onwards, no default secret for service account is created.
203+ // However, for dex to work we need to provide the token of the secret used
204+ // by the dex service account as an OAuth token. This change helps achieve that.
205+ secret := & corev1.Secret {
206+ ObjectMeta : metav1.ObjectMeta {
207+ GenerateName : "argocd-dex-server-token-" ,
208+ Namespace : cr .Namespace ,
209+ Annotations : map [string ]string {
210+ corev1 .ServiceAccountNameKey : sa .Name ,
211+ },
212+ },
213+ Type : corev1 .SecretTypeServiceAccountToken ,
214+ }
215+ argoutil .AddTrackedByOperatorLabel (& secret .ObjectMeta )
216+ argoutil .LogResourceCreation (log , secret )
217+
218+ err := r .Create (context .TODO (), secret )
219+ if err != nil {
220+ return nil , errors .New ("unable to locate and create ServiceAccount token for OAuth client secret" )
221+ }
222+
223+ err = controllerutil .SetControllerReference (cr , secret , r .Scheme )
224+ if err != nil {
225+ return nil , err
226+ }
227+
228+ tokenSecret = & corev1.ObjectReference {
229+ Name : secret .Name ,
230+ Namespace : cr .Namespace ,
231+ }
232+ sa .Secrets = append (sa .Secrets , * tokenSecret )
233+
234+ argoutil .LogResourceUpdate (log , sa , "adding ServiceAccount token for OAuth client secret" )
235+ err = r .Update (context .TODO (), sa )
236+ if err != nil {
237+ return nil , errors .New ("failed to add ServiceAccount token for OAuth client secret" )
238+ }
239+ }
240+
241+ // Fetch the secret to obtain the token
242+ secret := argoutil .NewSecretWithName (cr , tokenSecret .Name )
243+ if err := argoutil .FetchObject (r .Client , cr .Namespace , secret .Name , secret ); err != nil {
244+ return nil , err
245+ }
246+
247+ token := string (secret .Data ["token" ])
248+ return & token , nil
249+ }
250+
162251// reconcileDexLegacySATokenSecrets deletes non-expiring kubernetes.io/service-account-token
163252// Secrets for the Dex SA and removes their stale references from the SA.
164253func (r * ReconcileArgoCD ) reconcileDexLegacySATokenSecrets (cr * argoproj.ArgoCD ) error {
0 commit comments