1 # Copyright (C) The Arvados Authors. All rights reserved.
3 # SPDX-License-Identifier: AGPL-3.0
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.
11 class ApiTokensScopeTest < ActionDispatch::IntegrationTest
15 (['', 'arvados', 'v1'] + parts).join('/')
18 test "user list token can only list users" do
19 get_args = [params: {}, headers: 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)
26 get(v1_url('virtual_machines'), *get_args)
30 test "narrow + wide scoped tokens for different users" do
32 reader_tokens: [api_client_authorizations(:anonymous).api_token]
33 }, headers: 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)
40 get(v1_url('virtual_machines'), *get_args)
44 test "specimens token can see exactly owned specimens" do
45 get_args = [params: {}, headers: auth(:active_specimens)]
46 get(v1_url('specimens'), *get_args)
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)
56 test "token with multiple scopes can use them all" do
58 get(v1_url('api_client_authorizations'),
60 headers: auth(:active_apitokens))
61 assert_response :success
62 token_count = JSON.parse(@response.body)['items_available']
63 assert_not_nil(token_count, "could not find token count")
67 token_count = get_token_count
68 # Test the POST scope.
69 post(v1_url('api_client_authorizations'),
70 params: {api_client_authorization: {user_id: users(:active).id}},
71 headers: auth(:active_apitokens))
72 assert_response :success
73 assert_equal(token_count + 1, get_token_count,
74 "token count suggests POST was not accepted")
75 # Test other requests are denied.
76 get(v1_url('api_client_authorizations',
77 api_client_authorizations(:active_apitokens).uuid),
78 params: {}, headers: auth(:active_apitokens))
82 test "token without scope has no access" do
83 # Logs are good for this test, because logs have relatively
84 # few access controls enforced at the model level.
85 req_args = [params: {}, headers: auth(:admin_noscope)]
86 get(v1_url('logs'), *req_args)
88 get(v1_url('logs', logs(:noop).uuid), *req_args)
90 post(v1_url('logs'), *req_args)
94 test "VM login scopes work" do
95 # A system administration script makes an API token with limited scope
96 # for virtual machines to let it see logins.
97 def vm_logins_url(name)
98 v1_url('virtual_machines', virtual_machines(name).uuid, 'logins')
100 get_args = [params: {}, headers: auth(:admin_vm)]
101 get(vm_logins_url(:testvm), *get_args)
102 assert_response :success
103 get(vm_logins_url(:testvm2), *get_args)
104 assert_includes(400..419, @response.status,
105 "getting testvm2 logins should have failed")