github.com/zoomfoo/nomad@v0.8.5-0.20180907175415-f28fd3a1a056/nomad/acl_endpoint_test.go (about) 1 package nomad 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 "strings" 9 "testing" 10 "time" 11 12 msgpackrpc "github.com/hashicorp/net-rpc-msgpackrpc" 13 "github.com/hashicorp/nomad/helper/uuid" 14 "github.com/hashicorp/nomad/nomad/mock" 15 "github.com/hashicorp/nomad/nomad/structs" 16 "github.com/hashicorp/nomad/testutil" 17 "github.com/stretchr/testify/assert" 18 ) 19 20 func TestACLEndpoint_GetPolicy(t *testing.T) { 21 t.Parallel() 22 s1, root := TestACLServer(t, nil) 23 defer s1.Shutdown() 24 codec := rpcClient(t, s1) 25 testutil.WaitForLeader(t, s1.RPC) 26 27 // Create the register request 28 policy := mock.ACLPolicy() 29 s1.fsm.State().UpsertACLPolicies(1000, []*structs.ACLPolicy{policy}) 30 31 // Create a token with one the policy 32 token := mock.ACLToken() 33 token.Policies = []string{policy.Name} 34 s1.fsm.State().UpsertACLTokens(1001, []*structs.ACLToken{token}) 35 36 // Lookup the policy 37 get := &structs.ACLPolicySpecificRequest{ 38 Name: policy.Name, 39 QueryOptions: structs.QueryOptions{ 40 Region: "global", 41 AuthToken: root.SecretID, 42 }, 43 } 44 var resp structs.SingleACLPolicyResponse 45 if err := msgpackrpc.CallWithCodec(codec, "ACL.GetPolicy", get, &resp); err != nil { 46 t.Fatalf("err: %v", err) 47 } 48 assert.Equal(t, uint64(1000), resp.Index) 49 assert.Equal(t, policy, resp.Policy) 50 51 // Lookup non-existing policy 52 get.Name = uuid.Generate() 53 if err := msgpackrpc.CallWithCodec(codec, "ACL.GetPolicy", get, &resp); err != nil { 54 t.Fatalf("err: %v", err) 55 } 56 assert.Equal(t, uint64(1000), resp.Index) 57 assert.Nil(t, resp.Policy) 58 59 // Lookup the policy with the token 60 get = &structs.ACLPolicySpecificRequest{ 61 Name: policy.Name, 62 QueryOptions: structs.QueryOptions{ 63 Region: "global", 64 AuthToken: token.SecretID, 65 }, 66 } 67 var resp2 structs.SingleACLPolicyResponse 68 if err := msgpackrpc.CallWithCodec(codec, "ACL.GetPolicy", get, &resp2); err != nil { 69 t.Fatalf("err: %v", err) 70 } 71 assert.EqualValues(t, 1000, resp2.Index) 72 assert.Equal(t, policy, resp2.Policy) 73 } 74 75 func TestACLEndpoint_GetPolicy_Blocking(t *testing.T) { 76 t.Parallel() 77 s1, root := TestACLServer(t, nil) 78 defer s1.Shutdown() 79 state := s1.fsm.State() 80 codec := rpcClient(t, s1) 81 testutil.WaitForLeader(t, s1.RPC) 82 83 // Create the policies 84 p1 := mock.ACLPolicy() 85 p2 := mock.ACLPolicy() 86 87 // First create an unrelated policy 88 time.AfterFunc(100*time.Millisecond, func() { 89 err := state.UpsertACLPolicies(100, []*structs.ACLPolicy{p1}) 90 if err != nil { 91 t.Fatalf("err: %v", err) 92 } 93 }) 94 95 // Upsert the policy we are watching later 96 time.AfterFunc(200*time.Millisecond, func() { 97 err := state.UpsertACLPolicies(200, []*structs.ACLPolicy{p2}) 98 if err != nil { 99 t.Fatalf("err: %v", err) 100 } 101 }) 102 103 // Lookup the policy 104 req := &structs.ACLPolicySpecificRequest{ 105 Name: p2.Name, 106 QueryOptions: structs.QueryOptions{ 107 Region: "global", 108 MinQueryIndex: 150, 109 AuthToken: root.SecretID, 110 }, 111 } 112 var resp structs.SingleACLPolicyResponse 113 start := time.Now() 114 if err := msgpackrpc.CallWithCodec(codec, "ACL.GetPolicy", req, &resp); err != nil { 115 t.Fatalf("err: %v", err) 116 } 117 118 if elapsed := time.Since(start); elapsed < 200*time.Millisecond { 119 t.Fatalf("should block (returned in %s) %#v", elapsed, resp) 120 } 121 if resp.Index != 200 { 122 t.Fatalf("Bad index: %d %d", resp.Index, 200) 123 } 124 if resp.Policy == nil || resp.Policy.Name != p2.Name { 125 t.Fatalf("bad: %#v", resp.Policy) 126 } 127 128 // Eval delete triggers watches 129 time.AfterFunc(100*time.Millisecond, func() { 130 err := state.DeleteACLPolicies(300, []string{p2.Name}) 131 if err != nil { 132 t.Fatalf("err: %v", err) 133 } 134 }) 135 136 req.QueryOptions.MinQueryIndex = 250 137 var resp2 structs.SingleACLPolicyResponse 138 start = time.Now() 139 if err := msgpackrpc.CallWithCodec(codec, "ACL.GetPolicy", req, &resp2); err != nil { 140 t.Fatalf("err: %v", err) 141 } 142 143 if elapsed := time.Since(start); elapsed < 100*time.Millisecond { 144 t.Fatalf("should block (returned in %s) %#v", elapsed, resp2) 145 } 146 if resp2.Index != 300 { 147 t.Fatalf("Bad index: %d %d", resp2.Index, 300) 148 } 149 if resp2.Policy != nil { 150 t.Fatalf("bad: %#v", resp2.Policy) 151 } 152 } 153 154 func TestACLEndpoint_GetPolicies(t *testing.T) { 155 t.Parallel() 156 s1, root := TestACLServer(t, nil) 157 defer s1.Shutdown() 158 codec := rpcClient(t, s1) 159 testutil.WaitForLeader(t, s1.RPC) 160 161 // Create the register request 162 policy := mock.ACLPolicy() 163 policy2 := mock.ACLPolicy() 164 s1.fsm.State().UpsertACLPolicies(1000, []*structs.ACLPolicy{policy, policy2}) 165 166 // Lookup the policy 167 get := &structs.ACLPolicySetRequest{ 168 Names: []string{policy.Name, policy2.Name}, 169 QueryOptions: structs.QueryOptions{ 170 Region: "global", 171 AuthToken: root.SecretID, 172 }, 173 } 174 var resp structs.ACLPolicySetResponse 175 if err := msgpackrpc.CallWithCodec(codec, "ACL.GetPolicies", get, &resp); err != nil { 176 t.Fatalf("err: %v", err) 177 } 178 assert.Equal(t, uint64(1000), resp.Index) 179 assert.Equal(t, 2, len(resp.Policies)) 180 assert.Equal(t, policy, resp.Policies[policy.Name]) 181 assert.Equal(t, policy2, resp.Policies[policy2.Name]) 182 183 // Lookup non-existing policy 184 get.Names = []string{uuid.Generate()} 185 resp = structs.ACLPolicySetResponse{} 186 if err := msgpackrpc.CallWithCodec(codec, "ACL.GetPolicies", get, &resp); err != nil { 187 t.Fatalf("err: %v", err) 188 } 189 assert.Equal(t, uint64(1000), resp.Index) 190 assert.Equal(t, 0, len(resp.Policies)) 191 } 192 193 func TestACLEndpoint_GetPolicies_TokenSubset(t *testing.T) { 194 t.Parallel() 195 s1, _ := TestACLServer(t, nil) 196 defer s1.Shutdown() 197 codec := rpcClient(t, s1) 198 testutil.WaitForLeader(t, s1.RPC) 199 200 // Create the register request 201 policy := mock.ACLPolicy() 202 policy2 := mock.ACLPolicy() 203 s1.fsm.State().UpsertACLPolicies(1000, []*structs.ACLPolicy{policy, policy2}) 204 205 token := mock.ACLToken() 206 token.Policies = []string{policy.Name} 207 s1.fsm.State().UpsertACLTokens(1000, []*structs.ACLToken{token}) 208 209 // Lookup the policy which is a subset of our tokens 210 get := &structs.ACLPolicySetRequest{ 211 Names: []string{policy.Name}, 212 QueryOptions: structs.QueryOptions{ 213 Region: "global", 214 AuthToken: token.SecretID, 215 }, 216 } 217 var resp structs.ACLPolicySetResponse 218 if err := msgpackrpc.CallWithCodec(codec, "ACL.GetPolicies", get, &resp); err != nil { 219 t.Fatalf("err: %v", err) 220 } 221 assert.Equal(t, uint64(1000), resp.Index) 222 assert.Equal(t, 1, len(resp.Policies)) 223 assert.Equal(t, policy, resp.Policies[policy.Name]) 224 225 // Lookup non-associated policy 226 get.Names = []string{policy2.Name} 227 resp = structs.ACLPolicySetResponse{} 228 if err := msgpackrpc.CallWithCodec(codec, "ACL.GetPolicies", get, &resp); err == nil { 229 t.Fatalf("expected error") 230 } 231 } 232 233 func TestACLEndpoint_GetPolicies_Blocking(t *testing.T) { 234 t.Parallel() 235 s1, root := TestACLServer(t, nil) 236 defer s1.Shutdown() 237 state := s1.fsm.State() 238 codec := rpcClient(t, s1) 239 testutil.WaitForLeader(t, s1.RPC) 240 241 // Create the policies 242 p1 := mock.ACLPolicy() 243 p2 := mock.ACLPolicy() 244 245 // First create an unrelated policy 246 time.AfterFunc(100*time.Millisecond, func() { 247 err := state.UpsertACLPolicies(100, []*structs.ACLPolicy{p1}) 248 if err != nil { 249 t.Fatalf("err: %v", err) 250 } 251 }) 252 253 // Upsert the policy we are watching later 254 time.AfterFunc(200*time.Millisecond, func() { 255 err := state.UpsertACLPolicies(200, []*structs.ACLPolicy{p2}) 256 if err != nil { 257 t.Fatalf("err: %v", err) 258 } 259 }) 260 261 // Lookup the policy 262 req := &structs.ACLPolicySetRequest{ 263 Names: []string{p2.Name}, 264 QueryOptions: structs.QueryOptions{ 265 Region: "global", 266 MinQueryIndex: 150, 267 AuthToken: root.SecretID, 268 }, 269 } 270 var resp structs.ACLPolicySetResponse 271 start := time.Now() 272 if err := msgpackrpc.CallWithCodec(codec, "ACL.GetPolicies", req, &resp); err != nil { 273 t.Fatalf("err: %v", err) 274 } 275 276 if elapsed := time.Since(start); elapsed < 200*time.Millisecond { 277 t.Fatalf("should block (returned in %s) %#v", elapsed, resp) 278 } 279 if resp.Index != 200 { 280 t.Fatalf("Bad index: %d %d", resp.Index, 200) 281 } 282 if len(resp.Policies) == 0 || resp.Policies[p2.Name] == nil { 283 t.Fatalf("bad: %#v", resp.Policies) 284 } 285 286 // Eval delete triggers watches 287 time.AfterFunc(100*time.Millisecond, func() { 288 err := state.DeleteACLPolicies(300, []string{p2.Name}) 289 if err != nil { 290 t.Fatalf("err: %v", err) 291 } 292 }) 293 294 req.QueryOptions.MinQueryIndex = 250 295 var resp2 structs.ACLPolicySetResponse 296 start = time.Now() 297 if err := msgpackrpc.CallWithCodec(codec, "ACL.GetPolicies", req, &resp2); err != nil { 298 t.Fatalf("err: %v", err) 299 } 300 301 if elapsed := time.Since(start); elapsed < 100*time.Millisecond { 302 t.Fatalf("should block (returned in %s) %#v", elapsed, resp2) 303 } 304 if resp2.Index != 300 { 305 t.Fatalf("Bad index: %d %d", resp2.Index, 300) 306 } 307 if len(resp2.Policies) != 0 { 308 t.Fatalf("bad: %#v", resp2.Policies) 309 } 310 } 311 312 func TestACLEndpoint_ListPolicies(t *testing.T) { 313 assert := assert.New(t) 314 t.Parallel() 315 s1, root := TestACLServer(t, nil) 316 defer s1.Shutdown() 317 codec := rpcClient(t, s1) 318 testutil.WaitForLeader(t, s1.RPC) 319 320 // Create the register request 321 p1 := mock.ACLPolicy() 322 p2 := mock.ACLPolicy() 323 324 p1.Name = "aaaaaaaa-3350-4b4b-d185-0e1992ed43e9" 325 p2.Name = "aaaabbbb-3350-4b4b-d185-0e1992ed43e9" 326 s1.fsm.State().UpsertACLPolicies(1000, []*structs.ACLPolicy{p1, p2}) 327 328 // Create a token with one of those policies 329 token := mock.ACLToken() 330 token.Policies = []string{p1.Name} 331 s1.fsm.State().UpsertACLTokens(1001, []*structs.ACLToken{token}) 332 333 // Lookup the policies 334 get := &structs.ACLPolicyListRequest{ 335 QueryOptions: structs.QueryOptions{ 336 Region: "global", 337 AuthToken: root.SecretID, 338 }, 339 } 340 var resp structs.ACLPolicyListResponse 341 if err := msgpackrpc.CallWithCodec(codec, "ACL.ListPolicies", get, &resp); err != nil { 342 t.Fatalf("err: %v", err) 343 } 344 assert.EqualValues(1000, resp.Index) 345 assert.Len(resp.Policies, 2) 346 347 // Lookup the policies by prefix 348 get = &structs.ACLPolicyListRequest{ 349 QueryOptions: structs.QueryOptions{ 350 Region: "global", 351 Prefix: "aaaabb", 352 AuthToken: root.SecretID, 353 }, 354 } 355 var resp2 structs.ACLPolicyListResponse 356 if err := msgpackrpc.CallWithCodec(codec, "ACL.ListPolicies", get, &resp2); err != nil { 357 t.Fatalf("err: %v", err) 358 } 359 assert.EqualValues(1000, resp2.Index) 360 assert.Len(resp2.Policies, 1) 361 362 // List policies using the created token 363 get = &structs.ACLPolicyListRequest{ 364 QueryOptions: structs.QueryOptions{ 365 Region: "global", 366 AuthToken: token.SecretID, 367 }, 368 } 369 var resp3 structs.ACLPolicyListResponse 370 if err := msgpackrpc.CallWithCodec(codec, "ACL.ListPolicies", get, &resp3); err != nil { 371 t.Fatalf("err: %v", err) 372 } 373 assert.EqualValues(1000, resp3.Index) 374 if assert.Len(resp3.Policies, 1) { 375 assert.Equal(resp3.Policies[0].Name, p1.Name) 376 } 377 } 378 379 func TestACLEndpoint_ListPolicies_Blocking(t *testing.T) { 380 t.Parallel() 381 s1, root := TestACLServer(t, nil) 382 defer s1.Shutdown() 383 state := s1.fsm.State() 384 codec := rpcClient(t, s1) 385 testutil.WaitForLeader(t, s1.RPC) 386 387 // Create the policy 388 policy := mock.ACLPolicy() 389 390 // Upsert eval triggers watches 391 time.AfterFunc(100*time.Millisecond, func() { 392 if err := state.UpsertACLPolicies(2, []*structs.ACLPolicy{policy}); err != nil { 393 t.Fatalf("err: %v", err) 394 } 395 }) 396 397 req := &structs.ACLPolicyListRequest{ 398 QueryOptions: structs.QueryOptions{ 399 Region: "global", 400 MinQueryIndex: 1, 401 AuthToken: root.SecretID, 402 }, 403 } 404 start := time.Now() 405 var resp structs.ACLPolicyListResponse 406 if err := msgpackrpc.CallWithCodec(codec, "ACL.ListPolicies", req, &resp); err != nil { 407 t.Fatalf("err: %v", err) 408 } 409 410 if elapsed := time.Since(start); elapsed < 100*time.Millisecond { 411 t.Fatalf("should block (returned in %s) %#v", elapsed, resp) 412 } 413 assert.Equal(t, uint64(2), resp.Index) 414 if len(resp.Policies) != 1 || resp.Policies[0].Name != policy.Name { 415 t.Fatalf("bad: %#v", resp.Policies) 416 } 417 418 // Eval deletion triggers watches 419 time.AfterFunc(100*time.Millisecond, func() { 420 if err := state.DeleteACLPolicies(3, []string{policy.Name}); err != nil { 421 t.Fatalf("err: %v", err) 422 } 423 }) 424 425 req.MinQueryIndex = 2 426 start = time.Now() 427 var resp2 structs.ACLPolicyListResponse 428 if err := msgpackrpc.CallWithCodec(codec, "ACL.ListPolicies", req, &resp2); err != nil { 429 t.Fatalf("err: %v", err) 430 } 431 432 if elapsed := time.Since(start); elapsed < 100*time.Millisecond { 433 t.Fatalf("should block (returned in %s) %#v", elapsed, resp2) 434 } 435 assert.Equal(t, uint64(3), resp2.Index) 436 assert.Equal(t, 0, len(resp2.Policies)) 437 } 438 439 func TestACLEndpoint_DeletePolicies(t *testing.T) { 440 t.Parallel() 441 s1, root := TestACLServer(t, nil) 442 defer s1.Shutdown() 443 codec := rpcClient(t, s1) 444 testutil.WaitForLeader(t, s1.RPC) 445 446 // Create the register request 447 p1 := mock.ACLPolicy() 448 s1.fsm.State().UpsertACLPolicies(1000, []*structs.ACLPolicy{p1}) 449 450 // Lookup the policies 451 req := &structs.ACLPolicyDeleteRequest{ 452 Names: []string{p1.Name}, 453 WriteRequest: structs.WriteRequest{ 454 Region: "global", 455 AuthToken: root.SecretID, 456 }, 457 } 458 var resp structs.GenericResponse 459 if err := msgpackrpc.CallWithCodec(codec, "ACL.DeletePolicies", req, &resp); err != nil { 460 t.Fatalf("err: %v", err) 461 } 462 assert.NotEqual(t, uint64(0), resp.Index) 463 } 464 465 func TestACLEndpoint_UpsertPolicies(t *testing.T) { 466 t.Parallel() 467 s1, root := TestACLServer(t, nil) 468 defer s1.Shutdown() 469 codec := rpcClient(t, s1) 470 testutil.WaitForLeader(t, s1.RPC) 471 472 // Create the register request 473 p1 := mock.ACLPolicy() 474 475 // Lookup the policies 476 req := &structs.ACLPolicyUpsertRequest{ 477 Policies: []*structs.ACLPolicy{p1}, 478 WriteRequest: structs.WriteRequest{ 479 Region: "global", 480 AuthToken: root.SecretID, 481 }, 482 } 483 var resp structs.GenericResponse 484 if err := msgpackrpc.CallWithCodec(codec, "ACL.UpsertPolicies", req, &resp); err != nil { 485 t.Fatalf("err: %v", err) 486 } 487 assert.NotEqual(t, uint64(0), resp.Index) 488 489 // Check we created the policy 490 out, err := s1.fsm.State().ACLPolicyByName(nil, p1.Name) 491 assert.Nil(t, err) 492 assert.NotNil(t, out) 493 } 494 495 func TestACLEndpoint_UpsertPolicies_Invalid(t *testing.T) { 496 t.Parallel() 497 s1, root := TestACLServer(t, nil) 498 defer s1.Shutdown() 499 codec := rpcClient(t, s1) 500 testutil.WaitForLeader(t, s1.RPC) 501 502 // Create the register request 503 p1 := mock.ACLPolicy() 504 p1.Rules = "blah blah invalid" 505 506 // Lookup the policies 507 req := &structs.ACLPolicyUpsertRequest{ 508 Policies: []*structs.ACLPolicy{p1}, 509 WriteRequest: structs.WriteRequest{ 510 Region: "global", 511 AuthToken: root.SecretID, 512 }, 513 } 514 var resp structs.GenericResponse 515 err := msgpackrpc.CallWithCodec(codec, "ACL.UpsertPolicies", req, &resp) 516 assert.NotNil(t, err) 517 if !strings.Contains(err.Error(), "failed to parse") { 518 t.Fatalf("bad: %s", err) 519 } 520 } 521 522 func TestACLEndpoint_GetToken(t *testing.T) { 523 t.Parallel() 524 s1, root := TestACLServer(t, nil) 525 defer s1.Shutdown() 526 codec := rpcClient(t, s1) 527 testutil.WaitForLeader(t, s1.RPC) 528 529 // Create the register request 530 token := mock.ACLToken() 531 s1.fsm.State().UpsertACLTokens(1000, []*structs.ACLToken{token}) 532 533 // Lookup the token 534 get := &structs.ACLTokenSpecificRequest{ 535 AccessorID: token.AccessorID, 536 QueryOptions: structs.QueryOptions{ 537 Region: "global", 538 AuthToken: root.SecretID, 539 }, 540 } 541 var resp structs.SingleACLTokenResponse 542 if err := msgpackrpc.CallWithCodec(codec, "ACL.GetToken", get, &resp); err != nil { 543 t.Fatalf("err: %v", err) 544 } 545 assert.Equal(t, uint64(1000), resp.Index) 546 assert.Equal(t, token, resp.Token) 547 548 // Lookup non-existing token 549 get.AccessorID = uuid.Generate() 550 if err := msgpackrpc.CallWithCodec(codec, "ACL.GetToken", get, &resp); err != nil { 551 t.Fatalf("err: %v", err) 552 } 553 assert.Equal(t, uint64(1000), resp.Index) 554 assert.Nil(t, resp.Token) 555 556 // Lookup the token by accessor id using the tokens secret ID 557 get.AccessorID = token.AccessorID 558 get.AuthToken = token.SecretID 559 var resp2 structs.SingleACLTokenResponse 560 if err := msgpackrpc.CallWithCodec(codec, "ACL.GetToken", get, &resp2); err != nil { 561 t.Fatalf("err: %v", err) 562 } 563 assert.Equal(t, uint64(1000), resp2.Index) 564 assert.Equal(t, token, resp2.Token) 565 } 566 567 func TestACLEndpoint_GetToken_Blocking(t *testing.T) { 568 t.Parallel() 569 s1, root := TestACLServer(t, nil) 570 defer s1.Shutdown() 571 state := s1.fsm.State() 572 codec := rpcClient(t, s1) 573 testutil.WaitForLeader(t, s1.RPC) 574 575 // Create the tokens 576 p1 := mock.ACLToken() 577 p2 := mock.ACLToken() 578 579 // First create an unrelated token 580 time.AfterFunc(100*time.Millisecond, func() { 581 err := state.UpsertACLTokens(100, []*structs.ACLToken{p1}) 582 if err != nil { 583 t.Fatalf("err: %v", err) 584 } 585 }) 586 587 // Upsert the token we are watching later 588 time.AfterFunc(200*time.Millisecond, func() { 589 err := state.UpsertACLTokens(200, []*structs.ACLToken{p2}) 590 if err != nil { 591 t.Fatalf("err: %v", err) 592 } 593 }) 594 595 // Lookup the token 596 req := &structs.ACLTokenSpecificRequest{ 597 AccessorID: p2.AccessorID, 598 QueryOptions: structs.QueryOptions{ 599 Region: "global", 600 MinQueryIndex: 150, 601 AuthToken: root.SecretID, 602 }, 603 } 604 var resp structs.SingleACLTokenResponse 605 start := time.Now() 606 if err := msgpackrpc.CallWithCodec(codec, "ACL.GetToken", req, &resp); err != nil { 607 t.Fatalf("err: %v", err) 608 } 609 610 if elapsed := time.Since(start); elapsed < 200*time.Millisecond { 611 t.Fatalf("should block (returned in %s) %#v", elapsed, resp) 612 } 613 if resp.Index != 200 { 614 t.Fatalf("Bad index: %d %d", resp.Index, 200) 615 } 616 if resp.Token == nil || resp.Token.AccessorID != p2.AccessorID { 617 t.Fatalf("bad: %#v", resp.Token) 618 } 619 620 // Eval delete triggers watches 621 time.AfterFunc(100*time.Millisecond, func() { 622 err := state.DeleteACLTokens(300, []string{p2.AccessorID}) 623 if err != nil { 624 t.Fatalf("err: %v", err) 625 } 626 }) 627 628 req.QueryOptions.MinQueryIndex = 250 629 var resp2 structs.SingleACLTokenResponse 630 start = time.Now() 631 if err := msgpackrpc.CallWithCodec(codec, "ACL.GetToken", req, &resp2); err != nil { 632 t.Fatalf("err: %v", err) 633 } 634 635 if elapsed := time.Since(start); elapsed < 100*time.Millisecond { 636 t.Fatalf("should block (returned in %s) %#v", elapsed, resp2) 637 } 638 if resp2.Index != 300 { 639 t.Fatalf("Bad index: %d %d", resp2.Index, 300) 640 } 641 if resp2.Token != nil { 642 t.Fatalf("bad: %#v", resp2.Token) 643 } 644 } 645 646 func TestACLEndpoint_GetTokens(t *testing.T) { 647 t.Parallel() 648 s1, root := TestACLServer(t, nil) 649 defer s1.Shutdown() 650 codec := rpcClient(t, s1) 651 testutil.WaitForLeader(t, s1.RPC) 652 653 // Create the register request 654 token := mock.ACLToken() 655 token2 := mock.ACLToken() 656 s1.fsm.State().UpsertACLTokens(1000, []*structs.ACLToken{token, token2}) 657 658 // Lookup the token 659 get := &structs.ACLTokenSetRequest{ 660 AccessorIDS: []string{token.AccessorID, token2.AccessorID}, 661 QueryOptions: structs.QueryOptions{ 662 Region: "global", 663 AuthToken: root.SecretID, 664 }, 665 } 666 var resp structs.ACLTokenSetResponse 667 if err := msgpackrpc.CallWithCodec(codec, "ACL.GetTokens", get, &resp); err != nil { 668 t.Fatalf("err: %v", err) 669 } 670 assert.Equal(t, uint64(1000), resp.Index) 671 assert.Equal(t, 2, len(resp.Tokens)) 672 assert.Equal(t, token, resp.Tokens[token.AccessorID]) 673 674 // Lookup non-existing token 675 get.AccessorIDS = []string{uuid.Generate()} 676 resp = structs.ACLTokenSetResponse{} 677 if err := msgpackrpc.CallWithCodec(codec, "ACL.GetTokens", get, &resp); err != nil { 678 t.Fatalf("err: %v", err) 679 } 680 assert.Equal(t, uint64(1000), resp.Index) 681 assert.Equal(t, 0, len(resp.Tokens)) 682 } 683 684 func TestACLEndpoint_GetTokens_Blocking(t *testing.T) { 685 t.Parallel() 686 s1, root := TestACLServer(t, nil) 687 defer s1.Shutdown() 688 state := s1.fsm.State() 689 codec := rpcClient(t, s1) 690 testutil.WaitForLeader(t, s1.RPC) 691 692 // Create the tokens 693 p1 := mock.ACLToken() 694 p2 := mock.ACLToken() 695 696 // First create an unrelated token 697 time.AfterFunc(100*time.Millisecond, func() { 698 err := state.UpsertACLTokens(100, []*structs.ACLToken{p1}) 699 if err != nil { 700 t.Fatalf("err: %v", err) 701 } 702 }) 703 704 // Upsert the token we are watching later 705 time.AfterFunc(200*time.Millisecond, func() { 706 err := state.UpsertACLTokens(200, []*structs.ACLToken{p2}) 707 if err != nil { 708 t.Fatalf("err: %v", err) 709 } 710 }) 711 712 // Lookup the token 713 req := &structs.ACLTokenSetRequest{ 714 AccessorIDS: []string{p2.AccessorID}, 715 QueryOptions: structs.QueryOptions{ 716 Region: "global", 717 MinQueryIndex: 150, 718 AuthToken: root.SecretID, 719 }, 720 } 721 var resp structs.ACLTokenSetResponse 722 start := time.Now() 723 if err := msgpackrpc.CallWithCodec(codec, "ACL.GetTokens", req, &resp); err != nil { 724 t.Fatalf("err: %v", err) 725 } 726 727 if elapsed := time.Since(start); elapsed < 200*time.Millisecond { 728 t.Fatalf("should block (returned in %s) %#v", elapsed, resp) 729 } 730 if resp.Index != 200 { 731 t.Fatalf("Bad index: %d %d", resp.Index, 200) 732 } 733 if len(resp.Tokens) == 0 || resp.Tokens[p2.AccessorID] == nil { 734 t.Fatalf("bad: %#v", resp.Tokens) 735 } 736 737 // Eval delete triggers watches 738 time.AfterFunc(100*time.Millisecond, func() { 739 err := state.DeleteACLTokens(300, []string{p2.AccessorID}) 740 if err != nil { 741 t.Fatalf("err: %v", err) 742 } 743 }) 744 745 req.QueryOptions.MinQueryIndex = 250 746 var resp2 structs.ACLTokenSetResponse 747 start = time.Now() 748 if err := msgpackrpc.CallWithCodec(codec, "ACL.GetTokens", req, &resp2); err != nil { 749 t.Fatalf("err: %v", err) 750 } 751 752 if elapsed := time.Since(start); elapsed < 100*time.Millisecond { 753 t.Fatalf("should block (returned in %s) %#v", elapsed, resp2) 754 } 755 if resp2.Index != 300 { 756 t.Fatalf("Bad index: %d %d", resp2.Index, 300) 757 } 758 if len(resp2.Tokens) != 0 { 759 t.Fatalf("bad: %#v", resp2.Tokens) 760 } 761 } 762 763 func TestACLEndpoint_ListTokens(t *testing.T) { 764 t.Parallel() 765 s1, root := TestACLServer(t, nil) 766 defer s1.Shutdown() 767 codec := rpcClient(t, s1) 768 testutil.WaitForLeader(t, s1.RPC) 769 770 // Create the register request 771 p1 := mock.ACLToken() 772 p2 := mock.ACLToken() 773 p2.Global = true 774 775 p1.AccessorID = "aaaaaaaa-3350-4b4b-d185-0e1992ed43e9" 776 p2.AccessorID = "aaaabbbb-3350-4b4b-d185-0e1992ed43e9" 777 s1.fsm.State().UpsertACLTokens(1000, []*structs.ACLToken{p1, p2}) 778 779 // Lookup the tokens 780 get := &structs.ACLTokenListRequest{ 781 QueryOptions: structs.QueryOptions{ 782 Region: "global", 783 AuthToken: root.SecretID, 784 }, 785 } 786 var resp structs.ACLTokenListResponse 787 if err := msgpackrpc.CallWithCodec(codec, "ACL.ListTokens", get, &resp); err != nil { 788 t.Fatalf("err: %v", err) 789 } 790 assert.Equal(t, uint64(1000), resp.Index) 791 assert.Equal(t, 3, len(resp.Tokens)) 792 793 // Lookup the tokens by prefix 794 get = &structs.ACLTokenListRequest{ 795 QueryOptions: structs.QueryOptions{ 796 Region: "global", 797 Prefix: "aaaabb", 798 AuthToken: root.SecretID, 799 }, 800 } 801 var resp2 structs.ACLTokenListResponse 802 if err := msgpackrpc.CallWithCodec(codec, "ACL.ListTokens", get, &resp2); err != nil { 803 t.Fatalf("err: %v", err) 804 } 805 assert.Equal(t, uint64(1000), resp2.Index) 806 assert.Equal(t, 1, len(resp2.Tokens)) 807 808 // Lookup the global tokens 809 get = &structs.ACLTokenListRequest{ 810 GlobalOnly: true, 811 QueryOptions: structs.QueryOptions{ 812 Region: "global", 813 AuthToken: root.SecretID, 814 }, 815 } 816 var resp3 structs.ACLTokenListResponse 817 if err := msgpackrpc.CallWithCodec(codec, "ACL.ListTokens", get, &resp3); err != nil { 818 t.Fatalf("err: %v", err) 819 } 820 assert.Equal(t, uint64(1000), resp3.Index) 821 assert.Equal(t, 2, len(resp3.Tokens)) 822 } 823 824 func TestACLEndpoint_ListTokens_Blocking(t *testing.T) { 825 t.Parallel() 826 s1, root := TestACLServer(t, nil) 827 defer s1.Shutdown() 828 state := s1.fsm.State() 829 codec := rpcClient(t, s1) 830 testutil.WaitForLeader(t, s1.RPC) 831 832 // Create the token 833 token := mock.ACLToken() 834 835 // Upsert eval triggers watches 836 time.AfterFunc(100*time.Millisecond, func() { 837 if err := state.UpsertACLTokens(3, []*structs.ACLToken{token}); err != nil { 838 t.Fatalf("err: %v", err) 839 } 840 }) 841 842 req := &structs.ACLTokenListRequest{ 843 QueryOptions: structs.QueryOptions{ 844 Region: "global", 845 MinQueryIndex: 2, 846 AuthToken: root.SecretID, 847 }, 848 } 849 start := time.Now() 850 var resp structs.ACLTokenListResponse 851 if err := msgpackrpc.CallWithCodec(codec, "ACL.ListTokens", req, &resp); err != nil { 852 t.Fatalf("err: %v", err) 853 } 854 855 if elapsed := time.Since(start); elapsed < 100*time.Millisecond { 856 t.Fatalf("should block (returned in %s) %#v", elapsed, resp) 857 } 858 assert.Equal(t, uint64(3), resp.Index) 859 if len(resp.Tokens) != 2 { 860 t.Fatalf("bad: %#v", resp.Tokens) 861 } 862 863 // Eval deletion triggers watches 864 time.AfterFunc(100*time.Millisecond, func() { 865 if err := state.DeleteACLTokens(4, []string{token.AccessorID}); err != nil { 866 t.Fatalf("err: %v", err) 867 } 868 }) 869 870 req.MinQueryIndex = 3 871 start = time.Now() 872 var resp2 structs.ACLTokenListResponse 873 if err := msgpackrpc.CallWithCodec(codec, "ACL.ListTokens", req, &resp2); err != nil { 874 t.Fatalf("err: %v", err) 875 } 876 877 if elapsed := time.Since(start); elapsed < 100*time.Millisecond { 878 t.Fatalf("should block (returned in %s) %#v", elapsed, resp2) 879 } 880 assert.Equal(t, uint64(4), resp2.Index) 881 assert.Equal(t, 1, len(resp2.Tokens)) 882 } 883 884 func TestACLEndpoint_DeleteTokens(t *testing.T) { 885 t.Parallel() 886 s1, root := TestACLServer(t, nil) 887 defer s1.Shutdown() 888 codec := rpcClient(t, s1) 889 testutil.WaitForLeader(t, s1.RPC) 890 891 // Create the register request 892 p1 := mock.ACLToken() 893 s1.fsm.State().UpsertACLTokens(1000, []*structs.ACLToken{p1}) 894 895 // Lookup the tokens 896 req := &structs.ACLTokenDeleteRequest{ 897 AccessorIDs: []string{p1.AccessorID}, 898 WriteRequest: structs.WriteRequest{ 899 Region: "global", 900 AuthToken: root.SecretID, 901 }, 902 } 903 var resp structs.GenericResponse 904 if err := msgpackrpc.CallWithCodec(codec, "ACL.DeleteTokens", req, &resp); err != nil { 905 t.Fatalf("err: %v", err) 906 } 907 assert.NotEqual(t, uint64(0), resp.Index) 908 } 909 910 func TestACLEndpoint_DeleteTokens_WithNonexistentToken(t *testing.T) { 911 t.Parallel() 912 assert := assert.New(t) 913 914 s1, root := TestACLServer(t, nil) 915 defer s1.Shutdown() 916 codec := rpcClient(t, s1) 917 testutil.WaitForLeader(t, s1.RPC) 918 919 nonexistentToken := mock.ACLToken() 920 921 // Lookup the policies 922 req := &structs.ACLTokenDeleteRequest{ 923 AccessorIDs: []string{nonexistentToken.AccessorID}, 924 WriteRequest: structs.WriteRequest{ 925 Region: "global", 926 AuthToken: root.SecretID, 927 }, 928 } 929 var resp structs.GenericResponse 930 err := msgpackrpc.CallWithCodec(codec, "ACL.DeleteTokens", req, &resp) 931 932 assert.NotNil(err) 933 expectedError := fmt.Sprintf("Cannot delete nonexistent tokens: %s", nonexistentToken.AccessorID) 934 assert.Contains(expectedError, err.Error()) 935 } 936 937 func TestACLEndpoint_Bootstrap(t *testing.T) { 938 t.Parallel() 939 s1 := TestServer(t, func(c *Config) { 940 c.ACLEnabled = true 941 }) 942 defer s1.Shutdown() 943 codec := rpcClient(t, s1) 944 testutil.WaitForLeader(t, s1.RPC) 945 946 // Lookup the tokens 947 req := &structs.ACLTokenBootstrapRequest{ 948 WriteRequest: structs.WriteRequest{Region: "global"}, 949 } 950 var resp structs.ACLTokenUpsertResponse 951 if err := msgpackrpc.CallWithCodec(codec, "ACL.Bootstrap", req, &resp); err != nil { 952 t.Fatalf("err: %v", err) 953 } 954 assert.NotEqual(t, uint64(0), resp.Index) 955 assert.NotNil(t, resp.Tokens[0]) 956 957 // Get the token out from the response 958 created := resp.Tokens[0] 959 assert.NotEqual(t, "", created.AccessorID) 960 assert.NotEqual(t, "", created.SecretID) 961 assert.NotEqual(t, time.Time{}, created.CreateTime) 962 assert.Equal(t, structs.ACLManagementToken, created.Type) 963 assert.Equal(t, "Bootstrap Token", created.Name) 964 assert.Equal(t, true, created.Global) 965 966 // Check we created the token 967 out, err := s1.fsm.State().ACLTokenByAccessorID(nil, created.AccessorID) 968 assert.Nil(t, err) 969 assert.Equal(t, created, out) 970 } 971 972 func TestACLEndpoint_Bootstrap_Reset(t *testing.T) { 973 t.Parallel() 974 dir := tmpDir(t) 975 defer os.RemoveAll(dir) 976 s1 := TestServer(t, func(c *Config) { 977 c.ACLEnabled = true 978 c.DataDir = dir 979 c.DevMode = false 980 c.Bootstrap = true 981 c.DevDisableBootstrap = false 982 }) 983 defer s1.Shutdown() 984 codec := rpcClient(t, s1) 985 testutil.WaitForLeader(t, s1.RPC) 986 987 // Lookup the tokens 988 req := &structs.ACLTokenBootstrapRequest{ 989 WriteRequest: structs.WriteRequest{Region: "global"}, 990 } 991 var resp structs.ACLTokenUpsertResponse 992 if err := msgpackrpc.CallWithCodec(codec, "ACL.Bootstrap", req, &resp); err != nil { 993 t.Fatalf("err: %v", err) 994 } 995 assert.NotEqual(t, uint64(0), resp.Index) 996 assert.NotNil(t, resp.Tokens[0]) 997 resetIdx := resp.Tokens[0].CreateIndex 998 999 // Try again, should fail 1000 if err := msgpackrpc.CallWithCodec(codec, "ACL.Bootstrap", req, &resp); err == nil { 1001 t.Fatalf("expected err") 1002 } 1003 1004 // Create the reset file 1005 output := []byte(fmt.Sprintf("%d", resetIdx)) 1006 path := filepath.Join(dir, aclBootstrapReset) 1007 assert.Nil(t, ioutil.WriteFile(path, output, 0755)) 1008 1009 // Try again, should work with reset 1010 if err := msgpackrpc.CallWithCodec(codec, "ACL.Bootstrap", req, &resp); err != nil { 1011 t.Fatalf("err: %v", err) 1012 } 1013 assert.NotEqual(t, uint64(0), resp.Index) 1014 assert.NotNil(t, resp.Tokens[0]) 1015 1016 // Get the token out from the response 1017 created := resp.Tokens[0] 1018 assert.NotEqual(t, "", created.AccessorID) 1019 assert.NotEqual(t, "", created.SecretID) 1020 assert.NotEqual(t, time.Time{}, created.CreateTime) 1021 assert.Equal(t, structs.ACLManagementToken, created.Type) 1022 assert.Equal(t, "Bootstrap Token", created.Name) 1023 assert.Equal(t, true, created.Global) 1024 1025 // Check we created the token 1026 out, err := s1.fsm.State().ACLTokenByAccessorID(nil, created.AccessorID) 1027 assert.Nil(t, err) 1028 assert.Equal(t, created, out) 1029 1030 // Try again, should fail 1031 if err := msgpackrpc.CallWithCodec(codec, "ACL.Bootstrap", req, &resp); err == nil { 1032 t.Fatalf("expected err") 1033 } 1034 } 1035 1036 func TestACLEndpoint_UpsertTokens(t *testing.T) { 1037 t.Parallel() 1038 s1, root := TestACLServer(t, nil) 1039 defer s1.Shutdown() 1040 codec := rpcClient(t, s1) 1041 testutil.WaitForLeader(t, s1.RPC) 1042 1043 // Create the register request 1044 p1 := mock.ACLToken() 1045 p1.AccessorID = "" // Blank to create 1046 1047 // Lookup the tokens 1048 req := &structs.ACLTokenUpsertRequest{ 1049 Tokens: []*structs.ACLToken{p1}, 1050 WriteRequest: structs.WriteRequest{ 1051 Region: "global", 1052 AuthToken: root.SecretID, 1053 }, 1054 } 1055 var resp structs.ACLTokenUpsertResponse 1056 if err := msgpackrpc.CallWithCodec(codec, "ACL.UpsertTokens", req, &resp); err != nil { 1057 t.Fatalf("err: %v", err) 1058 } 1059 assert.NotEqual(t, uint64(0), resp.Index) 1060 1061 // Get the token out from the response 1062 created := resp.Tokens[0] 1063 assert.NotEqual(t, "", created.AccessorID) 1064 assert.NotEqual(t, "", created.SecretID) 1065 assert.NotEqual(t, time.Time{}, created.CreateTime) 1066 assert.Equal(t, p1.Type, created.Type) 1067 assert.Equal(t, p1.Policies, created.Policies) 1068 assert.Equal(t, p1.Name, created.Name) 1069 1070 // Check we created the token 1071 out, err := s1.fsm.State().ACLTokenByAccessorID(nil, created.AccessorID) 1072 assert.Nil(t, err) 1073 assert.Equal(t, created, out) 1074 1075 // Update the token type 1076 req.Tokens[0] = created 1077 created.Type = "management" 1078 created.Policies = nil 1079 1080 // Upsert again 1081 if err := msgpackrpc.CallWithCodec(codec, "ACL.UpsertTokens", req, &resp); err != nil { 1082 t.Fatalf("err: %v", err) 1083 } 1084 assert.NotEqual(t, uint64(0), resp.Index) 1085 1086 // Check we modified the token 1087 out, err = s1.fsm.State().ACLTokenByAccessorID(nil, created.AccessorID) 1088 assert.Nil(t, err) 1089 assert.Equal(t, created, out) 1090 } 1091 1092 func TestACLEndpoint_UpsertTokens_Invalid(t *testing.T) { 1093 t.Parallel() 1094 s1, root := TestACLServer(t, nil) 1095 defer s1.Shutdown() 1096 codec := rpcClient(t, s1) 1097 testutil.WaitForLeader(t, s1.RPC) 1098 1099 // Create the register request 1100 p1 := mock.ACLToken() 1101 p1.Type = "blah blah" 1102 1103 // Lookup the tokens 1104 req := &structs.ACLTokenUpsertRequest{ 1105 Tokens: []*structs.ACLToken{p1}, 1106 WriteRequest: structs.WriteRequest{ 1107 Region: "global", 1108 AuthToken: root.SecretID, 1109 }, 1110 } 1111 var resp structs.GenericResponse 1112 err := msgpackrpc.CallWithCodec(codec, "ACL.UpsertTokens", req, &resp) 1113 assert.NotNil(t, err) 1114 if !strings.Contains(err.Error(), "client or management") { 1115 t.Fatalf("bad: %s", err) 1116 } 1117 } 1118 1119 func TestACLEndpoint_ResolveToken(t *testing.T) { 1120 t.Parallel() 1121 s1, _ := TestACLServer(t, nil) 1122 defer s1.Shutdown() 1123 codec := rpcClient(t, s1) 1124 testutil.WaitForLeader(t, s1.RPC) 1125 1126 // Create the register request 1127 token := mock.ACLToken() 1128 s1.fsm.State().UpsertACLTokens(1000, []*structs.ACLToken{token}) 1129 1130 // Lookup the token 1131 get := &structs.ResolveACLTokenRequest{ 1132 SecretID: token.SecretID, 1133 QueryOptions: structs.QueryOptions{Region: "global"}, 1134 } 1135 var resp structs.ResolveACLTokenResponse 1136 if err := msgpackrpc.CallWithCodec(codec, "ACL.ResolveToken", get, &resp); err != nil { 1137 t.Fatalf("err: %v", err) 1138 } 1139 assert.Equal(t, uint64(1000), resp.Index) 1140 assert.Equal(t, token, resp.Token) 1141 1142 // Lookup non-existing token 1143 get.SecretID = uuid.Generate() 1144 if err := msgpackrpc.CallWithCodec(codec, "ACL.ResolveToken", get, &resp); err != nil { 1145 t.Fatalf("err: %v", err) 1146 } 1147 assert.Equal(t, uint64(1000), resp.Index) 1148 assert.Nil(t, resp.Token) 1149 }