Merge ~ack/maas:1812201-list-allocated-rbac into maas:master

Proposed by Alberto Donato
Status: Merged
Approved by: Alberto Donato
Approved revision: 06b656eba25a48edd762ca4282f25b049141835d
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~ack/maas:1812201-list-allocated-rbac
Merge into: maas:master
Diff against target: 111 lines (+42/-25)
4 files modified
src/maasserver/api/machines.py (+6/-4)
src/maasserver/api/tests/test_machines.py (+35/-0)
src/maasserver/models/node.py (+0/-21)
src/maasserver/models/tests/test_node.py (+1/-0)
Reviewer Review Type Date Requested Status
Björn Tillenius Approve
MAAS Lander Approve
Review via email: mp+362186@code.launchpad.net

Commit message

LP: #1812201 - filter allocated machines based on pools with RBAC

To post a comment you must log in.
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b 1812201-list-allocated-rbac lp:~ack/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci-jenkins.internal:8080/job/maas/job/branch-tester/4940/console
COMMIT: d0bdf2658f42eb458a58ebec0a5b740db199aa5a

review: Needs Fixing
Revision history for this message
Björn Tillenius (bjornt) wrote :

The fix looks good, and thanks for adding some more tests. But you forgot to add a test that confirms that the fix is good. Even after reverting the fix, all the tests you added still pass.

review: Needs Fixing
Revision history for this message
Alberto Donato (ack) wrote :

I do get a test failure on the RBAC test without the change, don't you?

Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b 1812201-list-allocated-rbac lp:~ack/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: c0ee3c591339a1a1c51bf7295bd4bb6fa44ba0f5

review: Approve
Revision history for this message
Björn Tillenius (bjornt) wrote :

Ah, sorry. I ran the wrong tests. Although that said, it took me a while to understand what the test actually tested.

I'd said ideally you would split the test to test one thing, or at least add comments for what the different machines are needed for.

That said, I wonder if this fix is really in the right place. The get_allocated_visible_machines() is quite general. You would expect that if an admin called that method for someone else's token, they would get the full list.

I think it makes more sense to fix this in the API method itself, and use ids to limit which machines to consider. Otherwise it will be really hard to understand how get_allocated_visible_machines work. Maybe it would be more clear if you added a for_user parameter, though.

Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b 1812201-list-allocated-rbac lp:~ack/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: 4468e28c3593e115e69e967e5bfe2f0b72f12d6e

review: Approve
Revision history for this message
Björn Tillenius (bjornt) wrote :

+1 with some suggestions inline.

review: Approve
Revision history for this message
Alberto Donato (ack) wrote :

addressed all points, thanks

Revision history for this message
MAAS Lander (maas-lander) wrote :

There was an error fetching revisions from git servers. Please try again in a few minutes. If the problem persists, contact Launchpad support.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/maasserver/api/machines.py b/src/maasserver/api/machines.py
2index aec4a29..9c4513a 100644
3--- a/src/maasserver/api/machines.py
4+++ b/src/maasserver/api/machines.py
5@@ -1939,10 +1939,12 @@ class MachinesHandler(NodesHandler, PowersMixin):
6 @success-example "success-json" [exkey=machines-placeholder]
7 placeholder text
8 """
9- token = get_oauth_token(request)
10- match_ids = get_optional_list(request.GET, 'id')
11- machines = Machine.objects.get_allocated_visible_machines(
12- token, match_ids)
13+ # limit to machines that the user can view
14+ machines = Machine.objects.get_nodes(request.user, NodePermission.view)
15+ machines = machines.filter(token=get_oauth_token(request))
16+ system_ids = get_optional_list(request.GET, 'id')
17+ if system_ids:
18+ machines = machines.filter(system_id__in=system_ids)
19 return machines.order_by('id')
20
21 @operation(idempotent=False)
22diff --git a/src/maasserver/api/tests/test_machines.py b/src/maasserver/api/tests/test_machines.py
23index 282c6bb..5eac395 100644
24--- a/src/maasserver/api/tests/test_machines.py
25+++ b/src/maasserver/api/tests/test_machines.py
26@@ -629,6 +629,41 @@ class TestMachinesAPI(APITestCase.ForUser):
27 self.assertItemsEqual(
28 required_machine_ids, extract_system_ids(parsed_result))
29
30+ def test_GET_list_allocated_with_rbac(self):
31+ self.patch(auth, 'validate_user_external_auth').return_value = True
32+ rbac = self.useFixture(RBACEnabled())
33+ self.become_non_local()
34+
35+ user = factory.make_User()
36+ pool = factory.make_ResourcePool()
37+ rbac.store.allow(user.username, pool, 'view')
38+
39+ pool = factory.make_ResourcePool()
40+ rbac.store.add_pool(pool)
41+ rbac.store.allow(self.user.username, pool, 'view')
42+
43+ token = get_auth_tokens(self.user)[0]
44+ factory.make_Node(
45+ hostname='viewable', owner=self.user, token=token, pool=pool,
46+ status=NODE_STATUS.ALLOCATED)
47+ # a machine with the same token but not accesssible to the user (not in
48+ # the allowed pool)
49+ factory.make_Node(
50+ hostname='not-accessible', owner=self.user, token=token,
51+ status=NODE_STATUS.ALLOCATED)
52+ # a machine owned by another user in the accessible pool
53+ factory.make_Node(
54+ hostname='other-user', owner=factory.make_User(),
55+ status=NODE_STATUS.ALLOCATED, pool=pool)
56+
57+ response = self.client.get(
58+ reverse('machines_handler'), {'op': 'list_allocated'})
59+ self.assertEqual(http.client.OK, response.status_code)
60+ parsed_result = json.loads(
61+ response.content.decode(settings.DEFAULT_CHARSET))
62+ hostnames = [machine['hostname'] for machine in parsed_result]
63+ self.assertEqual(['viewable'], hostnames)
64+
65 def test_POST_allocate_returns_available_machine(self):
66 # The "allocate" operation returns an available machine.
67 available_status = NODE_STATUS.READY
68diff --git a/src/maasserver/models/node.py b/src/maasserver/models/node.py
69index 8f744d9..998e02c 100644
70--- a/src/maasserver/models/node.py
71+++ b/src/maasserver/models/node.py
72@@ -604,27 +604,6 @@ class MachineManager(BaseNodeManager):
73
74 extra_filters = {'node_type': NODE_TYPE.MACHINE}
75
76- def get_allocated_visible_machines(self, token, ids):
77- """Fetch Machines that were allocated to the User_/oauth token.
78-
79- :param user: The user whose machines to fetch
80- :type user: User_
81- :param token: The OAuth token associated with the Machines.
82- :type token: piston3.models.Token.
83- :param ids: Optional set of IDs to filter by. If given, machines whose
84- system_ids are not in `ids` will be ignored.
85- :type param_ids: Sequence
86-
87- .. _User: https://
88- docs.djangoproject.com/en/dev/topics/auth/
89- #django.contrib.auth.models.User
90- """
91- if ids is None:
92- machines = self.filter(token=token)
93- else:
94- machines = self.filter(token=token, system_id__in=ids)
95- return machines
96-
97 def get_available_machines_for_acquisition(self, for_user):
98 """Find the machines that can be acquired by the given user.
99
100diff --git a/src/maasserver/models/tests/test_node.py b/src/maasserver/models/tests/test_node.py
101index c4ebd6e..361b6f8 100644
102--- a/src/maasserver/models/tests/test_node.py
103+++ b/src/maasserver/models/tests/test_node.py
104@@ -432,6 +432,7 @@ class TestNodeManager(MAASServerTestCase):
105
106
107 class TestMachineManager(MAASServerTestCase):
108+
109 def make_machine(self, user=None, **kwargs):
110 """Create a machine, allocated to `user` if given."""
111 if user is None:

Subscribers

People subscribed via source and target branches