Skip to content

Commit 2d25393

Browse files
authored
config: Add WithCredentialCacheOptions for LoadDefaultConfig's LoadOptions (#1523)
* config: add load option for CredentialCache Adds a new member to the LoadOptions struct, CredentialsCacheOptions. This member allows specifying a function that will be used to configure the CredentialsCache. The CredentialsCacheOptions will only be used if the configuration loader will wrap the underlying credential provider in the CredentialsCache. * fixup copy/paste in description
1 parent 9ebb3ef commit 2d25393

File tree

8 files changed

+142
-10
lines changed

8 files changed

+142
-10
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"id": "e8196bb0-44a3-4f06-8048-17bb03c87bff",
3+
"type": "feature",
4+
"description": "Add load option for CredentialCache. Adds a new member to the LoadOptions struct, CredentialsCacheOptions. This member allows specifying a function that will be used to configure the CredentialsCache. The CredentialsCacheOptions will only be used if the configuration loader will wrap the underlying credential provider in the CredentialsCache.",
5+
"modules": [
6+
"config"
7+
]
8+
}

config/codegen/main.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ var implAsserts = map[string][]string{
2626
"regionProvider": {envConfigType, sharedConfigType, loadOptionsType, ec2IMDSRegionType},
2727
"credentialsProviderProvider": {loadOptionsType},
2828
"defaultRegionProvider": {loadOptionsType},
29+
"credentialsCacheOptionsProvider": {loadOptionsType},
30+
"processCredentialOptions": {loadOptionsType},
2931
"ec2RoleCredentialOptionsProvider": {loadOptionsType},
3032
"endpointCredentialOptionsProvider": {loadOptionsType},
3133
"assumeRoleCredentialOptionsProvider": {loadOptionsType},

config/example_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"log"
77
"net/http"
88
"path/filepath"
9+
"time"
910

1011
"github.com/aws/aws-sdk-go-v2/aws"
1112
awshttp "github.com/aws/aws-sdk-go-v2/aws/transport/http"
@@ -16,6 +17,18 @@ import (
1617
smithyhttp "github.com/aws/smithy-go/transport/http"
1718
)
1819

20+
func ExampleWithCredentialsCacheOptions() {
21+
cfg, err := config.LoadDefaultConfig(context.TODO(),
22+
config.WithCredentialsCacheOptions(func(o *aws.CredentialsCacheOptions) {
23+
o.ExpiryWindow = 10 * time.Minute
24+
}),
25+
)
26+
if err != nil {
27+
log.Fatal(err)
28+
}
29+
_ = cfg
30+
}
31+
1932
func ExampleWithSharedConfigProfile() {
2033
cfg, err := config.LoadDefaultConfig(context.TODO(),
2134
// Specify the shared configuration profile to load.

config/load_options.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ type LoadOptions struct {
101101
// from the EC2 Metadata service
102102
UseEC2IMDSRegion *UseEC2IMDSRegion
103103

104+
// CredentialsCacheOptions is a function for setting the
105+
// aws.CredentialsCacheOptions
106+
CredentialsCacheOptions func(*aws.CredentialsCacheOptions)
107+
104108
// ProcessCredentialOptions is a function for setting
105109
// the processcreds.Options
106110
ProcessCredentialOptions func(*processcreds.Options)
@@ -365,6 +369,29 @@ func WithCredentialsProvider(v aws.CredentialsProvider) LoadOptionsFunc {
365369
}
366370
}
367371

372+
// getCredentialsCacheOptionsProvider returns the wrapped function to set aws.CredentialsCacheOptions
373+
func (o LoadOptions) getCredentialsCacheOptions(ctx context.Context) (func(*aws.CredentialsCacheOptions), bool, error) {
374+
if o.CredentialsCacheOptions == nil {
375+
return nil, false, nil
376+
}
377+
378+
return o.CredentialsCacheOptions, true, nil
379+
}
380+
381+
// WithCredentialsCacheOptions is a helper function to construct functional
382+
// options that sets a function to modify the aws.CredentialsCacheOptions the
383+
// aws.CredentialsCache will be configured with, if the CredentialsCache is used
384+
// by the configuration loader.
385+
//
386+
// If multiple WithCredentialsCacheOptions calls are made, the last call
387+
// overrides the previous call values.
388+
func WithCredentialsCacheOptions(v func(*aws.CredentialsCacheOptions)) LoadOptionsFunc {
389+
return func(o *LoadOptions) error {
390+
o.CredentialsCacheOptions = v
391+
return nil
392+
}
393+
}
394+
368395
// getProcessCredentialOptions returns the wrapped function to set processcreds.Options
369396
func (o LoadOptions) getProcessCredentialOptions(ctx context.Context) (func(*processcreds.Options), bool, error) {
370397
if o.ProcessCredentialOptions == nil {

config/provider.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,28 @@ func getCredentialsProvider(ctx context.Context, configs configs) (p aws.Credent
162162
return
163163
}
164164

165+
// credentialsCacheOptionsProvider is an interface for retrieving a function for setting
166+
// the aws.CredentialsCacheOptions.
167+
type credentialsCacheOptionsProvider interface {
168+
getCredentialsCacheOptions(ctx context.Context) (func(*aws.CredentialsCacheOptions), bool, error)
169+
}
170+
171+
// getCredentialsCacheOptionsProvider is an interface for retrieving a function for setting
172+
// the aws.CredentialsCacheOptions.
173+
func getCredentialsCacheOptionsProvider(ctx context.Context, configs configs) (
174+
f func(*aws.CredentialsCacheOptions), found bool, err error,
175+
) {
176+
for _, config := range configs {
177+
if p, ok := config.(credentialsCacheOptionsProvider); ok {
178+
f, found, err = p.getCredentialsCacheOptions(ctx)
179+
if err != nil || found {
180+
break
181+
}
182+
}
183+
}
184+
return
185+
}
186+
165187
// processCredentialOptions is an interface for retrieving a function for setting
166188
// the processcreds.Options.
167189
type processCredentialOptions interface {

config/provider_assert_test.go

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/resolve_credentials.go

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,19 @@ func resolveCredentials(ctx context.Context, cfg *aws.Config, configs configs) e
5959
//
6060
// Config providers used:
6161
// * credentialsProviderProvider
62-
func resolveCredentialProvider(ctx context.Context, cfg *aws.Config, cfgs configs) (bool, error) {
63-
credProvider, found, err := getCredentialsProvider(ctx, cfgs)
62+
func resolveCredentialProvider(ctx context.Context, cfg *aws.Config, configs configs) (bool, error) {
63+
credProvider, found, err := getCredentialsProvider(ctx, configs)
6464
if err != nil {
6565
return false, err
6666
}
6767
if !found {
6868
return false, nil
6969
}
7070

71-
cfg.Credentials = wrapWithCredentialsCache(credProvider)
71+
cfg.Credentials, err = wrapWithCredentialsCache(ctx, configs, credProvider)
72+
if err != nil {
73+
return false, err
74+
}
7275

7376
return true, nil
7477
}
@@ -105,7 +108,10 @@ func resolveCredentialChain(ctx context.Context, cfg *aws.Config, configs config
105108
}
106109

107110
// Wrap the resolved provider in a cache so the SDK will cache credentials.
108-
cfg.Credentials = wrapWithCredentialsCache(cfg.Credentials)
111+
cfg.Credentials, err = wrapWithCredentialsCache(ctx, configs, cfg.Credentials)
112+
if err != nil {
113+
return err
114+
}
109115

110116
return nil
111117
}
@@ -248,9 +254,12 @@ func resolveHTTPCredProvider(ctx context.Context, cfg *aws.Config, url, authToke
248254

249255
provider := endpointcreds.New(url, optFns...)
250256

251-
cfg.Credentials = wrapWithCredentialsCache(provider, func(options *aws.CredentialsCacheOptions) {
257+
cfg.Credentials, err = wrapWithCredentialsCache(ctx, configs, provider, func(options *aws.CredentialsCacheOptions) {
252258
options.ExpiryWindow = 5 * time.Minute
253259
})
260+
if err != nil {
261+
return err
262+
}
254263

255264
return nil
256265
}
@@ -296,9 +305,12 @@ func resolveEC2RoleCredentials(ctx context.Context, cfg *aws.Config, configs con
296305

297306
provider := ec2rolecreds.New(optFns...)
298307

299-
cfg.Credentials = wrapWithCredentialsCache(provider, func(options *aws.CredentialsCacheOptions) {
308+
cfg.Credentials, err = wrapWithCredentialsCache(ctx, configs, provider, func(options *aws.CredentialsCacheOptions) {
300309
options.ExpiryWindow = 5 * time.Minute
301310
})
311+
if err != nil {
312+
return err
313+
}
302314

303315
return nil
304316
}
@@ -430,12 +442,31 @@ func credsFromAssumeRole(ctx context.Context, cfg *aws.Config, sharedCfg *Shared
430442
return nil
431443
}
432444

433-
// wrapWithCredentialsCache will wrap provider with an aws.CredentialsCache with the provided options if the provider is not already a aws.CredentialsCache.
434-
func wrapWithCredentialsCache(provider aws.CredentialsProvider, optFns ...func(options *aws.CredentialsCacheOptions)) aws.CredentialsProvider {
445+
// wrapWithCredentialsCache will wrap provider with an aws.CredentialsCache
446+
// with the provided options if the provider is not already a
447+
// aws.CredentialsCache.
448+
func wrapWithCredentialsCache(
449+
ctx context.Context,
450+
cfgs configs,
451+
provider aws.CredentialsProvider,
452+
optFns ...func(options *aws.CredentialsCacheOptions),
453+
) (aws.CredentialsProvider, error) {
435454
_, ok := provider.(*aws.CredentialsCache)
436455
if ok {
437-
return provider
456+
return provider, nil
457+
}
458+
459+
credCacheOptions, found, err := getCredentialsCacheOptionsProvider(ctx, cfgs)
460+
if err != nil {
461+
return nil, err
462+
}
463+
464+
// force allocation of a new slice if the additional options are
465+
// needed, to prevent overwriting the passed in slice of options.
466+
optFns = optFns[:len(optFns):len(optFns)]
467+
if found {
468+
optFns = append(optFns, credCacheOptions)
438469
}
439470

440-
return aws.NewCredentialsCache(provider, optFns...)
471+
return aws.NewCredentialsCache(provider, optFns...), nil
441472
}

config/resolve_credentials_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,3 +452,22 @@ func TestSharedConfigCredentialSource(t *testing.T) {
452452
})
453453
}
454454
}
455+
456+
func TestResolveCredentialsCacheOptions(t *testing.T) {
457+
var cfg aws.Config
458+
var optionsFnCalled bool
459+
460+
err := resolveCredentials(context.Background(), &cfg, configs{LoadOptions{
461+
CredentialsCacheOptions: func(o *aws.CredentialsCacheOptions) {
462+
optionsFnCalled = true
463+
o.ExpiryWindow = time.Minute * 5
464+
},
465+
}})
466+
if err != nil {
467+
t.Fatalf("expect no error, got %v", err)
468+
}
469+
470+
if !optionsFnCalled {
471+
t.Errorf("expect options to be called")
472+
}
473+
}

0 commit comments

Comments
 (0)