1//go:build go1.7 2// +build go1.7 3 4package session 5 6import ( 7 "fmt" 8 "path/filepath" 9 "reflect" 10 "strconv" 11 "strings" 12 "testing" 13 14 "github.com/aws/aws-sdk-go/aws/credentials" 15 "github.com/aws/aws-sdk-go/aws/endpoints" 16 "github.com/aws/aws-sdk-go/internal/ini" 17) 18 19var ( 20 testConfigFilename = filepath.Join("testdata", "shared_config") 21 testConfigOtherFilename = filepath.Join("testdata", "shared_config_other") 22) 23 24func TestLoadSharedConfig(t *testing.T) { 25 cases := []struct { 26 Filenames []string 27 Profile string 28 Expected sharedConfig 29 Err error 30 }{ 31 { 32 Filenames: []string{"file_not_exists"}, 33 Profile: "default", 34 Expected: sharedConfig{ 35 Profile: "default", 36 }, 37 }, 38 { 39 Filenames: []string{testConfigFilename}, 40 Expected: sharedConfig{ 41 Profile: "default", 42 Region: "default_region", 43 }, 44 }, 45 { 46 Filenames: []string{testConfigOtherFilename, testConfigFilename}, 47 Profile: "config_file_load_order", 48 Expected: sharedConfig{ 49 Profile: "config_file_load_order", 50 Region: "shared_config_region", 51 Creds: credentials.Value{ 52 AccessKeyID: "shared_config_akid", 53 SecretAccessKey: "shared_config_secret", 54 ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", testConfigFilename), 55 }, 56 }, 57 }, 58 { 59 Filenames: []string{testConfigFilename, testConfigOtherFilename}, 60 Profile: "config_file_load_order", 61 Expected: sharedConfig{ 62 Profile: "config_file_load_order", 63 Region: "shared_config_other_region", 64 Creds: credentials.Value{ 65 AccessKeyID: "shared_config_other_akid", 66 SecretAccessKey: "shared_config_other_secret", 67 ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", testConfigOtherFilename), 68 }, 69 }, 70 }, 71 { 72 Filenames: []string{testConfigOtherFilename, testConfigFilename}, 73 Profile: "assume_role", 74 Expected: sharedConfig{ 75 Profile: "assume_role", 76 RoleARN: "assume_role_role_arn", 77 SourceProfileName: "complete_creds", 78 SourceProfile: &sharedConfig{ 79 Profile: "complete_creds", 80 Creds: credentials.Value{ 81 AccessKeyID: "complete_creds_akid", 82 SecretAccessKey: "complete_creds_secret", 83 ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", testConfigFilename), 84 }, 85 }, 86 }, 87 }, 88 { 89 Filenames: []string{testConfigOtherFilename, testConfigFilename}, 90 Profile: "assume_role_invalid_source_profile", 91 Expected: sharedConfig{ 92 Profile: "assume_role_invalid_source_profile", 93 RoleARN: "assume_role_invalid_source_profile_role_arn", 94 SourceProfileName: "profile_not_exists", 95 }, 96 Err: SharedConfigAssumeRoleError{ 97 RoleARN: "assume_role_invalid_source_profile_role_arn", 98 SourceProfile: "profile_not_exists", 99 }, 100 }, 101 { 102 Filenames: []string{testConfigOtherFilename, testConfigFilename}, 103 Profile: "assume_role_w_creds", 104 Expected: sharedConfig{ 105 Profile: "assume_role_w_creds", 106 RoleARN: "assume_role_w_creds_role_arn", 107 ExternalID: "1234", 108 RoleSessionName: "assume_role_w_creds_session_name", 109 SourceProfileName: "assume_role_w_creds", 110 SourceProfile: &sharedConfig{ 111 Profile: "assume_role_w_creds", 112 Creds: credentials.Value{ 113 AccessKeyID: "assume_role_w_creds_akid", 114 SecretAccessKey: "assume_role_w_creds_secret", 115 ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", testConfigFilename), 116 }, 117 }, 118 }, 119 }, 120 { 121 Filenames: []string{testConfigOtherFilename, testConfigFilename}, 122 Profile: "assume_role_wo_creds", 123 Expected: sharedConfig{ 124 Profile: "assume_role_wo_creds", 125 RoleARN: "assume_role_wo_creds_role_arn", 126 SourceProfileName: "assume_role_wo_creds", 127 }, 128 Err: SharedConfigAssumeRoleError{ 129 RoleARN: "assume_role_wo_creds_role_arn", 130 SourceProfile: "assume_role_wo_creds", 131 }, 132 }, 133 { 134 Filenames: []string{filepath.Join("testdata", "shared_config_invalid_ini")}, 135 Profile: "profile_name", 136 Err: SharedConfigLoadError{Filename: filepath.Join("testdata", "shared_config_invalid_ini")}, 137 }, 138 { 139 Filenames: []string{testConfigOtherFilename, testConfigFilename}, 140 Profile: "assume_role_with_credential_source", 141 Expected: sharedConfig{ 142 Profile: "assume_role_with_credential_source", 143 RoleARN: "assume_role_with_credential_source_role_arn", 144 CredentialSource: credSourceEc2Metadata, 145 }, 146 }, 147 { 148 Filenames: []string{testConfigOtherFilename, testConfigFilename}, 149 Profile: "multiple_assume_role", 150 Expected: sharedConfig{ 151 Profile: "multiple_assume_role", 152 RoleARN: "multiple_assume_role_role_arn", 153 SourceProfileName: "assume_role", 154 SourceProfile: &sharedConfig{ 155 Profile: "assume_role", 156 RoleARN: "assume_role_role_arn", 157 SourceProfileName: "complete_creds", 158 SourceProfile: &sharedConfig{ 159 Profile: "complete_creds", 160 Creds: credentials.Value{ 161 AccessKeyID: "complete_creds_akid", 162 SecretAccessKey: "complete_creds_secret", 163 ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", testConfigFilename), 164 }, 165 }, 166 }, 167 }, 168 }, 169 { 170 Filenames: []string{testConfigOtherFilename, testConfigFilename}, 171 Profile: "multiple_assume_role_with_credential_source", 172 Expected: sharedConfig{ 173 Profile: "multiple_assume_role_with_credential_source", 174 RoleARN: "multiple_assume_role_with_credential_source_role_arn", 175 SourceProfileName: "assume_role_with_credential_source", 176 SourceProfile: &sharedConfig{ 177 Profile: "assume_role_with_credential_source", 178 RoleARN: "assume_role_with_credential_source_role_arn", 179 CredentialSource: credSourceEc2Metadata, 180 }, 181 }, 182 }, 183 { 184 Filenames: []string{testConfigOtherFilename, testConfigFilename}, 185 Profile: "multiple_assume_role_with_credential_source2", 186 Expected: sharedConfig{ 187 Profile: "multiple_assume_role_with_credential_source2", 188 RoleARN: "multiple_assume_role_with_credential_source2_role_arn", 189 SourceProfileName: "multiple_assume_role_with_credential_source", 190 SourceProfile: &sharedConfig{ 191 Profile: "multiple_assume_role_with_credential_source", 192 RoleARN: "multiple_assume_role_with_credential_source_role_arn", 193 SourceProfileName: "assume_role_with_credential_source", 194 SourceProfile: &sharedConfig{ 195 Profile: "assume_role_with_credential_source", 196 RoleARN: "assume_role_with_credential_source_role_arn", 197 CredentialSource: credSourceEc2Metadata, 198 }, 199 }, 200 }, 201 }, 202 { 203 Filenames: []string{testConfigFilename}, 204 Profile: "with_sts_regional", 205 Expected: sharedConfig{ 206 Profile: "with_sts_regional", 207 STSRegionalEndpoint: endpoints.RegionalSTSEndpoint, 208 }, 209 }, 210 { 211 Filenames: []string{testConfigFilename}, 212 Profile: "with_s3_us_east_1_regional", 213 Expected: sharedConfig{ 214 Profile: "with_s3_us_east_1_regional", 215 S3UsEast1RegionalEndpoint: endpoints.RegionalS3UsEast1Endpoint, 216 }, 217 }, 218 { 219 Filenames: []string{testConfigFilename}, 220 Profile: "sso_creds", 221 Expected: sharedConfig{ 222 Profile: "sso_creds", 223 SSOAccountID: "012345678901", 224 SSORegion: "us-west-2", 225 SSORoleName: "TestRole", 226 SSOStartURL: "https://127.0.0.1/start", 227 }, 228 }, 229 { 230 Filenames: []string{testConfigFilename}, 231 Profile: "source_sso_creds", 232 Expected: sharedConfig{ 233 Profile: "source_sso_creds", 234 RoleARN: "source_sso_creds_arn", 235 SourceProfileName: "sso_creds", 236 SourceProfile: &sharedConfig{ 237 Profile: "sso_creds", 238 SSOAccountID: "012345678901", 239 SSORegion: "us-west-2", 240 SSORoleName: "TestRole", 241 SSOStartURL: "https://127.0.0.1/start", 242 }, 243 }, 244 }, 245 { 246 Filenames: []string{testConfigFilename}, 247 Profile: "sso_and_static", 248 Expected: sharedConfig{ 249 Profile: "sso_and_static", 250 Creds: credentials.Value{ 251 AccessKeyID: "sso_and_static_akid", 252 SecretAccessKey: "sso_and_static_secret", 253 SessionToken: "sso_and_static_token", 254 ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", testConfigFilename), 255 }, 256 SSOAccountID: "012345678901", 257 SSORegion: "us-west-2", 258 SSORoleName: "TestRole", 259 SSOStartURL: "https://THIS_SHOULD_NOT_BE_IN_TESTDATA_CACHE/start", 260 }, 261 }, 262 { 263 Filenames: []string{testConfigFilename}, 264 Profile: "source_sso_and_assume", 265 Expected: sharedConfig{ 266 Profile: "source_sso_and_assume", 267 RoleARN: "source_sso_and_assume_arn", 268 SourceProfileName: "sso_and_assume", 269 SourceProfile: &sharedConfig{ 270 Profile: "sso_and_assume", 271 RoleARN: "sso_with_assume_role_arn", 272 SourceProfileName: "multiple_assume_role_with_credential_source", 273 SourceProfile: &sharedConfig{ 274 Profile: "multiple_assume_role_with_credential_source", 275 RoleARN: "multiple_assume_role_with_credential_source_role_arn", 276 SourceProfileName: "assume_role_with_credential_source", 277 SourceProfile: &sharedConfig{ 278 Profile: "assume_role_with_credential_source", 279 RoleARN: "assume_role_with_credential_source_role_arn", 280 CredentialSource: credSourceEc2Metadata, 281 }, 282 }, 283 }, 284 }, 285 }, 286 { 287 Filenames: []string{testConfigFilename}, 288 Profile: "sso_mixed_credproc", 289 Expected: sharedConfig{ 290 Profile: "sso_mixed_credproc", 291 SSOAccountID: "012345678901", 292 SSORegion: "us-west-2", 293 SSORoleName: "TestRole", 294 SSOStartURL: "https://127.0.0.1/start", 295 CredentialProcess: "/path/to/process", 296 }, 297 }, 298 { 299 Filenames: []string{testConfigFilename}, 300 Profile: "EC2MetadataServiceEndpoint", 301 Expected: sharedConfig{ 302 Profile: "EC2MetadataServiceEndpoint", 303 EC2IMDSEndpoint: "http://endpoint.localhost", 304 }, 305 }, 306 { 307 Filenames: []string{testConfigFilename}, 308 Profile: "EC2MetadataServiceEndpointModeIPv6", 309 Expected: sharedConfig{ 310 Profile: "EC2MetadataServiceEndpointModeIPv6", 311 EC2IMDSEndpointMode: endpoints.EC2IMDSEndpointModeStateIPv6, 312 }, 313 }, 314 { 315 Filenames: []string{testConfigFilename}, 316 Profile: "EC2MetadataServiceEndpointModeIPv4", 317 Expected: sharedConfig{ 318 Profile: "EC2MetadataServiceEndpointModeIPv4", 319 EC2IMDSEndpointMode: endpoints.EC2IMDSEndpointModeStateIPv4, 320 }, 321 }, 322 { 323 Filenames: []string{testConfigFilename}, 324 Profile: "EC2MetadataServiceEndpointModeUnknown", 325 Expected: sharedConfig{ 326 Profile: "EC2MetadataServiceEndpointModeUnknown", 327 }, 328 Err: fmt.Errorf("failed to load ec2_metadata_service_endpoint_mode from shared config"), 329 }, 330 { 331 Filenames: []string{testConfigFilename}, 332 Profile: "EC2MetadataServiceEndpointAndModeMixed", 333 Expected: sharedConfig{ 334 Profile: "EC2MetadataServiceEndpointAndModeMixed", 335 EC2IMDSEndpoint: "http://endpoint.localhost", 336 EC2IMDSEndpointMode: endpoints.EC2IMDSEndpointModeStateIPv6, 337 }, 338 }, 339 } 340 341 for i, c := range cases { 342 t.Run(strconv.Itoa(i)+"_"+c.Profile, func(t *testing.T) { 343 cfg, err := loadSharedConfig(c.Profile, c.Filenames, true) 344 if c.Err != nil { 345 if err == nil { 346 t.Fatalf("expect error, got none") 347 } 348 if e, a := c.Err.Error(), err.Error(); !strings.Contains(a, e) { 349 t.Errorf("expect %v, to be in %v", e, a) 350 } 351 return 352 } 353 354 if err != nil { 355 t.Fatalf("expect no error, got %v", err) 356 } 357 if e, a := c.Expected, cfg; !reflect.DeepEqual(e, a) { 358 t.Errorf("expect %v, got %v", e, a) 359 } 360 }) 361 } 362} 363 364func TestLoadSharedConfigFromFile(t *testing.T) { 365 filename := testConfigFilename 366 f, err := ini.OpenFile(filename) 367 if err != nil { 368 t.Fatalf("failed to load test config file, %s, %v", filename, err) 369 } 370 iniFile := sharedConfigFile{IniData: f, Filename: filename} 371 372 cases := []struct { 373 Profile string 374 Expected sharedConfig 375 Err error 376 }{ 377 { 378 Profile: "default", 379 Expected: sharedConfig{Region: "default_region"}, 380 }, 381 { 382 Profile: "alt_profile_name", 383 Expected: sharedConfig{Region: "alt_profile_name_region"}, 384 }, 385 { 386 Profile: "short_profile_name_first", 387 Expected: sharedConfig{Region: "short_profile_name_first_short"}, 388 }, 389 { 390 Profile: "partial_creds", 391 Expected: sharedConfig{}, 392 }, 393 { 394 Profile: "complete_creds", 395 Expected: sharedConfig{ 396 Creds: credentials.Value{ 397 AccessKeyID: "complete_creds_akid", 398 SecretAccessKey: "complete_creds_secret", 399 ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", testConfigFilename), 400 }, 401 }, 402 }, 403 { 404 Profile: "complete_creds_with_token", 405 Expected: sharedConfig{ 406 Creds: credentials.Value{ 407 AccessKeyID: "complete_creds_with_token_akid", 408 SecretAccessKey: "complete_creds_with_token_secret", 409 SessionToken: "complete_creds_with_token_token", 410 ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", testConfigFilename), 411 }, 412 }, 413 }, 414 { 415 Profile: "full_profile", 416 Expected: sharedConfig{ 417 Creds: credentials.Value{ 418 AccessKeyID: "full_profile_akid", 419 SecretAccessKey: "full_profile_secret", 420 ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", testConfigFilename), 421 }, 422 Region: "full_profile_region", 423 }, 424 }, 425 { 426 Profile: "partial_assume_role", 427 Expected: sharedConfig{ 428 RoleARN: "partial_assume_role_role_arn", 429 }, 430 }, 431 { 432 Profile: "assume_role", 433 Expected: sharedConfig{ 434 RoleARN: "assume_role_role_arn", 435 SourceProfileName: "complete_creds", 436 }, 437 }, 438 { 439 Profile: "assume_role_w_mfa", 440 Expected: sharedConfig{ 441 RoleARN: "assume_role_role_arn", 442 SourceProfileName: "complete_creds", 443 MFASerial: "0123456789", 444 }, 445 }, 446 { 447 Profile: "does_not_exists", 448 Err: SharedConfigProfileNotExistsError{Profile: "does_not_exists"}, 449 }, 450 { 451 Profile: "valid_arn_region", 452 Expected: sharedConfig{ 453 S3UseARNRegion: true, 454 }, 455 }, 456 } 457 458 for i, c := range cases { 459 t.Run(strconv.Itoa(i)+"_"+c.Profile, func(t *testing.T) { 460 cfg := sharedConfig{} 461 462 err := cfg.setFromIniFile(c.Profile, iniFile, true) 463 if c.Err != nil { 464 if err == nil { 465 t.Fatalf("expect error, got none") 466 } 467 if e, a := c.Err.Error(), err.Error(); !strings.Contains(a, e) { 468 t.Errorf("expect %v, to be in %v", e, a) 469 } 470 return 471 } 472 473 if err != nil { 474 t.Errorf("expect no error, got %v", err) 475 } 476 if e, a := c.Expected, cfg; !reflect.DeepEqual(e, a) { 477 t.Errorf("expect %v, got %v", e, a) 478 } 479 }) 480 } 481} 482 483func TestLoadSharedConfigIniFiles(t *testing.T) { 484 cases := []struct { 485 Filenames []string 486 Expected []sharedConfigFile 487 }{ 488 { 489 Filenames: []string{"not_exists", testConfigFilename}, 490 Expected: []sharedConfigFile{ 491 {Filename: testConfigFilename}, 492 }, 493 }, 494 { 495 Filenames: []string{testConfigFilename, testConfigOtherFilename}, 496 Expected: []sharedConfigFile{ 497 {Filename: testConfigFilename}, 498 {Filename: testConfigOtherFilename}, 499 }, 500 }, 501 } 502 503 for i, c := range cases { 504 t.Run(strconv.Itoa(i), func(t *testing.T) { 505 files, err := loadSharedConfigIniFiles(c.Filenames) 506 if err != nil { 507 t.Fatalf("expect no error, got %v", err) 508 } 509 if e, a := len(c.Expected), len(files); e != a { 510 t.Errorf("expect %v, got %v", e, a) 511 } 512 513 for i, expectedFile := range c.Expected { 514 if e, a := expectedFile.Filename, files[i].Filename; e != a { 515 t.Errorf("expect %v, got %v", e, a) 516 } 517 } 518 }) 519 } 520} 521