diff --git a/lib/tbot/service_workload_identity_api.go b/lib/tbot/service_workload_identity_api.go index 5ef37e3fb971e..bdff56d3bb64d 100644 --- a/lib/tbot/service_workload_identity_api.go +++ b/lib/tbot/service_workload_identity_api.go @@ -309,8 +309,13 @@ func (s *WorkloadIdentityAPIService) FetchX509SVID( if err != nil { return trace.Wrap(err, "fetching CRL set from cache") } + renewalInterval := cmp.Or( + s.cfg.CredentialLifetime, s.botCfg.CredentialLifetime, + ).RenewalInterval var svids []*workloadpb.X509SVID + renewalTimer := time.NewTimer(renewalInterval) + defer renewalTimer.Stop() for { log.InfoContext(ctx, "Starting to issue X509 SVIDs to workload") @@ -320,6 +325,10 @@ func (s *WorkloadIdentityAPIService) FetchX509SVID( if err != nil { return trace.Wrap(err) } + // Reset our renewal timer to renew these freshly fetched SVIDs + // renewal_interval from now. + renewalTimer.Reset(renewalInterval) + // The SPIFFE Workload API (5.2.1): // // If the client is not entitled to receive any X509-SVIDs, then the @@ -334,7 +343,6 @@ func (s *WorkloadIdentityAPIService) FetchX509SVID( "workload did not pass attestation for any SVIDs", ) } - } resp := &workloadpb.X509SVIDResponse{ @@ -378,7 +386,7 @@ func (s *WorkloadIdentityAPIService) FetchX509SVID( log.DebugContext(ctx, "CRL set has been updated, distributing to client") crlSet = newCRLSet continue - case <-time.After(cmp.Or(s.cfg.CredentialLifetime, s.botCfg.CredentialLifetime).RenewalInterval): + case <-renewalTimer.C: log.DebugContext(ctx, "Renewal interval reached, renewing SVIDs") svids = nil continue diff --git a/lib/tbot/service_workload_identity_x509.go b/lib/tbot/service_workload_identity_x509.go index a4a52f967dc38..5bdabb637be3c 100644 --- a/lib/tbot/service_workload_identity_x509.go +++ b/lib/tbot/service_workload_identity_x509.go @@ -105,6 +105,9 @@ func (s *WorkloadIdentityX509Service) Run(ctx context.Context) error { if err != nil { return trace.Wrap(err, "getting CRL set from cache") } + renewalInterval := cmp.Or( + s.cfg.CredentialLifetime, s.botCfg.CredentialLifetime, + ).RenewalInterval if s.statusReporter == nil { s.statusReporter = readyz.NoopReporter() @@ -116,6 +119,8 @@ func (s *WorkloadIdentityX509Service) Run(ctx context.Context) error { var failures int firstRun := make(chan struct{}, 1) firstRun <- struct{}{} + renewalTimer := time.NewTimer(renewalInterval) + defer renewalTimer.Stop() for { var retryAfter <-chan time.Time if failures > 0 { @@ -155,7 +160,7 @@ func (s *WorkloadIdentityX509Service) Run(ctx context.Context) error { } crlSet = newCRLSet s.log.DebugContext(ctx, "CRL set has been updated, will regenerate output") - case <-time.After(cmp.Or(s.cfg.CredentialLifetime, s.botCfg.CredentialLifetime).RenewalInterval): + case <-renewalTimer.C: s.log.InfoContext(ctx, "Renewal interval reached, renewing SVIDs") x509Cred = nil privateKey = nil @@ -170,6 +175,8 @@ func (s *WorkloadIdentityX509Service) Run(ctx context.Context) error { failures++ continue } + // Reset the renewal timer to the configured interval. + renewalTimer.Reset(renewalInterval) } if err := s.render( ctx, bundleSet, x509Cred, privateKey, crlSet,