1package session
2
3import (
4	"os"
5	"strconv"
6
7	"github.com/aws/aws-sdk-go/aws/credentials"
8)
9
10// EnvProviderName provides a name of the provider when config is loaded from environment.
11const EnvProviderName = "EnvConfigCredentials"
12
13// envConfig is a collection of environment values the SDK will read
14// setup config from. All environment values are optional. But some values
15// such as credentials require multiple values to be complete or the values
16// will be ignored.
17type envConfig struct {
18	// Environment configuration values. If set both Access Key ID and Secret Access
19	// Key must be provided. Session Token and optionally also be provided, but is
20	// not required.
21	//
22	//	# Access Key ID
23	//	AWS_ACCESS_KEY_ID=AKID
24	//	AWS_ACCESS_KEY=AKID # only read if AWS_ACCESS_KEY_ID is not set.
25	//
26	//	# Secret Access Key
27	//	AWS_SECRET_ACCESS_KEY=SECRET
28	//	AWS_SECRET_KEY=SECRET=SECRET # only read if AWS_SECRET_ACCESS_KEY is not set.
29	//
30	//	# Session Token
31	//	AWS_SESSION_TOKEN=TOKEN
32	Creds credentials.Value
33
34	// Region value will instruct the SDK where to make service API requests to. If is
35	// not provided in the environment the region must be provided before a service
36	// client request is made.
37	//
38	//	AWS_REGION=us-east-1
39	//
40	//	# AWS_DEFAULT_REGION is only read if AWS_SDK_LOAD_CONFIG is also set,
41	//	# and AWS_REGION is not also set.
42	//	AWS_DEFAULT_REGION=us-east-1
43	Region string
44
45	// Profile name the SDK should load use when loading shared configuration from the
46	// shared configuration files. If not provided "default" will be used as the
47	// profile name.
48	//
49	//	AWS_PROFILE=my_profile
50	//
51	//	# AWS_DEFAULT_PROFILE is only read if AWS_SDK_LOAD_CONFIG is also set,
52	//	# and AWS_PROFILE is not also set.
53	//	AWS_DEFAULT_PROFILE=my_profile
54	Profile string
55
56	// SDK load config instructs the SDK to load the shared config in addition to
57	// shared credentials. This also expands the configuration loaded from the shared
58	// credentials to have parity with the shared config file. This also enables
59	// Region and Profile support for the AWS_DEFAULT_REGION and AWS_DEFAULT_PROFILE
60	// env values as well.
61	//
62	//	AWS_SDK_LOAD_CONFIG=1
63	EnableSharedConfig bool
64
65	// Shared credentials file path can be set to instruct the SDK to use an alternate
66	// file for the shared credentials. If not set the file will be loaded from
67	// $HOME/.aws/credentials on Linux/Unix based systems, and
68	// %USERPROFILE%\.aws\credentials on Windows.
69	//
70	//	AWS_SHARED_CREDENTIALS_FILE=$HOME/my_shared_credentials
71	SharedCredentialsFile string
72
73	// Shared config file path can be set to instruct the SDK to use an alternate
74	// file for the shared config. If not set the file will be loaded from
75	// $HOME/.aws/config on Linux/Unix based systems, and
76	// %USERPROFILE%\.aws\config on Windows.
77	//
78	//	AWS_CONFIG_FILE=$HOME/my_shared_config
79	SharedConfigFile string
80
81	// Sets the path to a custom Credentials Authroity (CA) Bundle PEM file
82	// that the SDK will use instead of the system's root CA bundle.
83	// Only use this if you want to configure the SDK to use a custom set
84	// of CAs.
85	//
86	// Enabling this option will attempt to merge the Transport
87	// into the SDK's HTTP client. If the client's Transport is
88	// not a http.Transport an error will be returned. If the
89	// Transport's TLS config is set this option will cause the
90	// SDK to overwrite the Transport's TLS config's  RootCAs value.
91	//
92	// Setting a custom HTTPClient in the aws.Config options will override this setting.
93	// To use this option and custom HTTP client, the HTTP client needs to be provided
94	// when creating the session. Not the service client.
95	//
96	//  AWS_CA_BUNDLE=$HOME/my_custom_ca_bundle
97	CustomCABundle string
98}
99
100var (
101	credAccessEnvKey = []string{
102		"AWS_ACCESS_KEY_ID",
103		"AWS_ACCESS_KEY",
104	}
105	credSecretEnvKey = []string{
106		"AWS_SECRET_ACCESS_KEY",
107		"AWS_SECRET_KEY",
108	}
109	credSessionEnvKey = []string{
110		"AWS_SESSION_TOKEN",
111	}
112
113	regionEnvKeys = []string{
114		"AWS_REGION",
115		"AWS_DEFAULT_REGION", // Only read if AWS_SDK_LOAD_CONFIG is also set
116	}
117	profileEnvKeys = []string{
118		"AWS_PROFILE",
119		"AWS_DEFAULT_PROFILE", // Only read if AWS_SDK_LOAD_CONFIG is also set
120	}
121	sharedCredsFileEnvKey = []string{
122		"AWS_SHARED_CREDENTIALS_FILE",
123	}
124	sharedConfigFileEnvKey = []string{
125		"AWS_CONFIG_FILE",
126	}
127)
128
129// loadEnvConfig retrieves the SDK's environment configuration.
130// See `envConfig` for the values that will be retrieved.
131//
132// If the environment variable `AWS_SDK_LOAD_CONFIG` is set to a truthy value
133// the shared SDK config will be loaded in addition to the SDK's specific
134// configuration values.
135func loadEnvConfig() envConfig {
136	enableSharedConfig, _ := strconv.ParseBool(os.Getenv("AWS_SDK_LOAD_CONFIG"))
137	return envConfigLoad(enableSharedConfig)
138}
139
140// loadEnvSharedConfig retrieves the SDK's environment configuration, and the
141// SDK shared config. See `envConfig` for the values that will be retrieved.
142//
143// Loads the shared configuration in addition to the SDK's specific configuration.
144// This will load the same values as `loadEnvConfig` if the `AWS_SDK_LOAD_CONFIG`
145// environment variable is set.
146func loadSharedEnvConfig() envConfig {
147	return envConfigLoad(true)
148}
149
150func envConfigLoad(enableSharedConfig bool) envConfig {
151	cfg := envConfig{}
152
153	cfg.EnableSharedConfig = enableSharedConfig
154
155	setFromEnvVal(&cfg.Creds.AccessKeyID, credAccessEnvKey)
156	setFromEnvVal(&cfg.Creds.SecretAccessKey, credSecretEnvKey)
157	setFromEnvVal(&cfg.Creds.SessionToken, credSessionEnvKey)
158
159	// Require logical grouping of credentials
160	if len(cfg.Creds.AccessKeyID) == 0 || len(cfg.Creds.SecretAccessKey) == 0 {
161		cfg.Creds = credentials.Value{}
162	} else {
163		cfg.Creds.ProviderName = EnvProviderName
164	}
165
166	regionKeys := regionEnvKeys
167	profileKeys := profileEnvKeys
168	if !cfg.EnableSharedConfig {
169		regionKeys = regionKeys[:1]
170		profileKeys = profileKeys[:1]
171	}
172
173	setFromEnvVal(&cfg.Region, regionKeys)
174	setFromEnvVal(&cfg.Profile, profileKeys)
175
176	setFromEnvVal(&cfg.SharedCredentialsFile, sharedCredsFileEnvKey)
177	setFromEnvVal(&cfg.SharedConfigFile, sharedConfigFileEnvKey)
178
179	cfg.CustomCABundle = os.Getenv("AWS_CA_BUNDLE")
180
181	return cfg
182}
183
184func setFromEnvVal(dst *string, keys []string) {
185	for _, k := range keys {
186		if v := os.Getenv(k); len(v) > 0 {
187			*dst = v
188			break
189		}
190	}
191}
192