in core/app/credentialrefresher/credentialrefresher.go [294:421]
func (c *credentialsRefresher) credentialRefresherRoutine() {
var err error
defer func() {
if err := recover(); err != nil {
c.log.Errorf("credentials refresher panic: %v", err)
c.log.Errorf("Stacktrace:\n%s", debug.Stack())
c.log.Flush()
// We never want to exit this loop unless explicitly asked to do so, restart loop
time.Sleep(5 * time.Minute)
go c.credentialRefresherRoutine()
}
}()
// if credentials are not expired, verify that credentials are available.
if c.identityRuntimeConfig.CredentialsExpiresAt.After(c.getCurrentTimeFunc()) {
if c.identityRuntimeConfig.ShareFile == "" && c.identityRuntimeConfig.CredentialSource == credentialSourceEC2 {
c.sendCredentialsReadyMessage()
} else {
localCredsProvider := newSharedCredentials(c.identityRuntimeConfig.ShareFile, c.identityRuntimeConfig.ShareProfile)
if _, err := localCredsProvider.Get(); err != nil {
c.log.Warnf("Credentials are not available when they should be: %v", err)
// set expiration and retrieved to beginning of time if shared credentials are not available to force credential refresh
c.identityRuntimeConfig.CredentialsExpiresAt = time.Time{}
} else {
c.sendCredentialsReadyMessage()
}
}
}
c.log.Info("Starting credentials refresher loop")
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
for {
select {
case <-c.stopCredentialRefresherChan:
c.log.Info("Stopping credentials refresher")
c.log.Flush()
return
case <-c.timeAfterFunc(c.durationUntilRefresh()):
c.log.Debug("Calling Retrieve on credentials provider")
creds, stopped := c.retrieveCredsWithRetry(ctx)
credentialsRetrievedAt := c.getCurrentTimeFunc()
if stopped {
c.log.Info("Stopping credentials refresher")
c.log.Flush()
return
}
credentialSource := c.provider.CredentialSource()
isEC2CredentialSource := credentialSource == ec2roleprovider.CredentialSourceEC2
isEc2CredFilePresent := fileExists(appconfig.DefaultEC2SharedCredentialsFilePath)
c.log.Tracef("Credential source %v", isEC2CredentialSource)
c.log.Tracef("Cred file present %v", isEc2CredFilePresent)
isCredFilePurged := false
if isEC2CredentialSource && isEc2CredFilePresent {
documentSessionWorkerRunning := c.isDocumentSessionWorkerProcessRunning()
credSaveDefaultSSMAgentPresent := c.credentialFileConsumerPresent()
c.log.Tracef("Document/session worker source %v", documentSessionWorkerRunning)
c.log.Tracef("Cred save default ssm agent %v", credSaveDefaultSSMAgentPresent)
if !(documentSessionWorkerRunning && credSaveDefaultSSMAgentPresent) {
c.log.Info("Starting credential purging")
err = backoffRetry(func() error {
return purgeSharedCredentials(appconfig.DefaultEC2SharedCredentialsFilePath)
}, c.backoffConfig)
if err != nil {
c.log.Warnf("error while purging cred file: %v", err)
} else {
isCredFilePurged = true
}
}
}
// ShareFile may be updated after retrieveCredsWithRetry()
newShareFile := c.provider.ShareFile()
if isCredFilePurged {
c.log.Info("Credential file purged")
} else {
// when ShouldPurgeInstanceProfileRoleCreds config is used,
// the credential file created in 3.2 for EC2 will be deleted irrespective of whether doc/session worker is running or not
c.tryPurgeCreds(newShareFile)
}
// skip saving when the credential source is EC2
if !isEC2CredentialSource && newShareFile != "" {
err = backoffRetry(func() error {
return storeSharedCredentials(c.log, creds.AccessKeyID, creds.SecretAccessKey, creds.SessionToken,
newShareFile, c.identityRuntimeConfig.ShareProfile, false)
}, c.backoffConfig)
// If failed, try once more with force
if err != nil {
c.log.Warn("Failed to write credentials to disk, attempting force write")
err = storeSharedCredentials(c.log, creds.AccessKeyID, creds.SecretAccessKey, creds.SessionToken,
newShareFile, c.identityRuntimeConfig.ShareProfile, true)
}
if err != nil {
// Saving credentials has been retried 6 times at this point.
c.log.Errorf("Failed to write credentials to disk even with force, retrying: %v", err)
continue
}
c.log.Debug("Successfully stored credentials")
}
c.log.Debug("Writing runtime configuration with updated expiration time")
configCopy := c.identityRuntimeConfig
configCopy.CredentialsRetrievedAt = credentialsRetrievedAt
configCopy.CredentialsExpiresAt = c.provider.RemoteExpiresAt()
configCopy.ShareFile = newShareFile
configCopy.CredentialSource = credentialSource
err = backoffRetry(func() error {
return c.runtimeConfigClient.SaveConfig(configCopy)
}, c.backoffConfig)
if err != nil {
c.log.Warnf("Failed to save new expiration: %v", err)
continue
}
c.identityRuntimeConfig = configCopy
c.sendCredentialsReadyMessage()
}
}
}