13650: Merge branch 'master' into 13650-document-arvados-kubernetes
[arvados.git] / services / api / test / integration / api_client_authorizations_scopes_test.rb
1 # Copyright (C) The Arvados Authors. All rights reserved.
2 #
3 # SPDX-License-Identifier: AGPL-3.0
4
5 # The v1 API uses token scopes to control access to the REST API at the path
6 # level.  This is enforced in the base ApplicationController, making it a
7 # functional test that we can run against many different controllers.
8
9 require 'test_helper'
10
11 class ApiTokensScopeTest < ActionDispatch::IntegrationTest
12   fixtures :all
13
14   def v1_url(*parts)
15     (['', 'arvados', 'v1'] + parts).join('/')
16   end
17
18   test "user list token can only list users" do
19     get_args = [{}, auth(:active_userlist)]
20     get(v1_url('users'), *get_args)
21     assert_response :success
22     get(v1_url('users', ''), *get_args)  # Add trailing slash.
23     assert_response :success
24     get(v1_url('users', 'current'), *get_args)
25     assert_response 403
26     get(v1_url('virtual_machines'), *get_args)
27     assert_response 403
28   end
29
30   test "narrow + wide scoped tokens for different users" do
31     get_args = [{
32                   reader_tokens: [api_client_authorizations(:anonymous).api_token]
33                 }, auth(:active_userlist)]
34     get(v1_url('users'), *get_args)
35     assert_response :success
36     get(v1_url('users', ''), *get_args)  # Add trailing slash.
37     assert_response :success
38     get(v1_url('users', 'current'), *get_args)
39     assert_response 403
40     get(v1_url('virtual_machines'), *get_args)
41     assert_response 403
42    end
43
44   test "specimens token can see exactly owned specimens" do
45     get_args = [{}, auth(:active_specimens)]
46     get(v1_url('specimens'), *get_args)
47     assert_response 403
48     get(v1_url('specimens', specimens(:owned_by_active_user).uuid), *get_args)
49     assert_response :success
50     head(v1_url('specimens', specimens(:owned_by_active_user).uuid), *get_args)
51     assert_response :success
52     get(v1_url('specimens', specimens(:owned_by_spectator).uuid), *get_args)
53     assert_includes(403..404, @response.status)
54   end
55
56   test "token with multiple scopes can use them all" do
57     def get_token_count
58       get(v1_url('api_client_authorizations'), {}, auth(:active_apitokens))
59       assert_response :success
60       token_count = JSON.parse(@response.body)['items_available']
61       assert_not_nil(token_count, "could not find token count")
62       token_count
63     end
64     # Test the GET scope.
65     token_count = get_token_count
66     # Test the POST scope.
67     post(v1_url('api_client_authorizations'),
68          {api_client_authorization: {user_id: users(:active).id}},
69          auth(:active_apitokens))
70     assert_response :success
71     assert_equal(token_count + 1, get_token_count,
72                  "token count suggests POST was not accepted")
73     # Test other requests are denied.
74     get(v1_url('api_client_authorizations',
75                api_client_authorizations(:active_apitokens).uuid),
76         {}, auth(:active_apitokens))
77     assert_response 403
78   end
79
80   test "token without scope has no access" do
81     # Logs are good for this test, because logs have relatively
82     # few access controls enforced at the model level.
83     req_args = [{}, auth(:admin_noscope)]
84     get(v1_url('logs'), *req_args)
85     assert_response 403
86     get(v1_url('logs', logs(:noop).uuid), *req_args)
87     assert_response 403
88     post(v1_url('logs'), *req_args)
89     assert_response 403
90   end
91
92   test "VM login scopes work" do
93     # A system administration script makes an API token with limited scope
94     # for virtual machines to let it see logins.
95     def vm_logins_url(name)
96       v1_url('virtual_machines', virtual_machines(name).uuid, 'logins')
97     end
98     get_args = [{}, auth(:admin_vm)]
99     get(vm_logins_url(:testvm), *get_args)
100     assert_response :success
101     get(vm_logins_url(:testvm2), *get_args)
102     assert_includes(400..419, @response.status,
103                     "getting testvm2 logins should have failed")
104   end
105 end