1// Copyright 2016 The etcd Authors 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package auth 16 17import ( 18 "context" 19 "fmt" 20 "os" 21 "reflect" 22 "strings" 23 "sync" 24 "testing" 25 "time" 26 27 "github.com/coreos/etcd/auth/authpb" 28 pb "github.com/coreos/etcd/etcdserver/etcdserverpb" 29 "github.com/coreos/etcd/mvcc/backend" 30 31 "golang.org/x/crypto/bcrypt" 32 "google.golang.org/grpc/metadata" 33) 34 35func init() { BcryptCost = bcrypt.MinCost } 36 37func dummyIndexWaiter(index uint64) <-chan struct{} { 38 ch := make(chan struct{}) 39 go func() { 40 ch <- struct{}{} 41 }() 42 return ch 43} 44 45// TestNewAuthStoreRevision ensures newly auth store 46// keeps the old revision when there are no changes. 47func TestNewAuthStoreRevision(t *testing.T) { 48 b, tPath := backend.NewDefaultTmpBackend() 49 defer os.Remove(tPath) 50 51 tp, err := NewTokenProvider(tokenTypeSimple, dummyIndexWaiter) 52 if err != nil { 53 t.Fatal(err) 54 } 55 as := NewAuthStore(b, tp) 56 err = enableAuthAndCreateRoot(as) 57 if err != nil { 58 t.Fatal(err) 59 } 60 old := as.Revision() 61 b.Close() 62 as.Close() 63 64 // no changes to commit 65 b2 := backend.NewDefaultBackend(tPath) 66 as = NewAuthStore(b2, tp) 67 new := as.Revision() 68 b2.Close() 69 as.Close() 70 71 if old != new { 72 t.Fatalf("expected revision %d, got %d", old, new) 73 } 74} 75 76func setupAuthStore(t *testing.T) (store *authStore, teardownfunc func(t *testing.T)) { 77 b, tPath := backend.NewDefaultTmpBackend() 78 79 tp, err := NewTokenProvider(tokenTypeSimple, dummyIndexWaiter) 80 if err != nil { 81 t.Fatal(err) 82 } 83 as := NewAuthStore(b, tp) 84 err = enableAuthAndCreateRoot(as) 85 if err != nil { 86 t.Fatal(err) 87 } 88 89 // adds a new role 90 _, err = as.RoleAdd(&pb.AuthRoleAddRequest{Name: "role-test"}) 91 if err != nil { 92 t.Fatal(err) 93 } 94 95 ua := &pb.AuthUserAddRequest{Name: "foo", Password: "bar"} 96 _, err = as.UserAdd(ua) // add a non-existing user 97 if err != nil { 98 t.Fatal(err) 99 } 100 101 tearDown := func(t *testing.T) { 102 b.Close() 103 os.Remove(tPath) 104 as.Close() 105 } 106 return as, tearDown 107} 108 109func enableAuthAndCreateRoot(as *authStore) error { 110 _, err := as.UserAdd(&pb.AuthUserAddRequest{Name: "root", Password: "root"}) 111 if err != nil { 112 return err 113 } 114 115 _, err = as.RoleAdd(&pb.AuthRoleAddRequest{Name: "root"}) 116 if err != nil { 117 return err 118 } 119 120 _, err = as.UserGrantRole(&pb.AuthUserGrantRoleRequest{User: "root", Role: "root"}) 121 if err != nil { 122 return err 123 } 124 125 return as.AuthEnable() 126} 127 128func TestUserAdd(t *testing.T) { 129 as, tearDown := setupAuthStore(t) 130 defer tearDown(t) 131 132 ua := &pb.AuthUserAddRequest{Name: "foo"} 133 _, err := as.UserAdd(ua) // add an existing user 134 if err == nil { 135 t.Fatalf("expected %v, got %v", ErrUserAlreadyExist, err) 136 } 137 if err != ErrUserAlreadyExist { 138 t.Fatalf("expected %v, got %v", ErrUserAlreadyExist, err) 139 } 140 141 ua = &pb.AuthUserAddRequest{Name: ""} 142 _, err = as.UserAdd(ua) // add a user with empty name 143 if err != ErrUserEmpty { 144 t.Fatal(err) 145 } 146} 147 148func TestCheckPassword(t *testing.T) { 149 as, tearDown := setupAuthStore(t) 150 defer tearDown(t) 151 152 // auth a non-existing user 153 _, err := as.CheckPassword("foo-test", "bar") 154 if err == nil { 155 t.Fatalf("expected %v, got %v", ErrAuthFailed, err) 156 } 157 if err != ErrAuthFailed { 158 t.Fatalf("expected %v, got %v", ErrAuthFailed, err) 159 } 160 161 // auth an existing user with correct password 162 _, err = as.CheckPassword("foo", "bar") 163 if err != nil { 164 t.Fatal(err) 165 } 166 167 // auth an existing user but with wrong password 168 _, err = as.CheckPassword("foo", "") 169 if err == nil { 170 t.Fatalf("expected %v, got %v", ErrAuthFailed, err) 171 } 172 if err != ErrAuthFailed { 173 t.Fatalf("expected %v, got %v", ErrAuthFailed, err) 174 } 175} 176 177func TestUserDelete(t *testing.T) { 178 as, tearDown := setupAuthStore(t) 179 defer tearDown(t) 180 181 // delete an existing user 182 ud := &pb.AuthUserDeleteRequest{Name: "foo"} 183 _, err := as.UserDelete(ud) 184 if err != nil { 185 t.Fatal(err) 186 } 187 188 // delete a non-existing user 189 _, err = as.UserDelete(ud) 190 if err == nil { 191 t.Fatalf("expected %v, got %v", ErrUserNotFound, err) 192 } 193 if err != ErrUserNotFound { 194 t.Fatalf("expected %v, got %v", ErrUserNotFound, err) 195 } 196} 197 198func TestUserChangePassword(t *testing.T) { 199 as, tearDown := setupAuthStore(t) 200 defer tearDown(t) 201 202 ctx1 := context.WithValue(context.WithValue(context.TODO(), AuthenticateParamIndex{}, uint64(1)), AuthenticateParamSimpleTokenPrefix{}, "dummy") 203 _, err := as.Authenticate(ctx1, "foo", "bar") 204 if err != nil { 205 t.Fatal(err) 206 } 207 208 _, err = as.UserChangePassword(&pb.AuthUserChangePasswordRequest{Name: "foo", Password: "baz"}) 209 if err != nil { 210 t.Fatal(err) 211 } 212 213 ctx2 := context.WithValue(context.WithValue(context.TODO(), AuthenticateParamIndex{}, uint64(2)), AuthenticateParamSimpleTokenPrefix{}, "dummy") 214 _, err = as.Authenticate(ctx2, "foo", "baz") 215 if err != nil { 216 t.Fatal(err) 217 } 218 219 // change a non-existing user 220 _, err = as.UserChangePassword(&pb.AuthUserChangePasswordRequest{Name: "foo-test", Password: "bar"}) 221 if err == nil { 222 t.Fatalf("expected %v, got %v", ErrUserNotFound, err) 223 } 224 if err != ErrUserNotFound { 225 t.Fatalf("expected %v, got %v", ErrUserNotFound, err) 226 } 227} 228 229func TestRoleAdd(t *testing.T) { 230 as, tearDown := setupAuthStore(t) 231 defer tearDown(t) 232 233 // adds a new role 234 _, err := as.RoleAdd(&pb.AuthRoleAddRequest{Name: "role-test-1"}) 235 if err != nil { 236 t.Fatal(err) 237 } 238} 239 240func TestUserGrant(t *testing.T) { 241 as, tearDown := setupAuthStore(t) 242 defer tearDown(t) 243 244 // grants a role to the user 245 _, err := as.UserGrantRole(&pb.AuthUserGrantRoleRequest{User: "foo", Role: "role-test"}) 246 if err != nil { 247 t.Fatal(err) 248 } 249 250 // grants a role to a non-existing user 251 _, err = as.UserGrantRole(&pb.AuthUserGrantRoleRequest{User: "foo-test", Role: "role-test"}) 252 if err == nil { 253 t.Errorf("expected %v, got %v", ErrUserNotFound, err) 254 } 255 if err != ErrUserNotFound { 256 t.Errorf("expected %v, got %v", ErrUserNotFound, err) 257 } 258} 259 260func TestGetUser(t *testing.T) { 261 as, tearDown := setupAuthStore(t) 262 defer tearDown(t) 263 264 _, err := as.UserGrantRole(&pb.AuthUserGrantRoleRequest{User: "foo", Role: "role-test"}) 265 if err != nil { 266 t.Fatal(err) 267 } 268 269 u, err := as.UserGet(&pb.AuthUserGetRequest{Name: "foo"}) 270 if err != nil { 271 t.Fatal(err) 272 } 273 if u == nil { 274 t.Fatal("expect user not nil, got nil") 275 } 276 expected := []string{"role-test"} 277 if !reflect.DeepEqual(expected, u.Roles) { 278 t.Errorf("expected %v, got %v", expected, u.Roles) 279 } 280} 281 282func TestListUsers(t *testing.T) { 283 as, tearDown := setupAuthStore(t) 284 defer tearDown(t) 285 286 ua := &pb.AuthUserAddRequest{Name: "user1", Password: "pwd1"} 287 _, err := as.UserAdd(ua) // add a non-existing user 288 if err != nil { 289 t.Fatal(err) 290 } 291 292 ul, err := as.UserList(&pb.AuthUserListRequest{}) 293 if err != nil { 294 t.Fatal(err) 295 } 296 if !contains(ul.Users, "root") { 297 t.Errorf("expected %v in %v", "root", ul.Users) 298 } 299 if !contains(ul.Users, "user1") { 300 t.Errorf("expected %v in %v", "user1", ul.Users) 301 } 302} 303 304func TestRoleGrantPermission(t *testing.T) { 305 as, tearDown := setupAuthStore(t) 306 defer tearDown(t) 307 308 _, err := as.RoleAdd(&pb.AuthRoleAddRequest{Name: "role-test-1"}) 309 if err != nil { 310 t.Fatal(err) 311 } 312 313 perm := &authpb.Permission{ 314 PermType: authpb.WRITE, 315 Key: []byte("Keys"), 316 RangeEnd: []byte("RangeEnd"), 317 } 318 _, err = as.RoleGrantPermission(&pb.AuthRoleGrantPermissionRequest{ 319 Name: "role-test-1", 320 Perm: perm, 321 }) 322 323 if err != nil { 324 t.Error(err) 325 } 326 327 r, err := as.RoleGet(&pb.AuthRoleGetRequest{Role: "role-test-1"}) 328 if err != nil { 329 t.Fatal(err) 330 } 331 332 if !reflect.DeepEqual(perm, r.Perm[0]) { 333 t.Errorf("expected %v, got %v", perm, r.Perm[0]) 334 } 335} 336 337func TestRoleRevokePermission(t *testing.T) { 338 as, tearDown := setupAuthStore(t) 339 defer tearDown(t) 340 341 _, err := as.RoleAdd(&pb.AuthRoleAddRequest{Name: "role-test-1"}) 342 if err != nil { 343 t.Fatal(err) 344 } 345 346 perm := &authpb.Permission{ 347 PermType: authpb.WRITE, 348 Key: []byte("Keys"), 349 RangeEnd: []byte("RangeEnd"), 350 } 351 _, err = as.RoleGrantPermission(&pb.AuthRoleGrantPermissionRequest{ 352 Name: "role-test-1", 353 Perm: perm, 354 }) 355 356 if err != nil { 357 t.Fatal(err) 358 } 359 360 _, err = as.RoleGet(&pb.AuthRoleGetRequest{Role: "role-test-1"}) 361 if err != nil { 362 t.Fatal(err) 363 } 364 365 _, err = as.RoleRevokePermission(&pb.AuthRoleRevokePermissionRequest{ 366 Role: "role-test-1", 367 Key: "Keys", 368 RangeEnd: "RangeEnd", 369 }) 370 if err != nil { 371 t.Fatal(err) 372 } 373 374 var r *pb.AuthRoleGetResponse 375 r, err = as.RoleGet(&pb.AuthRoleGetRequest{Role: "role-test-1"}) 376 if err != nil { 377 t.Fatal(err) 378 } 379 if len(r.Perm) != 0 { 380 t.Errorf("expected %v, got %v", 0, len(r.Perm)) 381 } 382} 383 384func TestUserRevokePermission(t *testing.T) { 385 as, tearDown := setupAuthStore(t) 386 defer tearDown(t) 387 388 _, err := as.RoleAdd(&pb.AuthRoleAddRequest{Name: "role-test-1"}) 389 if err != nil { 390 t.Fatal(err) 391 } 392 393 _, err = as.UserGrantRole(&pb.AuthUserGrantRoleRequest{User: "foo", Role: "role-test"}) 394 if err != nil { 395 t.Fatal(err) 396 } 397 398 _, err = as.UserGrantRole(&pb.AuthUserGrantRoleRequest{User: "foo", Role: "role-test-1"}) 399 if err != nil { 400 t.Fatal(err) 401 } 402 403 u, err := as.UserGet(&pb.AuthUserGetRequest{Name: "foo"}) 404 if err != nil { 405 t.Fatal(err) 406 } 407 408 expected := []string{"role-test", "role-test-1"} 409 if !reflect.DeepEqual(expected, u.Roles) { 410 t.Fatalf("expected %v, got %v", expected, u.Roles) 411 } 412 413 _, err = as.UserRevokeRole(&pb.AuthUserRevokeRoleRequest{Name: "foo", Role: "role-test-1"}) 414 if err != nil { 415 t.Fatal(err) 416 } 417 418 u, err = as.UserGet(&pb.AuthUserGetRequest{Name: "foo"}) 419 if err != nil { 420 t.Fatal(err) 421 } 422 423 expected = []string{"role-test"} 424 if !reflect.DeepEqual(expected, u.Roles) { 425 t.Errorf("expected %v, got %v", expected, u.Roles) 426 } 427} 428 429func TestRoleDelete(t *testing.T) { 430 as, tearDown := setupAuthStore(t) 431 defer tearDown(t) 432 433 _, err := as.RoleDelete(&pb.AuthRoleDeleteRequest{Role: "role-test"}) 434 if err != nil { 435 t.Fatal(err) 436 } 437 rl, err := as.RoleList(&pb.AuthRoleListRequest{}) 438 if err != nil { 439 t.Fatal(err) 440 } 441 expected := []string{"root"} 442 if !reflect.DeepEqual(expected, rl.Roles) { 443 t.Errorf("expected %v, got %v", expected, rl.Roles) 444 } 445} 446 447func TestAuthInfoFromCtx(t *testing.T) { 448 as, tearDown := setupAuthStore(t) 449 defer tearDown(t) 450 451 ctx := context.Background() 452 ai, err := as.AuthInfoFromCtx(ctx) 453 if err != nil && ai != nil { 454 t.Errorf("expected (nil, nil), got (%v, %v)", ai, err) 455 } 456 457 // as if it came from RPC 458 ctx = metadata.NewIncomingContext(context.Background(), metadata.New(map[string]string{"tokens": "dummy"})) 459 ai, err = as.AuthInfoFromCtx(ctx) 460 if err != nil && ai != nil { 461 t.Errorf("expected (nil, nil), got (%v, %v)", ai, err) 462 } 463 464 ctx = context.WithValue(context.WithValue(context.TODO(), AuthenticateParamIndex{}, uint64(1)), AuthenticateParamSimpleTokenPrefix{}, "dummy") 465 resp, err := as.Authenticate(ctx, "foo", "bar") 466 if err != nil { 467 t.Error(err) 468 } 469 470 ctx = metadata.NewIncomingContext(context.Background(), metadata.New(map[string]string{"token": "Invalid Token"})) 471 _, err = as.AuthInfoFromCtx(ctx) 472 if err != ErrInvalidAuthToken { 473 t.Errorf("expected %v, got %v", ErrInvalidAuthToken, err) 474 } 475 476 ctx = metadata.NewIncomingContext(context.Background(), metadata.New(map[string]string{"token": "Invalid.Token"})) 477 _, err = as.AuthInfoFromCtx(ctx) 478 if err != ErrInvalidAuthToken { 479 t.Errorf("expected %v, got %v", ErrInvalidAuthToken, err) 480 } 481 482 ctx = metadata.NewIncomingContext(context.Background(), metadata.New(map[string]string{"token": resp.Token})) 483 ai, err = as.AuthInfoFromCtx(ctx) 484 if err != nil { 485 t.Error(err) 486 } 487 if ai.Username != "foo" { 488 t.Errorf("expected %v, got %v", "foo", ai.Username) 489 } 490} 491 492func TestAuthDisable(t *testing.T) { 493 as, tearDown := setupAuthStore(t) 494 defer tearDown(t) 495 496 as.AuthDisable() 497 ctx := context.WithValue(context.WithValue(context.TODO(), AuthenticateParamIndex{}, uint64(2)), AuthenticateParamSimpleTokenPrefix{}, "dummy") 498 _, err := as.Authenticate(ctx, "foo", "bar") 499 if err != ErrAuthNotEnabled { 500 t.Errorf("expected %v, got %v", ErrAuthNotEnabled, err) 501 } 502 503 // Disabling disabled auth to make sure it can return safely if store is already disabled. 504 as.AuthDisable() 505 _, err = as.Authenticate(ctx, "foo", "bar") 506 if err != ErrAuthNotEnabled { 507 t.Errorf("expected %v, got %v", ErrAuthNotEnabled, err) 508 } 509} 510 511// TestAuthRevisionRace ensures that access to authStore.revision is thread-safe. 512func TestAuthInfoFromCtxRace(t *testing.T) { 513 b, tPath := backend.NewDefaultTmpBackend() 514 defer os.Remove(tPath) 515 516 tp, err := NewTokenProvider(tokenTypeSimple, dummyIndexWaiter) 517 if err != nil { 518 t.Fatal(err) 519 } 520 as := NewAuthStore(b, tp) 521 defer as.Close() 522 523 donec := make(chan struct{}) 524 go func() { 525 defer close(donec) 526 ctx := metadata.NewIncomingContext(context.Background(), metadata.New(map[string]string{"token": "test"})) 527 as.AuthInfoFromCtx(ctx) 528 }() 529 as.UserAdd(&pb.AuthUserAddRequest{Name: "test"}) 530 <-donec 531} 532 533func TestIsAdminPermitted(t *testing.T) { 534 as, tearDown := setupAuthStore(t) 535 defer tearDown(t) 536 537 err := as.IsAdminPermitted(&AuthInfo{Username: "root", Revision: 1}) 538 if err != nil { 539 t.Errorf("expected nil, got %v", err) 540 } 541 542 // invalid user 543 err = as.IsAdminPermitted(&AuthInfo{Username: "rooti", Revision: 1}) 544 if err != ErrUserNotFound { 545 t.Errorf("expected %v, got %v", ErrUserNotFound, err) 546 } 547 548 // non-admin user 549 err = as.IsAdminPermitted(&AuthInfo{Username: "foo", Revision: 1}) 550 if err != ErrPermissionDenied { 551 t.Errorf("expected %v, got %v", ErrPermissionDenied, err) 552 } 553 554 // disabled auth should return nil 555 as.AuthDisable() 556 err = as.IsAdminPermitted(&AuthInfo{Username: "root", Revision: 1}) 557 if err != nil { 558 t.Errorf("expected nil, got %v", err) 559 } 560} 561 562func TestRecoverFromSnapshot(t *testing.T) { 563 as, _ := setupAuthStore(t) 564 565 ua := &pb.AuthUserAddRequest{Name: "foo"} 566 _, err := as.UserAdd(ua) // add an existing user 567 if err == nil { 568 t.Fatalf("expected %v, got %v", ErrUserAlreadyExist, err) 569 } 570 if err != ErrUserAlreadyExist { 571 t.Fatalf("expected %v, got %v", ErrUserAlreadyExist, err) 572 } 573 574 ua = &pb.AuthUserAddRequest{Name: ""} 575 _, err = as.UserAdd(ua) // add a user with empty name 576 if err != ErrUserEmpty { 577 t.Fatal(err) 578 } 579 580 as.Close() 581 582 tp, err := NewTokenProvider(tokenTypeSimple, dummyIndexWaiter) 583 if err != nil { 584 t.Fatal(err) 585 } 586 as2 := NewAuthStore(as.be, tp) 587 defer func(a *authStore) { 588 a.Close() 589 }(as2) 590 591 if !as2.isAuthEnabled() { 592 t.Fatal("recovering authStore from existing backend failed") 593 } 594 595 ul, err := as.UserList(&pb.AuthUserListRequest{}) 596 if err != nil { 597 t.Fatal(err) 598 } 599 if !contains(ul.Users, "root") { 600 t.Errorf("expected %v in %v", "root", ul.Users) 601 } 602} 603 604func contains(array []string, str string) bool { 605 for _, s := range array { 606 if s == str { 607 return true 608 } 609 } 610 return false 611} 612 613func TestHammerSimpleAuthenticate(t *testing.T) { 614 // set TTL values low to try to trigger races 615 oldTTL, oldTTLRes := simpleTokenTTL, simpleTokenTTLResolution 616 defer func() { 617 simpleTokenTTL = oldTTL 618 simpleTokenTTLResolution = oldTTLRes 619 }() 620 simpleTokenTTL = 10 * time.Millisecond 621 simpleTokenTTLResolution = simpleTokenTTL 622 users := make(map[string]struct{}) 623 624 as, tearDown := setupAuthStore(t) 625 defer tearDown(t) 626 627 // create lots of users 628 for i := 0; i < 50; i++ { 629 u := fmt.Sprintf("user-%d", i) 630 ua := &pb.AuthUserAddRequest{Name: u, Password: "123"} 631 if _, err := as.UserAdd(ua); err != nil { 632 t.Fatal(err) 633 } 634 users[u] = struct{}{} 635 } 636 637 // hammer on authenticate with lots of users 638 for i := 0; i < 10; i++ { 639 var wg sync.WaitGroup 640 wg.Add(len(users)) 641 for u := range users { 642 go func(user string) { 643 defer wg.Done() 644 token := fmt.Sprintf("%s(%d)", user, i) 645 ctx := context.WithValue(context.WithValue(context.TODO(), AuthenticateParamIndex{}, uint64(1)), AuthenticateParamSimpleTokenPrefix{}, token) 646 if _, err := as.Authenticate(ctx, user, "123"); err != nil { 647 t.Fatal(err) 648 } 649 if _, err := as.AuthInfoFromCtx(ctx); err != nil { 650 t.Fatal(err) 651 } 652 }(u) 653 } 654 time.Sleep(time.Millisecond) 655 wg.Wait() 656 } 657} 658 659// TestRolesOrder tests authpb.User.Roles is sorted 660func TestRolesOrder(t *testing.T) { 661 b, tPath := backend.NewDefaultTmpBackend() 662 defer os.Remove(tPath) 663 664 tp, err := NewTokenProvider(tokenTypeSimple, dummyIndexWaiter) 665 if err != nil { 666 t.Fatal(err) 667 } 668 as := NewAuthStore(b, tp) 669 err = enableAuthAndCreateRoot(as) 670 if err != nil { 671 t.Fatal(err) 672 } 673 674 username := "user" 675 _, err = as.UserAdd(&pb.AuthUserAddRequest{Name: username, Password: "pass"}) 676 if err != nil { 677 t.Fatal(err) 678 } 679 680 roles := []string{"role1", "role2", "abc", "xyz", "role3"} 681 for _, role := range roles { 682 _, err = as.RoleAdd(&pb.AuthRoleAddRequest{Name: role}) 683 if err != nil { 684 t.Fatal(err) 685 } 686 687 _, err = as.UserGrantRole(&pb.AuthUserGrantRoleRequest{User: username, Role: role}) 688 if err != nil { 689 t.Fatal(err) 690 } 691 } 692 693 user, err := as.UserGet(&pb.AuthUserGetRequest{Name: username}) 694 if err != nil { 695 t.Fatal(err) 696 } 697 698 for i := 1; i < len(user.Roles); i++ { 699 if strings.Compare(user.Roles[i-1], user.Roles[i]) != -1 { 700 t.Errorf("User.Roles isn't sorted (%s vs %s)", user.Roles[i-1], user.Roles[i]) 701 } 702 } 703} 704 705func TestAuthInfoFromCtxWithRootSimple(t *testing.T) { 706 testAuthInfoFromCtxWithRoot(t, tokenTypeSimple) 707} 708 709func TestAuthInfoFromCtxWithRootJWT(t *testing.T) { 710 opts := testJWTOpts() 711 testAuthInfoFromCtxWithRoot(t, opts) 712} 713 714// testAuthInfoFromCtxWithRoot ensures "WithRoot" properly embeds token in the context. 715func testAuthInfoFromCtxWithRoot(t *testing.T, opts string) { 716 b, tPath := backend.NewDefaultTmpBackend() 717 defer os.Remove(tPath) 718 719 tp, err := NewTokenProvider(opts, dummyIndexWaiter) 720 if err != nil { 721 t.Fatal(err) 722 } 723 as := NewAuthStore(b, tp) 724 defer as.Close() 725 726 if err = enableAuthAndCreateRoot(as); err != nil { 727 t.Fatal(err) 728 } 729 730 ctx := context.Background() 731 ctx = as.WithRoot(ctx) 732 733 ai, aerr := as.AuthInfoFromCtx(ctx) 734 if aerr != nil { 735 t.Error(err) 736 } 737 if ai == nil { 738 t.Error("expected non-nil *AuthInfo") 739 } 740 if ai.Username != "root" { 741 t.Errorf("expected user name 'root', got %+v", ai) 742 } 743} 744