@@ -20,8 +20,8 @@ import (
2020 "bytes"
2121 "context"
2222 "fmt"
23- "io/ioutil"
2423 "os"
24+ "path"
2525 "strings"
2626 "sync"
2727 "time"
@@ -45,6 +45,7 @@ import (
4545 configv1 "github.com/openshift/api/config/v1"
4646 machineapiapierrors "github.com/openshift/machine-api-operator/pkg/controller/machine"
4747 apimachineryerrors "k8s.io/apimachinery/pkg/api/errors"
48+ "k8s.io/apimachinery/pkg/util/rand"
4849)
4950
5051//go:generate go run ../../vendor/github.com/golang/mock/mockgen -source=./client.go -destination=./mock/client_generated.go -package=mock
@@ -68,6 +69,11 @@ const (
6869 awsRegionsCacheExpirationDuration = time .Minute * 30
6970)
7071
72+ var (
73+ sharedCredentialsFileMutex sync.Mutex
74+ sharedCredentialsFileName = path .Join (os .TempDir (), "aws-shared-credentials" + rand .String (16 ))
75+ )
76+
7177// AwsClientBuilderFuncType is function type for building aws client
7278type AwsClientBuilderFuncType func (client client.Client , secretName , namespace , region string , configManagedClient client.Client , regionCache RegionCache ) (Client , error )
7379
@@ -369,10 +375,18 @@ func newAWSSession(ctrlRuntimeClient client.Client, secretName, namespace, regio
369375 }
370376 return nil , err
371377 }
378+ sharedCredentialsFileMutex .Lock ()
379+ defer sharedCredentialsFileMutex .Unlock ()
372380 sharedCredsFile , err := sharedCredentialsFileFromSecret (& secret )
373381 if err != nil {
374382 return nil , fmt .Errorf ("failed to create shared credentials file from Secret: %v" , err )
375383 }
384+
385+ // Ensure the file gets deleted in any case.
386+ defer func () {
387+ os .Remove (sharedCredsFile )
388+ }()
389+
376390 sessionOptions .SharedConfigState = session .SharedConfigEnable
377391 sessionOptions .SharedConfigFiles = []string {sharedCredsFile }
378392 }
@@ -392,11 +406,6 @@ func newAWSSession(ctrlRuntimeClient client.Client, secretName, namespace, regio
392406 return nil , err
393407 }
394408
395- // Remove any temporary shared credentials files after session creation so they don't accumulate
396- if len (sessionOptions .SharedConfigFiles ) > 0 {
397- os .Remove (sessionOptions .SharedConfigFiles [0 ])
398- }
399-
400409 s .Handlers .Build .PushBackNamed (addProviderVersionToUserAgent )
401410
402411 return s , nil
@@ -471,12 +480,16 @@ func sharedCredentialsFileFromSecret(secret *corev1.Secret) (string, error) {
471480 return "" , fmt .Errorf ("invalid secret for aws credentials" )
472481 }
473482
474- f , err := ioutil .TempFile ("" , "aws-shared-credentials" )
483+ // Re-using the same file every time to prevent leakage of memory to slab.
484+ // Related issue: https://issues.redhat.com/browse/RHEL-119532
485+ f , err := os .Create (sharedCredentialsFileName )
475486 if err != nil {
476487 return "" , fmt .Errorf ("failed to create file for shared credentials: %v" , err )
477488 }
478489 defer f .Close ()
479490 if _ , err := f .Write (data ); err != nil {
491+ // Delete the file in case of having an error. Otherwise the calling function needs to handle deletion.
492+ defer func () { os .Remove (f .Name ()) }()
480493 return "" , fmt .Errorf ("failed to write credentials to %s: %v" , f .Name (), err )
481494 }
482495 return f .Name (), nil
0 commit comments