1 package config
2
3 import (
4 "os"
5 "reflect"
6 "strconv"
7 "testing"
8
9 "github.com/aws/aws-sdk-go-v2/aws"
10 "github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
11 "github.com/aws/aws-sdk-go-v2/internal/awstesting"
12 "github.com/aws/smithy-go/ptr"
13 )
14
15 var _ sharedConfigProfileProvider = (*EnvConfig)(nil)
16 var _ sharedConfigFilesProvider = (*EnvConfig)(nil)
17 var _ customCABundleProvider = (*EnvConfig)(nil)
18 var _ regionProvider = (*EnvConfig)(nil)
19
20 func TestNewEnvConfig_Creds(t *testing.T) {
21 restoreEnv := awstesting.StashEnv()
22 defer awstesting.PopEnv(restoreEnv)
23
24 cases := []struct {
25 Env map[string]string
26 Val aws.Credentials
27 }{
28 {
29 Env: map[string]string{
30 "AWS_ACCESS_KEY": "AKID",
31 },
32 Val: aws.Credentials{},
33 },
34 {
35 Env: map[string]string{
36 "AWS_ACCESS_KEY_ID": "AKID",
37 },
38 Val: aws.Credentials{},
39 },
40 {
41 Env: map[string]string{
42 "AWS_SECRET_KEY": "SECRET",
43 },
44 Val: aws.Credentials{},
45 },
46 {
47 Env: map[string]string{
48 "AWS_SECRET_ACCESS_KEY": "SECRET",
49 },
50 Val: aws.Credentials{},
51 },
52 {
53 Env: map[string]string{
54 "AWS_ACCESS_KEY_ID": "AKID",
55 "AWS_SECRET_ACCESS_KEY": "SECRET",
56 },
57 Val: aws.Credentials{
58 AccessKeyID: "AKID", SecretAccessKey: "SECRET",
59 Source: CredentialsSourceName,
60 },
61 },
62 {
63 Env: map[string]string{
64 "AWS_ACCESS_KEY": "AKID",
65 "AWS_SECRET_KEY": "SECRET",
66 },
67 Val: aws.Credentials{
68 AccessKeyID: "AKID", SecretAccessKey: "SECRET",
69 Source: CredentialsSourceName,
70 },
71 },
72 {
73 Env: map[string]string{
74 "AWS_ACCESS_KEY": "AKID",
75 "AWS_SECRET_KEY": "SECRET",
76 "AWS_SESSION_TOKEN": "TOKEN",
77 },
78 Val: aws.Credentials{
79 AccessKeyID: "AKID", SecretAccessKey: "SECRET", SessionToken: "TOKEN",
80 Source: CredentialsSourceName,
81 },
82 },
83 }
84
85 for i, c := range cases {
86 os.Clearenv()
87
88 for k, v := range c.Env {
89 os.Setenv(k, v)
90 }
91
92 cfg, err := NewEnvConfig()
93 if err != nil {
94 t.Fatalf("%d, expect no error, got %v", i, err)
95 }
96
97 if !reflect.DeepEqual(c.Val, cfg.Credentials) {
98 t.Errorf("%d, expect aws to match.\n%s", i,
99 awstesting.SprintExpectActual(c.Val, cfg.Credentials))
100 }
101 }
102 }
103
104 func TestNewEnvConfig(t *testing.T) {
105 restoreEnv := awstesting.StashEnv()
106 defer awstesting.PopEnv(restoreEnv)
107
108 cases := []struct {
109 Env map[string]string
110 Config EnvConfig
111 WantErr bool
112 }{
113 0: {
114 Env: map[string]string{
115 "AWS_REGION": "region",
116 "AWS_PROFILE": "profile",
117 },
118 Config: EnvConfig{
119 Region: "region", SharedConfigProfile: "profile",
120 },
121 },
122 1: {
123 Env: map[string]string{
124 "AWS_REGION": "region",
125 "AWS_DEFAULT_REGION": "default_region",
126 "AWS_PROFILE": "profile",
127 "AWS_DEFAULT_PROFILE": "default_profile",
128 },
129 Config: EnvConfig{
130 Region: "region", SharedConfigProfile: "profile",
131 },
132 },
133 2: {
134 Env: map[string]string{
135 "AWS_REGION": "region",
136 "AWS_DEFAULT_REGION": "default_region",
137 "AWS_PROFILE": "profile",
138 "AWS_DEFAULT_PROFILE": "default_profile",
139 },
140 Config: EnvConfig{
141 Region: "region", SharedConfigProfile: "profile",
142 },
143 },
144 3: {
145 Env: map[string]string{
146 "AWS_DEFAULT_REGION": "default_region",
147 "AWS_DEFAULT_PROFILE": "default_profile",
148 },
149 Config: EnvConfig{
150 Region: "default_region", SharedConfigProfile: "default_profile",
151 },
152 },
153 4: {
154 Env: map[string]string{
155 "AWS_REGION": "region",
156 "AWS_PROFILE": "profile",
157 },
158 Config: EnvConfig{
159 Region: "region", SharedConfigProfile: "profile",
160 },
161 },
162 5: {
163 Env: map[string]string{
164 "AWS_REGION": "region",
165 "AWS_DEFAULT_REGION": "default_region",
166 "AWS_PROFILE": "profile",
167 "AWS_DEFAULT_PROFILE": "default_profile",
168 },
169 Config: EnvConfig{
170 Region: "region", SharedConfigProfile: "profile",
171 },
172 },
173 6: {
174 Env: map[string]string{
175 "AWS_REGION": "region",
176 "AWS_DEFAULT_REGION": "default_region",
177 "AWS_PROFILE": "profile",
178 "AWS_DEFAULT_PROFILE": "default_profile",
179 },
180 Config: EnvConfig{
181 Region: "region", SharedConfigProfile: "profile",
182 },
183 },
184 7: {
185 Env: map[string]string{
186 "AWS_DEFAULT_REGION": "default_region",
187 "AWS_DEFAULT_PROFILE": "default_profile",
188 },
189 Config: EnvConfig{
190 Region: "default_region", SharedConfigProfile: "default_profile",
191 },
192 },
193 8: {
194 Env: map[string]string{
195 "AWS_CA_BUNDLE": "custom_ca_bundle",
196 },
197 Config: EnvConfig{
198 CustomCABundle: "custom_ca_bundle",
199 },
200 },
201 9: {
202 Env: map[string]string{
203 "AWS_CA_BUNDLE": "custom_ca_bundle",
204 },
205 Config: EnvConfig{
206 CustomCABundle: "custom_ca_bundle",
207 },
208 },
209 10: {
210 Env: map[string]string{
211 "AWS_SHARED_CREDENTIALS_FILE": "/path/to/aws/file",
212 "AWS_CONFIG_FILE": "/path/to/config/file",
213 },
214 Config: EnvConfig{
215 SharedCredentialsFile: "/path/to/aws/file",
216 SharedConfigFile: "/path/to/config/file",
217 },
218 },
219 11: {
220 Env: map[string]string{
221 "AWS_S3_USE_ARN_REGION": "true",
222 },
223 Config: EnvConfig{
224 S3UseARNRegion: ptr.Bool(true),
225 },
226 },
227 12: {
228 Env: map[string]string{
229 "AWS_ENABLE_ENDPOINT_DISCOVERY": "true",
230 },
231 Config: EnvConfig{
232 EnableEndpointDiscovery: aws.EndpointDiscoveryEnabled,
233 },
234 },
235 13: {
236 Env: map[string]string{
237 "AWS_ENABLE_ENDPOINT_DISCOVERY": "auto",
238 },
239 Config: EnvConfig{
240 EnableEndpointDiscovery: aws.EndpointDiscoveryAuto,
241 },
242 },
243 14: {
244 Env: map[string]string{
245 "AWS_ENABLE_ENDPOINT_DISCOVERY": "false",
246 },
247 Config: EnvConfig{
248 EnableEndpointDiscovery: aws.EndpointDiscoveryDisabled,
249 },
250 },
251 15: {
252 Env: map[string]string{},
253 Config: EnvConfig{},
254 },
255 16: {
256 Env: map[string]string{
257 "AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE": "IPv6",
258 },
259 Config: EnvConfig{
260 EC2IMDSEndpointMode: imds.EndpointModeStateIPv6,
261 },
262 },
263 17: {
264 Env: map[string]string{
265 "AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE": "IPv4",
266 },
267 Config: EnvConfig{
268 EC2IMDSEndpointMode: imds.EndpointModeStateIPv4,
269 },
270 },
271 18: {
272 Env: map[string]string{
273 "AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE": "foobar",
274 },
275 Config: EnvConfig{},
276 WantErr: true,
277 },
278 19: {
279 Env: map[string]string{
280 "AWS_EC2_METADATA_SERVICE_ENDPOINT": "http://endpoint.localhost",
281 },
282 Config: EnvConfig{
283 EC2IMDSEndpoint: "http://endpoint.localhost",
284 },
285 },
286 20: {
287 Env: map[string]string{
288 "AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE": "IPv6",
289 "AWS_EC2_METADATA_SERVICE_ENDPOINT": "http://endpoint.localhost",
290 },
291 Config: EnvConfig{
292 EC2IMDSEndpoint: "http://endpoint.localhost",
293 EC2IMDSEndpointMode: imds.EndpointModeStateIPv6,
294 },
295 },
296 21: {
297 Env: map[string]string{
298 "AWS_EC2_METADATA_DISABLED": "false",
299 },
300 Config: EnvConfig{
301 EC2IMDSClientEnableState: imds.ClientEnabled,
302 },
303 },
304 22: {
305 Env: map[string]string{
306 "AWS_EC2_METADATA_DISABLED": "true",
307 },
308 Config: EnvConfig{
309 EC2IMDSClientEnableState: imds.ClientDisabled,
310 },
311 },
312 23: {
313 Env: map[string]string{
314 "AWS_EC2_METADATA_DISABLED": "foobar",
315 },
316 Config: EnvConfig{},
317 },
318 24: {
319 Env: map[string]string{
320 "AWS_S3_DISABLE_MULTIREGION_ACCESS_POINTS": "true",
321 },
322 Config: EnvConfig{
323 S3DisableMultiRegionAccessPoints: ptr.Bool(true),
324 },
325 },
326 25: {
327 Env: map[string]string{
328 "AWS_USE_DUALSTACK_ENDPOINT": "true",
329 },
330 Config: EnvConfig{
331 UseDualStackEndpoint: aws.DualStackEndpointStateEnabled,
332 },
333 },
334 26: {
335 Env: map[string]string{
336 "AWS_USE_DUALSTACK_ENDPOINT": "false",
337 },
338 Config: EnvConfig{
339 UseDualStackEndpoint: aws.DualStackEndpointStateDisabled,
340 },
341 },
342 27: {
343 Env: map[string]string{
344 "AWS_USE_DUALSTACK_ENDPOINT": "invalid",
345 },
346 WantErr: true,
347 },
348 28: {
349 Env: map[string]string{
350 "AWS_USE_FIPS_ENDPOINT": "true",
351 },
352 Config: EnvConfig{
353 UseFIPSEndpoint: aws.FIPSEndpointStateEnabled,
354 },
355 },
356 29: {
357 Env: map[string]string{
358 "AWS_USE_FIPS_ENDPOINT": "false",
359 },
360 Config: EnvConfig{
361 UseFIPSEndpoint: aws.FIPSEndpointStateDisabled,
362 },
363 },
364 30: {
365 Env: map[string]string{
366 "AWS_USE_FIPS_ENDPOINT": "invalid",
367 },
368 WantErr: true,
369 },
370 31: {
371 Env: map[string]string{
372 "AWS_DEFAULTS_MODE": "auto",
373 },
374 Config: EnvConfig{
375 DefaultsMode: aws.DefaultsModeAuto,
376 },
377 },
378 32: {
379 Env: map[string]string{
380 "AWS_DEFAULTS_MODE": "standard",
381 },
382 Config: EnvConfig{
383 DefaultsMode: aws.DefaultsModeStandard,
384 },
385 },
386 33: {
387 Env: map[string]string{
388 "AWS_DEFAULTS_MODE": "invalid",
389 },
390 Config: EnvConfig{
391 DefaultsMode: aws.DefaultsMode("invalid"),
392 },
393 WantErr: true,
394 },
395 34: {
396 Env: map[string]string{
397 "AWS_MAX_ATTEMPTS": "2",
398 },
399 Config: EnvConfig{
400 RetryMaxAttempts: 2,
401 },
402 },
403 35: {
404 Env: map[string]string{
405 "AWS_MAX_ATTEMPTS": "invalid",
406 },
407 Config: EnvConfig{},
408 WantErr: true,
409 },
410 36: {
411 Env: map[string]string{
412 "AWS_RETRY_MODE": "adaptive",
413 },
414 Config: EnvConfig{
415 RetryMode: aws.RetryModeAdaptive,
416 },
417 },
418 37: {
419 Env: map[string]string{
420 "AWS_RETRY_MODE": "invalid",
421 },
422 Config: EnvConfig{},
423 WantErr: true,
424 },
425 38: {
426 Env: map[string]string{
427 "AWS_ENDPOINT_URL": "https://example.com",
428 },
429 Config: EnvConfig{
430 BaseEndpoint: "https://example.com",
431 },
432 },
433 39: {
434 Env: map[string]string{
435 "AWS_IGNORE_CONFIGURED_ENDPOINT_URLS": "true",
436 },
437 Config: EnvConfig{
438 IgnoreConfiguredEndpoints: ptr.Bool(true),
439 },
440 },
441 40: {
442 Env: map[string]string{
443 "AWS_EC2_METADATA_V1_DISABLED": "tRuE",
444 },
445 Config: EnvConfig{
446 EC2IMDSv1Disabled: aws.Bool(true),
447 },
448 },
449 41: {
450 Env: map[string]string{
451 "AWS_EC2_METADATA_V1_DISABLED": "invalid",
452 },
453 Config: EnvConfig{
454 EC2IMDSv1Disabled: aws.Bool(false),
455 },
456 WantErr: true,
457 },
458 42: {
459 Env: map[string]string{
460 "AWS_DISABLE_REQUEST_COMPRESSION": "true",
461 "AWS_REQUEST_MIN_COMPRESSION_SIZE_BYTES": "12345",
462 },
463 Config: EnvConfig{
464 DisableRequestCompression: aws.Bool(true),
465 RequestMinCompressSizeBytes: aws.Int64(12345),
466 },
467 },
468 43: {
469 Env: map[string]string{
470 "AWS_DISABLE_REQUEST_COMPRESSION": "blabla",
471 "AWS_REQUEST_MIN_COMPRESSION_SIZE_BYTES": "12345",
472 },
473 Config: EnvConfig{
474 DisableRequestCompression: aws.Bool(false),
475 },
476 WantErr: true,
477 },
478 44: {
479 Env: map[string]string{
480 "AWS_DISABLE_REQUEST_COMPRESSION": "true",
481 "AWS_REQUEST_MIN_COMPRESSION_SIZE_BYTES": "1.1",
482 },
483 Config: EnvConfig{
484 DisableRequestCompression: aws.Bool(true),
485 },
486 WantErr: true,
487 },
488
489 45: {
490 Env: map[string]string{
491 "AWS_DISABLE_REQUEST_COMPRESSION": "false",
492 "AWS_REQUEST_MIN_COMPRESSION_SIZE_BYTES": "10485761",
493 },
494 Config: EnvConfig{
495 DisableRequestCompression: aws.Bool(false),
496 },
497 WantErr: true,
498 },
499 }
500
501 for i, c := range cases {
502 t.Run(strconv.Itoa(i), func(t *testing.T) {
503 os.Clearenv()
504
505 for k, v := range c.Env {
506 os.Setenv(k, v)
507 }
508
509 cfg, err := NewEnvConfig()
510 if (err != nil) != c.WantErr {
511 t.Fatalf("WantErr=%v, got err=%v", c.WantErr, err)
512 }
513
514 if diff := cmpDiff(c.Config, cfg); len(diff) > 0 {
515 t.Errorf("expect config to match.\n%s",
516 diff)
517 }
518 })
519 }
520 }
521
522 func TestSetEnvValue(t *testing.T) {
523 restoreEnv := awstesting.StashEnv()
524 defer awstesting.PopEnv(restoreEnv)
525
526 os.Setenv("empty_key", "")
527 os.Setenv("second_key", "2")
528 os.Setenv("third_key", "3")
529
530 var dst string
531 setStringFromEnvVal(&dst, []string{
532 "empty_key", "first_key", "second_key", "third_key",
533 })
534
535 if e, a := "2", dst; e != a {
536 t.Errorf("expect %s value from environment, got %s", e, a)
537 }
538 }
539
View as plain text