resolve_bearer_token.go (3787B)
1 package config 2 3 import ( 4 "context" 5 "fmt" 6 "time" 7 8 "github.com/aws/aws-sdk-go-v2/aws" 9 "github.com/aws/aws-sdk-go-v2/credentials/ssocreds" 10 "github.com/aws/aws-sdk-go-v2/service/ssooidc" 11 smithybearer "github.com/aws/smithy-go/auth/bearer" 12 ) 13 14 // resolveBearerAuthToken extracts a token provider from the config sources. 15 // 16 // If an explicit bearer authentication token provider is not found the 17 // resolver will fallback to resolving token provider via other config sources 18 // such as SharedConfig. 19 func resolveBearerAuthToken(ctx context.Context, cfg *aws.Config, configs configs) error { 20 found, err := resolveBearerAuthTokenProvider(ctx, cfg, configs) 21 if found || err != nil { 22 return err 23 } 24 25 return resolveBearerAuthTokenProviderChain(ctx, cfg, configs) 26 } 27 28 // resolveBearerAuthTokenProvider extracts the first instance of 29 // BearerAuthTokenProvider from the config sources. 30 // 31 // The resolved BearerAuthTokenProvider will be wrapped in a cache to ensure 32 // the Token is only refreshed when needed. This also protects the 33 // TokenProvider so it can be used concurrently. 34 // 35 // Config providers used: 36 // * bearerAuthTokenProviderProvider 37 func resolveBearerAuthTokenProvider(ctx context.Context, cfg *aws.Config, configs configs) (bool, error) { 38 tokenProvider, found, err := getBearerAuthTokenProvider(ctx, configs) 39 if !found || err != nil { 40 return false, err 41 } 42 43 cfg.BearerAuthTokenProvider, err = wrapWithBearerAuthTokenCache( 44 ctx, configs, tokenProvider) 45 if err != nil { 46 return false, err 47 } 48 49 return true, nil 50 } 51 52 func resolveBearerAuthTokenProviderChain(ctx context.Context, cfg *aws.Config, configs configs) (err error) { 53 _, sharedConfig, _ := getAWSConfigSources(configs) 54 55 var provider smithybearer.TokenProvider 56 57 if sharedConfig.SSOSession != nil { 58 provider, err = resolveBearerAuthSSOTokenProvider( 59 ctx, cfg, sharedConfig.SSOSession, configs) 60 } 61 62 if err == nil && provider != nil { 63 cfg.BearerAuthTokenProvider, err = wrapWithBearerAuthTokenCache( 64 ctx, configs, provider) 65 } 66 67 return err 68 } 69 70 func resolveBearerAuthSSOTokenProvider(ctx context.Context, cfg *aws.Config, session *SSOSession, configs configs) (*ssocreds.SSOTokenProvider, error) { 71 ssoTokenProviderOptionsFn, found, err := getSSOTokenProviderOptions(ctx, configs) 72 if err != nil { 73 return nil, fmt.Errorf("failed to get SSOTokenProviderOptions from config sources, %w", err) 74 } 75 76 var optFns []func(*ssocreds.SSOTokenProviderOptions) 77 if found { 78 optFns = append(optFns, ssoTokenProviderOptionsFn) 79 } 80 81 cachePath, err := ssocreds.StandardCachedTokenFilepath(session.Name) 82 if err != nil { 83 return nil, fmt.Errorf("failed to get SSOTokenProvider's cache path, %w", err) 84 } 85 86 client := ssooidc.NewFromConfig(*cfg) 87 provider := ssocreds.NewSSOTokenProvider(client, cachePath, optFns...) 88 89 return provider, nil 90 } 91 92 // wrapWithBearerAuthTokenCache will wrap provider with an smithy-go 93 // bearer/auth#TokenCache with the provided options if the provider is not 94 // already a TokenCache. 95 func wrapWithBearerAuthTokenCache( 96 ctx context.Context, 97 cfgs configs, 98 provider smithybearer.TokenProvider, 99 optFns ...func(*smithybearer.TokenCacheOptions), 100 ) (smithybearer.TokenProvider, error) { 101 _, ok := provider.(*smithybearer.TokenCache) 102 if ok { 103 return provider, nil 104 } 105 106 tokenCacheConfigOptions, optionsFound, err := getBearerAuthTokenCacheOptions(ctx, cfgs) 107 if err != nil { 108 return nil, err 109 } 110 111 opts := make([]func(*smithybearer.TokenCacheOptions), 0, 2+len(optFns)) 112 opts = append(opts, func(o *smithybearer.TokenCacheOptions) { 113 o.RefreshBeforeExpires = 5 * time.Minute 114 o.RetrieveBearerTokenTimeout = 30 * time.Second 115 }) 116 opts = append(opts, optFns...) 117 if optionsFound { 118 opts = append(opts, tokenCacheConfigOptions) 119 } 120 121 return smithybearer.NewTokenCache(provider, opts...), nil 122 }