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