config.go (7580B)
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 81 // Sets the RequestMinCompressSizeBytes if present in env var or shared config profile 82 resolveRequestMinCompressSizeBytes, 83 } 84 85 // A Config represents a generic configuration value or set of values. This type 86 // will be used by the AWSConfigResolvers to extract 87 // 88 // General the Config type will use type assertion against the Provider interfaces 89 // to extract specific data from the Config. 90 type Config interface{} 91 92 // A loader is used to load external configuration data and returns it as 93 // a generic Config type. 94 // 95 // The loader should return an error if it fails to load the external configuration 96 // or the configuration data is malformed, or required components missing. 97 type loader func(context.Context, configs) (Config, error) 98 99 // An awsConfigResolver will extract configuration data from the configs slice 100 // using the provider interfaces to extract specific functionality. The extracted 101 // configuration values will be written to the AWS Config value. 102 // 103 // The resolver should return an error if it it fails to extract the data, the 104 // data is malformed, or incomplete. 105 type awsConfigResolver func(ctx context.Context, cfg *aws.Config, configs configs) error 106 107 // configs is a slice of Config values. These values will be used by the 108 // AWSConfigResolvers to extract external configuration values to populate the 109 // AWS Config type. 110 // 111 // Use AppendFromLoaders to add additional external Config values that are 112 // loaded from external sources. 113 // 114 // Use ResolveAWSConfig after external Config values have been added or loaded 115 // to extract the loaded configuration values into the AWS Config. 116 type configs []Config 117 118 // AppendFromLoaders iterates over the slice of loaders passed in calling each 119 // loader function in order. The external config value returned by the loader 120 // will be added to the returned configs slice. 121 // 122 // If a loader returns an error this method will stop iterating and return 123 // that error. 124 func (cs configs) AppendFromLoaders(ctx context.Context, loaders []loader) (configs, error) { 125 for _, fn := range loaders { 126 cfg, err := fn(ctx, cs) 127 if err != nil { 128 return nil, err 129 } 130 131 cs = append(cs, cfg) 132 } 133 134 return cs, nil 135 } 136 137 // ResolveAWSConfig returns a AWS configuration populated with values by calling 138 // the resolvers slice passed in. Each resolver is called in order. Any resolver 139 // may overwrite the AWS Configuration value of a previous resolver. 140 // 141 // If an resolver returns an error this method will return that error, and stop 142 // iterating over the resolvers. 143 func (cs configs) ResolveAWSConfig(ctx context.Context, resolvers []awsConfigResolver) (aws.Config, error) { 144 var cfg aws.Config 145 146 for _, fn := range resolvers { 147 if err := fn(ctx, &cfg, cs); err != nil { 148 return aws.Config{}, err 149 } 150 } 151 152 return cfg, nil 153 } 154 155 // ResolveConfig calls the provide function passing slice of configuration sources. 156 // This implements the aws.ConfigResolver interface. 157 func (cs configs) ResolveConfig(f func(configs []interface{}) error) error { 158 var cfgs []interface{} 159 for i := range cs { 160 cfgs = append(cfgs, cs[i]) 161 } 162 return f(cfgs) 163 } 164 165 // LoadDefaultConfig reads the SDK's default external configurations, and 166 // populates an AWS Config with the values from the external configurations. 167 // 168 // An optional variadic set of additional Config values can be provided as input 169 // that will be prepended to the configs slice. Use this to add custom configuration. 170 // The custom configurations must satisfy the respective providers for their data 171 // or the custom data will be ignored by the resolvers and config loaders. 172 // 173 // cfg, err := config.LoadDefaultConfig( context.TODO(), 174 // config.WithSharedConfigProfile("test-profile"), 175 // ) 176 // if err != nil { 177 // panic(fmt.Sprintf("failed loading config, %v", err)) 178 // } 179 // 180 // The default configuration sources are: 181 // * Environment Variables 182 // * Shared Configuration and Shared Credentials files. 183 func LoadDefaultConfig(ctx context.Context, optFns ...func(*LoadOptions) error) (cfg aws.Config, err error) { 184 var options LoadOptions 185 for _, optFn := range optFns { 186 if err := optFn(&options); err != nil { 187 return aws.Config{}, err 188 } 189 } 190 191 // assign Load Options to configs 192 var cfgCpy = configs{options} 193 194 cfgCpy, err = cfgCpy.AppendFromLoaders(ctx, resolveConfigLoaders(&options)) 195 if err != nil { 196 return aws.Config{}, err 197 } 198 199 cfg, err = cfgCpy.ResolveAWSConfig(ctx, defaultAWSConfigResolvers) 200 if err != nil { 201 return aws.Config{}, err 202 } 203 204 return cfg, nil 205 } 206 207 func resolveConfigLoaders(options *LoadOptions) []loader { 208 loaders := make([]loader, 2) 209 loaders[0] = loadEnvConfig 210 211 // specification of a profile should cause a load failure if it doesn't exist 212 if os.Getenv(awsProfileEnvVar) != "" || options.SharedConfigProfile != "" { 213 loaders[1] = loadSharedConfig 214 } else { 215 loaders[1] = loadSharedConfigIgnoreNotExist 216 } 217 218 return loaders 219 }