Skip to content

Commit 36e2ff3

Browse files
committed
client: re-use a single file for building the session instead of randomly named files
1 parent d1cc300 commit 36e2ff3

File tree

1 file changed

+20
-7
lines changed

1 file changed

+20
-7
lines changed

pkg/client/client.go

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -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
7278
type 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

Comments
 (0)