src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

env_config.go (25002B)


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