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