diff options
Diffstat (limited to 'bitbake/lib/hashserv/tests.py')
-rw-r--r-- | bitbake/lib/hashserv/tests.py | 276 |
1 files changed, 267 insertions, 9 deletions
diff --git a/bitbake/lib/hashserv/tests.py b/bitbake/lib/hashserv/tests.py index e9a361dc4b..f92f37c459 100644 --- a/bitbake/lib/hashserv/tests.py +++ b/bitbake/lib/hashserv/tests.py | |||
@@ -6,6 +6,8 @@ | |||
6 | # | 6 | # |
7 | 7 | ||
8 | from . import create_server, create_client | 8 | from . import create_server, create_client |
9 | from .server import DEFAULT_ANON_PERMS, ALL_PERMISSIONS | ||
10 | from bb.asyncrpc import InvokeError | ||
9 | import hashlib | 11 | import hashlib |
10 | import logging | 12 | import logging |
11 | import multiprocessing | 13 | import multiprocessing |
@@ -29,8 +31,9 @@ class HashEquivalenceTestSetup(object): | |||
29 | METHOD = 'TestMethod' | 31 | METHOD = 'TestMethod' |
30 | 32 | ||
31 | server_index = 0 | 33 | server_index = 0 |
34 | client_index = 0 | ||
32 | 35 | ||
33 | def start_server(self, dbpath=None, upstream=None, read_only=False, prefunc=server_prefunc): | 36 | def start_server(self, dbpath=None, upstream=None, read_only=False, prefunc=server_prefunc, anon_perms=DEFAULT_ANON_PERMS, admin_username=None, admin_password=None): |
34 | self.server_index += 1 | 37 | self.server_index += 1 |
35 | if dbpath is None: | 38 | if dbpath is None: |
36 | dbpath = self.make_dbpath() | 39 | dbpath = self.make_dbpath() |
@@ -45,7 +48,10 @@ class HashEquivalenceTestSetup(object): | |||
45 | server = create_server(self.get_server_addr(self.server_index), | 48 | server = create_server(self.get_server_addr(self.server_index), |
46 | dbpath, | 49 | dbpath, |
47 | upstream=upstream, | 50 | upstream=upstream, |
48 | read_only=read_only) | 51 | read_only=read_only, |
52 | anon_perms=anon_perms, | ||
53 | admin_username=admin_username, | ||
54 | admin_password=admin_password) | ||
49 | server.dbpath = dbpath | 55 | server.dbpath = dbpath |
50 | 56 | ||
51 | server.serve_as_process(prefunc=prefunc, args=(self.server_index,)) | 57 | server.serve_as_process(prefunc=prefunc, args=(self.server_index,)) |
@@ -56,18 +62,31 @@ class HashEquivalenceTestSetup(object): | |||
56 | def make_dbpath(self): | 62 | def make_dbpath(self): |
57 | return os.path.join(self.temp_dir.name, "db%d.sqlite" % self.server_index) | 63 | return os.path.join(self.temp_dir.name, "db%d.sqlite" % self.server_index) |
58 | 64 | ||
59 | def start_client(self, server_address): | 65 | def start_client(self, server_address, username=None, password=None): |
60 | def cleanup_client(client): | 66 | def cleanup_client(client): |
61 | client.close() | 67 | client.close() |
62 | 68 | ||
63 | client = create_client(server_address) | 69 | client = create_client(server_address, username=username, password=password) |
64 | self.addCleanup(cleanup_client, client) | 70 | self.addCleanup(cleanup_client, client) |
65 | 71 | ||
66 | return client | 72 | return client |
67 | 73 | ||
68 | def start_test_server(self): | 74 | def start_test_server(self): |
69 | server = self.start_server() | 75 | self.server = self.start_server() |
70 | return server.address | 76 | return self.server.address |
77 | |||
78 | def start_auth_server(self): | ||
79 | self.auth_server = self.start_server(self.server.dbpath, anon_perms=[], admin_username="admin", admin_password="password") | ||
80 | self.admin_client = self.start_client(self.auth_server.address, username="admin", password="password") | ||
81 | return self.admin_client | ||
82 | |||
83 | def auth_client(self, user): | ||
84 | return self.start_client(self.auth_server.address, user["username"], user["token"]) | ||
85 | |||
86 | def auth_perms(self, *permissions): | ||
87 | self.client_index += 1 | ||
88 | user = self.admin_client.new_user(f"user-{self.client_index}", permissions) | ||
89 | return self.auth_client(user) | ||
71 | 90 | ||
72 | def setUp(self): | 91 | def setUp(self): |
73 | if sys.version_info < (3, 5, 0): | 92 | if sys.version_info < (3, 5, 0): |
@@ -86,18 +105,21 @@ class HashEquivalenceTestSetup(object): | |||
86 | 105 | ||
87 | 106 | ||
88 | class HashEquivalenceCommonTests(object): | 107 | class HashEquivalenceCommonTests(object): |
89 | def test_create_hash(self): | 108 | def create_test_hash(self, client): |
90 | # Simple test that hashes can be created | 109 | # Simple test that hashes can be created |
91 | taskhash = '35788efcb8dfb0a02659d81cf2bfd695fb30faf9' | 110 | taskhash = '35788efcb8dfb0a02659d81cf2bfd695fb30faf9' |
92 | outhash = '2765d4a5884be49b28601445c2760c5f21e7e5c0ee2b7e3fce98fd7e5970796f' | 111 | outhash = '2765d4a5884be49b28601445c2760c5f21e7e5c0ee2b7e3fce98fd7e5970796f' |
93 | unihash = 'f46d3fbb439bd9b921095da657a4de906510d2cd' | 112 | unihash = 'f46d3fbb439bd9b921095da657a4de906510d2cd' |
94 | 113 | ||
95 | self.assertClientGetHash(self.client, taskhash, None) | 114 | self.assertClientGetHash(client, taskhash, None) |
96 | 115 | ||
97 | result = self.client.report_unihash(taskhash, self.METHOD, outhash, unihash) | 116 | result = client.report_unihash(taskhash, self.METHOD, outhash, unihash) |
98 | self.assertEqual(result['unihash'], unihash, 'Server returned bad unihash') | 117 | self.assertEqual(result['unihash'], unihash, 'Server returned bad unihash') |
99 | return taskhash, outhash, unihash | 118 | return taskhash, outhash, unihash |
100 | 119 | ||
120 | def test_create_hash(self): | ||
121 | return self.create_test_hash(self.client) | ||
122 | |||
101 | def test_create_equivalent(self): | 123 | def test_create_equivalent(self): |
102 | # Tests that a second reported task with the same outhash will be | 124 | # Tests that a second reported task with the same outhash will be |
103 | # assigned the same unihash | 125 | # assigned the same unihash |
@@ -471,6 +493,242 @@ class HashEquivalenceCommonTests(object): | |||
471 | # shares a taskhash with Task 2 | 493 | # shares a taskhash with Task 2 |
472 | self.assertClientGetHash(self.client, taskhash2, unihash2) | 494 | self.assertClientGetHash(self.client, taskhash2, unihash2) |
473 | 495 | ||
496 | def test_auth_read_perms(self): | ||
497 | admin_client = self.start_auth_server() | ||
498 | |||
499 | # Create hashes with non-authenticated server | ||
500 | taskhash, outhash, unihash = self.test_create_hash() | ||
501 | |||
502 | # Validate hash can be retrieved using authenticated client | ||
503 | with self.auth_perms("@read") as client: | ||
504 | self.assertClientGetHash(client, taskhash, unihash) | ||
505 | |||
506 | with self.auth_perms() as client, self.assertRaises(InvokeError): | ||
507 | self.assertClientGetHash(client, taskhash, unihash) | ||
508 | |||
509 | def test_auth_report_perms(self): | ||
510 | admin_client = self.start_auth_server() | ||
511 | |||
512 | # Without read permission, the user is completely denied | ||
513 | with self.auth_perms() as client, self.assertRaises(InvokeError): | ||
514 | self.create_test_hash(client) | ||
515 | |||
516 | # Read permission allows the call to succeed, but it doesn't record | ||
517 | # anythin in the database | ||
518 | with self.auth_perms("@read") as client: | ||
519 | taskhash, outhash, unihash = self.create_test_hash(client) | ||
520 | self.assertClientGetHash(client, taskhash, None) | ||
521 | |||
522 | # Report permission alone is insufficient | ||
523 | with self.auth_perms("@report") as client, self.assertRaises(InvokeError): | ||
524 | self.create_test_hash(client) | ||
525 | |||
526 | # Read and report permission actually modify the database | ||
527 | with self.auth_perms("@read", "@report") as client: | ||
528 | taskhash, outhash, unihash = self.create_test_hash(client) | ||
529 | self.assertClientGetHash(client, taskhash, unihash) | ||
530 | |||
531 | def test_auth_no_token_refresh_from_anon_user(self): | ||
532 | self.start_auth_server() | ||
533 | |||
534 | with self.start_client(self.auth_server.address) as client, self.assertRaises(InvokeError): | ||
535 | client.refresh_token() | ||
536 | |||
537 | def assertUserCanAuth(self, user): | ||
538 | with self.start_client(self.auth_server.address) as client: | ||
539 | client.auth(user["username"], user["token"]) | ||
540 | |||
541 | def assertUserCannotAuth(self, user): | ||
542 | with self.start_client(self.auth_server.address) as client, self.assertRaises(InvokeError): | ||
543 | client.auth(user["username"], user["token"]) | ||
544 | |||
545 | def test_auth_self_token_refresh(self): | ||
546 | admin_client = self.start_auth_server() | ||
547 | |||
548 | # Create a new user with no permissions | ||
549 | user = admin_client.new_user("test-user", []) | ||
550 | |||
551 | with self.auth_client(user) as client: | ||
552 | new_user = client.refresh_token() | ||
553 | |||
554 | self.assertEqual(user["username"], new_user["username"]) | ||
555 | self.assertNotEqual(user["token"], new_user["token"]) | ||
556 | self.assertUserCanAuth(new_user) | ||
557 | self.assertUserCannotAuth(user) | ||
558 | |||
559 | # Explicitly specifying with your own username is fine also | ||
560 | with self.auth_client(new_user) as client: | ||
561 | new_user2 = client.refresh_token(user["username"]) | ||
562 | |||
563 | self.assertEqual(user["username"], new_user2["username"]) | ||
564 | self.assertNotEqual(user["token"], new_user2["token"]) | ||
565 | self.assertUserCanAuth(new_user2) | ||
566 | self.assertUserCannotAuth(new_user) | ||
567 | self.assertUserCannotAuth(user) | ||
568 | |||
569 | def test_auth_token_refresh(self): | ||
570 | admin_client = self.start_auth_server() | ||
571 | |||
572 | user = admin_client.new_user("test-user", []) | ||
573 | |||
574 | with self.auth_perms() as client, self.assertRaises(InvokeError): | ||
575 | client.refresh_token(user["username"]) | ||
576 | |||
577 | with self.auth_perms("@user-admin") as client: | ||
578 | new_user = client.refresh_token(user["username"]) | ||
579 | |||
580 | self.assertEqual(user["username"], new_user["username"]) | ||
581 | self.assertNotEqual(user["token"], new_user["token"]) | ||
582 | self.assertUserCanAuth(new_user) | ||
583 | self.assertUserCannotAuth(user) | ||
584 | |||
585 | def test_auth_self_get_user(self): | ||
586 | admin_client = self.start_auth_server() | ||
587 | |||
588 | user = admin_client.new_user("test-user", []) | ||
589 | user_info = user.copy() | ||
590 | del user_info["token"] | ||
591 | |||
592 | with self.auth_client(user) as client: | ||
593 | info = client.get_user() | ||
594 | self.assertEqual(info, user_info) | ||
595 | |||
596 | # Explicitly asking for your own username is fine also | ||
597 | info = client.get_user(user["username"]) | ||
598 | self.assertEqual(info, user_info) | ||
599 | |||
600 | def test_auth_get_user(self): | ||
601 | admin_client = self.start_auth_server() | ||
602 | |||
603 | user = admin_client.new_user("test-user", []) | ||
604 | user_info = user.copy() | ||
605 | del user_info["token"] | ||
606 | |||
607 | with self.auth_perms() as client, self.assertRaises(InvokeError): | ||
608 | client.get_user(user["username"]) | ||
609 | |||
610 | with self.auth_perms("@user-admin") as client: | ||
611 | info = client.get_user(user["username"]) | ||
612 | self.assertEqual(info, user_info) | ||
613 | |||
614 | info = client.get_user("nonexist-user") | ||
615 | self.assertIsNone(info) | ||
616 | |||
617 | def test_auth_reconnect(self): | ||
618 | admin_client = self.start_auth_server() | ||
619 | |||
620 | user = admin_client.new_user("test-user", []) | ||
621 | user_info = user.copy() | ||
622 | del user_info["token"] | ||
623 | |||
624 | with self.auth_client(user) as client: | ||
625 | info = client.get_user() | ||
626 | self.assertEqual(info, user_info) | ||
627 | |||
628 | client.disconnect() | ||
629 | |||
630 | info = client.get_user() | ||
631 | self.assertEqual(info, user_info) | ||
632 | |||
633 | def test_auth_delete_user(self): | ||
634 | admin_client = self.start_auth_server() | ||
635 | |||
636 | user = admin_client.new_user("test-user", []) | ||
637 | |||
638 | # No self service | ||
639 | with self.auth_client(user) as client, self.assertRaises(InvokeError): | ||
640 | client.delete_user(user["username"]) | ||
641 | |||
642 | with self.auth_perms() as client, self.assertRaises(InvokeError): | ||
643 | client.delete_user(user["username"]) | ||
644 | |||
645 | with self.auth_perms("@user-admin") as client: | ||
646 | client.delete_user(user["username"]) | ||
647 | |||
648 | # User doesn't exist, so even though the permission is correct, it's an | ||
649 | # error | ||
650 | with self.auth_perms("@user-admin") as client, self.assertRaises(InvokeError): | ||
651 | client.delete_user(user["username"]) | ||
652 | |||
653 | def assertUserPerms(self, user, permissions): | ||
654 | with self.auth_client(user) as client: | ||
655 | info = client.get_user() | ||
656 | self.assertEqual(info, { | ||
657 | "username": user["username"], | ||
658 | "permissions": permissions, | ||
659 | }) | ||
660 | |||
661 | def test_auth_set_user_perms(self): | ||
662 | admin_client = self.start_auth_server() | ||
663 | |||
664 | user = admin_client.new_user("test-user", []) | ||
665 | |||
666 | self.assertUserPerms(user, []) | ||
667 | |||
668 | # No self service to change permissions | ||
669 | with self.auth_client(user) as client, self.assertRaises(InvokeError): | ||
670 | client.set_user_perms(user["username"], ["@all"]) | ||
671 | self.assertUserPerms(user, []) | ||
672 | |||
673 | with self.auth_perms() as client, self.assertRaises(InvokeError): | ||
674 | client.set_user_perms(user["username"], ["@all"]) | ||
675 | self.assertUserPerms(user, []) | ||
676 | |||
677 | with self.auth_perms("@user-admin") as client: | ||
678 | client.set_user_perms(user["username"], ["@all"]) | ||
679 | self.assertUserPerms(user, sorted(list(ALL_PERMISSIONS))) | ||
680 | |||
681 | # Bad permissions | ||
682 | with self.auth_perms("@user-admin") as client, self.assertRaises(InvokeError): | ||
683 | client.set_user_perms(user["username"], ["@this-is-not-a-permission"]) | ||
684 | self.assertUserPerms(user, sorted(list(ALL_PERMISSIONS))) | ||
685 | |||
686 | def test_auth_get_all_users(self): | ||
687 | admin_client = self.start_auth_server() | ||
688 | |||
689 | user = admin_client.new_user("test-user", []) | ||
690 | |||
691 | with self.auth_client(user) as client, self.assertRaises(InvokeError): | ||
692 | client.get_all_users() | ||
693 | |||
694 | # Give the test user the correct permission | ||
695 | admin_client.set_user_perms(user["username"], ["@user-admin"]) | ||
696 | |||
697 | with self.auth_client(user) as client: | ||
698 | all_users = client.get_all_users() | ||
699 | |||
700 | # Convert to a dictionary for easier comparison | ||
701 | all_users = {u["username"]: u for u in all_users} | ||
702 | |||
703 | self.assertEqual(all_users, | ||
704 | { | ||
705 | "admin": { | ||
706 | "username": "admin", | ||
707 | "permissions": sorted(list(ALL_PERMISSIONS)), | ||
708 | }, | ||
709 | "test-user": { | ||
710 | "username": "test-user", | ||
711 | "permissions": ["@user-admin"], | ||
712 | } | ||
713 | } | ||
714 | ) | ||
715 | |||
716 | def test_auth_new_user(self): | ||
717 | self.start_auth_server() | ||
718 | |||
719 | permissions = ["@read", "@report", "@db-admin", "@user-admin"] | ||
720 | permissions.sort() | ||
721 | |||
722 | with self.auth_perms() as client, self.assertRaises(InvokeError): | ||
723 | client.new_user("test-user", permissions) | ||
724 | |||
725 | with self.auth_perms("@user-admin") as client: | ||
726 | user = client.new_user("test-user", permissions) | ||
727 | self.assertIn("token", user) | ||
728 | self.assertEqual(user["username"], "test-user") | ||
729 | self.assertEqual(user["permissions"], permissions) | ||
730 | |||
731 | |||
474 | class TestHashEquivalenceUnixServer(HashEquivalenceTestSetup, HashEquivalenceCommonTests, unittest.TestCase): | 732 | class TestHashEquivalenceUnixServer(HashEquivalenceTestSetup, HashEquivalenceCommonTests, unittest.TestCase): |
475 | def get_server_addr(self, server_idx): | 733 | def get_server_addr(self, server_idx): |
476 | return "unix://" + os.path.join(self.temp_dir.name, 'sock%d' % server_idx) | 734 | return "unix://" + os.path.join(self.temp_dir.name, 'sock%d' % server_idx) |