code.dwrz.net

Go monorepo.
Log | Files | Refs

env_config.go (19995B)


      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 )
     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 	awsAccessKeyIDEnvVar = "AWS_ACCESS_KEY_ID"
     24 	awsAccessKeyEnvVar   = "AWS_ACCESS_KEY"
     25 
     26 	awsSecretAccessKeyEnvVar = "AWS_SECRET_ACCESS_KEY"
     27 	awsSecretKeyEnvVar       = "AWS_SECRET_KEY"
     28 
     29 	awsSessionTokenEnvVar = "AWS_SESSION_TOKEN"
     30 
     31 	awsContainerCredentialsEndpointEnvVar     = "AWS_CONTAINER_CREDENTIALS_FULL_URI"
     32 	awsContainerCredentialsRelativePathEnvVar = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"
     33 	awsContainerPProviderAuthorizationEnvVar  = "AWS_CONTAINER_AUTHORIZATION_TOKEN"
     34 
     35 	awsRegionEnvVar        = "AWS_REGION"
     36 	awsDefaultRegionEnvVar = "AWS_DEFAULT_REGION"
     37 
     38 	awsProfileEnvVar        = "AWS_PROFILE"
     39 	awsDefaultProfileEnvVar = "AWS_DEFAULT_PROFILE"
     40 
     41 	awsSharedCredentialsFileEnvVar = "AWS_SHARED_CREDENTIALS_FILE"
     42 
     43 	awsConfigFileEnvVar = "AWS_CONFIG_FILE"
     44 
     45 	awsCustomCABundleEnvVar = "AWS_CA_BUNDLE"
     46 
     47 	awsWebIdentityTokenFilePathEnvVar = "AWS_WEB_IDENTITY_TOKEN_FILE"
     48 
     49 	awsRoleARNEnvVar         = "AWS_ROLE_ARN"
     50 	awsRoleSessionNameEnvVar = "AWS_ROLE_SESSION_NAME"
     51 
     52 	awsEnableEndpointDiscoveryEnvVar = "AWS_ENABLE_ENDPOINT_DISCOVERY"
     53 
     54 	awsS3UseARNRegionEnvVar = "AWS_S3_USE_ARN_REGION"
     55 
     56 	awsEc2MetadataServiceEndpointModeEnvVar = "AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE"
     57 
     58 	awsEc2MetadataServiceEndpointEnvVar = "AWS_EC2_METADATA_SERVICE_ENDPOINT"
     59 
     60 	awsEc2MetadataDisabled = "AWS_EC2_METADATA_DISABLED"
     61 
     62 	awsS3DisableMultiRegionAccessPointEnvVar = "AWS_S3_DISABLE_MULTIREGION_ACCESS_POINTS"
     63 
     64 	awsUseDualStackEndpoint = "AWS_USE_DUALSTACK_ENDPOINT"
     65 
     66 	awsUseFIPSEndpoint = "AWS_USE_FIPS_ENDPOINT"
     67 
     68 	awsDefaultMode = "AWS_DEFAULTS_MODE"
     69 
     70 	awsRetryMaxAttempts = "AWS_MAX_ATTEMPTS"
     71 	awsRetryMode        = "AWS_RETRY_MODE"
     72 )
     73 
     74 var (
     75 	credAccessEnvKeys = []string{
     76 		awsAccessKeyIDEnvVar,
     77 		awsAccessKeyEnvVar,
     78 	}
     79 	credSecretEnvKeys = []string{
     80 		awsSecretAccessKeyEnvVar,
     81 		awsSecretKeyEnvVar,
     82 	}
     83 	regionEnvKeys = []string{
     84 		awsRegionEnvVar,
     85 		awsDefaultRegionEnvVar,
     86 	}
     87 	profileEnvKeys = []string{
     88 		awsProfileEnvVar,
     89 		awsDefaultProfileEnvVar,
     90 	}
     91 )
     92 
     93 // EnvConfig is a collection of environment values the SDK will read
     94 // setup config from. All environment values are optional. But some values
     95 // such as credentials require multiple values to be complete or the values
     96 // will be ignored.
     97 type EnvConfig struct {
     98 	// Environment configuration values. If set both Access Key ID and Secret Access
     99 	// Key must be provided. Session Token and optionally also be provided, but is
    100 	// not required.
    101 	//
    102 	//	# Access Key ID
    103 	//	AWS_ACCESS_KEY_ID=AKID
    104 	//	AWS_ACCESS_KEY=AKID # only read if AWS_ACCESS_KEY_ID is not set.
    105 	//
    106 	//	# Secret Access Key
    107 	//	AWS_SECRET_ACCESS_KEY=SECRET
    108 	//	AWS_SECRET_KEY=SECRET # only read if AWS_SECRET_ACCESS_KEY is not set.
    109 	//
    110 	//	# Session Token
    111 	//	AWS_SESSION_TOKEN=TOKEN
    112 	Credentials aws.Credentials
    113 
    114 	// ContainerCredentialsEndpoint value is the HTTP enabled endpoint to retrieve credentials
    115 	// using the endpointcreds.Provider
    116 	ContainerCredentialsEndpoint string
    117 
    118 	// ContainerCredentialsRelativePath is the relative URI path that will be used when attempting to retrieve
    119 	// credentials from the container endpoint.
    120 	ContainerCredentialsRelativePath string
    121 
    122 	// ContainerAuthorizationToken is the authorization token that will be included in the HTTP Authorization
    123 	// header when attempting to retrieve credentials from the container credentials endpoint.
    124 	ContainerAuthorizationToken string
    125 
    126 	// Region value will instruct the SDK where to make service API requests to. If is
    127 	// not provided in the environment the region must be provided before a service
    128 	// client request is made.
    129 	//
    130 	//	AWS_REGION=us-west-2
    131 	//	AWS_DEFAULT_REGION=us-west-2
    132 	Region string
    133 
    134 	// Profile name the SDK should load use when loading shared configuration from the
    135 	// shared configuration files. If not provided "default" will be used as the
    136 	// profile name.
    137 	//
    138 	//	AWS_PROFILE=my_profile
    139 	//	AWS_DEFAULT_PROFILE=my_profile
    140 	SharedConfigProfile string
    141 
    142 	// Shared credentials file path can be set to instruct the SDK to use an alternate
    143 	// file for the shared credentials. If not set the file will be loaded from
    144 	// $HOME/.aws/credentials on Linux/Unix based systems, and
    145 	// %USERPROFILE%\.aws\credentials on Windows.
    146 	//
    147 	//	AWS_SHARED_CREDENTIALS_FILE=$HOME/my_shared_credentials
    148 	SharedCredentialsFile string
    149 
    150 	// Shared config file path can be set to instruct the SDK to use an alternate
    151 	// file for the shared config. If not set the file will be loaded from
    152 	// $HOME/.aws/config on Linux/Unix based systems, and
    153 	// %USERPROFILE%\.aws\config on Windows.
    154 	//
    155 	//	AWS_CONFIG_FILE=$HOME/my_shared_config
    156 	SharedConfigFile string
    157 
    158 	// Sets the path to a custom Credentials Authority (CA) Bundle PEM file
    159 	// that the SDK will use instead of the system's root CA bundle.
    160 	// Only use this if you want to configure the SDK to use a custom set
    161 	// of CAs.
    162 	//
    163 	// Enabling this option will attempt to merge the Transport
    164 	// into the SDK's HTTP client. If the client's Transport is
    165 	// not a http.Transport an error will be returned. If the
    166 	// Transport's TLS config is set this option will cause the
    167 	// SDK to overwrite the Transport's TLS config's  RootCAs value.
    168 	//
    169 	// Setting a custom HTTPClient in the aws.Config options will override this setting.
    170 	// To use this option and custom HTTP client, the HTTP client needs to be provided
    171 	// when creating the config. Not the service client.
    172 	//
    173 	//  AWS_CA_BUNDLE=$HOME/my_custom_ca_bundle
    174 	CustomCABundle string
    175 
    176 	// Enables endpoint discovery via environment variables.
    177 	//
    178 	//	AWS_ENABLE_ENDPOINT_DISCOVERY=true
    179 	EnableEndpointDiscovery aws.EndpointDiscoveryEnableState
    180 
    181 	// Specifies the WebIdentity token the SDK should use to assume a role
    182 	// with.
    183 	//
    184 	//  AWS_WEB_IDENTITY_TOKEN_FILE=file_path
    185 	WebIdentityTokenFilePath string
    186 
    187 	// Specifies the IAM role arn to use when assuming an role.
    188 	//
    189 	//  AWS_ROLE_ARN=role_arn
    190 	RoleARN string
    191 
    192 	// Specifies the IAM role session name to use when assuming a role.
    193 	//
    194 	//  AWS_ROLE_SESSION_NAME=session_name
    195 	RoleSessionName string
    196 
    197 	// Specifies if the S3 service should allow ARNs to direct the region
    198 	// the client's requests are sent to.
    199 	//
    200 	// AWS_S3_USE_ARN_REGION=true
    201 	S3UseARNRegion *bool
    202 
    203 	// Specifies if the EC2 IMDS service client is enabled.
    204 	//
    205 	// AWS_EC2_METADATA_DISABLED=true
    206 	EC2IMDSClientEnableState imds.ClientEnableState
    207 
    208 	// Specifies the EC2 Instance Metadata Service default endpoint selection mode (IPv4 or IPv6)
    209 	//
    210 	// AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE=IPv6
    211 	EC2IMDSEndpointMode imds.EndpointModeState
    212 
    213 	// Specifies the EC2 Instance Metadata Service endpoint to use. If specified it overrides EC2IMDSEndpointMode.
    214 	//
    215 	// AWS_EC2_METADATA_SERVICE_ENDPOINT=http://fd00:ec2::254
    216 	EC2IMDSEndpoint string
    217 
    218 	// Specifies if the S3 service should disable multi-region access points
    219 	// support.
    220 	//
    221 	// AWS_S3_DISABLE_MULTIREGION_ACCESS_POINTS=true
    222 	S3DisableMultiRegionAccessPoints *bool
    223 
    224 	// Specifies that SDK clients must resolve a dual-stack endpoint for
    225 	// services.
    226 	//
    227 	// AWS_USE_DUALSTACK_ENDPOINT=true
    228 	UseDualStackEndpoint aws.DualStackEndpointState
    229 
    230 	// Specifies that SDK clients must resolve a FIPS endpoint for
    231 	// services.
    232 	//
    233 	// AWS_USE_FIPS_ENDPOINT=true
    234 	UseFIPSEndpoint aws.FIPSEndpointState
    235 
    236 	// Specifies the SDK Defaults Mode used by services.
    237 	//
    238 	// AWS_DEFAULTS_MODE=standard
    239 	DefaultsMode aws.DefaultsMode
    240 
    241 	// Specifies the maximum number attempts an API client will call an
    242 	// operation that fails with a retryable error.
    243 	//
    244 	// AWS_MAX_ATTEMPTS=3
    245 	RetryMaxAttempts int
    246 
    247 	// Specifies the retry model the API client will be created with.
    248 	//
    249 	// aws_retry_mode=standard
    250 	RetryMode aws.RetryMode
    251 }
    252 
    253 // loadEnvConfig reads configuration values from the OS's environment variables.
    254 // Returning the a Config typed EnvConfig to satisfy the ConfigLoader func type.
    255 func loadEnvConfig(ctx context.Context, cfgs configs) (Config, error) {
    256 	return NewEnvConfig()
    257 }
    258 
    259 // NewEnvConfig retrieves the SDK's environment configuration.
    260 // See `EnvConfig` for the values that will be retrieved.
    261 func NewEnvConfig() (EnvConfig, error) {
    262 	var cfg EnvConfig
    263 
    264 	creds := aws.Credentials{
    265 		Source: CredentialsSourceName,
    266 	}
    267 	setStringFromEnvVal(&creds.AccessKeyID, credAccessEnvKeys)
    268 	setStringFromEnvVal(&creds.SecretAccessKey, credSecretEnvKeys)
    269 	if creds.HasKeys() {
    270 		creds.SessionToken = os.Getenv(awsSessionTokenEnvVar)
    271 		cfg.Credentials = creds
    272 	}
    273 
    274 	cfg.ContainerCredentialsEndpoint = os.Getenv(awsContainerCredentialsEndpointEnvVar)
    275 	cfg.ContainerCredentialsRelativePath = os.Getenv(awsContainerCredentialsRelativePathEnvVar)
    276 	cfg.ContainerAuthorizationToken = os.Getenv(awsContainerPProviderAuthorizationEnvVar)
    277 
    278 	setStringFromEnvVal(&cfg.Region, regionEnvKeys)
    279 	setStringFromEnvVal(&cfg.SharedConfigProfile, profileEnvKeys)
    280 
    281 	cfg.SharedCredentialsFile = os.Getenv(awsSharedCredentialsFileEnvVar)
    282 	cfg.SharedConfigFile = os.Getenv(awsConfigFileEnvVar)
    283 
    284 	cfg.CustomCABundle = os.Getenv(awsCustomCABundleEnvVar)
    285 
    286 	cfg.WebIdentityTokenFilePath = os.Getenv(awsWebIdentityTokenFilePathEnvVar)
    287 
    288 	cfg.RoleARN = os.Getenv(awsRoleARNEnvVar)
    289 	cfg.RoleSessionName = os.Getenv(awsRoleSessionNameEnvVar)
    290 
    291 	if err := setEndpointDiscoveryTypeFromEnvVal(&cfg.EnableEndpointDiscovery, []string{awsEnableEndpointDiscoveryEnvVar}); err != nil {
    292 		return cfg, err
    293 	}
    294 
    295 	if err := setBoolPtrFromEnvVal(&cfg.S3UseARNRegion, []string{awsS3UseARNRegionEnvVar}); err != nil {
    296 		return cfg, err
    297 	}
    298 
    299 	setEC2IMDSClientEnableState(&cfg.EC2IMDSClientEnableState, []string{awsEc2MetadataDisabled})
    300 	if err := setEC2IMDSEndpointMode(&cfg.EC2IMDSEndpointMode, []string{awsEc2MetadataServiceEndpointModeEnvVar}); err != nil {
    301 		return cfg, err
    302 	}
    303 	cfg.EC2IMDSEndpoint = os.Getenv(awsEc2MetadataServiceEndpointEnvVar)
    304 
    305 	if err := setBoolPtrFromEnvVal(&cfg.S3DisableMultiRegionAccessPoints, []string{awsS3DisableMultiRegionAccessPointEnvVar}); err != nil {
    306 		return cfg, err
    307 	}
    308 
    309 	if err := setUseDualStackEndpointFromEnvVal(&cfg.UseDualStackEndpoint, []string{awsUseDualStackEndpoint}); err != nil {
    310 		return cfg, err
    311 	}
    312 
    313 	if err := setUseFIPSEndpointFromEnvVal(&cfg.UseFIPSEndpoint, []string{awsUseFIPSEndpoint}); err != nil {
    314 		return cfg, err
    315 	}
    316 
    317 	if err := setDefaultsModeFromEnvVal(&cfg.DefaultsMode, []string{awsDefaultMode}); err != nil {
    318 		return cfg, err
    319 	}
    320 
    321 	if err := setIntFromEnvVal(&cfg.RetryMaxAttempts, []string{awsRetryMaxAttempts}); err != nil {
    322 		return cfg, err
    323 	}
    324 	if err := setRetryModeFromEnvVal(&cfg.RetryMode, []string{awsRetryMode}); err != nil {
    325 		return cfg, err
    326 	}
    327 
    328 	return cfg, nil
    329 }
    330 
    331 func (c EnvConfig) getDefaultsMode(ctx context.Context) (aws.DefaultsMode, bool, error) {
    332 	if len(c.DefaultsMode) == 0 {
    333 		return "", false, nil
    334 	}
    335 	return c.DefaultsMode, true, nil
    336 }
    337 
    338 // GetRetryMaxAttempts returns the value of AWS_MAX_ATTEMPTS if was specified,
    339 // and not 0.
    340 func (c EnvConfig) GetRetryMaxAttempts(ctx context.Context) (int, bool, error) {
    341 	if c.RetryMaxAttempts == 0 {
    342 		return 0, false, nil
    343 	}
    344 	return c.RetryMaxAttempts, true, nil
    345 }
    346 
    347 // GetRetryMode returns the RetryMode of AWS_RETRY_MODE if was specified, and a
    348 // valid value.
    349 func (c EnvConfig) GetRetryMode(ctx context.Context) (aws.RetryMode, bool, error) {
    350 	if len(c.RetryMode) == 0 {
    351 		return "", false, nil
    352 	}
    353 	return c.RetryMode, true, nil
    354 }
    355 
    356 func setEC2IMDSClientEnableState(state *imds.ClientEnableState, keys []string) {
    357 	for _, k := range keys {
    358 		value := os.Getenv(k)
    359 		if len(value) == 0 {
    360 			continue
    361 		}
    362 		switch {
    363 		case strings.EqualFold(value, "true"):
    364 			*state = imds.ClientDisabled
    365 		case strings.EqualFold(value, "false"):
    366 			*state = imds.ClientEnabled
    367 		default:
    368 			continue
    369 		}
    370 		break
    371 	}
    372 }
    373 
    374 func setDefaultsModeFromEnvVal(mode *aws.DefaultsMode, keys []string) error {
    375 	for _, k := range keys {
    376 		if value := os.Getenv(k); len(value) > 0 {
    377 			if ok := mode.SetFromString(value); !ok {
    378 				return fmt.Errorf("invalid %s value: %s", k, value)
    379 			}
    380 			break
    381 		}
    382 	}
    383 	return nil
    384 }
    385 
    386 func setRetryModeFromEnvVal(mode *aws.RetryMode, keys []string) (err error) {
    387 	for _, k := range keys {
    388 		if value := os.Getenv(k); len(value) > 0 {
    389 			*mode, err = aws.ParseRetryMode(value)
    390 			if err != nil {
    391 				return fmt.Errorf("invalid %s value, %w", k, err)
    392 			}
    393 			break
    394 		}
    395 	}
    396 	return nil
    397 }
    398 
    399 func setEC2IMDSEndpointMode(mode *imds.EndpointModeState, keys []string) error {
    400 	for _, k := range keys {
    401 		value := os.Getenv(k)
    402 		if len(value) == 0 {
    403 			continue
    404 		}
    405 		if err := mode.SetFromString(value); err != nil {
    406 			return fmt.Errorf("invalid value for environment variable, %s=%s, %v", k, value, err)
    407 		}
    408 	}
    409 	return nil
    410 }
    411 
    412 // GetRegion returns the AWS Region if set in the environment. Returns an empty
    413 // string if not set.
    414 func (c EnvConfig) getRegion(ctx context.Context) (string, bool, error) {
    415 	if len(c.Region) == 0 {
    416 		return "", false, nil
    417 	}
    418 	return c.Region, true, nil
    419 }
    420 
    421 // GetSharedConfigProfile returns the shared config profile if set in the
    422 // environment. Returns an empty string if not set.
    423 func (c EnvConfig) getSharedConfigProfile(ctx context.Context) (string, bool, error) {
    424 	if len(c.SharedConfigProfile) == 0 {
    425 		return "", false, nil
    426 	}
    427 
    428 	return c.SharedConfigProfile, true, nil
    429 }
    430 
    431 // getSharedConfigFiles returns a slice of filenames set in the environment.
    432 //
    433 // Will return the filenames in the order of:
    434 // * Shared Config
    435 func (c EnvConfig) getSharedConfigFiles(context.Context) ([]string, bool, error) {
    436 	var files []string
    437 	if v := c.SharedConfigFile; len(v) > 0 {
    438 		files = append(files, v)
    439 	}
    440 
    441 	if len(files) == 0 {
    442 		return nil, false, nil
    443 	}
    444 	return files, true, nil
    445 }
    446 
    447 // getSharedCredentialsFiles returns a slice of filenames set in the environment.
    448 //
    449 // Will return the filenames in the order of:
    450 // * Shared Credentials
    451 func (c EnvConfig) getSharedCredentialsFiles(context.Context) ([]string, bool, error) {
    452 	var files []string
    453 	if v := c.SharedCredentialsFile; len(v) > 0 {
    454 		files = append(files, v)
    455 	}
    456 	if len(files) == 0 {
    457 		return nil, false, nil
    458 	}
    459 	return files, true, nil
    460 }
    461 
    462 // GetCustomCABundle returns the custom CA bundle's PEM bytes if the file was
    463 func (c EnvConfig) getCustomCABundle(context.Context) (io.Reader, bool, error) {
    464 	if len(c.CustomCABundle) == 0 {
    465 		return nil, false, nil
    466 	}
    467 
    468 	b, err := ioutil.ReadFile(c.CustomCABundle)
    469 	if err != nil {
    470 		return nil, false, err
    471 	}
    472 	return bytes.NewReader(b), true, nil
    473 }
    474 
    475 // GetS3UseARNRegion returns whether to allow ARNs to direct the region
    476 // the S3 client's requests are sent to.
    477 func (c EnvConfig) GetS3UseARNRegion(ctx context.Context) (value, ok bool, err error) {
    478 	if c.S3UseARNRegion == nil {
    479 		return false, false, nil
    480 	}
    481 
    482 	return *c.S3UseARNRegion, true, nil
    483 }
    484 
    485 // GetS3DisableMultRegionAccessPoints returns whether to disable multi-region access point
    486 // support for the S3 client.
    487 func (c EnvConfig) GetS3DisableMultRegionAccessPoints(ctx context.Context) (value, ok bool, err error) {
    488 	if c.S3DisableMultiRegionAccessPoints == nil {
    489 		return false, false, nil
    490 	}
    491 
    492 	return *c.S3DisableMultiRegionAccessPoints, true, nil
    493 }
    494 
    495 // GetUseDualStackEndpoint returns whether the service's dual-stack endpoint should be
    496 // used for requests.
    497 func (c EnvConfig) GetUseDualStackEndpoint(ctx context.Context) (value aws.DualStackEndpointState, found bool, err error) {
    498 	if c.UseDualStackEndpoint == aws.DualStackEndpointStateUnset {
    499 		return aws.DualStackEndpointStateUnset, false, nil
    500 	}
    501 
    502 	return c.UseDualStackEndpoint, true, nil
    503 }
    504 
    505 // GetUseFIPSEndpoint returns whether the service's FIPS endpoint should be
    506 // used for requests.
    507 func (c EnvConfig) GetUseFIPSEndpoint(ctx context.Context) (value aws.FIPSEndpointState, found bool, err error) {
    508 	if c.UseFIPSEndpoint == aws.FIPSEndpointStateUnset {
    509 		return aws.FIPSEndpointStateUnset, false, nil
    510 	}
    511 
    512 	return c.UseFIPSEndpoint, true, nil
    513 }
    514 
    515 func setStringFromEnvVal(dst *string, keys []string) {
    516 	for _, k := range keys {
    517 		if v := os.Getenv(k); len(v) > 0 {
    518 			*dst = v
    519 			break
    520 		}
    521 	}
    522 }
    523 
    524 func setIntFromEnvVal(dst *int, keys []string) error {
    525 	for _, k := range keys {
    526 		if v := os.Getenv(k); len(v) > 0 {
    527 			i, err := strconv.ParseInt(v, 10, 64)
    528 			if err != nil {
    529 				return fmt.Errorf("invalid value %s=%s, %w", k, v, err)
    530 			}
    531 			*dst = int(i)
    532 			break
    533 		}
    534 	}
    535 
    536 	return nil
    537 }
    538 
    539 func setBoolPtrFromEnvVal(dst **bool, keys []string) error {
    540 	for _, k := range keys {
    541 		value := os.Getenv(k)
    542 		if len(value) == 0 {
    543 			continue
    544 		}
    545 
    546 		if *dst == nil {
    547 			*dst = new(bool)
    548 		}
    549 
    550 		switch {
    551 		case strings.EqualFold(value, "false"):
    552 			**dst = false
    553 		case strings.EqualFold(value, "true"):
    554 			**dst = true
    555 		default:
    556 			return fmt.Errorf(
    557 				"invalid value for environment variable, %s=%s, need true or false",
    558 				k, value)
    559 		}
    560 		break
    561 	}
    562 
    563 	return nil
    564 }
    565 
    566 func setEndpointDiscoveryTypeFromEnvVal(dst *aws.EndpointDiscoveryEnableState, keys []string) error {
    567 	for _, k := range keys {
    568 		value := os.Getenv(k)
    569 		if len(value) == 0 {
    570 			continue // skip if empty
    571 		}
    572 
    573 		switch {
    574 		case strings.EqualFold(value, endpointDiscoveryDisabled):
    575 			*dst = aws.EndpointDiscoveryDisabled
    576 		case strings.EqualFold(value, endpointDiscoveryEnabled):
    577 			*dst = aws.EndpointDiscoveryEnabled
    578 		case strings.EqualFold(value, endpointDiscoveryAuto):
    579 			*dst = aws.EndpointDiscoveryAuto
    580 		default:
    581 			return fmt.Errorf(
    582 				"invalid value for environment variable, %s=%s, need true, false or auto",
    583 				k, value)
    584 		}
    585 	}
    586 	return nil
    587 }
    588 
    589 func setUseDualStackEndpointFromEnvVal(dst *aws.DualStackEndpointState, keys []string) error {
    590 	for _, k := range keys {
    591 		value := os.Getenv(k)
    592 		if len(value) == 0 {
    593 			continue // skip if empty
    594 		}
    595 
    596 		switch {
    597 		case strings.EqualFold(value, "true"):
    598 			*dst = aws.DualStackEndpointStateEnabled
    599 		case strings.EqualFold(value, "false"):
    600 			*dst = aws.DualStackEndpointStateDisabled
    601 		default:
    602 			return fmt.Errorf(
    603 				"invalid value for environment variable, %s=%s, need true, false",
    604 				k, value)
    605 		}
    606 	}
    607 	return nil
    608 }
    609 
    610 func setUseFIPSEndpointFromEnvVal(dst *aws.FIPSEndpointState, keys []string) error {
    611 	for _, k := range keys {
    612 		value := os.Getenv(k)
    613 		if len(value) == 0 {
    614 			continue // skip if empty
    615 		}
    616 
    617 		switch {
    618 		case strings.EqualFold(value, "true"):
    619 			*dst = aws.FIPSEndpointStateEnabled
    620 		case strings.EqualFold(value, "false"):
    621 			*dst = aws.FIPSEndpointStateDisabled
    622 		default:
    623 			return fmt.Errorf(
    624 				"invalid value for environment variable, %s=%s, need true, false",
    625 				k, value)
    626 		}
    627 	}
    628 	return nil
    629 }
    630 
    631 // GetEnableEndpointDiscovery returns resolved value for EnableEndpointDiscovery env variable setting.
    632 func (c EnvConfig) GetEnableEndpointDiscovery(ctx context.Context) (value aws.EndpointDiscoveryEnableState, found bool, err error) {
    633 	if c.EnableEndpointDiscovery == aws.EndpointDiscoveryUnset {
    634 		return aws.EndpointDiscoveryUnset, false, nil
    635 	}
    636 
    637 	return c.EnableEndpointDiscovery, true, nil
    638 }
    639 
    640 // GetEC2IMDSClientEnableState implements a EC2IMDSClientEnableState options resolver interface.
    641 func (c EnvConfig) GetEC2IMDSClientEnableState() (imds.ClientEnableState, bool, error) {
    642 	if c.EC2IMDSClientEnableState == imds.ClientDefaultEnableState {
    643 		return imds.ClientDefaultEnableState, false, nil
    644 	}
    645 
    646 	return c.EC2IMDSClientEnableState, true, nil
    647 }
    648 
    649 // GetEC2IMDSEndpointMode implements a EC2IMDSEndpointMode option resolver interface.
    650 func (c EnvConfig) GetEC2IMDSEndpointMode() (imds.EndpointModeState, bool, error) {
    651 	if c.EC2IMDSEndpointMode == imds.EndpointModeStateUnset {
    652 		return imds.EndpointModeStateUnset, false, nil
    653 	}
    654 
    655 	return c.EC2IMDSEndpointMode, true, nil
    656 }
    657 
    658 // GetEC2IMDSEndpoint implements a EC2IMDSEndpoint option resolver interface.
    659 func (c EnvConfig) GetEC2IMDSEndpoint() (string, bool, error) {
    660 	if len(c.EC2IMDSEndpoint) == 0 {
    661 		return "", false, nil
    662 	}
    663 
    664 	return c.EC2IMDSEndpoint, true, nil
    665 }