1package config
2
3import (
4 "bytes"
5 "context"
6 "fmt"
7 "io"
8 "io/ioutil"
9 "os"
10 "strconv"
11 "strings"
12
13 "github.com/aws/aws-sdk-go-v2/aws"
14 "github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
15 smithyrequestcompression "github.com/aws/smithy-go/private/requestcompression"
16)
17
18// CredentialsSourceName provides a name of the provider when config is
19// loaded from environment.
20const CredentialsSourceName = "EnvConfigCredentials"
21
22// Environment variables that will be read for configuration values.
23const (
24 awsAccessKeyIDEnvVar = "AWS_ACCESS_KEY_ID"
25 awsAccessKeyEnvVar = "AWS_ACCESS_KEY"
26
27 awsSecretAccessKeyEnvVar = "AWS_SECRET_ACCESS_KEY"
28 awsSecretKeyEnvVar = "AWS_SECRET_KEY"
29
30 awsSessionTokenEnvVar = "AWS_SESSION_TOKEN"
31
32 awsContainerCredentialsEndpointEnvVar = "AWS_CONTAINER_CREDENTIALS_FULL_URI"
33 awsContainerCredentialsRelativePathEnvVar = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"
34 awsContainerPProviderAuthorizationEnvVar = "AWS_CONTAINER_AUTHORIZATION_TOKEN"
35
36 awsRegionEnvVar = "AWS_REGION"
37 awsDefaultRegionEnvVar = "AWS_DEFAULT_REGION"
38
39 awsProfileEnvVar = "AWS_PROFILE"
40 awsDefaultProfileEnvVar = "AWS_DEFAULT_PROFILE"
41
42 awsSharedCredentialsFileEnvVar = "AWS_SHARED_CREDENTIALS_FILE"
43
44 awsConfigFileEnvVar = "AWS_CONFIG_FILE"
45
46 awsCustomCABundleEnvVar = "AWS_CA_BUNDLE"
47
48 awsWebIdentityTokenFilePathEnvVar = "AWS_WEB_IDENTITY_TOKEN_FILE"
49
50 awsRoleARNEnvVar = "AWS_ROLE_ARN"
51 awsRoleSessionNameEnvVar = "AWS_ROLE_SESSION_NAME"
52
53 awsEnableEndpointDiscoveryEnvVar = "AWS_ENABLE_ENDPOINT_DISCOVERY"
54
55 awsS3UseARNRegionEnvVar = "AWS_S3_USE_ARN_REGION"
56
57 awsEc2MetadataServiceEndpointModeEnvVar = "AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE"
58
59 awsEc2MetadataServiceEndpointEnvVar = "AWS_EC2_METADATA_SERVICE_ENDPOINT"
60
61 awsEc2MetadataDisabled = "AWS_EC2_METADATA_DISABLED"
62 awsEc2MetadataV1DisabledEnvVar = "AWS_EC2_METADATA_V1_DISABLED"
63
64 awsS3DisableMultiRegionAccessPointEnvVar = "AWS_S3_DISABLE_MULTIREGION_ACCESS_POINTS"
65
66 awsUseDualStackEndpoint = "AWS_USE_DUALSTACK_ENDPOINT"
67
68 awsUseFIPSEndpoint = "AWS_USE_FIPS_ENDPOINT"
69
70 awsDefaultMode = "AWS_DEFAULTS_MODE"
71
72 awsRetryMaxAttempts = "AWS_MAX_ATTEMPTS"
73 awsRetryMode = "AWS_RETRY_MODE"
74 awsSdkAppID = "AWS_SDK_UA_APP_ID"
75
76 awsIgnoreConfiguredEndpoints = "AWS_IGNORE_CONFIGURED_ENDPOINT_URLS"
77 awsEndpointURL = "AWS_ENDPOINT_URL"
78
79 awsDisableRequestCompression = "AWS_DISABLE_REQUEST_COMPRESSION"
80 awsRequestMinCompressionSizeBytes = "AWS_REQUEST_MIN_COMPRESSION_SIZE_BYTES"
81
82 awsS3DisableExpressSessionAuthEnv = "AWS_S3_DISABLE_EXPRESS_SESSION_AUTH"
83
84 awsAccountIDEnv = "AWS_ACCOUNT_ID"
85 awsAccountIDEndpointModeEnv = "AWS_ACCOUNT_ID_ENDPOINT_MODE"
86)
87
88var (
89 credAccessEnvKeys = []string{
90 awsAccessKeyIDEnvVar,
91 awsAccessKeyEnvVar,
92 }
93 credSecretEnvKeys = []string{
94 awsSecretAccessKeyEnvVar,
95 awsSecretKeyEnvVar,
96 }
97 regionEnvKeys = []string{
98 awsRegionEnvVar,
99 awsDefaultRegionEnvVar,
100 }
101 profileEnvKeys = []string{
102 awsProfileEnvVar,
103 awsDefaultProfileEnvVar,
104 }
105)
106
107// EnvConfig is a collection of environment values the SDK will read
108// setup config from. All environment values are optional. But some values
109// such as credentials require multiple values to be complete or the values
110// will be ignored.
111type EnvConfig struct {
112 // Environment configuration values. If set both Access Key ID and Secret Access
113 // Key must be provided. Session Token and optionally also be provided, but is
114 // not required.
115 //
116 // # Access Key ID
117 // AWS_ACCESS_KEY_ID=AKID
118 // AWS_ACCESS_KEY=AKID # only read if AWS_ACCESS_KEY_ID is not set.
119 //
120 // # Secret Access Key
121 // AWS_SECRET_ACCESS_KEY=SECRET
122 // AWS_SECRET_KEY=SECRET # only read if AWS_SECRET_ACCESS_KEY is not set.
123 //
124 // # Session Token
125 // AWS_SESSION_TOKEN=TOKEN
126 Credentials aws.Credentials
127
128 // ContainerCredentialsEndpoint value is the HTTP enabled endpoint to retrieve credentials
129 // using the endpointcreds.Provider
130 ContainerCredentialsEndpoint string
131
132 // ContainerCredentialsRelativePath is the relative URI path that will be used when attempting to retrieve
133 // credentials from the container endpoint.
134 ContainerCredentialsRelativePath string
135
136 // ContainerAuthorizationToken is the authorization token that will be included in the HTTP Authorization
137 // header when attempting to retrieve credentials from the container credentials endpoint.
138 ContainerAuthorizationToken string
139
140 // Region value will instruct the SDK where to make service API requests to. If is
141 // not provided in the environment the region must be provided before a service
142 // client request is made.
143 //
144 // AWS_REGION=us-west-2
145 // AWS_DEFAULT_REGION=us-west-2
146 Region string
147
148 // Profile name the SDK should load use when loading shared configuration from the
149 // shared configuration files. If not provided "default" will be used as the
150 // profile name.
151 //
152 // AWS_PROFILE=my_profile
153 // AWS_DEFAULT_PROFILE=my_profile
154 SharedConfigProfile string
155
156 // Shared credentials file path can be set to instruct the SDK to use an alternate
157 // file for the shared credentials. If not set the file will be loaded from
158 // $HOME/.aws/credentials on Linux/Unix based systems, and
159 // %USERPROFILE%\.aws\credentials on Windows.
160 //
161 // AWS_SHARED_CREDENTIALS_FILE=$HOME/my_shared_credentials
162 SharedCredentialsFile string
163
164 // Shared config file path can be set to instruct the SDK to use an alternate
165 // file for the shared config. If not set the file will be loaded from
166 // $HOME/.aws/config on Linux/Unix based systems, and
167 // %USERPROFILE%\.aws\config on Windows.
168 //
169 // AWS_CONFIG_FILE=$HOME/my_shared_config
170 SharedConfigFile string
171
172 // Sets the path to a custom Credentials Authority (CA) Bundle PEM file
173 // that the SDK will use instead of the system's root CA bundle.
174 // Only use this if you want to configure the SDK to use a custom set
175 // of CAs.
176 //
177 // Enabling this option will attempt to merge the Transport
178 // into the SDK's HTTP client. If the client's Transport is
179 // not a http.Transport an error will be returned. If the
180 // Transport's TLS config is set this option will cause the
181 // SDK to overwrite the Transport's TLS config's RootCAs value.
182 //
183 // Setting a custom HTTPClient in the aws.Config options will override this setting.
184 // To use this option and custom HTTP client, the HTTP client needs to be provided
185 // when creating the config. Not the service client.
186 //
187 // AWS_CA_BUNDLE=$HOME/my_custom_ca_bundle
188 CustomCABundle string
189
190 // Enables endpoint discovery via environment variables.
191 //
192 // AWS_ENABLE_ENDPOINT_DISCOVERY=true
193 EnableEndpointDiscovery aws.EndpointDiscoveryEnableState
194
195 // Specifies the WebIdentity token the SDK should use to assume a role
196 // with.
197 //
198 // AWS_WEB_IDENTITY_TOKEN_FILE=file_path
199 WebIdentityTokenFilePath string
200
201 // Specifies the IAM role arn to use when assuming an role.
202 //
203 // AWS_ROLE_ARN=role_arn
204 RoleARN string
205
206 // Specifies the IAM role session name to use when assuming a role.
207 //
208 // AWS_ROLE_SESSION_NAME=session_name
209 RoleSessionName string
210
211 // Specifies if the S3 service should allow ARNs to direct the region
212 // the client's requests are sent to.
213 //
214 // AWS_S3_USE_ARN_REGION=true
215 S3UseARNRegion *bool
216
217 // Specifies if the EC2 IMDS service client is enabled.
218 //
219 // AWS_EC2_METADATA_DISABLED=true
220 EC2IMDSClientEnableState imds.ClientEnableState
221
222 // Specifies if EC2 IMDSv1 fallback is disabled.
223 //
224 // AWS_EC2_METADATA_V1_DISABLED=true
225 EC2IMDSv1Disabled *bool
226
227 // Specifies the EC2 Instance Metadata Service default endpoint selection mode (IPv4 or IPv6)
228 //
229 // AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE=IPv6
230 EC2IMDSEndpointMode imds.EndpointModeState
231
232 // Specifies the EC2 Instance Metadata Service endpoint to use. If specified it overrides EC2IMDSEndpointMode.
233 //
234 // AWS_EC2_METADATA_SERVICE_ENDPOINT=http://fd00:ec2::254
235 EC2IMDSEndpoint string
236
237 // Specifies if the S3 service should disable multi-region access points
238 // support.
239 //
240 // AWS_S3_DISABLE_MULTIREGION_ACCESS_POINTS=true
241 S3DisableMultiRegionAccessPoints *bool
242
243 // Specifies that SDK clients must resolve a dual-stack endpoint for
244 // services.
245 //
246 // AWS_USE_DUALSTACK_ENDPOINT=true
247 UseDualStackEndpoint aws.DualStackEndpointState
248
249 // Specifies that SDK clients must resolve a FIPS endpoint for
250 // services.
251 //
252 // AWS_USE_FIPS_ENDPOINT=true
253 UseFIPSEndpoint aws.FIPSEndpointState
254
255 // Specifies the SDK Defaults Mode used by services.
256 //
257 // AWS_DEFAULTS_MODE=standard
258 DefaultsMode aws.DefaultsMode
259
260 // Specifies the maximum number attempts an API client will call an
261 // operation that fails with a retryable error.
262 //
263 // AWS_MAX_ATTEMPTS=3
264 RetryMaxAttempts int
265
266 // Specifies the retry model the API client will be created with.
267 //
268 // aws_retry_mode=standard
269 RetryMode aws.RetryMode
270
271 // aws sdk app ID that can be added to user agent header string
272 AppID string
273
274 // Flag used to disable configured endpoints.
275 IgnoreConfiguredEndpoints *bool
276
277 // Value to contain configured endpoints to be propagated to
278 // corresponding endpoint resolution field.
279 BaseEndpoint string
280
281 // determine if request compression is allowed, default to false
282 // retrieved from env var AWS_DISABLE_REQUEST_COMPRESSION
283 DisableRequestCompression *bool
284
285 // inclusive threshold request body size to trigger compression,
286 // default to 10240 and must be within 0 and 10485760 bytes inclusive
287 // retrieved from env var AWS_REQUEST_MIN_COMPRESSION_SIZE_BYTES
288 RequestMinCompressSizeBytes *int64
289
290 // Whether S3Express auth is disabled.
291 //
292 // This will NOT prevent requests from being made to S3Express buckets, it
293 // will only bypass the modified endpoint routing and signing behaviors
294 // associated with the feature.
295 S3DisableExpressAuth *bool
296
297 // Indicates whether account ID will be required/ignored in endpoint2.0 routing
298 AccountIDEndpointMode aws.AccountIDEndpointMode
299}
300
301// loadEnvConfig reads configuration values from the OS's environment variables.
302// Returning the a Config typed EnvConfig to satisfy the ConfigLoader func type.
303func loadEnvConfig(ctx context.Context, cfgs configs) (Config, error) {
304 return NewEnvConfig()
305}
306
307// NewEnvConfig retrieves the SDK's environment configuration.
308// See `EnvConfig` for the values that will be retrieved.
309func NewEnvConfig() (EnvConfig, error) {
310 var cfg EnvConfig
311
312 creds := aws.Credentials{
313 Source: CredentialsSourceName,
314 }
315 setStringFromEnvVal(&creds.AccessKeyID, credAccessEnvKeys)
316 setStringFromEnvVal(&creds.SecretAccessKey, credSecretEnvKeys)
317 if creds.HasKeys() {
318 creds.AccountID = os.Getenv(awsAccountIDEnv)
319 creds.SessionToken = os.Getenv(awsSessionTokenEnvVar)
320 cfg.Credentials = creds
321 }
322
323 cfg.ContainerCredentialsEndpoint = os.Getenv(awsContainerCredentialsEndpointEnvVar)
324 cfg.ContainerCredentialsRelativePath = os.Getenv(awsContainerCredentialsRelativePathEnvVar)
325 cfg.ContainerAuthorizationToken = os.Getenv(awsContainerPProviderAuthorizationEnvVar)
326
327 setStringFromEnvVal(&cfg.Region, regionEnvKeys)
328 setStringFromEnvVal(&cfg.SharedConfigProfile, profileEnvKeys)
329
330 cfg.SharedCredentialsFile = os.Getenv(awsSharedCredentialsFileEnvVar)
331 cfg.SharedConfigFile = os.Getenv(awsConfigFileEnvVar)
332
333 cfg.CustomCABundle = os.Getenv(awsCustomCABundleEnvVar)
334
335 cfg.WebIdentityTokenFilePath = os.Getenv(awsWebIdentityTokenFilePathEnvVar)
336
337 cfg.RoleARN = os.Getenv(awsRoleARNEnvVar)
338 cfg.RoleSessionName = os.Getenv(awsRoleSessionNameEnvVar)
339
340 cfg.AppID = os.Getenv(awsSdkAppID)
341
342 if err := setBoolPtrFromEnvVal(&cfg.DisableRequestCompression, []string{awsDisableRequestCompression}); err != nil {
343 return cfg, err
344 }
345 if err := setInt64PtrFromEnvVal(&cfg.RequestMinCompressSizeBytes, []string{awsRequestMinCompressionSizeBytes}, smithyrequestcompression.MaxRequestMinCompressSizeBytes); err != nil {
346 return cfg, err
347 }
348
349 if err := setEndpointDiscoveryTypeFromEnvVal(&cfg.EnableEndpointDiscovery, []string{awsEnableEndpointDiscoveryEnvVar}); err != nil {
350 return cfg, err
351 }
352
353 if err := setBoolPtrFromEnvVal(&cfg.S3UseARNRegion, []string{awsS3UseARNRegionEnvVar}); err != nil {
354 return cfg, err
355 }
356
357 setEC2IMDSClientEnableState(&cfg.EC2IMDSClientEnableState, []string{awsEc2MetadataDisabled})
358 if err := setEC2IMDSEndpointMode(&cfg.EC2IMDSEndpointMode, []string{awsEc2MetadataServiceEndpointModeEnvVar}); err != nil {
359 return cfg, err
360 }
361 cfg.EC2IMDSEndpoint = os.Getenv(awsEc2MetadataServiceEndpointEnvVar)
362 if err := setBoolPtrFromEnvVal(&cfg.EC2IMDSv1Disabled, []string{awsEc2MetadataV1DisabledEnvVar}); err != nil {
363 return cfg, err
364 }
365
366 if err := setBoolPtrFromEnvVal(&cfg.S3DisableMultiRegionAccessPoints, []string{awsS3DisableMultiRegionAccessPointEnvVar}); err != nil {
367 return cfg, err
368 }
369
370 if err := setUseDualStackEndpointFromEnvVal(&cfg.UseDualStackEndpoint, []string{awsUseDualStackEndpoint}); err != nil {
371 return cfg, err
372 }
373
374 if err := setUseFIPSEndpointFromEnvVal(&cfg.UseFIPSEndpoint, []string{awsUseFIPSEndpoint}); err != nil {
375 return cfg, err
376 }
377
378 if err := setDefaultsModeFromEnvVal(&cfg.DefaultsMode, []string{awsDefaultMode}); err != nil {
379 return cfg, err
380 }
381
382 if err := setIntFromEnvVal(&cfg.RetryMaxAttempts, []string{awsRetryMaxAttempts}); err != nil {
383 return cfg, err
384 }
385 if err := setRetryModeFromEnvVal(&cfg.RetryMode, []string{awsRetryMode}); err != nil {
386 return cfg, err
387 }
388
389 setStringFromEnvVal(&cfg.BaseEndpoint, []string{awsEndpointURL})
390
391 if err := setBoolPtrFromEnvVal(&cfg.IgnoreConfiguredEndpoints, []string{awsIgnoreConfiguredEndpoints}); err != nil {
392 return cfg, err
393 }
394
395 if err := setBoolPtrFromEnvVal(&cfg.S3DisableExpressAuth, []string{awsS3DisableExpressSessionAuthEnv}); err != nil {
396 return cfg, err
397 }
398
399 if err := setAIDEndPointModeFromEnvVal(&cfg.AccountIDEndpointMode, []string{awsAccountIDEndpointModeEnv}); err != nil {
400 return cfg, err
401 }
402
403 return cfg, nil
404}
405
406func (c EnvConfig) getDefaultsMode(ctx context.Context) (aws.DefaultsMode, bool, error) {
407 if len(c.DefaultsMode) == 0 {
408 return "", false, nil
409 }
410 return c.DefaultsMode, true, nil
411}
412
413func (c EnvConfig) getAppID(context.Context) (string, bool, error) {
414 return c.AppID, len(c.AppID) > 0, nil
415}
416
417func (c EnvConfig) getDisableRequestCompression(context.Context) (bool, bool, error) {
418 if c.DisableRequestCompression == nil {
419 return false, false, nil
420 }
421 return *c.DisableRequestCompression, true, nil
422}
423
424func (c EnvConfig) getRequestMinCompressSizeBytes(context.Context) (int64, bool, error) {
425 if c.RequestMinCompressSizeBytes == nil {
426 return 0, false, nil
427 }
428 return *c.RequestMinCompressSizeBytes, true, nil
429}
430
431func (c EnvConfig) getAccountIDEndpointMode(context.Context) (aws.AccountIDEndpointMode, bool, error) {
432 return c.AccountIDEndpointMode, len(c.AccountIDEndpointMode) > 0, nil
433}
434
435// GetRetryMaxAttempts returns the value of AWS_MAX_ATTEMPTS if was specified,
436// and not 0.
437func (c EnvConfig) GetRetryMaxAttempts(ctx context.Context) (int, bool, error) {
438 if c.RetryMaxAttempts == 0 {
439 return 0, false, nil
440 }
441 return c.RetryMaxAttempts, true, nil
442}
443
444// GetRetryMode returns the RetryMode of AWS_RETRY_MODE if was specified, and a
445// valid value.
446func (c EnvConfig) GetRetryMode(ctx context.Context) (aws.RetryMode, bool, error) {
447 if len(c.RetryMode) == 0 {
448 return "", false, nil
449 }
450 return c.RetryMode, true, nil
451}
452
453func setEC2IMDSClientEnableState(state *imds.ClientEnableState, keys []string) {
454 for _, k := range keys {
455 value := os.Getenv(k)
456 if len(value) == 0 {
457 continue
458 }
459 switch {
460 case strings.EqualFold(value, "true"):
461 *state = imds.ClientDisabled
462 case strings.EqualFold(value, "false"):
463 *state = imds.ClientEnabled
464 default:
465 continue
466 }
467 break
468 }
469}
470
471func setDefaultsModeFromEnvVal(mode *aws.DefaultsMode, keys []string) error {
472 for _, k := range keys {
473 if value := os.Getenv(k); len(value) > 0 {
474 if ok := mode.SetFromString(value); !ok {
475 return fmt.Errorf("invalid %s value: %s", k, value)
476 }
477 break
478 }
479 }
480 return nil
481}
482
483func setRetryModeFromEnvVal(mode *aws.RetryMode, keys []string) (err error) {
484 for _, k := range keys {
485 if value := os.Getenv(k); len(value) > 0 {
486 *mode, err = aws.ParseRetryMode(value)
487 if err != nil {
488 return fmt.Errorf("invalid %s value, %w", k, err)
489 }
490 break
491 }
492 }
493 return nil
494}
495
496func setEC2IMDSEndpointMode(mode *imds.EndpointModeState, keys []string) error {
497 for _, k := range keys {
498 value := os.Getenv(k)
499 if len(value) == 0 {
500 continue
501 }
502 if err := mode.SetFromString(value); err != nil {
503 return fmt.Errorf("invalid value for environment variable, %s=%s, %v", k, value, err)
504 }
505 }
506 return nil
507}
508
509func setAIDEndPointModeFromEnvVal(m *aws.AccountIDEndpointMode, keys []string) error {
510 for _, k := range keys {
511 value := os.Getenv(k)
512 if len(value) == 0 {
513 continue
514 }
515
516 switch value {
517 case "preferred":
518 *m = aws.AccountIDEndpointModePreferred
519 case "required":
520 *m = aws.AccountIDEndpointModeRequired
521 case "disabled":
522 *m = aws.AccountIDEndpointModeDisabled
523 default:
524 return fmt.Errorf("invalid value for environment variable, %s=%s, must be preferred/required/disabled", k, value)
525 }
526 break
527 }
528 return nil
529}
530
531// GetRegion returns the AWS Region if set in the environment. Returns an empty
532// string if not set.
533func (c EnvConfig) getRegion(ctx context.Context) (string, bool, error) {
534 if len(c.Region) == 0 {
535 return "", false, nil
536 }
537 return c.Region, true, nil
538}
539
540// GetSharedConfigProfile returns the shared config profile if set in the
541// environment. Returns an empty string if not set.
542func (c EnvConfig) getSharedConfigProfile(ctx context.Context) (string, bool, error) {
543 if len(c.SharedConfigProfile) == 0 {
544 return "", false, nil
545 }
546
547 return c.SharedConfigProfile, true, nil
548}
549
550// getSharedConfigFiles returns a slice of filenames set in the environment.
551//
552// Will return the filenames in the order of:
553// * Shared Config
554func (c EnvConfig) getSharedConfigFiles(context.Context) ([]string, bool, error) {
555 var files []string
556 if v := c.SharedConfigFile; len(v) > 0 {
557 files = append(files, v)
558 }
559
560 if len(files) == 0 {
561 return nil, false, nil
562 }
563 return files, true, nil
564}
565
566// getSharedCredentialsFiles returns a slice of filenames set in the environment.
567//
568// Will return the filenames in the order of:
569// * Shared Credentials
570func (c EnvConfig) getSharedCredentialsFiles(context.Context) ([]string, bool, error) {
571 var files []string
572 if v := c.SharedCredentialsFile; len(v) > 0 {
573 files = append(files, v)
574 }
575 if len(files) == 0 {
576 return nil, false, nil
577 }
578 return files, true, nil
579}
580
581// GetCustomCABundle returns the custom CA bundle's PEM bytes if the file was
582func (c EnvConfig) getCustomCABundle(context.Context) (io.Reader, bool, error) {
583 if len(c.CustomCABundle) == 0 {
584 return nil, false, nil
585 }
586
587 b, err := ioutil.ReadFile(c.CustomCABundle)
588 if err != nil {
589 return nil, false, err
590 }
591 return bytes.NewReader(b), true, nil
592}
593
594// GetIgnoreConfiguredEndpoints is used in knowing when to disable configured
595// endpoints feature.
596func (c EnvConfig) GetIgnoreConfiguredEndpoints(context.Context) (bool, bool, error) {
597 if c.IgnoreConfiguredEndpoints == nil {
598 return false, false, nil
599 }
600
601 return *c.IgnoreConfiguredEndpoints, true, nil
602}
603
604func (c EnvConfig) getBaseEndpoint(context.Context) (string, bool, error) {
605 return c.BaseEndpoint, len(c.BaseEndpoint) > 0, nil
606}
607
608// GetServiceBaseEndpoint is used to retrieve a normalized SDK ID for use
609// with configured endpoints.
610func (c EnvConfig) GetServiceBaseEndpoint(ctx context.Context, sdkID string) (string, bool, error) {
611 if endpt := os.Getenv(fmt.Sprintf("%s_%s", awsEndpointURL, normalizeEnv(sdkID))); endpt != "" {
612 return endpt, true, nil
613 }
614 return "", false, nil
615}
616
617func normalizeEnv(sdkID string) string {
618 upper := strings.ToUpper(sdkID)
619 return strings.ReplaceAll(upper, " ", "_")
620}
621
622// GetS3UseARNRegion returns whether to allow ARNs to direct the region
623// the S3 client's requests are sent to.
624func (c EnvConfig) GetS3UseARNRegion(ctx context.Context) (value, ok bool, err error) {
625 if c.S3UseARNRegion == nil {
626 return false, false, nil
627 }
628
629 return *c.S3UseARNRegion, true, nil
630}
631
632// GetS3DisableMultiRegionAccessPoints returns whether to disable multi-region access point
633// support for the S3 client.
634func (c EnvConfig) GetS3DisableMultiRegionAccessPoints(ctx context.Context) (value, ok bool, err error) {
635 if c.S3DisableMultiRegionAccessPoints == nil {
636 return false, false, nil
637 }
638
639 return *c.S3DisableMultiRegionAccessPoints, true, nil
640}
641
642// GetUseDualStackEndpoint returns whether the service's dual-stack endpoint should be
643// used for requests.
644func (c EnvConfig) GetUseDualStackEndpoint(ctx context.Context) (value aws.DualStackEndpointState, found bool, err error) {
645 if c.UseDualStackEndpoint == aws.DualStackEndpointStateUnset {
646 return aws.DualStackEndpointStateUnset, false, nil
647 }
648
649 return c.UseDualStackEndpoint, true, nil
650}
651
652// GetUseFIPSEndpoint returns whether the service's FIPS endpoint should be
653// used for requests.
654func (c EnvConfig) GetUseFIPSEndpoint(ctx context.Context) (value aws.FIPSEndpointState, found bool, err error) {
655 if c.UseFIPSEndpoint == aws.FIPSEndpointStateUnset {
656 return aws.FIPSEndpointStateUnset, false, nil
657 }
658
659 return c.UseFIPSEndpoint, true, nil
660}
661
662func setStringFromEnvVal(dst *string, keys []string) {
663 for _, k := range keys {
664 if v := os.Getenv(k); len(v) > 0 {
665 *dst = v
666 break
667 }
668 }
669}
670
671func setIntFromEnvVal(dst *int, keys []string) error {
672 for _, k := range keys {
673 if v := os.Getenv(k); len(v) > 0 {
674 i, err := strconv.ParseInt(v, 10, 64)
675 if err != nil {
676 return fmt.Errorf("invalid value %s=%s, %w", k, v, err)
677 }
678 *dst = int(i)
679 break
680 }
681 }
682
683 return nil
684}
685
686func setBoolPtrFromEnvVal(dst **bool, keys []string) error {
687 for _, k := range keys {
688 value := os.Getenv(k)
689 if len(value) == 0 {
690 continue
691 }
692
693 if *dst == nil {
694 *dst = new(bool)
695 }
696
697 switch {
698 case strings.EqualFold(value, "false"):
699 **dst = false
700 case strings.EqualFold(value, "true"):
701 **dst = true
702 default:
703 return fmt.Errorf(
704 "invalid value for environment variable, %s=%s, need true or false",
705 k, value)
706 }
707 break
708 }
709
710 return nil
711}
712
713func setInt64PtrFromEnvVal(dst **int64, keys []string, max int64) error {
714 for _, k := range keys {
715 value := os.Getenv(k)
716 if len(value) == 0 {
717 continue
718 }
719
720 v, err := strconv.ParseInt(value, 10, 64)
721 if err != nil {
722 return fmt.Errorf("invalid value for env var, %s=%s, need int64", k, value)
723 } else if v < 0 || v > max {
724 return fmt.Errorf("invalid range for env var min request compression size bytes %q, must be within 0 and 10485760 inclusively", v)
725 }
726 if *dst == nil {
727 *dst = new(int64)
728 }
729
730 **dst = v
731 break
732 }
733
734 return nil
735}
736
737func setEndpointDiscoveryTypeFromEnvVal(dst *aws.EndpointDiscoveryEnableState, keys []string) error {
738 for _, k := range keys {
739 value := os.Getenv(k)
740 if len(value) == 0 {
741 continue // skip if empty
742 }
743
744 switch {
745 case strings.EqualFold(value, endpointDiscoveryDisabled):
746 *dst = aws.EndpointDiscoveryDisabled
747 case strings.EqualFold(value, endpointDiscoveryEnabled):
748 *dst = aws.EndpointDiscoveryEnabled
749 case strings.EqualFold(value, endpointDiscoveryAuto):
750 *dst = aws.EndpointDiscoveryAuto
751 default:
752 return fmt.Errorf(
753 "invalid value for environment variable, %s=%s, need true, false or auto",
754 k, value)
755 }
756 }
757 return nil
758}
759
760func setUseDualStackEndpointFromEnvVal(dst *aws.DualStackEndpointState, keys []string) error {
761 for _, k := range keys {
762 value := os.Getenv(k)
763 if len(value) == 0 {
764 continue // skip if empty
765 }
766
767 switch {
768 case strings.EqualFold(value, "true"):
769 *dst = aws.DualStackEndpointStateEnabled
770 case strings.EqualFold(value, "false"):
771 *dst = aws.DualStackEndpointStateDisabled
772 default:
773 return fmt.Errorf(
774 "invalid value for environment variable, %s=%s, need true, false",
775 k, value)
776 }
777 }
778 return nil
779}
780
781func setUseFIPSEndpointFromEnvVal(dst *aws.FIPSEndpointState, keys []string) error {
782 for _, k := range keys {
783 value := os.Getenv(k)
784 if len(value) == 0 {
785 continue // skip if empty
786 }
787
788 switch {
789 case strings.EqualFold(value, "true"):
790 *dst = aws.FIPSEndpointStateEnabled
791 case strings.EqualFold(value, "false"):
792 *dst = aws.FIPSEndpointStateDisabled
793 default:
794 return fmt.Errorf(
795 "invalid value for environment variable, %s=%s, need true, false",
796 k, value)
797 }
798 }
799 return nil
800}
801
802// GetEnableEndpointDiscovery returns resolved value for EnableEndpointDiscovery env variable setting.
803func (c EnvConfig) GetEnableEndpointDiscovery(ctx context.Context) (value aws.EndpointDiscoveryEnableState, found bool, err error) {
804 if c.EnableEndpointDiscovery == aws.EndpointDiscoveryUnset {
805 return aws.EndpointDiscoveryUnset, false, nil
806 }
807
808 return c.EnableEndpointDiscovery, true, nil
809}
810
811// GetEC2IMDSClientEnableState implements a EC2IMDSClientEnableState options resolver interface.
812func (c EnvConfig) GetEC2IMDSClientEnableState() (imds.ClientEnableState, bool, error) {
813 if c.EC2IMDSClientEnableState == imds.ClientDefaultEnableState {
814 return imds.ClientDefaultEnableState, false, nil
815 }
816
817 return c.EC2IMDSClientEnableState, true, nil
818}
819
820// GetEC2IMDSEndpointMode implements a EC2IMDSEndpointMode option resolver interface.
821func (c EnvConfig) GetEC2IMDSEndpointMode() (imds.EndpointModeState, bool, error) {
822 if c.EC2IMDSEndpointMode == imds.EndpointModeStateUnset {
823 return imds.EndpointModeStateUnset, false, nil
824 }
825
826 return c.EC2IMDSEndpointMode, true, nil
827}
828
829// GetEC2IMDSEndpoint implements a EC2IMDSEndpoint option resolver interface.
830func (c EnvConfig) GetEC2IMDSEndpoint() (string, bool, error) {
831 if len(c.EC2IMDSEndpoint) == 0 {
832 return "", false, nil
833 }
834
835 return c.EC2IMDSEndpoint, true, nil
836}
837
838// GetEC2IMDSV1FallbackDisabled implements an EC2IMDSV1FallbackDisabled option
839// resolver interface.
840func (c EnvConfig) GetEC2IMDSV1FallbackDisabled() (bool, bool) {
841 if c.EC2IMDSv1Disabled == nil {
842 return false, false
843 }
844
845 return *c.EC2IMDSv1Disabled, true
846}
847
848// GetS3DisableExpressAuth returns the configured value for
849// [EnvConfig.S3DisableExpressAuth].
850func (c EnvConfig) GetS3DisableExpressAuth() (value, ok bool) {
851 if c.S3DisableExpressAuth == nil {
852 return false, false
853 }
854
855 return *c.S3DisableExpressAuth, true
856}