config.go (7142B)
1 package config 2 3 import ( 4 "context" 5 6 "github.com/aws/aws-sdk-go-v2/aws" 7 ) 8 9 // defaultLoaders are a slice of functions that will read external configuration 10 // sources for configuration values. These values are read by the AWSConfigResolvers 11 // using interfaces to extract specific information from the external configuration. 12 var defaultLoaders = []loader{ 13 loadEnvConfig, 14 loadSharedConfigIgnoreNotExist, 15 } 16 17 // defaultAWSConfigResolvers are a slice of functions that will resolve external 18 // configuration values into AWS configuration values. 19 // 20 // This will setup the AWS configuration's Region, 21 var defaultAWSConfigResolvers = []awsConfigResolver{ 22 // Resolves the default configuration the SDK's aws.Config will be 23 // initialized with. 24 resolveDefaultAWSConfig, 25 26 // Sets the logger to be used. Could be user provided logger, and client 27 // logging mode. 28 resolveLogger, 29 resolveClientLogMode, 30 31 // Sets the HTTP client and configuration to use for making requests using 32 // the HTTP transport. 33 resolveHTTPClient, 34 resolveCustomCABundle, 35 36 // Sets the endpoint resolving behavior the API Clients will use for making 37 // requests to. Clients default to their own clients this allows overrides 38 // to be specified. The resolveEndpointResolver option is deprecated, but 39 // we still need to set it for backwards compatibility on config 40 // construction. 41 resolveEndpointResolver, 42 resolveEndpointResolverWithOptions, 43 44 // Sets the retry behavior API clients will use within their retry attempt 45 // middleware. Defaults to unset, allowing API clients to define their own 46 // retry behavior. 47 resolveRetryer, 48 49 // Sets the region the API Clients should use for making requests to. 50 resolveRegion, 51 resolveEC2IMDSRegion, 52 resolveDefaultRegion, 53 54 // Sets the additional set of middleware stack mutators that will custom 55 // API client request pipeline middleware. 56 resolveAPIOptions, 57 58 // Resolves the DefaultsMode that should be used by SDK clients. If this 59 // mode is set to DefaultsModeAuto. 60 // 61 // Comes after HTTPClient and CustomCABundle to ensure the HTTP client is 62 // configured if provided before invoking IMDS if mode is auto. Comes 63 // before resolving credentials so that those subsequent clients use the 64 // configured auto mode. 65 resolveDefaultsModeOptions, 66 67 // Sets the resolved credentials the API clients will use for 68 // authentication. Provides the SDK's default credential chain. 69 // 70 // Should probably be the last step in the resolve chain to ensure that all 71 // other configurations are resolved first in case downstream credentials 72 // implementations depend on or can be configured with earlier resolved 73 // configuration options. 74 resolveCredentials, 75 76 // Sets the resolved bearer authentication token API clients will use for 77 // httpBearerAuth authentication scheme. 78 resolveBearerAuthToken, 79 } 80 81 // A Config represents a generic configuration value or set of values. This type 82 // will be used by the AWSConfigResolvers to extract 83 // 84 // General the Config type will use type assertion against the Provider interfaces 85 // to extract specific data from the Config. 86 type Config interface{} 87 88 // A loader is used to load external configuration data and returns it as 89 // a generic Config type. 90 // 91 // The loader should return an error if it fails to load the external configuration 92 // or the configuration data is malformed, or required components missing. 93 type loader func(context.Context, configs) (Config, error) 94 95 // An awsConfigResolver will extract configuration data from the configs slice 96 // using the provider interfaces to extract specific functionality. The extracted 97 // configuration values will be written to the AWS Config value. 98 // 99 // The resolver should return an error if it it fails to extract the data, the 100 // data is malformed, or incomplete. 101 type awsConfigResolver func(ctx context.Context, cfg *aws.Config, configs configs) error 102 103 // configs is a slice of Config values. These values will be used by the 104 // AWSConfigResolvers to extract external configuration values to populate the 105 // AWS Config type. 106 // 107 // Use AppendFromLoaders to add additional external Config values that are 108 // loaded from external sources. 109 // 110 // Use ResolveAWSConfig after external Config values have been added or loaded 111 // to extract the loaded configuration values into the AWS Config. 112 type configs []Config 113 114 // AppendFromLoaders iterates over the slice of loaders passed in calling each 115 // loader function in order. The external config value returned by the loader 116 // will be added to the returned configs slice. 117 // 118 // If a loader returns an error this method will stop iterating and return 119 // that error. 120 func (cs configs) AppendFromLoaders(ctx context.Context, loaders []loader) (configs, error) { 121 for _, fn := range loaders { 122 cfg, err := fn(ctx, cs) 123 if err != nil { 124 return nil, err 125 } 126 127 cs = append(cs, cfg) 128 } 129 130 return cs, nil 131 } 132 133 // ResolveAWSConfig returns a AWS configuration populated with values by calling 134 // the resolvers slice passed in. Each resolver is called in order. Any resolver 135 // may overwrite the AWS Configuration value of a previous resolver. 136 // 137 // If an resolver returns an error this method will return that error, and stop 138 // iterating over the resolvers. 139 func (cs configs) ResolveAWSConfig(ctx context.Context, resolvers []awsConfigResolver) (aws.Config, error) { 140 var cfg aws.Config 141 142 for _, fn := range resolvers { 143 if err := fn(ctx, &cfg, cs); err != nil { 144 return aws.Config{}, err 145 } 146 } 147 148 return cfg, nil 149 } 150 151 // ResolveConfig calls the provide function passing slice of configuration sources. 152 // This implements the aws.ConfigResolver interface. 153 func (cs configs) ResolveConfig(f func(configs []interface{}) error) error { 154 var cfgs []interface{} 155 for i := range cs { 156 cfgs = append(cfgs, cs[i]) 157 } 158 return f(cfgs) 159 } 160 161 // LoadDefaultConfig reads the SDK's default external configurations, and 162 // populates an AWS Config with the values from the external configurations. 163 // 164 // An optional variadic set of additional Config values can be provided as input 165 // that will be prepended to the configs slice. Use this to add custom configuration. 166 // The custom configurations must satisfy the respective providers for their data 167 // or the custom data will be ignored by the resolvers and config loaders. 168 // 169 // cfg, err := config.LoadDefaultConfig( context.TODO(), 170 // WithSharedConfigProfile("test-profile"), 171 // ) 172 // if err != nil { 173 // panic(fmt.Sprintf("failed loading config, %v", err)) 174 // } 175 // 176 // The default configuration sources are: 177 // * Environment Variables 178 // * Shared Configuration and Shared Credentials files. 179 func LoadDefaultConfig(ctx context.Context, optFns ...func(*LoadOptions) error) (cfg aws.Config, err error) { 180 var options LoadOptions 181 for _, optFn := range optFns { 182 if err := optFn(&options); err != nil { 183 return aws.Config{}, err 184 } 185 } 186 187 // assign Load Options to configs 188 var cfgCpy = configs{options} 189 190 cfgCpy, err = cfgCpy.AppendFromLoaders(ctx, defaultLoaders) 191 if err != nil { 192 return aws.Config{}, err 193 } 194 195 cfg, err = cfgCpy.ResolveAWSConfig(ctx, defaultAWSConfigResolvers) 196 if err != nil { 197 return aws.Config{}, err 198 } 199 200 return cfg, nil 201 }