21700: Install Bundler system-wide in Rails postinst
[arvados.git] / services / api / test / integration / remote_user_test.rb
1 # Copyright (C) The Arvados Authors. All rights reserved.
2 #
3 # SPDX-License-Identifier: AGPL-3.0
4
5 require 'webrick'
6 require 'webrick/https'
7 require 'test_helper'
8 require 'helpers/users_test_helper'
9
10 class RemoteUsersTest < ActionDispatch::IntegrationTest
11   include DbCurrentTime
12
13   def salted_active_token(remote:)
14     salt_token(fixture: :active, remote: remote).sub('/zzzzz-', '/'+remote+'-')
15   end
16
17   def auth(remote:)
18     token = salted_active_token(remote: remote)
19     {"HTTP_AUTHORIZATION" => "Bearer #{token}"}
20   end
21
22   # For remote authentication tests, we bring up a simple stub server
23   # (on a port chosen by webrick) and configure the SUT so the stub is
24   # responsible for clusters "zbbbb" (a well-behaved cluster) and
25   # "zbork" (a misbehaving cluster).
26   #
27   # Test cases can override the stub's default response to
28   # .../users/current by changing @stub_status and @stub_content.
29   setup do
30     clnt = HTTPClient.new
31     clnt.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
32     HTTPClient.stubs(:new).returns clnt
33
34     @controller = Arvados::V1::UsersController.new
35     ready = Thread::Queue.new
36
37     @remote_server = []
38     @remote_host = []
39
40     ['zbbbb', 'zbork'].each do |clusterid|
41       srv = WEBrick::HTTPServer.new(
42         Port: 0,
43         Logger: WEBrick::Log.new(
44           Rails.root.join("log", "webrick.log").to_s,
45           WEBrick::Log::INFO),
46         AccessLog: [[File.open(Rails.root.join(
47                                  "log", "webrick_access.log").to_s, 'a+'),
48                      WEBrick::AccessLog::COMBINED_LOG_FORMAT]],
49         SSLEnable: true,
50         SSLVerifyClient: OpenSSL::SSL::VERIFY_NONE,
51         SSLPrivateKey: OpenSSL::PKey::RSA.new(
52           File.open(Rails.root.join("tmp", "self-signed.key")).read),
53         SSLCertificate: OpenSSL::X509::Certificate.new(
54           File.open(Rails.root.join("tmp", "self-signed.pem")).read),
55         SSLCertName: [["CN", WEBrick::Utils::getservername]],
56         StartCallback: lambda { ready.push(true) })
57       srv.mount_proc '/discovery/v1/apis/arvados/v1/rest' do |req, res|
58         res.body = Arvados::V1::SchemaController.new.send(:discovery_doc).to_json
59       end
60       srv.mount_proc '/arvados/v1/users/current' do |req, res|
61         if clusterid == 'zbbbb' and req.header['authorization'][0][10..14] == 'zbork'
62           # asking zbbbb about zbork should yield an error, zbbbb doesn't trust zbork
63           res.status = 401
64           return
65         end
66         res.status = @stub_status
67         res.body = @stub_content.is_a?(String) ? @stub_content : @stub_content.to_json
68       end
69       srv.mount_proc '/arvados/v1/api_client_authorizations/current' do |req, res|
70         if clusterid == 'zbbbb' and req.header['authorization'][0][10..14] == 'zbork'
71           # asking zbbbb about zbork should yield an error, zbbbb doesn't trust zbork
72           res.status = 401
73           return
74         end
75         res.status = @stub_token_status
76         if res.status == 200
77           body = {
78             uuid: @stub_token_uuid || api_client_authorizations(:active).uuid.sub('zzzzz', clusterid),
79             owner_uuid: "#{clusterid}-tpzed-00000000000000z",
80             scopes: @stub_token_scopes,
81           }
82           if @stub_content.is_a?(Hash) and owner_uuid = @stub_content[:uuid]
83             body[:owner_uuid] = owner_uuid
84           end
85           res.body = body.to_json
86         end
87       end
88       Thread.new do
89         srv.start
90       end
91       ready.pop
92       @remote_server << srv
93       @remote_host << "127.0.0.1:#{srv.config[:Port]}"
94     end
95     Rails.configuration.RemoteClusters = Rails.configuration.RemoteClusters.merge({zbbbb: ActiveSupport::InheritableOptions.new({Host: @remote_host[0]}),
96                                                                                    zbork: ActiveSupport::InheritableOptions.new({Host: @remote_host[1]})})
97     Arvados::V1::SchemaController.any_instance.stubs(:root_url).returns "https://#{@remote_host[0]}"
98     @stub_status = 200
99     @stub_content = {
100       uuid: 'zbbbb-tpzed-000000000000001',
101       email: 'foo@example.com',
102       username: 'barney',
103       first_name: "Barney",
104       last_name: "Foo",
105       is_admin: true,
106       is_active: true,
107       is_invited: true,
108     }
109     @stub_token_status = 200
110     @stub_token_scopes = ["all"]
111     @stub_token_uuid = nil
112     ActionMailer::Base.deliveries = []
113   end
114
115   teardown do
116     @remote_server.each do |srv|
117       srv.stop
118     end
119   end
120
121   def uncache_token(src)
122     if match = src.match(/\b(?:[a-z0-9]{5}-){2}[a-z0-9]{15}\b/)
123       tokens = ApiClientAuthorization.where(uuid: match[0])
124     else
125       tokens = ApiClientAuthorization.where("uuid like ?", "#{src}-%")
126     end
127     tokens.update_all(expires_at: "1995-05-15T01:02:03Z")
128   end
129
130   test 'authenticate with remote token that has limited scope' do
131     get '/arvados/v1/collections',
132         params: {format: 'json'},
133         headers: auth(remote: 'zbbbb')
134     assert_response :success
135
136     @stub_token_scopes = ["GET /arvados/v1/users/current"]
137
138     # re-authorize before cache expires
139     get '/arvados/v1/collections',
140         params: {format: 'json'},
141         headers: auth(remote: 'zbbbb')
142     assert_response :success
143
144     uncache_token('zbbbb')
145     # re-authorize after cache expires
146     get '/arvados/v1/collections',
147         params: {format: 'json'},
148         headers: auth(remote: 'zbbbb')
149     assert_response 403
150   end
151
152   test "authenticate with remote token with limited initial scope" do
153     @stub_token_scopes = ["GET /arvados/v1/users/"]
154     get "/arvados/v1/users/#{@stub_content[:uuid]}",
155         params: {format: "json"},
156         headers: auth(remote: "zbbbb")
157     assert_response :success
158   end
159
160   test 'authenticate with remote token' do
161     get '/arvados/v1/users/current',
162       params: {format: 'json'},
163       headers: auth(remote: 'zbbbb')
164     assert_response :success
165     assert_equal 'zbbbb-tpzed-000000000000001', json_response['uuid']
166     assert_equal false, json_response['is_admin']
167     assert_equal false, json_response['is_active']
168     assert_equal 'foo@example.com', json_response['email']
169     assert_equal 'barney', json_response['username']
170
171     # revoke original token
172     @stub_token_status = 401
173
174     # re-authorize before cache expires
175     get '/arvados/v1/users/current',
176       params: {format: 'json'},
177       headers: auth(remote: 'zbbbb')
178     assert_response :success
179
180     uncache_token('zbbbb')
181     # re-authorize after cache expires
182     get '/arvados/v1/users/current',
183       params: {format: 'json'},
184       headers: auth(remote: 'zbbbb')
185     assert_response 401
186
187     # simulate cached token indicating wrong user (e.g., local user
188     # entry was migrated out of the way taking the cached token with
189     # it, or authorizing cluster reassigned auth to a different user)
190     ApiClientAuthorization.where(
191       uuid: salted_active_token(remote: 'zbbbb').split('/')[1]).
192       update_all(user_id: users(:active).id)
193
194     # revive original token and re-authorize
195     @stub_token_status = 200
196     @stub_content[:username] = 'blarney'
197     @stub_content[:email] = 'blarney@example.com'
198     get '/arvados/v1/users/current',
199       params: {format: 'json'},
200       headers: auth(remote: 'zbbbb')
201     assert_response :success
202     assert_equal 'barney', json_response['username'], 'local username should not change once assigned'
203     assert_equal 'blarney@example.com', json_response['email']
204   end
205
206   test 'remote user is deactivated' do
207     Rails.configuration.RemoteClusters['zbbbb'].ActivateUsers = true
208     get '/arvados/v1/users/current',
209       params: {format: 'json'},
210       headers: auth(remote: 'zbbbb')
211     assert_response :success
212     assert_equal true, json_response['is_active']
213
214     # revoke original token
215     @stub_content[:is_active] = false
216     @stub_content[:is_invited] = false
217
218     uncache_token('zbbbb')
219     # re-authorize after cache expires
220     get '/arvados/v1/users/current',
221       params: {format: 'json'},
222       headers: auth(remote: 'zbbbb')
223     assert_equal false, json_response['is_active']
224
225   end
226
227   test 'authenticate with remote token, remote username conflicts with local' do
228     @stub_content[:username] = 'active'
229     get '/arvados/v1/users/current',
230       params: {format: 'json'},
231       headers: auth(remote: 'zbbbb')
232     assert_response :success
233     assert_equal 'active2', json_response['username']
234   end
235
236   test 'authenticate with remote token, remote username is nil' do
237     @stub_content.delete :username
238     get '/arvados/v1/users/current',
239       params: {format: 'json'},
240       headers: auth(remote: 'zbbbb')
241     assert_response :success
242     assert_equal 'foo', json_response['username']
243   end
244
245   test 'authenticate with remote token with secret part identical to previously cached token' do
246     get '/arvados/v1/users/current',
247       params: {format: 'json'},
248       headers: auth(remote: 'zbbbb')
249     assert_response :success
250     get '/arvados/v1/api_client_authorizations/current',
251       params: {format: 'json'},
252       headers: auth(remote: 'zbbbb')
253     assert_response :success
254
255     # Expire the cached token.
256     @cached_token_uuid = json_response['uuid']
257     act_as_system_user do
258       ApiClientAuthorization.where(uuid: @cached_token_uuid).update_all(expires_at: db_current_time() - 1.day)
259     end
260
261     # Now use the same bare token, but set up the remote cluster to
262     # return a different UUID this time.
263     @stub_token_uuid = 'zbbbb-gj3su-123451234512345'
264     get '/arvados/v1/users/current',
265       params: {format: 'json'},
266       headers: auth(remote: 'zbbbb')
267     assert_response :success
268
269     # Confirm that we actually retrieved the new UUID from the stub
270     # cluster -- otherwise we didn't really test the conflicting-UUID
271     # case.
272     get '/arvados/v1/api_client_authorizations/current',
273       params: {format: 'json'},
274       headers: auth(remote: 'zbbbb')
275     assert_response :success
276     assert_equal @stub_token_uuid, json_response['uuid']
277   end
278
279   test 'authenticate with remote token from misbehaving remote cluster' do
280     get '/arvados/v1/users/current',
281       params: {format: 'json'},
282       headers: auth(remote: 'zbork')
283     assert_response 401
284   end
285
286   test 'authenticate with remote token that fails validate' do
287     @stub_status = 401
288     @stub_content = {
289       error: 'not authorized',
290     }
291     get '/arvados/v1/users/current',
292       params: {format: 'json'},
293       headers: auth(remote: 'zbbbb')
294     assert_response 401
295   end
296
297   ['v2',
298    'v2/',
299    'v2//',
300    'v2///',
301    "v2/'; delete from users where 1=1; commit; select '/lol",
302    'v2/foo/bar',
303    'v2/zzzzz-gj3su-077z32aux8dg2s1',
304    'v2/zzzzz-gj3su-077z32aux8dg2s1/',
305    'v2/3kg6k6lzmp9kj5cpkcoxie963cmvjahbt2fod9zru30k1jqdmi',
306    'v2/3kg6k6lzmp9kj5cpkcoxie963cmvjahbt2fod9zru30k1jqdmi/zzzzz-gj3su-077z32aux8dg2s1',
307    'v2//3kg6k6lzmp9kj5cpkcoxie963cmvjahbt2fod9zru30k1jqdmi',
308    'v8/zzzzz-gj3su-077z32aux8dg2s1/3kg6k6lzmp9kj5cpkcoxie963cmvjahbt2fod9zru30k1jqdmi',
309    '/zzzzz-gj3su-077z32aux8dg2s1/3kg6k6lzmp9kj5cpkcoxie963cmvjahbt2fod9zru30k1jqdmi',
310    '"v2/zzzzz-gj3su-077z32aux8dg2s1/3kg6k6lzmp9kj5cpkcoxie963cmvjahbt2fod9zru30k1jqdmi"',
311    '/',
312    '//',
313    '///',
314   ].each do |token|
315     test "authenticate with malformed remote token #{token}" do
316       get '/arvados/v1/users/current',
317         params: {format: 'json'},
318         headers: {"HTTP_AUTHORIZATION" => "Bearer #{token}"}
319       assert_response 401
320     end
321   end
322
323   test "ignore extra fields in remote token" do
324     token = salted_active_token(remote: 'zbbbb') + '/foo/bar/baz/*'
325     get '/arvados/v1/users/current',
326       params: {format: 'json'},
327       headers: {"HTTP_AUTHORIZATION" => "Bearer #{token}"}
328     assert_response :success
329   end
330
331   test 'remote api server is not an api server' do
332     @stub_status = 200
333     @stub_content = '<html>bad</html>'
334     get '/arvados/v1/users/current',
335       params: {format: 'json'},
336       headers: auth(remote: 'zbbbb')
337     assert_response 401
338   end
339
340   ['zbbbb', 'z0000'].each do |token_valid_for|
341     test "validate #{token_valid_for}-salted token for remote cluster zbbbb" do
342       salted_token = salt_token(fixture: :active, remote: token_valid_for)
343       get '/arvados/v1/users/current',
344         params: {format: 'json', remote: 'zbbbb'},
345         headers: {"HTTP_AUTHORIZATION" => "Bearer #{salted_token}"}
346       if token_valid_for == 'zbbbb'
347         assert_response 200
348         assert_equal(users(:active).uuid, json_response['uuid'])
349       else
350         assert_response 401
351       end
352     end
353   end
354
355   test "list readable groups with salted token" do
356     Rails.configuration.Users.RoleGroupsVisibleToAll = false
357     salted_token = salt_token(fixture: :active, remote: 'zbbbb')
358     get '/arvados/v1/groups',
359       params: {
360         format: 'json',
361         remote: 'zbbbb',
362         limit: 10000,
363       },
364       headers: {"HTTP_AUTHORIZATION" => "Bearer #{salted_token}"}
365     assert_response 200
366     group_uuids = json_response['items'].collect { |i| i['uuid'] }
367     assert_includes(group_uuids, 'zzzzz-j7d0g-fffffffffffffff')
368     refute_includes(group_uuids, 'zzzzz-j7d0g-000000000000000')
369     assert_includes(group_uuids, groups(:aproject).uuid)
370     refute_includes(group_uuids, groups(:trashed_project).uuid)
371     refute_includes(group_uuids, groups(:testusergroup_admins).uuid)
372   end
373
374   test 'do not auto-activate user from untrusted cluster' do
375     Rails.configuration.RemoteClusters['zbbbb'].AutoSetupNewUsers = false
376     Rails.configuration.RemoteClusters['zbbbb'].ActivateUsers = false
377     get '/arvados/v1/users/current',
378       params: {format: 'json'},
379       headers: auth(remote: 'zbbbb')
380     assert_response :success
381     assert_equal 'zbbbb-tpzed-000000000000001', json_response['uuid']
382     assert_equal false, json_response['is_admin']
383     assert_equal false, json_response['is_active']
384     assert_equal 'foo@example.com', json_response['email']
385     assert_equal 'barney', json_response['username']
386     post '/arvados/v1/users/zbbbb-tpzed-000000000000001/activate',
387       params: {format: 'json'},
388       headers: auth(remote: 'zbbbb')
389     assert_response 422
390   end
391
392   test 'auto-activate user from trusted cluster' do
393     Rails.configuration.RemoteClusters['zbbbb'].ActivateUsers = true
394     get '/arvados/v1/users/current',
395       params: {format: 'json'},
396       headers: auth(remote: 'zbbbb')
397     assert_response :success
398     assert_equal 'zbbbb-tpzed-000000000000001', json_response['uuid']
399     assert_equal false, json_response['is_admin']
400     assert_equal true, json_response['is_active']
401     assert_equal 'foo@example.com', json_response['email']
402     assert_equal 'barney', json_response['username']
403   end
404
405   test 'get user from Login cluster' do
406     Rails.configuration.Login.LoginCluster = 'zbbbb'
407     email_dest = ActiveSupport::OrderedOptions.new
408     email_dest[:'arvados-admin@example.com'] = ActiveSupport::OrderedOptions.new
409     Rails.configuration.Users.UserNotifierEmailBcc = email_dest
410     Rails.configuration.Users.NewUserNotificationRecipients = email_dest
411     Rails.configuration.Users.NewInactiveUserNotificationRecipients = email_dest
412
413     get '/arvados/v1/users/current',
414       params: {format: 'json'},
415       headers: auth(remote: 'zbbbb')
416     assert_response :success
417     assert_equal 'zbbbb-tpzed-000000000000001', json_response['uuid']
418     assert_equal true, json_response['is_admin']
419     assert_equal true, json_response['is_active']
420     assert_equal 'foo@example.com', json_response['email']
421     assert_equal 'barney', json_response['username']
422
423     assert_equal 2, ActionMailer::Base.deliveries.length
424     assert_equal "Welcome to Arvados - account enabled", ActionMailer::Base.deliveries[0].subject
425     assert_equal "[ARVADOS] New user created notification", ActionMailer::Base.deliveries[1].subject
426   end
427
428   [true, false].each do |trusted|
429     [true, false].each do |logincluster|
430       [true, false, nil].each do |admin|
431         [true, false, nil].each do |active|
432           [true, false].each do |autosetup|
433             [true, false, nil].each do |invited|
434               test "get invited=#{invited}, active=#{active}, admin=#{admin} user from #{if logincluster then "Login" else "peer" end} cluster when AutoSetupNewUsers=#{autosetup} ActivateUsers=#{trusted}" do
435                 Rails.configuration.Login.LoginCluster = 'zbbbb' if logincluster
436                 Rails.configuration.RemoteClusters['zbbbb'].ActivateUsers = trusted
437                 Rails.configuration.Users.AutoSetupNewUsers = autosetup
438                 @stub_content = {
439                   uuid: 'zbbbb-tpzed-000000000000001',
440                   email: 'foo@example.com',
441                   username: 'barney',
442                   is_admin: admin,
443                   is_active: active,
444                   is_invited: invited,
445                 }
446                 get '/arvados/v1/users/current',
447                     params: {format: 'json'},
448                     headers: auth(remote: 'zbbbb')
449                 assert_response :success
450                 assert_equal 'zbbbb-tpzed-000000000000001', json_response['uuid']
451                 assert_equal (logincluster && !!admin && (invited != false) && !!active), json_response['is_admin']
452                 assert_equal ((invited == true || (invited == nil && !!active)) && (logincluster || trusted || autosetup)), json_response['is_invited']
453                 assert_equal ((invited != false) && (logincluster || trusted) && !!active), json_response['is_active']
454                 assert_equal 'foo@example.com', json_response['email']
455                 assert_equal 'barney', json_response['username']
456               end
457             end
458           end
459         end
460       end
461     end
462   end
463
464   test 'get active user from Login cluster when AutoSetupNewUsers is set' do
465     Rails.configuration.Login.LoginCluster = 'zbbbb'
466     Rails.configuration.Users.AutoSetupNewUsers = true
467     @stub_content = {
468       uuid: 'zbbbb-tpzed-000000000000001',
469       email: 'foo@example.com',
470       username: 'barney',
471       is_admin: false,
472       is_active: true,
473       is_invited: true,
474     }
475     get '/arvados/v1/users/current',
476       params: {format: 'json'},
477       headers: auth(remote: 'zbbbb')
478     assert_response :success
479     assert_equal 'zbbbb-tpzed-000000000000001', json_response['uuid']
480     assert_equal false, json_response['is_admin']
481     assert_equal true, json_response['is_active']
482     assert_equal true, json_response['is_invited']
483     assert_equal 'foo@example.com', json_response['email']
484     assert_equal 'barney', json_response['username']
485
486     @stub_content = {
487       uuid: 'zbbbb-tpzed-000000000000001',
488       email: 'foo@example.com',
489       username: 'barney',
490       is_admin: false,
491       is_active: false,
492       is_invited: false,
493     }
494
495     # Use cached value.  User will still be active because we haven't
496     # re-queried the upstream cluster.
497     get '/arvados/v1/users/current',
498       params: {format: 'json'},
499       headers: auth(remote: 'zbbbb')
500     assert_response :success
501     assert_equal 'zbbbb-tpzed-000000000000001', json_response['uuid']
502     assert_equal false, json_response['is_admin']
503     assert_equal true, json_response['is_active']
504     assert_equal true, json_response['is_invited']
505     assert_equal 'foo@example.com', json_response['email']
506     assert_equal 'barney', json_response['username']
507
508     uncache_token('zbbbb')
509     # User should be inactive now.
510     get '/arvados/v1/users/current',
511       params: {format: 'json'},
512       headers: auth(remote: 'zbbbb')
513     assert_response :success
514     assert_equal 'zbbbb-tpzed-000000000000001', json_response['uuid']
515     assert_equal false, json_response['is_admin']
516     assert_equal false, json_response['is_active']
517     assert_equal false, json_response['is_invited']
518     assert_equal 'foo@example.com', json_response['email']
519     assert_equal 'barney', json_response['username']
520
521   end
522
523   test 'pre-activate remote user' do
524     @stub_content = {
525       uuid: 'zbbbb-tpzed-000000000001234',
526       email: 'foo@example.com',
527       username: 'barney',
528       is_admin: true,
529       is_active: true,
530       is_invited: true,
531     }
532
533     post '/arvados/v1/users',
534       params: {
535         "user" => {
536           "uuid" => "zbbbb-tpzed-000000000001234",
537           "email" => 'foo@example.com',
538           "username" => 'barney',
539           "is_active" => true,
540           "is_admin" => false
541         }
542       },
543       headers: {'HTTP_AUTHORIZATION' => "OAuth2 #{api_token(:admin)}"}
544     assert_response :success
545
546     get '/arvados/v1/users/current',
547       params: {format: 'json'},
548       headers: auth(remote: 'zbbbb')
549     assert_response :success
550     assert_equal 'zbbbb-tpzed-000000000001234', json_response['uuid']
551     assert_equal false, json_response['is_admin']
552     assert_equal true, json_response['is_active']
553     assert_equal 'foo@example.com', json_response['email']
554     assert_equal 'barney', json_response['username']
555   end
556
557
558   test 'remote user inactive without pre-activation' do
559     @stub_content = {
560       uuid: 'zbbbb-tpzed-000000000001234',
561       email: 'foo@example.com',
562       username: 'barney',
563       is_admin: true,
564       is_active: true,
565       is_invited: true,
566     }
567
568     get '/arvados/v1/users/current',
569       params: {format: 'json'},
570       headers: auth(remote: 'zbbbb')
571     assert_response :success
572     assert_equal 'zbbbb-tpzed-000000000001234', json_response['uuid']
573     assert_equal false, json_response['is_admin']
574     assert_equal false, json_response['is_active']
575     assert_equal 'foo@example.com', json_response['email']
576     assert_equal 'barney', json_response['username']
577   end
578
579   test "validate unsalted v2 token for remote cluster zbbbb" do
580     auth = api_client_authorizations(:active)
581     token = "v2/#{auth.uuid}/#{auth.api_token}"
582     get '/arvados/v1/users/current',
583       params: {format: 'json', remote: 'zbbbb'},
584       headers: {"HTTP_AUTHORIZATION" => "Bearer #{token}"}
585     assert_response :success
586     assert_equal(users(:active).uuid, json_response['uuid'])
587   end
588
589   test 'container request with runtime_token' do
590     [["valid local", "v2/#{api_client_authorizations(:active).uuid}/#{api_client_authorizations(:active).api_token}"],
591      ["valid remote", "v2/zbbbb-gj3su-000000000000000/abc"],
592      ["invalid local", "v2/#{api_client_authorizations(:active).uuid}/fakefakefake"],
593      ["invalid remote", "v2/zbork-gj3su-000000000000000/abc"],
594     ].each do |label, runtime_token|
595       post '/arvados/v1/container_requests',
596         params: {
597           "container_request" => {
598             "command" => ["echo"],
599             "container_image" => "xyz",
600             "output_path" => "/",
601             "cwd" => "/",
602             "runtime_token" => runtime_token
603           }
604         },
605         headers: {"HTTP_AUTHORIZATION" => "Bearer #{api_client_authorizations(:active).api_token}"}
606       if label.include? "invalid"
607         assert_response 422
608       else
609         assert_response :success
610       end
611     end
612   end
613
614   test 'authenticate with remote token, remote user is system user' do
615     @stub_content[:uuid] = 'zbbbb-tpzed-000000000000000'
616     get '/arvados/v1/users/current',
617       params: {format: 'json'},
618       headers: auth(remote: 'zbbbb')
619     assert_equal 'from cluster zbbbb', json_response['last_name']
620   end
621
622   test 'authenticate with remote token, remote user is anonymous user' do
623     @stub_content[:uuid] = 'zbbbb-tpzed-anonymouspublic'
624     get '/arvados/v1/users/current',
625       params: {format: 'json'},
626       headers: auth(remote: 'zbbbb')
627     assert_response :success
628     assert_equal 'zzzzz-tpzed-anonymouspublic', json_response['uuid']
629   end
630
631   [400, 401, 403, 422, 500, 502, 503].each do |status|
632     test "handle #{status} response when checking remote-provided v2 token" do
633       @stub_token_status = status
634       get "/arvados/v1/users/#{@stub_content[:uuid]}",
635           params: {format: "json"},
636           headers: auth(remote: "zbbbb")
637       assert_response(status < 500 ? 401 : status)
638     end
639
640     test "handle #{status} response when checking remote-provided v2 token at anonymously accessible endpoint" do
641       @stub_token_status = status
642       get "/arvados/v1/keep_services/accessible",
643           params: {format: "json"},
644           headers: auth(remote: "zbbbb")
645       assert_response(status < 500 ? :success : status)
646     end
647
648     test "handle #{status} response when checking token issued by login cluster" do
649       @stub_token_status = status
650       Rails.configuration.Login.LoginCluster = "zbbbb"
651       get "/arvados/v1/users/current",
652           params: {format: "json"},
653           headers: {'HTTP_AUTHORIZATION' => "Bearer badtoken"}
654       assert_response(status < 500 ? 401 : status)
655     end
656
657     test "handle #{status} response when checking token issued by login cluster at anonymously accessible endpoint" do
658       @stub_token_status = status
659       Rails.configuration.Login.LoginCluster = "zbbbb"
660       get "/arvados/v1/keep_services/accessible",
661           params: {format: "json"},
662           headers: {'HTTP_AUTHORIZATION' => "Bearer badtoken"}
663       assert_response(status < 500 ? :success : status)
664     end
665   end
666
667   [401, 403, 422, 500, 502, 503].each do |status|
668     test "propagate #{status} response from getting uncached user" do
669       @stub_status = status
670       get "/arvados/v1/users/#{@stub_content[:uuid]}",
671           params: {format: "json"},
672           headers: auth(remote: "zbbbb")
673       assert_response status
674     end
675
676     test "use cached user after getting #{status} response" do
677       url_path = "/arvados/v1/users/#{@stub_content[:uuid]}"
678       params = {format: "json"}
679       headers = auth(remote: "zbbbb")
680
681       get url_path, params: params, headers: headers
682       assert_response :success
683
684       uncache_token(headers["HTTP_AUTHORIZATION"])
685       expect_email = @stub_content[:email]
686       @stub_content[:email] = "new#{expect_email}"
687       @stub_status = status
688       get url_path, params: params, headers: headers
689       assert_response :success
690       user = User.find_by_uuid(@stub_content[:uuid])
691       assert_not_nil user
692       assert_equal expect_email, user.email
693     end
694   end
695 end