github.com/aavshr/aws-sdk-go@v1.41.3/aws/session/env_config.go (about)

     1  package session
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"strconv"
     7  	"strings"
     8  
     9  	"github.com/aavshr/aws-sdk-go/aws"
    10  	"github.com/aavshr/aws-sdk-go/aws/credentials"
    11  	"github.com/aavshr/aws-sdk-go/aws/defaults"
    12  	"github.com/aavshr/aws-sdk-go/aws/endpoints"
    13  )
    14  
    15  // EnvProviderName provides a name of the provider when config is loaded from environment.
    16  const EnvProviderName = "EnvConfigCredentials"
    17  
    18  // envConfig is a collection of environment values the SDK will read
    19  // setup config from. All environment values are optional. But some values
    20  // such as credentials require multiple values to be complete or the values
    21  // will be ignored.
    22  type envConfig struct {
    23  	// Environment configuration values. If set both Access Key ID and Secret Access
    24  	// Key must be provided. Session Token and optionally also be provided, but is
    25  	// not required.
    26  	//
    27  	//	# Access Key ID
    28  	//	AWS_ACCESS_KEY_ID=AKID
    29  	//	AWS_ACCESS_KEY=AKID # only read if AWS_ACCESS_KEY_ID is not set.
    30  	//
    31  	//	# Secret Access Key
    32  	//	AWS_SECRET_ACCESS_KEY=SECRET
    33  	//	AWS_SECRET_KEY=SECRET=SECRET # only read if AWS_SECRET_ACCESS_KEY is not set.
    34  	//
    35  	//	# Session Token
    36  	//	AWS_SESSION_TOKEN=TOKEN
    37  	Creds credentials.Value
    38  
    39  	// Region value will instruct the SDK where to make service API requests to. If is
    40  	// not provided in the environment the region must be provided before a service
    41  	// client request is made.
    42  	//
    43  	//	AWS_REGION=us-east-1
    44  	//
    45  	//	# AWS_DEFAULT_REGION is only read if AWS_SDK_LOAD_CONFIG is also set,
    46  	//	# and AWS_REGION is not also set.
    47  	//	AWS_DEFAULT_REGION=us-east-1
    48  	Region string
    49  
    50  	// Profile name the SDK should load use when loading shared configuration from the
    51  	// shared configuration files. If not provided "default" will be used as the
    52  	// profile name.
    53  	//
    54  	//	AWS_PROFILE=my_profile
    55  	//
    56  	//	# AWS_DEFAULT_PROFILE is only read if AWS_SDK_LOAD_CONFIG is also set,
    57  	//	# and AWS_PROFILE is not also set.
    58  	//	AWS_DEFAULT_PROFILE=my_profile
    59  	Profile string
    60  
    61  	// SDK load config instructs the SDK to load the shared config in addition to
    62  	// shared credentials. This also expands the configuration loaded from the shared
    63  	// credentials to have parity with the shared config file. This also enables
    64  	// Region and Profile support for the AWS_DEFAULT_REGION and AWS_DEFAULT_PROFILE
    65  	// env values as well.
    66  	//
    67  	//	AWS_SDK_LOAD_CONFIG=1
    68  	EnableSharedConfig bool
    69  
    70  	// Shared credentials file path can be set to instruct the SDK to use an alternate
    71  	// file for the shared credentials. If not set the file will be loaded from
    72  	// $HOME/.aws/credentials on Linux/Unix based systems, and
    73  	// %USERPROFILE%\.aws\credentials on Windows.
    74  	//
    75  	//	AWS_SHARED_CREDENTIALS_FILE=$HOME/my_shared_credentials
    76  	SharedCredentialsFile string
    77  
    78  	// Shared config file path can be set to instruct the SDK to use an alternate
    79  	// file for the shared config. If not set the file will be loaded from
    80  	// $HOME/.aws/config on Linux/Unix based systems, and
    81  	// %USERPROFILE%\.aws\config on Windows.
    82  	//
    83  	//	AWS_CONFIG_FILE=$HOME/my_shared_config
    84  	SharedConfigFile string
    85  
    86  	// Sets the path to a custom Credentials Authority (CA) Bundle PEM file
    87  	// that the SDK will use instead of the system's root CA bundle.
    88  	// Only use this if you want to configure the SDK to use a custom set
    89  	// of CAs.
    90  	//
    91  	// Enabling this option will attempt to merge the Transport
    92  	// into the SDK's HTTP client. If the client's Transport is
    93  	// not a http.Transport an error will be returned. If the
    94  	// Transport's TLS config is set this option will cause the
    95  	// SDK to overwrite the Transport's TLS config's  RootCAs value.
    96  	//
    97  	// Setting a custom HTTPClient in the aws.Config options will override this setting.
    98  	// To use this option and custom HTTP client, the HTTP client needs to be provided
    99  	// when creating the session. Not the service client.
   100  	//
   101  	//  AWS_CA_BUNDLE=$HOME/my_custom_ca_bundle
   102  	CustomCABundle string
   103  
   104  	// Sets the TLC client certificate that should be used by the SDK's HTTP transport
   105  	// when making requests. The certificate must be paired with a TLS client key file.
   106  	//
   107  	//  AWS_SDK_GO_CLIENT_TLS_CERT=$HOME/my_client_cert
   108  	ClientTLSCert string
   109  
   110  	// Sets the TLC client key that should be used by the SDK's HTTP transport
   111  	// when making requests. The key must be paired with a TLS client certificate file.
   112  	//
   113  	//  AWS_SDK_GO_CLIENT_TLS_KEY=$HOME/my_client_key
   114  	ClientTLSKey string
   115  
   116  	csmEnabled  string
   117  	CSMEnabled  *bool
   118  	CSMPort     string
   119  	CSMHost     string
   120  	CSMClientID string
   121  
   122  	// Enables endpoint discovery via environment variables.
   123  	//
   124  	//	AWS_ENABLE_ENDPOINT_DISCOVERY=true
   125  	EnableEndpointDiscovery *bool
   126  	enableEndpointDiscovery string
   127  
   128  	// Specifies the WebIdentity token the SDK should use to assume a role
   129  	// with.
   130  	//
   131  	//  AWS_WEB_IDENTITY_TOKEN_FILE=file_path
   132  	WebIdentityTokenFilePath string
   133  
   134  	// Specifies the IAM role arn to use when assuming an role.
   135  	//
   136  	//  AWS_ROLE_ARN=role_arn
   137  	RoleARN string
   138  
   139  	// Specifies the IAM role session name to use when assuming a role.
   140  	//
   141  	//  AWS_ROLE_SESSION_NAME=session_name
   142  	RoleSessionName string
   143  
   144  	// Specifies the STS Regional Endpoint flag for the SDK to resolve the endpoint
   145  	// for a service.
   146  	//
   147  	// AWS_STS_REGIONAL_ENDPOINTS=regional
   148  	// This can take value as `regional` or `legacy`
   149  	STSRegionalEndpoint endpoints.STSRegionalEndpoint
   150  
   151  	// Specifies the S3 Regional Endpoint flag for the SDK to resolve the
   152  	// endpoint for a service.
   153  	//
   154  	// AWS_S3_US_EAST_1_REGIONAL_ENDPOINT=regional
   155  	// This can take value as `regional` or `legacy`
   156  	S3UsEast1RegionalEndpoint endpoints.S3UsEast1RegionalEndpoint
   157  
   158  	// Specifies if the S3 service should allow ARNs to direct the region
   159  	// the client's requests are sent to.
   160  	//
   161  	// AWS_S3_USE_ARN_REGION=true
   162  	S3UseARNRegion bool
   163  
   164  	// Specifies the EC2 Instance Metadata Service endpoint to use. If specified it overrides EC2IMDSEndpointMode.
   165  	//
   166  	// AWS_EC2_METADATA_SERVICE_ENDPOINT=http://[::1]
   167  	EC2IMDSEndpoint string
   168  
   169  	// Specifies the EC2 Instance Metadata Service default endpoint selection mode (IPv4 or IPv6)
   170  	//
   171  	// AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE=IPv6
   172  	EC2IMDSEndpointMode endpoints.EC2IMDSEndpointModeState
   173  }
   174  
   175  var (
   176  	csmEnabledEnvKey = []string{
   177  		"AWS_CSM_ENABLED",
   178  	}
   179  	csmHostEnvKey = []string{
   180  		"AWS_CSM_HOST",
   181  	}
   182  	csmPortEnvKey = []string{
   183  		"AWS_CSM_PORT",
   184  	}
   185  	csmClientIDEnvKey = []string{
   186  		"AWS_CSM_CLIENT_ID",
   187  	}
   188  	credAccessEnvKey = []string{
   189  		"AWS_ACCESS_KEY_ID",
   190  		"AWS_ACCESS_KEY",
   191  	}
   192  	credSecretEnvKey = []string{
   193  		"AWS_SECRET_ACCESS_KEY",
   194  		"AWS_SECRET_KEY",
   195  	}
   196  	credSessionEnvKey = []string{
   197  		"AWS_SESSION_TOKEN",
   198  	}
   199  
   200  	enableEndpointDiscoveryEnvKey = []string{
   201  		"AWS_ENABLE_ENDPOINT_DISCOVERY",
   202  	}
   203  
   204  	regionEnvKeys = []string{
   205  		"AWS_REGION",
   206  		"AWS_DEFAULT_REGION", // Only read if AWS_SDK_LOAD_CONFIG is also set
   207  	}
   208  	profileEnvKeys = []string{
   209  		"AWS_PROFILE",
   210  		"AWS_DEFAULT_PROFILE", // Only read if AWS_SDK_LOAD_CONFIG is also set
   211  	}
   212  	sharedCredsFileEnvKey = []string{
   213  		"AWS_SHARED_CREDENTIALS_FILE",
   214  	}
   215  	sharedConfigFileEnvKey = []string{
   216  		"AWS_CONFIG_FILE",
   217  	}
   218  	webIdentityTokenFilePathEnvKey = []string{
   219  		"AWS_WEB_IDENTITY_TOKEN_FILE",
   220  	}
   221  	roleARNEnvKey = []string{
   222  		"AWS_ROLE_ARN",
   223  	}
   224  	roleSessionNameEnvKey = []string{
   225  		"AWS_ROLE_SESSION_NAME",
   226  	}
   227  	stsRegionalEndpointKey = []string{
   228  		"AWS_STS_REGIONAL_ENDPOINTS",
   229  	}
   230  	s3UsEast1RegionalEndpoint = []string{
   231  		"AWS_S3_US_EAST_1_REGIONAL_ENDPOINT",
   232  	}
   233  	s3UseARNRegionEnvKey = []string{
   234  		"AWS_S3_USE_ARN_REGION",
   235  	}
   236  	ec2IMDSEndpointEnvKey = []string{
   237  		"AWS_EC2_METADATA_SERVICE_ENDPOINT",
   238  	}
   239  	ec2IMDSEndpointModeEnvKey = []string{
   240  		"AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE",
   241  	}
   242  	useCABundleKey = []string{
   243  		"AWS_CA_BUNDLE",
   244  	}
   245  	useClientTLSCert = []string{
   246  		"AWS_SDK_GO_CLIENT_TLS_CERT",
   247  	}
   248  	useClientTLSKey = []string{
   249  		"AWS_SDK_GO_CLIENT_TLS_KEY",
   250  	}
   251  )
   252  
   253  // loadEnvConfig retrieves the SDK's environment configuration.
   254  // See `envConfig` for the values that will be retrieved.
   255  //
   256  // If the environment variable `AWS_SDK_LOAD_CONFIG` is set to a truthy value
   257  // the shared SDK config will be loaded in addition to the SDK's specific
   258  // configuration values.
   259  func loadEnvConfig() (envConfig, error) {
   260  	enableSharedConfig, _ := strconv.ParseBool(os.Getenv("AWS_SDK_LOAD_CONFIG"))
   261  	return envConfigLoad(enableSharedConfig)
   262  }
   263  
   264  // loadEnvSharedConfig retrieves the SDK's environment configuration, and the
   265  // SDK shared config. See `envConfig` for the values that will be retrieved.
   266  //
   267  // Loads the shared configuration in addition to the SDK's specific configuration.
   268  // This will load the same values as `loadEnvConfig` if the `AWS_SDK_LOAD_CONFIG`
   269  // environment variable is set.
   270  func loadSharedEnvConfig() (envConfig, error) {
   271  	return envConfigLoad(true)
   272  }
   273  
   274  func envConfigLoad(enableSharedConfig bool) (envConfig, error) {
   275  	cfg := envConfig{}
   276  
   277  	cfg.EnableSharedConfig = enableSharedConfig
   278  
   279  	// Static environment credentials
   280  	var creds credentials.Value
   281  	setFromEnvVal(&creds.AccessKeyID, credAccessEnvKey)
   282  	setFromEnvVal(&creds.SecretAccessKey, credSecretEnvKey)
   283  	setFromEnvVal(&creds.SessionToken, credSessionEnvKey)
   284  	if creds.HasKeys() {
   285  		// Require logical grouping of credentials
   286  		creds.ProviderName = EnvProviderName
   287  		cfg.Creds = creds
   288  	}
   289  
   290  	// Role Metadata
   291  	setFromEnvVal(&cfg.RoleARN, roleARNEnvKey)
   292  	setFromEnvVal(&cfg.RoleSessionName, roleSessionNameEnvKey)
   293  
   294  	// Web identity environment variables
   295  	setFromEnvVal(&cfg.WebIdentityTokenFilePath, webIdentityTokenFilePathEnvKey)
   296  
   297  	// CSM environment variables
   298  	setFromEnvVal(&cfg.csmEnabled, csmEnabledEnvKey)
   299  	setFromEnvVal(&cfg.CSMHost, csmHostEnvKey)
   300  	setFromEnvVal(&cfg.CSMPort, csmPortEnvKey)
   301  	setFromEnvVal(&cfg.CSMClientID, csmClientIDEnvKey)
   302  
   303  	if len(cfg.csmEnabled) != 0 {
   304  		v, _ := strconv.ParseBool(cfg.csmEnabled)
   305  		cfg.CSMEnabled = &v
   306  	}
   307  
   308  	regionKeys := regionEnvKeys
   309  	profileKeys := profileEnvKeys
   310  	if !cfg.EnableSharedConfig {
   311  		regionKeys = regionKeys[:1]
   312  		profileKeys = profileKeys[:1]
   313  	}
   314  
   315  	setFromEnvVal(&cfg.Region, regionKeys)
   316  	setFromEnvVal(&cfg.Profile, profileKeys)
   317  
   318  	// endpoint discovery is in reference to it being enabled.
   319  	setFromEnvVal(&cfg.enableEndpointDiscovery, enableEndpointDiscoveryEnvKey)
   320  	if len(cfg.enableEndpointDiscovery) > 0 {
   321  		cfg.EnableEndpointDiscovery = aws.Bool(cfg.enableEndpointDiscovery != "false")
   322  	}
   323  
   324  	setFromEnvVal(&cfg.SharedCredentialsFile, sharedCredsFileEnvKey)
   325  	setFromEnvVal(&cfg.SharedConfigFile, sharedConfigFileEnvKey)
   326  
   327  	if len(cfg.SharedCredentialsFile) == 0 {
   328  		cfg.SharedCredentialsFile = defaults.SharedCredentialsFilename()
   329  	}
   330  	if len(cfg.SharedConfigFile) == 0 {
   331  		cfg.SharedConfigFile = defaults.SharedConfigFilename()
   332  	}
   333  
   334  	setFromEnvVal(&cfg.CustomCABundle, useCABundleKey)
   335  	setFromEnvVal(&cfg.ClientTLSCert, useClientTLSCert)
   336  	setFromEnvVal(&cfg.ClientTLSKey, useClientTLSKey)
   337  
   338  	var err error
   339  	// STS Regional Endpoint variable
   340  	for _, k := range stsRegionalEndpointKey {
   341  		if v := os.Getenv(k); len(v) != 0 {
   342  			cfg.STSRegionalEndpoint, err = endpoints.GetSTSRegionalEndpoint(v)
   343  			if err != nil {
   344  				return cfg, fmt.Errorf("failed to load, %v from env config, %v", k, err)
   345  			}
   346  		}
   347  	}
   348  
   349  	// S3 Regional Endpoint variable
   350  	for _, k := range s3UsEast1RegionalEndpoint {
   351  		if v := os.Getenv(k); len(v) != 0 {
   352  			cfg.S3UsEast1RegionalEndpoint, err = endpoints.GetS3UsEast1RegionalEndpoint(v)
   353  			if err != nil {
   354  				return cfg, fmt.Errorf("failed to load, %v from env config, %v", k, err)
   355  			}
   356  		}
   357  	}
   358  
   359  	var s3UseARNRegion string
   360  	setFromEnvVal(&s3UseARNRegion, s3UseARNRegionEnvKey)
   361  	if len(s3UseARNRegion) != 0 {
   362  		switch {
   363  		case strings.EqualFold(s3UseARNRegion, "false"):
   364  			cfg.S3UseARNRegion = false
   365  		case strings.EqualFold(s3UseARNRegion, "true"):
   366  			cfg.S3UseARNRegion = true
   367  		default:
   368  			return envConfig{}, fmt.Errorf(
   369  				"invalid value for environment variable, %s=%s, need true or false",
   370  				s3UseARNRegionEnvKey[0], s3UseARNRegion)
   371  		}
   372  	}
   373  
   374  	setFromEnvVal(&cfg.EC2IMDSEndpoint, ec2IMDSEndpointEnvKey)
   375  	if err := setEC2IMDSEndpointMode(&cfg.EC2IMDSEndpointMode, ec2IMDSEndpointModeEnvKey); err != nil {
   376  		return envConfig{}, err
   377  	}
   378  
   379  	return cfg, nil
   380  }
   381  
   382  func setFromEnvVal(dst *string, keys []string) {
   383  	for _, k := range keys {
   384  		if v := os.Getenv(k); len(v) != 0 {
   385  			*dst = v
   386  			break
   387  		}
   388  	}
   389  }
   390  
   391  func setEC2IMDSEndpointMode(mode *endpoints.EC2IMDSEndpointModeState, keys []string) error {
   392  	for _, k := range keys {
   393  		value := os.Getenv(k)
   394  		if len(value) == 0 {
   395  			continue
   396  		}
   397  		if err := mode.SetFromString(value); err != nil {
   398  			return fmt.Errorf("invalid value for environment variable, %s=%s, %v", k, value, err)
   399  		}
   400  		return nil
   401  	}
   402  	return nil
   403  }