1package api 2 3import ( 4 "strings" 5 "testing" 6 7 "github.com/hashicorp/consul/sdk/testutil/retry" 8 9 "github.com/stretchr/testify/require" 10) 11 12func TestAPI_ACLBootstrap(t *testing.T) { 13 // TODO (slackpad) We currently can't inject the version, and the 14 // version in the binary depends on Git tags, so we can't reliably 15 // test this until we are just running an agent in-process here and 16 // have full control over the config. 17} 18 19func TestAPI_ACLCreateDestroy(t *testing.T) { 20 t.Parallel() 21 c, s := makeACLClient(t) 22 defer s.Stop() 23 s.WaitForSerfCheck(t) 24 25 acl := c.ACL() 26 27 ae := ACLEntry{ 28 Name: "API test", 29 Type: ACLClientType, 30 Rules: `key "" { policy = "deny" }`, 31 } 32 33 id, wm, err := acl.Create(&ae, nil) 34 if err != nil { 35 t.Fatalf("err: %v", err) 36 } 37 38 if wm.RequestTime == 0 { 39 t.Fatalf("bad: %v", wm) 40 } 41 42 if id == "" { 43 t.Fatalf("invalid: %v", id) 44 } 45 46 ae2, _, err := acl.Info(id, nil) 47 if err != nil { 48 t.Fatalf("err: %v", err) 49 } 50 51 if ae2.Name != ae.Name || ae2.Type != ae.Type || ae2.Rules != ae.Rules { 52 t.Fatalf("Bad: %#v", ae2) 53 } 54 55 wm, err = acl.Destroy(id, nil) 56 if err != nil { 57 t.Fatalf("err: %v", err) 58 } 59 60 if wm.RequestTime == 0 { 61 t.Fatalf("bad: %v", wm) 62 } 63} 64 65func TestAPI_ACLCloneDestroy(t *testing.T) { 66 t.Parallel() 67 c, s := makeACLClient(t) 68 defer s.Stop() 69 70 acl := c.ACL() 71 72 id, wm, err := acl.Clone(c.config.Token, nil) 73 if err != nil { 74 t.Fatalf("err: %v", err) 75 } 76 77 if wm.RequestTime == 0 { 78 t.Fatalf("bad: %v", wm) 79 } 80 81 if id == "" { 82 t.Fatalf("invalid: %v", id) 83 } 84 85 wm, err = acl.Destroy(id, nil) 86 if err != nil { 87 t.Fatalf("err: %v", err) 88 } 89 90 if wm.RequestTime == 0 { 91 t.Fatalf("bad: %v", wm) 92 } 93} 94 95func TestAPI_ACLInfo(t *testing.T) { 96 t.Parallel() 97 c, s := makeACLClient(t) 98 defer s.Stop() 99 100 acl := c.ACL() 101 102 ae, qm, err := acl.Info(c.config.Token, nil) 103 if err != nil { 104 t.Fatalf("err: %v", err) 105 } 106 107 if qm.LastIndex == 0 { 108 t.Fatalf("bad: %v", qm) 109 } 110 if !qm.KnownLeader { 111 t.Fatalf("bad: %v", qm) 112 } 113 114 if ae == nil || ae.ID != c.config.Token || ae.Type != ACLManagementType { 115 t.Fatalf("bad: %#v", ae) 116 } 117} 118 119func TestAPI_ACLList(t *testing.T) { 120 t.Parallel() 121 c, s := makeACLClient(t) 122 defer s.Stop() 123 124 acl := c.ACL() 125 126 acls, qm, err := acl.List(nil) 127 if err != nil { 128 t.Fatalf("err: %v", err) 129 } 130 131 // anon token is a new token 132 if len(acls) < 1 { 133 t.Fatalf("bad: %v", acls) 134 } 135 136 if qm.LastIndex == 0 { 137 t.Fatalf("bad: %v", qm) 138 } 139 if !qm.KnownLeader { 140 t.Fatalf("bad: %v", qm) 141 } 142} 143 144func TestAPI_ACLReplication(t *testing.T) { 145 t.Parallel() 146 c, s := makeACLClient(t) 147 defer s.Stop() 148 149 acl := c.ACL() 150 151 repl, qm, err := acl.Replication(nil) 152 if err != nil { 153 t.Fatalf("err: %v", err) 154 } 155 156 if repl == nil { 157 t.Fatalf("bad: %v", repl) 158 } 159 160 if repl.Running { 161 t.Fatal("bad: repl should not be running") 162 } 163 164 if repl.Enabled { 165 t.Fatal("bad: repl should not be enabled") 166 } 167 168 if qm.RequestTime == 0 { 169 t.Fatalf("bad: %v", qm) 170 } 171} 172 173func TestAPI_ACLPolicy_CreateReadDelete(t *testing.T) { 174 t.Parallel() 175 c, s := makeACLClient(t) 176 defer s.Stop() 177 178 acl := c.ACL() 179 180 created, wm, err := acl.PolicyCreate(&ACLPolicy{ 181 Name: "test-policy", 182 Description: "test-policy description", 183 Rules: `node_prefix "" { policy = "read" }`, 184 Datacenters: []string{"dc1"}, 185 }, nil) 186 187 require.NoError(t, err) 188 require.NotNil(t, created) 189 require.NotEqual(t, "", created.ID) 190 require.NotEqual(t, 0, wm.RequestTime) 191 192 read, qm, err := acl.PolicyRead(created.ID, nil) 193 require.NoError(t, err) 194 require.NotEqual(t, 0, qm.LastIndex) 195 require.True(t, qm.KnownLeader) 196 197 require.Equal(t, created, read) 198 199 wm, err = acl.PolicyDelete(created.ID, nil) 200 require.NoError(t, err) 201 require.NotEqual(t, 0, wm.RequestTime) 202 203 read, _, err = acl.PolicyRead(created.ID, nil) 204 require.Nil(t, read) 205 require.Error(t, err) 206} 207 208func TestAPI_ACLPolicy_CreateReadByNameDelete(t *testing.T) { 209 t.Parallel() 210 c, s := makeACLClient(t) 211 defer s.Stop() 212 213 acl := c.ACL() 214 215 created, wm, err := acl.PolicyCreate(&ACLPolicy{ 216 Name: "test-policy", 217 Description: "test-policy description", 218 Rules: `node_prefix "" { policy = "read" }`, 219 Datacenters: []string{"dc1"}, 220 }, nil) 221 222 require.NoError(t, err) 223 require.NotNil(t, created) 224 require.NotEqual(t, "", created.ID) 225 require.NotEqual(t, 0, wm.RequestTime) 226 227 read, qm, err := acl.PolicyReadByName(created.Name, nil) 228 require.NoError(t, err) 229 require.NotEqual(t, 0, qm.LastIndex) 230 require.True(t, qm.KnownLeader) 231 232 require.Equal(t, created, read) 233 234 wm, err = acl.PolicyDelete(created.ID, nil) 235 require.NoError(t, err) 236 require.NotEqual(t, 0, wm.RequestTime) 237 238 read, _, err = acl.PolicyRead(created.ID, nil) 239 require.Nil(t, read) 240 require.Error(t, err) 241} 242 243func TestAPI_ACLPolicy_CreateUpdate(t *testing.T) { 244 t.Parallel() 245 c, s := makeACLClient(t) 246 defer s.Stop() 247 248 acl := c.ACL() 249 250 created, _, err := acl.PolicyCreate(&ACLPolicy{ 251 Name: "test-policy", 252 Description: "test-policy description", 253 Rules: `node_prefix "" { policy = "read" }`, 254 Datacenters: []string{"dc1"}, 255 }, nil) 256 257 require.NoError(t, err) 258 require.NotNil(t, created) 259 require.NotEqual(t, "", created.ID) 260 261 read, _, err := acl.PolicyRead(created.ID, nil) 262 require.NoError(t, err) 263 require.Equal(t, created, read) 264 265 read.Rules += ` service_prefix "" { policy = "read" }` 266 read.Datacenters = nil 267 268 updated, wm, err := acl.PolicyUpdate(read, nil) 269 require.NoError(t, err) 270 require.Equal(t, created.ID, updated.ID) 271 require.Equal(t, created.Description, updated.Description) 272 require.Equal(t, read.Rules, updated.Rules) 273 require.Equal(t, created.CreateIndex, updated.CreateIndex) 274 require.NotEqual(t, created.ModifyIndex, updated.ModifyIndex) 275 require.Nil(t, updated.Datacenters) 276 require.NotEqual(t, 0, wm.RequestTime) 277 278 updated_read, _, err := acl.PolicyRead(created.ID, nil) 279 require.NoError(t, err) 280 require.Equal(t, updated, updated_read) 281} 282 283func TestAPI_ACLPolicy_List(t *testing.T) { 284 t.Parallel() 285 c, s := makeACLClient(t) 286 defer s.Stop() 287 288 acl := c.ACL() 289 290 created1, _, err := acl.PolicyCreate(&ACLPolicy{ 291 Name: "policy1", 292 Description: "policy1 description", 293 Rules: `node_prefix "" { policy = "read" }`, 294 Datacenters: []string{"dc1"}, 295 }, nil) 296 297 require.NoError(t, err) 298 require.NotNil(t, created1) 299 require.NotEqual(t, "", created1.ID) 300 301 created2, _, err := acl.PolicyCreate(&ACLPolicy{ 302 Name: "policy2", 303 Description: "policy2 description", 304 Rules: `service "app" { policy = "write" }`, 305 Datacenters: []string{"dc1", "dc2"}, 306 }, nil) 307 308 require.NoError(t, err) 309 require.NotNil(t, created2) 310 require.NotEqual(t, "", created2.ID) 311 312 created3, _, err := acl.PolicyCreate(&ACLPolicy{ 313 Name: "policy3", 314 Description: "policy3 description", 315 Rules: `acl = "read"`, 316 }, nil) 317 318 require.NoError(t, err) 319 require.NotNil(t, created3) 320 require.NotEqual(t, "", created3.ID) 321 322 policies, qm, err := acl.PolicyList(nil) 323 require.NoError(t, err) 324 require.Len(t, policies, 4) 325 require.NotEqual(t, 0, qm.LastIndex) 326 require.True(t, qm.KnownLeader) 327 328 policyMap := make(map[string]*ACLPolicyListEntry) 329 for _, policy := range policies { 330 policyMap[policy.ID] = policy 331 } 332 333 policy1, ok := policyMap[created1.ID] 334 require.True(t, ok) 335 require.NotNil(t, policy1) 336 require.Equal(t, created1.Name, policy1.Name) 337 require.Equal(t, created1.Description, policy1.Description) 338 require.Equal(t, created1.CreateIndex, policy1.CreateIndex) 339 require.Equal(t, created1.ModifyIndex, policy1.ModifyIndex) 340 require.Equal(t, created1.Hash, policy1.Hash) 341 require.ElementsMatch(t, created1.Datacenters, policy1.Datacenters) 342 343 policy2, ok := policyMap[created2.ID] 344 require.True(t, ok) 345 require.NotNil(t, policy2) 346 require.Equal(t, created2.Name, policy2.Name) 347 require.Equal(t, created2.Description, policy2.Description) 348 require.Equal(t, created2.CreateIndex, policy2.CreateIndex) 349 require.Equal(t, created2.ModifyIndex, policy2.ModifyIndex) 350 require.Equal(t, created2.Hash, policy2.Hash) 351 require.ElementsMatch(t, created2.Datacenters, policy2.Datacenters) 352 353 policy3, ok := policyMap[created3.ID] 354 require.True(t, ok) 355 require.NotNil(t, policy3) 356 require.Equal(t, created3.Name, policy3.Name) 357 require.Equal(t, created3.Description, policy3.Description) 358 require.Equal(t, created3.CreateIndex, policy3.CreateIndex) 359 require.Equal(t, created3.ModifyIndex, policy3.ModifyIndex) 360 require.Equal(t, created3.Hash, policy3.Hash) 361 require.ElementsMatch(t, created3.Datacenters, policy3.Datacenters) 362 363 // make sure the 4th policy is the global management 364 policy4, ok := policyMap["00000000-0000-0000-0000-000000000001"] 365 require.True(t, ok) 366 require.NotNil(t, policy4) 367} 368 369func prepTokenPolicies(t *testing.T, acl *ACL) (policies []*ACLPolicy) { 370 policy, _, err := acl.PolicyCreate(&ACLPolicy{ 371 Name: "one", 372 Description: "one description", 373 Rules: `acl = "read"`, 374 Datacenters: []string{"dc1", "dc2"}, 375 }, nil) 376 377 require.NoError(t, err) 378 require.NotNil(t, policy) 379 policies = append(policies, policy) 380 381 policy, _, err = acl.PolicyCreate(&ACLPolicy{ 382 Name: "two", 383 Description: "two description", 384 Rules: `node_prefix "" { policy = "read" }`, 385 Datacenters: []string{"dc1", "dc2"}, 386 }, nil) 387 388 require.NoError(t, err) 389 require.NotNil(t, policy) 390 policies = append(policies, policy) 391 392 policy, _, err = acl.PolicyCreate(&ACLPolicy{ 393 Name: "three", 394 Description: "three description", 395 Rules: `service_prefix "" { policy = "read" }`, 396 }, nil) 397 398 require.NoError(t, err) 399 require.NotNil(t, policy) 400 policies = append(policies, policy) 401 402 policy, _, err = acl.PolicyCreate(&ACLPolicy{ 403 Name: "four", 404 Description: "four description", 405 Rules: `agent "foo" { policy = "write" }`, 406 }, nil) 407 408 require.NoError(t, err) 409 require.NotNil(t, policy) 410 policies = append(policies, policy) 411 return 412} 413 414func TestAPI_ACLToken_CreateReadDelete(t *testing.T) { 415 t.Parallel() 416 c, s := makeACLClient(t) 417 defer s.Stop() 418 419 acl := c.ACL() 420 421 policies := prepTokenPolicies(t, acl) 422 423 created, wm, err := acl.TokenCreate(&ACLToken{ 424 Description: "token created", 425 Policies: []*ACLTokenPolicyLink{ 426 &ACLTokenPolicyLink{ 427 ID: policies[0].ID, 428 }, 429 &ACLTokenPolicyLink{ 430 ID: policies[1].ID, 431 }, 432 &ACLTokenPolicyLink{ 433 Name: policies[2].Name, 434 }, 435 &ACLTokenPolicyLink{ 436 Name: policies[3].Name, 437 }, 438 }, 439 }, nil) 440 441 require.NoError(t, err) 442 require.NotNil(t, created) 443 require.NotEqual(t, "", created.AccessorID) 444 require.NotEqual(t, "", created.SecretID) 445 require.NotEqual(t, 0, wm.RequestTime) 446 447 read, qm, err := acl.TokenRead(created.AccessorID, nil) 448 require.NoError(t, err) 449 require.Equal(t, created, read) 450 require.NotEqual(t, 0, qm.LastIndex) 451 require.True(t, qm.KnownLeader) 452 453 acl.c.config.Token = created.SecretID 454 self, _, err := acl.TokenReadSelf(nil) 455 require.NoError(t, err) 456 require.Equal(t, created, self) 457 acl.c.config.Token = "root" 458 459 _, err = acl.TokenDelete(created.AccessorID, nil) 460 require.NoError(t, err) 461 462 read, _, err = acl.TokenRead(created.AccessorID, nil) 463 require.Nil(t, read) 464 require.Error(t, err) 465} 466 467func TestAPI_ACLToken_CreateUpdate(t *testing.T) { 468 t.Parallel() 469 c, s := makeACLClient(t) 470 defer s.Stop() 471 472 acl := c.ACL() 473 474 policies := prepTokenPolicies(t, acl) 475 476 created, _, err := acl.TokenCreate(&ACLToken{ 477 Description: "token created", 478 Policies: []*ACLTokenPolicyLink{ 479 &ACLTokenPolicyLink{ 480 ID: policies[0].ID, 481 }, 482 &ACLTokenPolicyLink{ 483 Name: policies[2].Name, 484 }, 485 }, 486 }, nil) 487 488 require.NoError(t, err) 489 require.NotNil(t, created) 490 require.NotEqual(t, "", created.AccessorID) 491 require.NotEqual(t, "", created.SecretID) 492 493 read, _, err := acl.TokenRead(created.AccessorID, nil) 494 require.NoError(t, err) 495 require.Equal(t, created, read) 496 497 read.Policies = append(read.Policies, &ACLTokenPolicyLink{ID: policies[1].ID}) 498 read.Policies = append(read.Policies, &ACLTokenPolicyLink{Name: policies[2].Name}) 499 500 expectedPolicies := []*ACLTokenPolicyLink{ 501 &ACLTokenPolicyLink{ 502 ID: policies[0].ID, 503 Name: policies[0].Name, 504 }, 505 &ACLTokenPolicyLink{ 506 ID: policies[1].ID, 507 Name: policies[1].Name, 508 }, 509 &ACLTokenPolicyLink{ 510 ID: policies[2].ID, 511 Name: policies[2].Name, 512 }, 513 } 514 515 updated, wm, err := acl.TokenUpdate(read, nil) 516 require.NoError(t, err) 517 require.Equal(t, created.AccessorID, updated.AccessorID) 518 require.Equal(t, created.SecretID, updated.SecretID) 519 require.Equal(t, created.Description, updated.Description) 520 require.Equal(t, created.CreateIndex, updated.CreateIndex) 521 require.NotEqual(t, created.ModifyIndex, updated.ModifyIndex) 522 require.ElementsMatch(t, expectedPolicies, updated.Policies) 523 require.NotEqual(t, 0, wm.RequestTime) 524 525 updated_read, _, err := acl.TokenRead(created.AccessorID, nil) 526 require.NoError(t, err) 527 require.Equal(t, updated, updated_read) 528} 529 530func TestAPI_ACLToken_List(t *testing.T) { 531 t.Parallel() 532 c, s := makeACLClient(t) 533 defer s.Stop() 534 535 acl := c.ACL() 536 s.WaitForSerfCheck(t) 537 538 policies := prepTokenPolicies(t, acl) 539 540 created1, _, err := acl.TokenCreate(&ACLToken{ 541 Description: "token created1", 542 Policies: []*ACLTokenPolicyLink{ 543 &ACLTokenPolicyLink{ 544 ID: policies[0].ID, 545 }, 546 }, 547 }, nil) 548 549 require.NoError(t, err) 550 require.NotNil(t, created1) 551 require.NotEqual(t, "", created1.AccessorID) 552 require.NotEqual(t, "", created1.SecretID) 553 554 created2, _, err := acl.TokenCreate(&ACLToken{ 555 Description: "token created2", 556 Policies: []*ACLTokenPolicyLink{ 557 &ACLTokenPolicyLink{ 558 ID: policies[1].ID, 559 }, 560 }, 561 }, nil) 562 563 require.NoError(t, err) 564 require.NotNil(t, created2) 565 require.NotEqual(t, "", created2.AccessorID) 566 require.NotEqual(t, "", created2.SecretID) 567 568 created3, _, err := acl.TokenCreate(&ACLToken{ 569 Description: "token created3", 570 Policies: []*ACLTokenPolicyLink{ 571 &ACLTokenPolicyLink{ 572 ID: policies[2].ID, 573 }, 574 }, 575 }, nil) 576 577 require.NoError(t, err) 578 require.NotNil(t, created3) 579 require.NotEqual(t, "", created3.AccessorID) 580 require.NotEqual(t, "", created3.SecretID) 581 582 tokens, qm, err := acl.TokenList(nil) 583 require.NoError(t, err) 584 // 3 + anon + master 585 require.Len(t, tokens, 5) 586 require.NotEqual(t, 0, qm.LastIndex) 587 require.True(t, qm.KnownLeader) 588 589 tokenMap := make(map[string]*ACLTokenListEntry) 590 for _, token := range tokens { 591 tokenMap[token.AccessorID] = token 592 } 593 594 token1, ok := tokenMap[created1.AccessorID] 595 require.True(t, ok) 596 require.NotNil(t, token1) 597 require.Equal(t, created1.Description, token1.Description) 598 require.Equal(t, created1.CreateIndex, token1.CreateIndex) 599 require.Equal(t, created1.ModifyIndex, token1.ModifyIndex) 600 require.Equal(t, created1.Hash, token1.Hash) 601 require.ElementsMatch(t, created1.Policies, token1.Policies) 602 603 token2, ok := tokenMap[created2.AccessorID] 604 require.True(t, ok) 605 require.NotNil(t, token2) 606 require.Equal(t, created2.Description, token2.Description) 607 require.Equal(t, created2.CreateIndex, token2.CreateIndex) 608 require.Equal(t, created2.ModifyIndex, token2.ModifyIndex) 609 require.Equal(t, created2.Hash, token2.Hash) 610 require.ElementsMatch(t, created2.Policies, token2.Policies) 611 612 token3, ok := tokenMap[created3.AccessorID] 613 require.True(t, ok) 614 require.NotNil(t, token3) 615 require.Equal(t, created3.Description, token3.Description) 616 require.Equal(t, created3.CreateIndex, token3.CreateIndex) 617 require.Equal(t, created3.ModifyIndex, token3.ModifyIndex) 618 require.Equal(t, created3.Hash, token3.Hash) 619 require.ElementsMatch(t, created3.Policies, token3.Policies) 620 621 // make sure the there is an anon token 622 token4, ok := tokenMap["00000000-0000-0000-0000-000000000002"] 623 require.True(t, ok) 624 require.NotNil(t, token4) 625 626 // ensure the 5th token is the root master token 627 root, _, err := acl.TokenReadSelf(nil) 628 require.NoError(t, err) 629 require.NotNil(t, root) 630 token5, ok := tokenMap[root.AccessorID] 631 require.True(t, ok) 632 require.NotNil(t, token5) 633} 634 635func TestAPI_ACLToken_Clone(t *testing.T) { 636 t.Parallel() 637 c, s := makeACLClient(t) 638 defer s.Stop() 639 640 acl := c.ACL() 641 642 master, _, err := acl.TokenReadSelf(nil) 643 require.NoError(t, err) 644 require.NotNil(t, master) 645 646 cloned, _, err := acl.TokenClone(master.AccessorID, "cloned", nil) 647 require.NoError(t, err) 648 require.NotNil(t, cloned) 649 require.NotEqual(t, master.AccessorID, cloned.AccessorID) 650 require.NotEqual(t, master.SecretID, cloned.SecretID) 651 require.Equal(t, "cloned", cloned.Description) 652 require.ElementsMatch(t, master.Policies, cloned.Policies) 653 654 read, _, err := acl.TokenRead(cloned.AccessorID, nil) 655 require.NoError(t, err) 656 require.NotNil(t, read) 657 require.Equal(t, cloned, read) 658} 659 660func TestAPI_RulesTranslate_FromToken(t *testing.T) { 661 t.Parallel() 662 c, s := makeACLClient(t) 663 defer s.Stop() 664 665 acl := c.ACL() 666 667 ae := ACLEntry{ 668 Name: "API test", 669 Type: ACLClientType, 670 Rules: `key "" { policy = "deny" }`, 671 } 672 673 id, _, err := acl.Create(&ae, nil) 674 require.NoError(t, err) 675 676 var accessor string 677 acl.c.config.Token = id 678 679 // This relies on the token upgrade loop running in the background 680 // to assign an accessor 681 retry.Run(t, func(r *retry.R) { 682 token, _, err := acl.TokenReadSelf(nil) 683 require.NoError(r, err) 684 require.NotEqual(r, "", token.AccessorID) 685 accessor = token.AccessorID 686 }) 687 acl.c.config.Token = "root" 688 689 rules, err := acl.RulesTranslateToken(accessor) 690 require.NoError(t, err) 691 require.Equal(t, "key_prefix \"\" {\n policy = \"deny\"\n}", rules) 692} 693 694func TestAPI_RulesTranslate_Raw(t *testing.T) { 695 t.Parallel() 696 c, s := makeACLClient(t) 697 defer s.Stop() 698 699 acl := c.ACL() 700 701 input := `#start of policy 702agent "" { 703 policy = "read" 704} 705 706node "" { 707 policy = "read" 708} 709 710service "" { 711 policy = "read" 712} 713 714key "" { 715 policy = "read" 716} 717 718session "" { 719 policy = "read" 720} 721 722event "" { 723 policy = "read" 724} 725 726query "" { 727 policy = "read" 728}` 729 730 expected := `#start of policy 731agent_prefix "" { 732 policy = "read" 733} 734 735node_prefix "" { 736 policy = "read" 737} 738 739service_prefix "" { 740 policy = "read" 741} 742 743key_prefix "" { 744 policy = "read" 745} 746 747session_prefix "" { 748 policy = "read" 749} 750 751event_prefix "" { 752 policy = "read" 753} 754 755query_prefix "" { 756 policy = "read" 757}` 758 759 rules, err := acl.RulesTranslate(strings.NewReader(input)) 760 require.NoError(t, err) 761 require.Equal(t, expected, rules) 762} 763