1package awsauth 2 3import ( 4 "context" 5 "reflect" 6 "strings" 7 "testing" 8 9 "github.com/go-test/deep" 10 "github.com/hashicorp/vault/sdk/helper/policyutil" 11 "github.com/hashicorp/vault/sdk/helper/strutil" 12 "github.com/hashicorp/vault/sdk/logical" 13) 14 15func TestBackend_pathRoleEc2(t *testing.T) { 16 config := logical.TestBackendConfig() 17 storage := &logical.InmemStorage{} 18 config.StorageView = storage 19 20 b, err := Backend(config) 21 if err != nil { 22 t.Fatal(err) 23 } 24 25 err = b.Setup(context.Background(), config) 26 if err != nil { 27 t.Fatal(err) 28 } 29 30 data := map[string]interface{}{ 31 "auth_type": "ec2", 32 "policies": "p,q,r,s", 33 "max_ttl": "2h", 34 "bound_ami_id": "ami-abcd123", 35 } 36 resp, err := b.HandleRequest(context.Background(), &logical.Request{ 37 Operation: logical.CreateOperation, 38 Path: "role/ami-abcd123", 39 Data: data, 40 Storage: storage, 41 }) 42 if resp != nil && resp.IsError() { 43 t.Fatalf("failed to create role") 44 } 45 if err != nil { 46 t.Fatal(err) 47 } 48 49 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 50 Operation: logical.ReadOperation, 51 Path: "role/ami-abcd123", 52 Storage: storage, 53 }) 54 if err != nil { 55 t.Fatal(err) 56 } 57 if resp == nil || resp.IsError() { 58 t.Fatal("failed to read the role entry") 59 } 60 if !policyutil.EquivalentPolicies(strings.Split(data["policies"].(string), ","), resp.Data["policies"].([]string)) { 61 t.Fatalf("bad: policies: expected: %#v\ngot: %#v\n", data, resp.Data) 62 } 63 64 data["allow_instance_migration"] = true 65 data["disallow_reauthentication"] = true 66 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 67 Operation: logical.UpdateOperation, 68 Path: "role/ami-abcd123", 69 Data: data, 70 Storage: storage, 71 }) 72 if err != nil { 73 t.Fatal(err) 74 } 75 if resp == nil || !resp.IsError() { 76 t.Fatalf("expected failure to create role with both allow_instance_migration true and disallow_reauthentication true") 77 } 78 data["disallow_reauthentication"] = false 79 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 80 Operation: logical.UpdateOperation, 81 Path: "role/ami-abcd123", 82 Data: data, 83 Storage: storage, 84 }) 85 if err != nil { 86 t.Fatal(err) 87 } 88 if resp != nil && resp.IsError() { 89 t.Fatalf("failure to update role: %v", resp.Data["error"]) 90 } 91 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 92 Operation: logical.ReadOperation, 93 Path: "role/ami-abcd123", 94 Storage: storage, 95 }) 96 if err != nil { 97 t.Fatal(err) 98 } 99 if !resp.Data["allow_instance_migration"].(bool) { 100 t.Fatal("bad: expected allow_instance_migration:true got:false\n") 101 } 102 103 if resp.Data["disallow_reauthentication"].(bool) { 104 t.Fatal("bad: expected disallow_reauthentication: false got:true\n") 105 } 106 107 // add another entry, to test listing of role entries 108 data["bound_ami_id"] = "ami-abcd456" 109 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 110 Operation: logical.CreateOperation, 111 Path: "role/ami-abcd456", 112 Data: data, 113 Storage: storage, 114 }) 115 if resp != nil && resp.IsError() { 116 t.Fatalf("failed to create role: %s", resp.Data["error"]) 117 } 118 if err != nil { 119 t.Fatal(err) 120 } 121 122 data["bound_iam_principal_arn"] = "" 123 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 124 Operation: logical.UpdateOperation, 125 Path: "role/ami-abcd456", 126 Data: data, 127 Storage: storage, 128 }) 129 if err != nil { 130 t.Fatal(err) 131 } 132 if resp != nil && resp.IsError() { 133 t.Fatalf("failed to update role with empty bound_iam_principal_arn: %s", resp.Data["error"]) 134 } 135 136 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 137 Operation: logical.ListOperation, 138 Path: "roles", 139 Storage: storage, 140 }) 141 if err != nil { 142 t.Fatal(err) 143 } 144 if resp == nil || resp.Data == nil || resp.IsError() { 145 t.Fatalf("failed to list the role entries") 146 } 147 keys := resp.Data["keys"].([]string) 148 if len(keys) != 2 { 149 t.Fatalf("bad: keys: %#v\n", keys) 150 } 151 152 _, err = b.HandleRequest(context.Background(), &logical.Request{ 153 Operation: logical.DeleteOperation, 154 Path: "role/ami-abcd123", 155 Storage: storage, 156 }) 157 if err != nil { 158 t.Fatal(err) 159 } 160 161 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 162 Operation: logical.ReadOperation, 163 Path: "role/ami-abcd123", 164 Storage: storage, 165 }) 166 if err != nil { 167 t.Fatal(err) 168 } 169 if resp != nil { 170 t.Fatalf("bad: response: expected:nil actual:%#v\n", resp) 171 } 172} 173 174func Test_enableIamIDResolution(t *testing.T) { 175 config := logical.TestBackendConfig() 176 storage := &logical.InmemStorage{} 177 config.StorageView = storage 178 179 b, err := Backend(config) 180 if err != nil { 181 t.Fatal(err) 182 } 183 err = b.Setup(context.Background(), config) 184 if err != nil { 185 t.Fatal(err) 186 } 187 roleName := "upgradable_role" 188 189 b.resolveArnToUniqueIDFunc = resolveArnToFakeUniqueId 190 191 boundIamRoleARNs := []string{"arn:aws:iam::123456789012:role/MyRole", "arn:aws:iam::123456789012:role/path/*"} 192 data := map[string]interface{}{ 193 "auth_type": iamAuthType, 194 "policies": "p,q", 195 "bound_iam_principal_arn": boundIamRoleARNs, 196 "resolve_aws_unique_ids": false, 197 } 198 199 submitRequest := func(roleName string, op logical.Operation) (*logical.Response, error) { 200 return b.HandleRequest(context.Background(), &logical.Request{ 201 Operation: op, 202 Path: "role/" + roleName, 203 Data: data, 204 Storage: storage, 205 }) 206 } 207 208 resp, err := submitRequest(roleName, logical.CreateOperation) 209 if err != nil { 210 t.Fatal(err) 211 } 212 if resp != nil && resp.IsError() { 213 t.Fatalf("failed to create role: %#v", resp) 214 } 215 216 resp, err = submitRequest(roleName, logical.ReadOperation) 217 if err != nil { 218 t.Fatal(err) 219 } 220 if resp == nil || resp.IsError() { 221 t.Fatalf("failed to read role: resp:%#v,\nerr:%#v", resp, err) 222 } 223 if resp.Data["bound_iam_principal_id"] != nil && len(resp.Data["bound_iam_principal_id"].([]string)) > 0 { 224 t.Fatalf("expected to get no unique ID in role, but got %q", resp.Data["bound_iam_principal_id"]) 225 } 226 227 data = map[string]interface{}{ 228 "resolve_aws_unique_ids": true, 229 } 230 resp, err = submitRequest(roleName, logical.UpdateOperation) 231 if err != nil { 232 t.Fatal(err) 233 } 234 if resp != nil && resp.IsError() { 235 t.Fatalf("unable to upgrade role to resolve internal IDs: resp:%#v", resp) 236 } 237 238 resp, err = submitRequest(roleName, logical.ReadOperation) 239 if err != nil { 240 t.Fatal(err) 241 } 242 if resp == nil || resp.IsError() { 243 t.Fatalf("failed to read role: resp:%#v,\nerr:%#v", resp, err) 244 } 245 principalIDs := resp.Data["bound_iam_principal_id"].([]string) 246 if len(principalIDs) != 1 || principalIDs[0] != "FakeUniqueId1" { 247 t.Fatalf("bad: expected upgrade of role resolve principal ID to %q, but got %q instead", "FakeUniqueId1", resp.Data["bound_iam_principal_id"]) 248 } 249 returnedARNs := resp.Data["bound_iam_principal_arn"].([]string) 250 if !strutil.EquivalentSlices(returnedARNs, boundIamRoleARNs) { 251 t.Fatalf("bad: expected to return bound_iam_principal_arn of %q, but got %q instead", boundIamRoleARNs, returnedARNs) 252 } 253} 254 255func TestBackend_pathIam(t *testing.T) { 256 config := logical.TestBackendConfig() 257 storage := &logical.InmemStorage{} 258 config.StorageView = storage 259 260 b, err := Backend(config) 261 if err != nil { 262 t.Fatal(err) 263 } 264 err = b.Setup(context.Background(), config) 265 if err != nil { 266 t.Fatal(err) 267 } 268 269 // make sure we start with empty roles, which gives us confidence that the read later 270 // actually is the two roles we created 271 resp, err := b.HandleRequest(context.Background(), &logical.Request{ 272 Operation: logical.ListOperation, 273 Path: "roles", 274 Storage: storage, 275 }) 276 if err != nil { 277 t.Fatal(err) 278 } 279 if resp == nil || resp.Data == nil || resp.IsError() { 280 t.Fatalf("failed to list role entries") 281 } 282 if resp.Data["keys"] != nil { 283 t.Fatalf("Received roles when expected none") 284 } 285 286 data := map[string]interface{}{ 287 "auth_type": iamAuthType, 288 "policies": "p,q,r,s", 289 "max_ttl": "2h", 290 "bound_iam_principal_arn": "n:aws:iam::123456789012:user/MyUserName", 291 "resolve_aws_unique_ids": false, 292 } 293 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 294 Operation: logical.CreateOperation, 295 Path: "role/MyRoleName", 296 Data: data, 297 Storage: storage, 298 }) 299 300 if err != nil { 301 t.Fatal(err) 302 } 303 if resp != nil && resp.IsError() { 304 t.Fatalf("failed to create the role entry; resp: %#v", resp) 305 } 306 307 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 308 Operation: logical.ReadOperation, 309 Path: "role/MyRoleName", 310 Storage: storage, 311 }) 312 if err != nil { 313 t.Fatal(err) 314 } 315 if resp == nil || resp.IsError() { 316 t.Fatal("failed to read the role entry") 317 } 318 if !policyutil.EquivalentPolicies(strings.Split(data["policies"].(string), ","), resp.Data["policies"].([]string)) { 319 t.Fatalf("bad: policies: expected %#v\ngot: %#v\n", data, resp.Data) 320 } 321 322 data["inferred_entity_type"] = "invalid" 323 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 324 Operation: logical.CreateOperation, 325 Path: "role/ShouldNeverExist", 326 Data: data, 327 Storage: storage, 328 }) 329 if resp == nil || !resp.IsError() { 330 t.Fatalf("Created role with invalid inferred_entity_type") 331 } 332 if err != nil { 333 t.Fatal(err) 334 } 335 336 data["inferred_entity_type"] = ec2EntityType 337 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 338 Operation: logical.CreateOperation, 339 Path: "role/ShouldNeverExist", 340 Data: data, 341 Storage: storage, 342 }) 343 if resp == nil || !resp.IsError() { 344 t.Fatalf("Created role without necessary inferred_aws_region") 345 } 346 if err != nil { 347 t.Fatal(err) 348 } 349 350 delete(data, "bound_iam_principal_arn") 351 data["inferred_aws_region"] = "us-east-1" 352 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 353 Operation: logical.CreateOperation, 354 Path: "role/ShouldNeverExist", 355 Data: data, 356 Storage: storage, 357 }) 358 if resp == nil || !resp.IsError() { 359 t.Fatalf("Created role without anything bound") 360 } 361 if err != nil { 362 t.Fatal(err) 363 } 364 365 // generate a second role, ensure we're able to list both 366 data["bound_ami_id"] = "ami-abcd123" 367 secondRole := &logical.Request{ 368 Operation: logical.CreateOperation, 369 Path: "role/MyOtherRoleName", 370 Data: data, 371 Storage: storage, 372 } 373 resp, err = b.HandleRequest(context.Background(), secondRole) 374 if err != nil { 375 t.Fatal(err) 376 } 377 if resp != nil && resp.IsError() { 378 t.Fatalf("failed to create additional role: %v", *secondRole) 379 } 380 381 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 382 Operation: logical.ListOperation, 383 Path: "roles", 384 Storage: storage, 385 }) 386 if err != nil { 387 t.Fatal(err) 388 } 389 if resp == nil || resp.Data == nil || resp.IsError() { 390 t.Fatalf("failed to list role entries") 391 } 392 keys := resp.Data["keys"].([]string) 393 if len(keys) != 2 { 394 t.Fatalf("bad: keys %#v\n", keys) 395 } 396 397 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 398 Operation: logical.DeleteOperation, 399 Path: "role/MyOtherRoleName", 400 Storage: storage, 401 }) 402 if err != nil { 403 t.Fatal(err) 404 } 405 406 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 407 Operation: logical.ReadOperation, 408 Path: "role/MyOtherRoleName", 409 Storage: storage, 410 }) 411 if err != nil { 412 t.Fatal(err) 413 } 414 if resp != nil { 415 t.Fatalf("bad: response: expected: nil actual:%3v\n", resp) 416 } 417} 418 419func TestBackend_pathRoleMixedTypes(t *testing.T) { 420 config := logical.TestBackendConfig() 421 storage := &logical.InmemStorage{} 422 config.StorageView = storage 423 424 b, err := Backend(config) 425 if err != nil { 426 t.Fatal(err) 427 } 428 err = b.Setup(context.Background(), config) 429 if err != nil { 430 t.Fatal(err) 431 } 432 433 data := map[string]interface{}{ 434 "policies": "p,q,r,s", 435 "bound_ami_id": "ami-abc1234", 436 "auth_type": "ec2,invalid", 437 } 438 439 submitRequest := func(roleName string, op logical.Operation) (*logical.Response, error) { 440 return b.HandleRequest(context.Background(), &logical.Request{ 441 Operation: op, 442 Path: "role/" + roleName, 443 Data: data, 444 Storage: storage, 445 }) 446 } 447 448 resp, err := submitRequest("shouldNeverExist", logical.CreateOperation) 449 if resp == nil || !resp.IsError() { 450 t.Fatalf("created role with invalid auth_type; resp: %#v", resp) 451 } 452 if err != nil { 453 t.Fatal(err) 454 } 455 456 data["auth_type"] = "ec2,,iam" 457 resp, err = submitRequest("shouldNeverExist", logical.CreateOperation) 458 if resp == nil || !resp.IsError() { 459 t.Fatalf("created role mixed auth types") 460 } 461 if err != nil { 462 t.Fatal(err) 463 } 464 465 data["auth_type"] = ec2AuthType 466 resp, err = submitRequest("ec2_to_iam", logical.CreateOperation) 467 if resp != nil && resp.IsError() { 468 t.Fatalf("failed to create valid role; resp: %#v", resp) 469 } 470 if err != nil { 471 t.Fatal(err) 472 } 473 474 data["auth_type"] = iamAuthType 475 delete(data, "bound_ami_id") 476 boundIamPrincipalARNs := []string{"arn:aws:iam::123456789012:role/MyRole", "arn:aws:iam::123456789012:role/path/*"} 477 data["bound_iam_principal_arn"] = boundIamPrincipalARNs 478 resp, err = submitRequest("ec2_to_iam", logical.UpdateOperation) 479 if resp == nil || !resp.IsError() { 480 t.Fatalf("changed auth type on the role") 481 } 482 if err != nil { 483 t.Fatal(err) 484 } 485 486 data["inferred_entity_type"] = ec2EntityType 487 data["inferred_aws_region"] = "us-east-1" 488 data["resolve_aws_unique_ids"] = false 489 resp, err = submitRequest("multipleTypesInferred", logical.CreateOperation) 490 if err != nil { 491 t.Fatal(err) 492 } 493 if resp.IsError() { 494 t.Fatalf("didn't allow creation of roles with only inferred bindings") 495 } 496 497 b.resolveArnToUniqueIDFunc = resolveArnToFakeUniqueId 498 data["resolve_aws_unique_ids"] = true 499 resp, err = submitRequest("withInternalIdResolution", logical.CreateOperation) 500 if err != nil { 501 t.Fatal(err) 502 } 503 if resp.IsError() { 504 t.Fatalf("didn't allow creation of role resolving unique IDs") 505 } 506 resp, err = submitRequest("withInternalIdResolution", logical.ReadOperation) 507 if err != nil { 508 t.Fatal(err) 509 } 510 principalIDs := resp.Data["bound_iam_principal_id"].([]string) 511 if len(principalIDs) != 1 || principalIDs[0] != "FakeUniqueId1" { 512 t.Fatalf("expected fake unique ID of FakeUniqueId1, got %q", resp.Data["bound_iam_principal_id"]) 513 } 514 returnedARNs := resp.Data["bound_iam_principal_arn"].([]string) 515 if !strutil.EquivalentSlices(returnedARNs, boundIamPrincipalARNs) { 516 t.Fatalf("bad: expected to return bound_iam_principal_arn of %q, but got %q instead", boundIamPrincipalARNs, returnedARNs) 517 } 518 data["resolve_aws_unique_ids"] = false 519 resp, err = submitRequest("withInternalIdResolution", logical.UpdateOperation) 520 if err != nil { 521 t.Fatal(err) 522 } 523 if !resp.IsError() { 524 t.Fatalf("allowed changing resolve_aws_unique_ids from true to false") 525 } 526 527} 528 529func TestAwsEc2_RoleCrud(t *testing.T) { 530 var err error 531 var resp *logical.Response 532 config := logical.TestBackendConfig() 533 storage := &logical.InmemStorage{} 534 config.StorageView = storage 535 536 b, err := Backend(config) 537 if err != nil { 538 t.Fatal(err) 539 } 540 541 err = b.Setup(context.Background(), config) 542 if err != nil { 543 t.Fatal(err) 544 } 545 546 role1Data := map[string]interface{}{ 547 "auth_type": "ec2", 548 "bound_vpc_id": "testvpcid", 549 "allow_instance_migration": true, 550 "policies": "testpolicy1,testpolicy2", 551 } 552 roleReq := &logical.Request{ 553 Operation: logical.UpdateOperation, 554 Storage: storage, 555 Path: "role/role1", 556 Data: role1Data, 557 } 558 559 resp, err = b.HandleRequest(context.Background(), roleReq) 560 if err != nil || (resp != nil && resp.IsError()) { 561 t.Fatalf("resp: %#v, err: %v", resp, err) 562 } 563 564 roleData := map[string]interface{}{ 565 "auth_type": "ec2", 566 "bound_ami_id": "testamiid", 567 "bound_account_id": "testaccountid", 568 "bound_region": "testregion", 569 "bound_iam_role_arn": "arn:aws:iam::123456789012:role/MyRole", 570 "bound_iam_instance_profile_arn": "arn:aws:iam::123456789012:instance-profile/MyInstancePro*", 571 "bound_subnet_id": "testsubnetid", 572 "bound_vpc_id": "testvpcid", 573 "bound_ec2_instance_id": "i-12345678901234567,i-76543210987654321", 574 "role_tag": "testtag", 575 "resolve_aws_unique_ids": false, 576 "allow_instance_migration": true, 577 "ttl": "10m", 578 "max_ttl": "20m", 579 "policies": "testpolicy1,testpolicy2", 580 "disallow_reauthentication": false, 581 "hmac_key": "testhmackey", 582 "period": "1m", 583 } 584 585 roleReq.Path = "role/testrole" 586 roleReq.Data = roleData 587 resp, err = b.HandleRequest(context.Background(), roleReq) 588 if err != nil || (resp != nil && resp.IsError()) { 589 t.Fatalf("resp: %#v, err: %v", resp, err) 590 } 591 592 roleReq.Operation = logical.ReadOperation 593 resp, err = b.HandleRequest(context.Background(), roleReq) 594 if err != nil || (resp != nil && resp.IsError()) { 595 t.Fatalf("resp: %#v, err: %v", resp, err) 596 } 597 598 expected := map[string]interface{}{ 599 "auth_type": ec2AuthType, 600 "bound_ami_id": []string{"testamiid"}, 601 "bound_account_id": []string{"testaccountid"}, 602 "bound_region": []string{"testregion"}, 603 "bound_ec2_instance_id": []string{"i-12345678901234567", "i-76543210987654321"}, 604 "bound_iam_principal_arn": []string{}, 605 "bound_iam_principal_id": []string{}, 606 "bound_iam_role_arn": []string{"arn:aws:iam::123456789012:role/MyRole"}, 607 "bound_iam_instance_profile_arn": []string{"arn:aws:iam::123456789012:instance-profile/MyInstancePro*"}, 608 "bound_subnet_id": []string{"testsubnetid"}, 609 "bound_vpc_id": []string{"testvpcid"}, 610 "inferred_entity_type": "", 611 "inferred_aws_region": "", 612 "resolve_aws_unique_ids": false, 613 "role_tag": "testtag", 614 "allow_instance_migration": true, 615 "ttl": int64(600), 616 "token_ttl": int64(600), 617 "max_ttl": int64(1200), 618 "token_max_ttl": int64(1200), 619 "token_explicit_max_ttl": int64(0), 620 "policies": []string{"testpolicy1", "testpolicy2"}, 621 "token_policies": []string{"testpolicy1", "testpolicy2"}, 622 "disallow_reauthentication": false, 623 "period": int64(60), 624 "token_period": int64(60), 625 "token_bound_cidrs": []string{}, 626 "token_no_default_policy": false, 627 "token_num_uses": 0, 628 "token_type": "default", 629 } 630 631 if resp.Data["role_id"] == nil { 632 t.Fatal("role_id not found in repsonse") 633 } 634 expected["role_id"] = resp.Data["role_id"] 635 if diff := deep.Equal(expected, resp.Data); diff != nil { 636 t.Fatal(diff) 637 } 638 639 roleData["bound_vpc_id"] = "newvpcid" 640 roleReq.Operation = logical.UpdateOperation 641 resp, err = b.HandleRequest(context.Background(), roleReq) 642 if err != nil || (resp != nil && resp.IsError()) { 643 t.Fatalf("resp: %#v, err: %v", resp, err) 644 } 645 646 roleReq.Operation = logical.ReadOperation 647 resp, err = b.HandleRequest(context.Background(), roleReq) 648 if err != nil || (resp != nil && resp.IsError()) { 649 t.Fatalf("resp: %#v, err: %v", resp, err) 650 } 651 expected["bound_vpc_id"] = []string{"newvpcid"} 652 if !reflect.DeepEqual(expected, resp.Data) { 653 t.Fatalf("bad: role data: expected: %#v\n actual: %#v", expected, resp.Data) 654 } 655 656 // Create a new backend so we have a new cache (thus populating from disk). 657 // Then test reading (reading from disk + lock), writing, reading, 658 // deleting, reading. 659 b, err = Backend(config) 660 if err != nil { 661 t.Fatal(err) 662 } 663 664 err = b.Setup(context.Background(), config) 665 if err != nil { 666 t.Fatal(err) 667 } 668 669 // Read again, make sure things are what we expect 670 resp, err = b.HandleRequest(context.Background(), roleReq) 671 if err != nil || (resp != nil && resp.IsError()) { 672 t.Fatalf("resp: %#v, err: %v", resp, err) 673 } 674 if !reflect.DeepEqual(expected, resp.Data) { 675 t.Fatalf("bad: role data: expected: %#v\n actual: %#v", expected, resp.Data) 676 } 677 678 roleReq.Operation = logical.UpdateOperation 679 roleData["bound_ami_id"] = "testamiid2" 680 resp, err = b.HandleRequest(context.Background(), roleReq) 681 if err != nil || (resp != nil && resp.IsError()) { 682 t.Fatalf("resp: %#v, err: %v", resp, err) 683 } 684 685 roleReq.Operation = logical.ReadOperation 686 resp, err = b.HandleRequest(context.Background(), roleReq) 687 if err != nil || (resp != nil && resp.IsError()) { 688 t.Fatalf("resp: %#v, err: %v", resp, err) 689 } 690 691 expected["bound_ami_id"] = []string{"testamiid2"} 692 if diff := deep.Equal(expected, resp.Data); diff != nil { 693 t.Fatal(diff) 694 } 695 696 // Delete which should remove from disk and also cache 697 roleReq.Operation = logical.DeleteOperation 698 resp, err = b.HandleRequest(context.Background(), roleReq) 699 if err != nil || (resp != nil && resp.IsError()) { 700 t.Fatalf("resp: %#v, err: %v", resp, err) 701 } 702 if resp != nil { 703 t.Fatalf("failed to delete role entry") 704 } 705 706 // Verify it was deleted, e.g. it isn't found in the role cache 707 roleReq.Operation = logical.ReadOperation 708 resp, err = b.HandleRequest(context.Background(), roleReq) 709 if err != nil || (resp != nil && resp.IsError()) { 710 t.Fatalf("resp: %#v, err: %v", resp, err) 711 } 712 if resp != nil { 713 t.Fatal("expected nil") 714 } 715} 716 717func TestAwsEc2_RoleDurationSeconds(t *testing.T) { 718 config := logical.TestBackendConfig() 719 storage := &logical.InmemStorage{} 720 config.StorageView = storage 721 722 b, err := Backend(config) 723 if err != nil { 724 t.Fatal(err) 725 } 726 727 err = b.Setup(context.Background(), config) 728 if err != nil { 729 t.Fatal(err) 730 } 731 732 roleData := map[string]interface{}{ 733 "auth_type": "ec2", 734 "bound_iam_instance_profile_arn": "arn:aws:iam::123456789012:instance-profile/test-profile-name", 735 "resolve_aws_unique_ids": false, 736 "ttl": "10s", 737 "max_ttl": "20s", 738 "period": "30s", 739 } 740 741 roleReq := &logical.Request{ 742 Operation: logical.CreateOperation, 743 Storage: storage, 744 Path: "role/testrole", 745 Data: roleData, 746 } 747 748 resp, err := b.HandleRequest(context.Background(), roleReq) 749 if err != nil || (resp != nil && resp.IsError()) { 750 t.Fatalf("resp: %#v, err: %v", resp, err) 751 } 752 753 roleReq.Operation = logical.ReadOperation 754 755 resp, err = b.HandleRequest(context.Background(), roleReq) 756 if err != nil || (resp != nil && resp.IsError()) { 757 t.Fatalf("resp: %#v, err: %v", resp, err) 758 } 759 760 if int64(resp.Data["ttl"].(int64)) != 10 { 761 t.Fatalf("bad: period; expected: 10, actual: %d", resp.Data["ttl"]) 762 } 763 if int64(resp.Data["max_ttl"].(int64)) != 20 { 764 t.Fatalf("bad: period; expected: 20, actual: %d", resp.Data["max_ttl"]) 765 } 766 if int64(resp.Data["period"].(int64)) != 30 { 767 t.Fatalf("bad: period; expected: 30, actual: %d", resp.Data["period"]) 768 } 769} 770 771func TestRoleEntryUpgradeV(t *testing.T) { 772 config := logical.TestBackendConfig() 773 storage := &logical.InmemStorage{} 774 config.StorageView = storage 775 b, err := Backend(config) 776 if err != nil { 777 t.Fatal(err) 778 } 779 780 err = b.Setup(context.Background(), config) 781 if err != nil { 782 t.Fatal(err) 783 } 784 785 roleEntryToUpgrade := &awsRoleEntry{ 786 BoundIamRoleARNs: []string{"arn:aws:iam::123456789012:role/my_role_prefix"}, 787 BoundIamInstanceProfileARNs: []string{"arn:aws:iam::123456789012:instance-profile/my_profile-prefix"}, 788 Version: 1, 789 } 790 expected := &awsRoleEntry{ 791 BoundIamRoleARNs: []string{"arn:aws:iam::123456789012:role/my_role_prefix*"}, 792 BoundIamInstanceProfileARNs: []string{"arn:aws:iam::123456789012:instance-profile/my_profile-prefix*"}, 793 Version: currentRoleStorageVersion, 794 } 795 796 upgraded, err := b.upgradeRole(context.Background(), storage, roleEntryToUpgrade) 797 if err != nil { 798 t.Fatalf("error upgrading role entry: %#v", err) 799 } 800 if !upgraded { 801 t.Fatalf("expected to upgrade role entry %#v but got no upgrade", roleEntryToUpgrade) 802 } 803 if roleEntryToUpgrade.RoleID == "" { 804 t.Fatal("expected role ID to be populated") 805 } 806 expected.RoleID = roleEntryToUpgrade.RoleID 807 if diff := deep.Equal(*roleEntryToUpgrade, *expected); diff != nil { 808 t.Fatal(diff) 809 } 810} 811 812func TestRoleInitialize(t *testing.T) { 813 814 config := logical.TestBackendConfig() 815 storage := &logical.InmemStorage{} 816 config.StorageView = storage 817 b, err := Backend(config) 818 if err != nil { 819 t.Fatal(err) 820 } 821 822 ctx := context.Background() 823 err = b.Setup(ctx, config) 824 if err != nil { 825 t.Fatal(err) 826 } 827 828 // create some role entries, some of which will need to be upgraded 829 type testData struct { 830 name string 831 entry *awsRoleEntry 832 } 833 834 before := []testData{ 835 { 836 name: "role1", 837 entry: &awsRoleEntry{ 838 BoundIamRoleARNs: []string{"arn:aws:iam::000000000001:role/my_role_prefix"}, 839 BoundIamInstanceProfileARNs: []string{"arn:aws:iam::000000000001:instance-profile/my_profile-prefix"}, 840 Version: 1, 841 }, 842 }, 843 { 844 name: "role2", 845 entry: &awsRoleEntry{ 846 BoundIamRoleARNs: []string{"arn:aws:iam::000000000002:role/my_role_prefix"}, 847 BoundIamInstanceProfileARNs: []string{"arn:aws:iam::000000000002:instance-profile/my_profile-prefix"}, 848 Version: 2, 849 }, 850 }, 851 { 852 name: "role3", 853 entry: &awsRoleEntry{ 854 BoundIamRoleARNs: []string{"arn:aws:iam::000000000003:role/my_role_prefix"}, 855 BoundIamInstanceProfileARNs: []string{"arn:aws:iam::000000000003:instance-profile/my_profile-prefix"}, 856 Version: currentRoleStorageVersion, 857 }, 858 }, 859 } 860 861 // put the entries in storage 862 for _, role := range before { 863 err = b.setRole(ctx, storage, role.name, role.entry) 864 if err != nil { 865 t.Fatal(err) 866 } 867 } 868 869 // upgrade all the entries 870 upgraded, err := b.upgrade(ctx, storage) 871 if err != nil { 872 t.Fatal(err) 873 } 874 if !upgraded { 875 t.Fatalf("expected upgrade") 876 } 877 878 // read the entries from storage 879 after := make([]testData, 0) 880 names, err := storage.List(ctx, "role/") 881 if err != nil { 882 t.Fatal(err) 883 } 884 for _, name := range names { 885 entry, err := b.role(ctx, storage, name) 886 if err != nil { 887 t.Fatal(err) 888 } 889 after = append(after, testData{name: name, entry: entry}) 890 } 891 892 // make sure each entry is at the current version 893 expected := []testData{ 894 { 895 name: "role1", 896 entry: &awsRoleEntry{ 897 BoundIamRoleARNs: []string{"arn:aws:iam::000000000001:role/my_role_prefix"}, 898 BoundIamInstanceProfileARNs: []string{"arn:aws:iam::000000000001:instance-profile/my_profile-prefix"}, 899 Version: currentRoleStorageVersion, 900 }, 901 }, 902 { 903 name: "role2", 904 entry: &awsRoleEntry{ 905 BoundIamRoleARNs: []string{"arn:aws:iam::000000000002:role/my_role_prefix"}, 906 BoundIamInstanceProfileARNs: []string{"arn:aws:iam::000000000002:instance-profile/my_profile-prefix"}, 907 Version: currentRoleStorageVersion, 908 }, 909 }, 910 { 911 name: "role3", 912 entry: &awsRoleEntry{ 913 BoundIamRoleARNs: []string{"arn:aws:iam::000000000003:role/my_role_prefix"}, 914 BoundIamInstanceProfileARNs: []string{"arn:aws:iam::000000000003:instance-profile/my_profile-prefix"}, 915 Version: currentRoleStorageVersion, 916 }, 917 }, 918 } 919 if diff := deep.Equal(expected, after); diff != nil { 920 t.Fatal(diff) 921 } 922 923 // run it again -- nothing will happen 924 upgraded, err = b.upgrade(ctx, storage) 925 if err != nil { 926 t.Fatal(err) 927 } 928 if upgraded { 929 t.Fatalf("expected no upgrade") 930 } 931 932 // make sure saved role version is correct 933 entry, err := storage.Get(ctx, "config/version") 934 if err != nil { 935 t.Fatal(err) 936 } 937 var version awsVersion 938 err = entry.DecodeJSON(&version) 939 if err != nil { 940 t.Fatal(err) 941 } 942 if version.Version != currentAwsVersion { 943 t.Fatalf("expected version %d, got %d", currentAwsVersion, version.Version) 944 } 945 946 // stomp on the saved version 947 version.Version = 0 948 e2, err := logical.StorageEntryJSON("config/version", version) 949 if err != nil { 950 t.Fatal(err) 951 } 952 err = storage.Put(ctx, e2) 953 if err != nil { 954 t.Fatal(err) 955 } 956 957 // run it again -- now an upgrade will happen 958 upgraded, err = b.upgrade(ctx, storage) 959 if err != nil { 960 t.Fatal(err) 961 } 962 if !upgraded { 963 t.Fatalf("expected upgrade") 964 } 965} 966 967func TestAwsVersion(t *testing.T) { 968 969 before := awsVersion{ 970 Version: 42, 971 } 972 973 entry, err := logical.StorageEntryJSON("config/version", &before) 974 if err != nil { 975 t.Fatal(err) 976 } 977 978 var after awsVersion 979 err = entry.DecodeJSON(&after) 980 if err != nil { 981 t.Fatal(err) 982 } 983 984 if diff := deep.Equal(before, after); diff != nil { 985 t.Fatal(diff) 986 } 987} 988 989func resolveArnToFakeUniqueId(ctx context.Context, s logical.Storage, arn string) (string, error) { 990 return "FakeUniqueId1", nil 991} 992