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