github.imxd.top/hashicorp/consul@v1.4.5/agent/consul/txn_endpoint_test.go (about) 1 package consul 2 3 import ( 4 "bytes" 5 "os" 6 "reflect" 7 "strings" 8 "testing" 9 "time" 10 11 "github.com/hashicorp/consul/acl" 12 "github.com/hashicorp/consul/agent/structs" 13 "github.com/hashicorp/consul/api" 14 "github.com/hashicorp/consul/testrpc" 15 "github.com/hashicorp/consul/types" 16 "github.com/hashicorp/net-rpc-msgpackrpc" 17 "github.com/pascaldekloe/goe/verify" 18 "github.com/stretchr/testify/require" 19 ) 20 21 var testTxnRules = ` 22 key "" { 23 policy = "deny" 24 } 25 key "foo" { 26 policy = "read" 27 } 28 key "test" { 29 policy = "write" 30 } 31 key "test/priv" { 32 policy = "read" 33 } 34 35 service "" { 36 policy = "deny" 37 } 38 service "foo-svc" { 39 policy = "read" 40 } 41 service "test-svc" { 42 policy = "write" 43 } 44 45 node "" { 46 policy = "deny" 47 } 48 node "foo-node" { 49 policy = "read" 50 } 51 node "test-node" { 52 policy = "write" 53 } 54 ` 55 56 var testNodeID = "9749a7df-fac5-46b4-8078-32a3d96c59f3" 57 58 func TestTxn_CheckNotExists(t *testing.T) { 59 t.Parallel() 60 dir1, s1 := testServer(t) 61 defer os.RemoveAll(dir1) 62 defer s1.Shutdown() 63 codec := rpcClient(t, s1) 64 defer codec.Close() 65 66 testrpc.WaitForLeader(t, s1.RPC, "dc1") 67 68 apply := func(arg *structs.TxnRequest) (*structs.TxnResponse, error) { 69 out := new(structs.TxnResponse) 70 err := msgpackrpc.CallWithCodec(codec, "Txn.Apply", arg, out) 71 return out, err 72 } 73 74 checkKeyNotExists := &structs.TxnRequest{ 75 Datacenter: "dc1", 76 Ops: structs.TxnOps{ 77 { 78 KV: &structs.TxnKVOp{ 79 Verb: api.KVCheckNotExists, 80 DirEnt: structs.DirEntry{Key: "test"}, 81 }, 82 }, 83 }, 84 } 85 86 createKey := &structs.TxnRequest{ 87 Datacenter: "dc1", 88 Ops: structs.TxnOps{ 89 { 90 KV: &structs.TxnKVOp{ 91 Verb: api.KVSet, 92 DirEnt: structs.DirEntry{Key: "test"}, 93 }, 94 }, 95 }, 96 } 97 98 if _, err := apply(checkKeyNotExists); err != nil { 99 t.Fatalf("testing for non-existent key failed: %s", err) 100 } 101 if _, err := apply(createKey); err != nil { 102 t.Fatalf("creating new key failed: %s", err) 103 } 104 out, err := apply(checkKeyNotExists) 105 if err != nil || out == nil || len(out.Errors) != 1 || out.Errors[0].Error() != `op 0: key "test" exists` { 106 t.Fatalf("testing for existent key failed: %#v", out) 107 } 108 } 109 110 func TestTxn_Apply(t *testing.T) { 111 t.Parallel() 112 dir1, s1 := testServer(t) 113 defer os.RemoveAll(dir1) 114 defer s1.Shutdown() 115 codec := rpcClient(t, s1) 116 defer codec.Close() 117 118 testrpc.WaitForLeader(t, s1.RPC, "dc1") 119 120 // Do a super basic request. The state store test covers the details so 121 // we just need to be sure that the transaction is sent correctly and 122 // the results are converted appropriately. 123 arg := structs.TxnRequest{ 124 Datacenter: "dc1", 125 Ops: structs.TxnOps{ 126 &structs.TxnOp{ 127 KV: &structs.TxnKVOp{ 128 Verb: api.KVSet, 129 DirEnt: structs.DirEntry{ 130 Key: "test", 131 Flags: 42, 132 Value: []byte("test"), 133 }, 134 }, 135 }, 136 &structs.TxnOp{ 137 KV: &structs.TxnKVOp{ 138 Verb: api.KVGet, 139 DirEnt: structs.DirEntry{ 140 Key: "test", 141 }, 142 }, 143 }, 144 &structs.TxnOp{ 145 Node: &structs.TxnNodeOp{ 146 Verb: api.NodeSet, 147 Node: structs.Node{ 148 ID: types.NodeID(testNodeID), 149 Node: "foo", 150 Address: "127.0.0.1", 151 }, 152 }, 153 }, 154 &structs.TxnOp{ 155 Node: &structs.TxnNodeOp{ 156 Verb: api.NodeGet, 157 Node: structs.Node{ 158 ID: types.NodeID(testNodeID), 159 Node: "foo", 160 }, 161 }, 162 }, 163 &structs.TxnOp{ 164 Service: &structs.TxnServiceOp{ 165 Verb: api.ServiceSet, 166 Node: "foo", 167 Service: structs.NodeService{ 168 ID: "svc-foo", 169 Service: "svc-foo", 170 Address: "1.1.1.1", 171 }, 172 }, 173 }, 174 &structs.TxnOp{ 175 Service: &structs.TxnServiceOp{ 176 Verb: api.ServiceGet, 177 Node: "foo", 178 Service: structs.NodeService{ 179 ID: "svc-foo", 180 Service: "svc-foo", 181 }, 182 }, 183 }, 184 &structs.TxnOp{ 185 Check: &structs.TxnCheckOp{ 186 Verb: api.CheckSet, 187 Check: structs.HealthCheck{ 188 Node: "foo", 189 CheckID: types.CheckID("check-foo"), 190 Name: "test", 191 Status: "passing", 192 }, 193 }, 194 }, 195 &structs.TxnOp{ 196 Check: &structs.TxnCheckOp{ 197 Verb: api.CheckGet, 198 Check: structs.HealthCheck{ 199 Node: "foo", 200 CheckID: types.CheckID("check-foo"), 201 Name: "test", 202 }, 203 }, 204 }, 205 }, 206 } 207 var out structs.TxnResponse 208 if err := msgpackrpc.CallWithCodec(codec, "Txn.Apply", &arg, &out); err != nil { 209 t.Fatalf("err: %v", err) 210 } 211 if len(out.Errors) != 0 { 212 t.Fatalf("errs: %v", out.Errors) 213 } 214 215 // Verify the state store directly. 216 state := s1.fsm.State() 217 _, d, err := state.KVSGet(nil, "test") 218 if err != nil { 219 t.Fatalf("err: %v", err) 220 } 221 if d == nil { 222 t.Fatalf("should not be nil") 223 } 224 if d.Flags != 42 || 225 !bytes.Equal(d.Value, []byte("test")) { 226 t.Fatalf("bad: %v", d) 227 } 228 229 _, n, err := state.GetNode("foo") 230 if err != nil { 231 t.Fatalf("err: %v", err) 232 } 233 if n.Node != "foo" || n.Address != "127.0.0.1" { 234 t.Fatalf("bad: %v", err) 235 } 236 237 _, s, err := state.NodeService("foo", "svc-foo") 238 if err != nil { 239 t.Fatalf("err: %v", err) 240 } 241 if s.ID != "svc-foo" || s.Address != "1.1.1.1" { 242 t.Fatalf("bad: %v", err) 243 } 244 245 _, c, err := state.NodeCheck("foo", types.CheckID("check-foo")) 246 if err != nil { 247 t.Fatalf("err: %v", err) 248 } 249 if c.CheckID != "check-foo" || c.Status != "passing" || c.Name != "test" { 250 t.Fatalf("bad: %v", err) 251 } 252 253 // Verify the transaction's return value. 254 expected := structs.TxnResponse{ 255 Results: structs.TxnResults{ 256 &structs.TxnResult{ 257 KV: &structs.DirEntry{ 258 Key: "test", 259 Flags: 42, 260 Value: nil, 261 RaftIndex: structs.RaftIndex{ 262 CreateIndex: d.CreateIndex, 263 ModifyIndex: d.ModifyIndex, 264 }, 265 }, 266 }, 267 &structs.TxnResult{ 268 KV: &structs.DirEntry{ 269 Key: "test", 270 Flags: 42, 271 Value: []byte("test"), 272 RaftIndex: structs.RaftIndex{ 273 CreateIndex: d.CreateIndex, 274 ModifyIndex: d.ModifyIndex, 275 }, 276 }, 277 }, 278 &structs.TxnResult{ 279 Node: n, 280 }, 281 &structs.TxnResult{ 282 Node: n, 283 }, 284 &structs.TxnResult{ 285 Service: s, 286 }, 287 &structs.TxnResult{ 288 Service: s, 289 }, 290 &structs.TxnResult{ 291 Check: c, 292 }, 293 &structs.TxnResult{ 294 Check: c, 295 }, 296 }, 297 } 298 verify.Values(t, "", out, expected) 299 } 300 301 func TestTxn_Apply_ACLDeny(t *testing.T) { 302 t.Parallel() 303 304 require := require.New(t) 305 306 dir1, s1 := testServerWithConfig(t, func(c *Config) { 307 c.ACLDatacenter = "dc1" 308 c.ACLsEnabled = true 309 c.ACLMasterToken = "root" 310 c.ACLDefaultPolicy = "deny" 311 }) 312 defer os.RemoveAll(dir1) 313 defer s1.Shutdown() 314 315 testrpc.WaitForLeader(t, s1.RPC, "dc1") 316 317 // Set up some state to read back. 318 state := s1.fsm.State() 319 d := &structs.DirEntry{ 320 Key: "nope", 321 Value: []byte("hello"), 322 } 323 require.NoError(state.KVSSet(1, d)) 324 325 node := &structs.Node{ 326 ID: types.NodeID(testNodeID), 327 Node: "nope", 328 } 329 require.NoError(state.EnsureNode(2, node)) 330 331 svc := structs.NodeService{ID: "nope", Service: "nope", Address: "127.0.0.1"} 332 require.NoError(state.EnsureService(3, "nope", &svc)) 333 334 check := structs.HealthCheck{Node: "nope", CheckID: types.CheckID("nope")} 335 state.EnsureCheck(4, &check) 336 337 // Create the ACL. 338 var id string 339 { 340 arg := structs.ACLRequest{ 341 Datacenter: "dc1", 342 Op: structs.ACLSet, 343 ACL: structs.ACL{ 344 Name: "User token", 345 Type: structs.ACLTokenTypeClient, 346 Rules: testTxnRules, 347 }, 348 WriteRequest: structs.WriteRequest{Token: "root"}, 349 } 350 if err := s1.RPC("ACL.Apply", &arg, &id); err != nil { 351 t.Fatalf("err: %v", err) 352 } 353 } 354 355 // Set up a transaction where every operation should get blocked due to 356 // ACLs. 357 arg := structs.TxnRequest{ 358 Datacenter: "dc1", 359 Ops: structs.TxnOps{ 360 &structs.TxnOp{ 361 KV: &structs.TxnKVOp{ 362 Verb: api.KVSet, 363 DirEnt: structs.DirEntry{ 364 Key: "nope", 365 }, 366 }, 367 }, 368 &structs.TxnOp{ 369 KV: &structs.TxnKVOp{ 370 Verb: api.KVDelete, 371 DirEnt: structs.DirEntry{ 372 Key: "nope", 373 }, 374 }, 375 }, 376 &structs.TxnOp{ 377 KV: &structs.TxnKVOp{ 378 Verb: api.KVDeleteCAS, 379 DirEnt: structs.DirEntry{ 380 Key: "nope", 381 }, 382 }, 383 }, 384 &structs.TxnOp{ 385 KV: &structs.TxnKVOp{ 386 Verb: api.KVDeleteTree, 387 DirEnt: structs.DirEntry{ 388 Key: "nope", 389 }, 390 }, 391 }, 392 &structs.TxnOp{ 393 KV: &structs.TxnKVOp{ 394 Verb: api.KVCAS, 395 DirEnt: structs.DirEntry{ 396 Key: "nope", 397 }, 398 }, 399 }, 400 &structs.TxnOp{ 401 KV: &structs.TxnKVOp{ 402 Verb: api.KVLock, 403 DirEnt: structs.DirEntry{ 404 Key: "nope", 405 }, 406 }, 407 }, 408 &structs.TxnOp{ 409 KV: &structs.TxnKVOp{ 410 Verb: api.KVUnlock, 411 DirEnt: structs.DirEntry{ 412 Key: "nope", 413 }, 414 }, 415 }, 416 &structs.TxnOp{ 417 KV: &structs.TxnKVOp{ 418 Verb: api.KVGet, 419 DirEnt: structs.DirEntry{ 420 Key: "nope", 421 }, 422 }, 423 }, 424 &structs.TxnOp{ 425 KV: &structs.TxnKVOp{ 426 Verb: api.KVGetTree, 427 DirEnt: structs.DirEntry{ 428 Key: "nope", 429 }, 430 }, 431 }, 432 &structs.TxnOp{ 433 KV: &structs.TxnKVOp{ 434 Verb: api.KVCheckSession, 435 DirEnt: structs.DirEntry{ 436 Key: "nope", 437 }, 438 }, 439 }, 440 &structs.TxnOp{ 441 KV: &structs.TxnKVOp{ 442 Verb: api.KVCheckIndex, 443 DirEnt: structs.DirEntry{ 444 Key: "nope", 445 }, 446 }, 447 }, 448 &structs.TxnOp{ 449 KV: &structs.TxnKVOp{ 450 Verb: api.KVCheckNotExists, 451 DirEnt: structs.DirEntry{ 452 Key: "nope", 453 }, 454 }, 455 }, 456 &structs.TxnOp{ 457 Node: &structs.TxnNodeOp{ 458 Verb: api.NodeGet, 459 Node: structs.Node{ID: node.ID, Node: node.Node}, 460 }, 461 }, 462 &structs.TxnOp{ 463 Node: &structs.TxnNodeOp{ 464 Verb: api.NodeSet, 465 Node: structs.Node{ID: node.ID, Node: node.Node}, 466 }, 467 }, 468 &structs.TxnOp{ 469 Node: &structs.TxnNodeOp{ 470 Verb: api.NodeCAS, 471 Node: structs.Node{ID: node.ID, Node: node.Node}, 472 }, 473 }, 474 &structs.TxnOp{ 475 Node: &structs.TxnNodeOp{ 476 Verb: api.NodeDelete, 477 Node: structs.Node{ID: node.ID, Node: node.Node}, 478 }, 479 }, 480 &structs.TxnOp{ 481 Node: &structs.TxnNodeOp{ 482 Verb: api.NodeDeleteCAS, 483 Node: structs.Node{ID: node.ID, Node: node.Node}, 484 }, 485 }, 486 &structs.TxnOp{ 487 Service: &structs.TxnServiceOp{ 488 Verb: api.ServiceGet, 489 Node: "foo-node", 490 Service: svc, 491 }, 492 }, 493 &structs.TxnOp{ 494 Service: &structs.TxnServiceOp{ 495 Verb: api.ServiceSet, 496 Node: "foo-node", 497 Service: svc, 498 }, 499 }, 500 &structs.TxnOp{ 501 Service: &structs.TxnServiceOp{ 502 Verb: api.ServiceCAS, 503 Node: "foo-node", 504 Service: svc, 505 }, 506 }, 507 &structs.TxnOp{ 508 Service: &structs.TxnServiceOp{ 509 Verb: api.ServiceDelete, 510 Node: "foo-node", 511 Service: svc, 512 }, 513 }, 514 &structs.TxnOp{ 515 Service: &structs.TxnServiceOp{ 516 Verb: api.ServiceDeleteCAS, 517 Node: "foo-node", 518 Service: svc, 519 }, 520 }, 521 &structs.TxnOp{ 522 Check: &structs.TxnCheckOp{ 523 Verb: api.CheckGet, 524 Check: check, 525 }, 526 }, 527 &structs.TxnOp{ 528 Check: &structs.TxnCheckOp{ 529 Verb: api.CheckSet, 530 Check: check, 531 }, 532 }, 533 &structs.TxnOp{ 534 Check: &structs.TxnCheckOp{ 535 Verb: api.CheckCAS, 536 Check: check, 537 }, 538 }, 539 &structs.TxnOp{ 540 Check: &structs.TxnCheckOp{ 541 Verb: api.CheckDelete, 542 Check: check, 543 }, 544 }, 545 &structs.TxnOp{ 546 Check: &structs.TxnCheckOp{ 547 Verb: api.CheckDeleteCAS, 548 Check: check, 549 }, 550 }, 551 }, 552 WriteRequest: structs.WriteRequest{ 553 Token: id, 554 }, 555 } 556 var out structs.TxnResponse 557 if err := s1.RPC("Txn.Apply", &arg, &out); err != nil { 558 t.Fatalf("err: %v", err) 559 } 560 561 // Verify the transaction's return value. 562 var expected structs.TxnResponse 563 for i, op := range arg.Ops { 564 switch { 565 case op.KV != nil: 566 switch op.KV.Verb { 567 case api.KVGet, api.KVGetTree: 568 // These get filtered but won't result in an error. 569 570 default: 571 expected.Errors = append(expected.Errors, &structs.TxnError{ 572 OpIndex: i, 573 What: acl.ErrPermissionDenied.Error(), 574 }) 575 } 576 case op.Node != nil: 577 switch op.Node.Verb { 578 case api.NodeGet: 579 // These get filtered but won't result in an error. 580 581 default: 582 expected.Errors = append(expected.Errors, &structs.TxnError{ 583 OpIndex: i, 584 What: acl.ErrPermissionDenied.Error(), 585 }) 586 } 587 case op.Service != nil: 588 switch op.Service.Verb { 589 case api.ServiceGet: 590 // These get filtered but won't result in an error. 591 592 default: 593 expected.Errors = append(expected.Errors, &structs.TxnError{ 594 OpIndex: i, 595 What: acl.ErrPermissionDenied.Error(), 596 }) 597 } 598 case op.Check != nil: 599 switch op.Check.Verb { 600 case api.CheckGet: 601 // These get filtered but won't result in an error. 602 603 default: 604 expected.Errors = append(expected.Errors, &structs.TxnError{ 605 OpIndex: i, 606 What: acl.ErrPermissionDenied.Error(), 607 }) 608 } 609 } 610 } 611 612 verify.Values(t, "", out, expected) 613 } 614 615 func TestTxn_Apply_LockDelay(t *testing.T) { 616 t.Parallel() 617 dir1, s1 := testServer(t) 618 defer os.RemoveAll(dir1) 619 defer s1.Shutdown() 620 codec := rpcClient(t, s1) 621 defer codec.Close() 622 623 testrpc.WaitForLeader(t, s1.RPC, "dc1") 624 625 // Create and invalidate a session with a lock. 626 state := s1.fsm.State() 627 if err := state.EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { 628 t.Fatalf("err: %v", err) 629 } 630 session := &structs.Session{ 631 ID: generateUUID(), 632 Node: "foo", 633 LockDelay: 50 * time.Millisecond, 634 } 635 if err := state.SessionCreate(2, session); err != nil { 636 t.Fatalf("err: %v", err) 637 } 638 id := session.ID 639 d := &structs.DirEntry{ 640 Key: "test", 641 Session: id, 642 } 643 if ok, err := state.KVSLock(3, d); err != nil || !ok { 644 t.Fatalf("err: %v", err) 645 } 646 if err := state.SessionDestroy(4, id); err != nil { 647 t.Fatalf("err: %v", err) 648 } 649 650 // Make a new session that is valid. 651 if err := state.SessionCreate(5, session); err != nil { 652 t.Fatalf("err: %v", err) 653 } 654 validID := session.ID 655 656 // Make a lock request via an atomic transaction. 657 arg := structs.TxnRequest{ 658 Datacenter: "dc1", 659 Ops: structs.TxnOps{ 660 &structs.TxnOp{ 661 KV: &structs.TxnKVOp{ 662 Verb: api.KVLock, 663 DirEnt: structs.DirEntry{ 664 Key: "test", 665 Session: validID, 666 }, 667 }, 668 }, 669 }, 670 } 671 { 672 var out structs.TxnResponse 673 if err := msgpackrpc.CallWithCodec(codec, "Txn.Apply", &arg, &out); err != nil { 674 t.Fatalf("err: %v", err) 675 } 676 if len(out.Results) != 0 || 677 len(out.Errors) != 1 || 678 out.Errors[0].OpIndex != 0 || 679 !strings.Contains(out.Errors[0].What, "due to lock delay") { 680 t.Fatalf("bad: %v", out) 681 } 682 } 683 684 // Wait for lock-delay. 685 time.Sleep(50 * time.Millisecond) 686 687 // Should acquire. 688 { 689 var out structs.TxnResponse 690 if err := msgpackrpc.CallWithCodec(codec, "Txn.Apply", &arg, &out); err != nil { 691 t.Fatalf("err: %v", err) 692 } 693 if len(out.Results) != 1 || 694 len(out.Errors) != 0 || 695 out.Results[0].KV.LockIndex != 2 { 696 t.Fatalf("bad: %v", out) 697 } 698 } 699 } 700 701 func TestTxn_Read(t *testing.T) { 702 t.Parallel() 703 704 require := require.New(t) 705 706 dir1, s1 := testServer(t) 707 defer os.RemoveAll(dir1) 708 defer s1.Shutdown() 709 codec := rpcClient(t, s1) 710 defer codec.Close() 711 712 testrpc.WaitForLeader(t, s1.RPC, "dc1") 713 714 // Put in a key to read back. 715 state := s1.fsm.State() 716 d := &structs.DirEntry{ 717 Key: "test", 718 Value: []byte("hello"), 719 } 720 if err := state.KVSSet(1, d); err != nil { 721 t.Fatalf("err: %v", err) 722 } 723 724 // Put in a node/check/service to read back. 725 node := &structs.Node{ 726 ID: types.NodeID(testNodeID), 727 Node: "foo", 728 } 729 require.NoError(state.EnsureNode(2, node)) 730 731 svc := structs.NodeService{ID: "svc-foo", Service: "svc-foo", Address: "127.0.0.1"} 732 require.NoError(state.EnsureService(3, "foo", &svc)) 733 734 check := structs.HealthCheck{Node: "foo", CheckID: types.CheckID("check-foo")} 735 state.EnsureCheck(4, &check) 736 737 // Do a super basic request. The state store test covers the details so 738 // we just need to be sure that the transaction is sent correctly and 739 // the results are converted appropriately. 740 arg := structs.TxnReadRequest{ 741 Datacenter: "dc1", 742 Ops: structs.TxnOps{ 743 &structs.TxnOp{ 744 KV: &structs.TxnKVOp{ 745 Verb: api.KVGet, 746 DirEnt: structs.DirEntry{ 747 Key: "test", 748 }, 749 }, 750 }, 751 &structs.TxnOp{ 752 Node: &structs.TxnNodeOp{ 753 Verb: api.NodeGet, 754 Node: structs.Node{ID: node.ID, Node: node.Node}, 755 }, 756 }, 757 &structs.TxnOp{ 758 Service: &structs.TxnServiceOp{ 759 Verb: api.ServiceGet, 760 Node: "foo", 761 Service: svc, 762 }, 763 }, 764 &structs.TxnOp{ 765 Check: &structs.TxnCheckOp{ 766 Verb: api.CheckGet, 767 Check: check, 768 }, 769 }, 770 }, 771 } 772 var out structs.TxnReadResponse 773 if err := msgpackrpc.CallWithCodec(codec, "Txn.Read", &arg, &out); err != nil { 774 t.Fatalf("err: %v", err) 775 } 776 777 // Verify the transaction's return value. 778 svc.Weights = &structs.Weights{Passing: 1, Warning: 1} 779 svc.RaftIndex = structs.RaftIndex{CreateIndex: 3, ModifyIndex: 3} 780 expected := structs.TxnReadResponse{ 781 TxnResponse: structs.TxnResponse{ 782 Results: structs.TxnResults{ 783 &structs.TxnResult{ 784 KV: &structs.DirEntry{ 785 Key: "test", 786 Value: []byte("hello"), 787 RaftIndex: structs.RaftIndex{ 788 CreateIndex: 1, 789 ModifyIndex: 1, 790 }, 791 }, 792 }, 793 &structs.TxnResult{ 794 Node: node, 795 }, 796 &structs.TxnResult{ 797 Service: &svc, 798 }, 799 &structs.TxnResult{ 800 Check: &check, 801 }, 802 }, 803 }, 804 QueryMeta: structs.QueryMeta{ 805 KnownLeader: true, 806 }, 807 } 808 verify.Values(t, "", out, expected) 809 } 810 811 func TestTxn_Read_ACLDeny(t *testing.T) { 812 t.Parallel() 813 814 require := require.New(t) 815 816 dir1, s1 := testServerWithConfig(t, func(c *Config) { 817 c.ACLDatacenter = "dc1" 818 c.ACLsEnabled = true 819 c.ACLMasterToken = "root" 820 c.ACLDefaultPolicy = "deny" 821 }) 822 defer os.RemoveAll(dir1) 823 defer s1.Shutdown() 824 codec := rpcClient(t, s1) 825 defer codec.Close() 826 827 testrpc.WaitForLeader(t, s1.RPC, "dc1") 828 829 // Put in a key to read back. 830 state := s1.fsm.State() 831 d := &structs.DirEntry{ 832 Key: "nope", 833 Value: []byte("hello"), 834 } 835 if err := state.KVSSet(1, d); err != nil { 836 t.Fatalf("err: %v", err) 837 } 838 839 // Put in a node/check/service to read back. 840 node := &structs.Node{ 841 ID: types.NodeID(testNodeID), 842 Node: "nope", 843 } 844 require.NoError(state.EnsureNode(2, node)) 845 846 svc := structs.NodeService{ID: "nope", Service: "nope", Address: "127.0.0.1"} 847 require.NoError(state.EnsureService(3, "nope", &svc)) 848 849 check := structs.HealthCheck{Node: "nope", CheckID: types.CheckID("nope")} 850 state.EnsureCheck(4, &check) 851 852 // Create the ACL. 853 var id string 854 { 855 arg := structs.ACLRequest{ 856 Datacenter: "dc1", 857 Op: structs.ACLSet, 858 ACL: structs.ACL{ 859 Name: "User token", 860 Type: structs.ACLTokenTypeClient, 861 Rules: testTxnRules, 862 }, 863 WriteRequest: structs.WriteRequest{Token: "root"}, 864 } 865 if err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &id); err != nil { 866 t.Fatalf("err: %v", err) 867 } 868 } 869 870 // Set up a transaction where every operation should get blocked due to 871 // ACLs. 872 arg := structs.TxnReadRequest{ 873 Datacenter: "dc1", 874 Ops: structs.TxnOps{ 875 &structs.TxnOp{ 876 KV: &structs.TxnKVOp{ 877 Verb: api.KVGet, 878 DirEnt: structs.DirEntry{ 879 Key: "nope", 880 }, 881 }, 882 }, 883 &structs.TxnOp{ 884 KV: &structs.TxnKVOp{ 885 Verb: api.KVGetTree, 886 DirEnt: structs.DirEntry{ 887 Key: "nope", 888 }, 889 }, 890 }, 891 &structs.TxnOp{ 892 KV: &structs.TxnKVOp{ 893 Verb: api.KVCheckSession, 894 DirEnt: structs.DirEntry{ 895 Key: "nope", 896 }, 897 }, 898 }, 899 &structs.TxnOp{ 900 KV: &structs.TxnKVOp{ 901 Verb: api.KVCheckIndex, 902 DirEnt: structs.DirEntry{ 903 Key: "nope", 904 }, 905 }, 906 }, 907 &structs.TxnOp{ 908 Node: &structs.TxnNodeOp{ 909 Verb: api.NodeGet, 910 Node: structs.Node{ID: node.ID, Node: node.Node}, 911 }, 912 }, 913 &structs.TxnOp{ 914 Service: &structs.TxnServiceOp{ 915 Verb: api.ServiceGet, 916 Node: "foo", 917 Service: svc, 918 }, 919 }, 920 &structs.TxnOp{ 921 Check: &structs.TxnCheckOp{ 922 Verb: api.CheckGet, 923 Check: check, 924 }, 925 }, 926 }, 927 QueryOptions: structs.QueryOptions{ 928 Token: id, 929 }, 930 } 931 var out structs.TxnReadResponse 932 if err := msgpackrpc.CallWithCodec(codec, "Txn.Read", &arg, &out); err != nil { 933 t.Fatalf("err: %v", err) 934 } 935 936 // Verify the transaction's return value. 937 expected := structs.TxnReadResponse{ 938 QueryMeta: structs.QueryMeta{ 939 KnownLeader: true, 940 }, 941 } 942 for i, op := range arg.Ops { 943 switch { 944 case op.KV != nil: 945 switch op.KV.Verb { 946 case api.KVGet, api.KVGetTree: 947 // These get filtered but won't result in an error. 948 949 default: 950 expected.Errors = append(expected.Errors, &structs.TxnError{ 951 OpIndex: i, 952 What: acl.ErrPermissionDenied.Error(), 953 }) 954 } 955 case op.Node != nil: 956 switch op.Node.Verb { 957 case api.NodeGet: 958 // These get filtered but won't result in an error. 959 960 default: 961 expected.Errors = append(expected.Errors, &structs.TxnError{ 962 OpIndex: i, 963 What: acl.ErrPermissionDenied.Error(), 964 }) 965 } 966 case op.Service != nil: 967 switch op.Service.Verb { 968 case api.ServiceGet: 969 // These get filtered but won't result in an error. 970 971 default: 972 expected.Errors = append(expected.Errors, &structs.TxnError{ 973 OpIndex: i, 974 What: acl.ErrPermissionDenied.Error(), 975 }) 976 } 977 case op.Check != nil: 978 switch op.Check.Verb { 979 case api.CheckGet: 980 // These get filtered but won't result in an error. 981 982 default: 983 expected.Errors = append(expected.Errors, &structs.TxnError{ 984 OpIndex: i, 985 What: acl.ErrPermissionDenied.Error(), 986 }) 987 } 988 } 989 } 990 if !reflect.DeepEqual(out, expected) { 991 t.Fatalf("bad %v", out) 992 } 993 }