[ARVADOS] updated: 03e570095885982d23e234bce8e1c068314b63af
git at public.curoverse.com
git at public.curoverse.com
Mon Apr 28 14:07:56 EDT 2014
Summary of changes:
.../api/app/controllers/application_controller.rb | 17 ++--
.../v1/api_client_authorizations_controller.rb | 32 +++++--
.../arvados/v1/keep_disks_controller.rb | 2 +-
.../app/controllers/arvados/v1/nodes_controller.rb | 2 +-
.../controllers/arvados/v1/schema_controller.rb | 6 +-
.../arvados/v1/virtual_machines_controller.rb | 16 ---
services/api/app/controllers/static_controller.rb | 2 +-
.../app/controllers/user_sessions_controller.rb | 2 +-
.../db/migrate/20140423133559_new_scope_format.rb | 48 +++++++++
services/api/db/schema.rb | 2 +-
services/api/lib/current_api_client.rb | 19 ++--
.../test/fixtures/api_client_authorizations.yml | 37 +++++++
.../api_client_authorizations_controller_test.rb | 30 ++++++-
.../api_client_authorizations_scopes_test.rb | 103 ++++++++++++++++++++
14 files changed, 270 insertions(+), 48 deletions(-)
create mode 100644 services/api/db/migrate/20140423133559_new_scope_format.rb
create mode 100644 services/api/test/integration/api_client_authorizations_scopes_test.rb
via 03e570095885982d23e234bce8e1c068314b63af (commit)
via 5c2758ca38d01a905253f86e63be3a5fe03a3871 (commit)
via 52c4f2b7fe631f3d7ad16105cb2f86cf6c004fc8 (commit)
via e54bdba73b65e31b03fd1d43bfe69d0f43bbd8d8 (commit)
via 0eb59e3acf9f13e89bd010f7f65a4d31554183fc (commit)
via 915de6c854cd559ebd029b24939149e37b18c8cf (commit)
from 71b1b7b045419817d1c9dc62a3a296b746d9117c (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
commit 03e570095885982d23e234bce8e1c068314b63af
Merge: 71b1b7b 5c2758c
Author: Brett Smith <brett at curoverse.com>
Date: Mon Apr 28 14:07:02 2014 -0400
Merge branch '1904-object-scopes'
Closes #2642, #2662, #2682.
commit 5c2758ca38d01a905253f86e63be3a5fe03a3871
Author: Brett Smith <brett at curoverse.com>
Date: Mon Apr 28 13:01:18 2014 -0400
api: Support filters in API client auths index.
Per comments on Refs #1904. filters is generally the preferred way to
do searching now. I maintained existing limits on what can be
searched with this method.
diff --git a/services/api/app/controllers/application_controller.rb b/services/api/app/controllers/application_controller.rb
index a86e35b..b091397 100644
--- a/services/api/app/controllers/application_controller.rb
+++ b/services/api/app/controllers/application_controller.rb
@@ -207,6 +207,10 @@ class ApplicationController < ActionController::Base
end
end
+ def default_orders
+ ["#{table_name}.modified_at desc"]
+ end
+
def load_limit_offset_order_params
if params[:limit]
unless params[:limit].to_s.match(/^\d+$/)
@@ -239,7 +243,7 @@ class ApplicationController < ActionController::Base
end
end
if @orders.empty?
- @orders << "#{table_name}.modified_at desc"
+ @orders = default_orders
end
end
diff --git a/services/api/app/controllers/arvados/v1/api_client_authorizations_controller.rb b/services/api/app/controllers/arvados/v1/api_client_authorizations_controller.rb
index ff322a7..dc95b2f 100644
--- a/services/api/app/controllers/arvados/v1/api_client_authorizations_controller.rb
+++ b/services/api/app/controllers/arvados/v1/api_client_authorizations_controller.rb
@@ -34,21 +34,34 @@ class Arvados::V1::ApiClientAuthorizationsController < ApplicationController
protected
+ def default_orders
+ ["#{table_name}.created_at desc"]
+ end
+
def find_objects_for_index
# Here we are deliberately less helpful about searching for client
- # authorizations. Rather than use the generic index/where/order
- # features, we look up tokens belonging to the current user and
- # filter by exact match on api_token (which we expect in the form
- # of a where[uuid] parameter to make things easier for API client
- # libraries).
+ # authorizations. We look up tokens belonging to the current user
+ # and filter by exact matches on api_token and scopes.
+ wanted_scopes = []
+ if @filters
+ wanted_scopes.concat(@filters.map { |attr, operator, operand|
+ ((attr == 'scopes') and (operator == '=')) ? operand : nil
+ })
+ @filters.select! { |attr, operator, operand|
+ (attr == 'uuid') and (operator == '=')
+ }
+ end
+ if @where
+ wanted_scopes << @where['scopes']
+ @where.select! { |attr, val| attr == 'uuid' }
+ end
@objects = model_class.
includes(:user, :api_client).
- where('user_id=? and (? or api_token=?)', current_user.id, !@where['uuid'], @where['uuid']).
- order('created_at desc')
- unless @where['scopes'].nil?
- @objects = @objects.select { |auth|
- (auth.scopes & @where['scopes']) == (auth.scopes | @where['scopes'])
- }
+ where('user_id=?', current_user.id)
+ super
+ wanted_scopes.compact.each do |scope_list|
+ sorted_scopes = scope_list.sort
+ @objects = @objects.select { |auth| auth.scopes.sort == sorted_scopes }
end
end
diff --git a/services/api/test/functional/arvados/v1/api_client_authorizations_controller_test.rb b/services/api/test/functional/arvados/v1/api_client_authorizations_controller_test.rb
index 0072792..8877719 100644
--- a/services/api/test/functional/arvados/v1/api_client_authorizations_controller_test.rb
+++ b/services/api/test/functional/arvados/v1/api_client_authorizations_controller_test.rb
@@ -37,22 +37,33 @@ class Arvados::V1::ApiClientAuthorizationsControllerTest < ActionController::Tes
assert_response 403
end
- test "admin search filters where scopes exactly match" do
- def check_tokens_by_scopes(scopes, *expected_tokens)
- expected_tokens.map! { |name| api_client_authorizations(name).api_token }
- get :index, where: {scopes: scopes}
- assert_response :success
- got_tokens = JSON.parse(@response.body)['items']
- .map { |auth| auth['api_token'] }
- assert_equal(expected_tokens.sort, got_tokens.sort,
- "wrong results for scopes = #{scopes}")
+ def assert_found_tokens(auth, search_params, *expected_tokens)
+ authorize_with auth
+ expected_tokens.map! { |name| api_client_authorizations(name).api_token }
+ get :index, search_params
+ assert_response :success
+ got_tokens = JSON.parse(@response.body)['items']
+ .map { |auth| auth['api_token'] }
+ assert_equal(expected_tokens.sort, got_tokens.sort,
+ "wrong results for #{search_params.inspect}")
+ end
+
+ # Three-tuples with auth to use, scopes to find, and expected tokens.
+ # Make two tests for each tuple, one searching with where and the other
+ # with filter.
+ [[:admin_trustedclient, [], :admin_noscope],
+ [:active_trustedclient, ["GET /arvados/v1/users"], :active_userlist],
+ [:active_trustedclient,
+ ["POST /arvados/v1/api_client_authorizations",
+ "GET /arvados/v1/api_client_authorizations"],
+ :active_apitokens],
+ ].each do |auth, scopes, *expected|
+ test "#{auth.to_s} can find auths where scopes=#{scopes.inspect}" do
+ assert_found_tokens(auth, {where: {scopes: scopes}}, *expected)
+ end
+
+ test "#{auth.to_s} can find auths filtered with scopes=#{scopes.inspect}" do
+ assert_found_tokens(auth, {filters: [['scopes', '=', scopes]]}, *expected)
end
- authorize_with :admin_trustedclient
- check_tokens_by_scopes([], :admin_noscope)
- authorize_with :active_trustedclient
- check_tokens_by_scopes(["GET /arvados/v1/users"], :active_userlist)
- check_tokens_by_scopes(["POST /arvados/v1/api_client_authorizations",
- "GET /arvados/v1/api_client_authorizations"],
- :active_apitokens)
end
end
commit 52c4f2b7fe631f3d7ad16105cb2f86cf6c004fc8
Author: Brett Smith <brett at curoverse.com>
Date: Wed Apr 23 16:15:37 2014 -0400
api: Support scope searching in API token index.
diff --git a/services/api/app/controllers/arvados/v1/api_client_authorizations_controller.rb b/services/api/app/controllers/arvados/v1/api_client_authorizations_controller.rb
index 8fd915d..ff322a7 100644
--- a/services/api/app/controllers/arvados/v1/api_client_authorizations_controller.rb
+++ b/services/api/app/controllers/arvados/v1/api_client_authorizations_controller.rb
@@ -45,6 +45,11 @@ class Arvados::V1::ApiClientAuthorizationsController < ApplicationController
includes(:user, :api_client).
where('user_id=? and (? or api_token=?)', current_user.id, !@where['uuid'], @where['uuid']).
order('created_at desc')
+ unless @where['scopes'].nil?
+ @objects = @objects.select { |auth|
+ (auth.scopes & @where['scopes']) == (auth.scopes | @where['scopes'])
+ }
+ end
end
def find_object_by_uuid
diff --git a/services/api/test/functional/arvados/v1/api_client_authorizations_controller_test.rb b/services/api/test/functional/arvados/v1/api_client_authorizations_controller_test.rb
index cbb0096..0072792 100644
--- a/services/api/test/functional/arvados/v1/api_client_authorizations_controller_test.rb
+++ b/services/api/test/functional/arvados/v1/api_client_authorizations_controller_test.rb
@@ -1,7 +1,6 @@
require 'test_helper'
class Arvados::V1::ApiClientAuthorizationsControllerTest < ActionController::TestCase
-
test "should get index" do
authorize_with :active_trustedclient
get :index
@@ -38,4 +37,22 @@ class Arvados::V1::ApiClientAuthorizationsControllerTest < ActionController::Tes
assert_response 403
end
+ test "admin search filters where scopes exactly match" do
+ def check_tokens_by_scopes(scopes, *expected_tokens)
+ expected_tokens.map! { |name| api_client_authorizations(name).api_token }
+ get :index, where: {scopes: scopes}
+ assert_response :success
+ got_tokens = JSON.parse(@response.body)['items']
+ .map { |auth| auth['api_token'] }
+ assert_equal(expected_tokens.sort, got_tokens.sort,
+ "wrong results for scopes = #{scopes}")
+ end
+ authorize_with :admin_trustedclient
+ check_tokens_by_scopes([], :admin_noscope)
+ authorize_with :active_trustedclient
+ check_tokens_by_scopes(["GET /arvados/v1/users"], :active_userlist)
+ check_tokens_by_scopes(["POST /arvados/v1/api_client_authorizations",
+ "GET /arvados/v1/api_client_authorizations"],
+ :active_apitokens)
+ end
end
commit e54bdba73b65e31b03fd1d43bfe69d0f43bbd8d8
Author: Brett Smith <brett at curoverse.com>
Date: Mon Apr 28 14:01:53 2014 -0400
api: Migrate VM auth scopes to new system.
VirtualMachinesController was the only one doing anything special with
API token scopes before we provided the more general-purpose system.
This commit removes its specialized code, and provides a database
migration to convert those specialized scopes to the general-purpose
schema.
diff --git a/services/api/app/controllers/arvados/v1/virtual_machines_controller.rb b/services/api/app/controllers/arvados/v1/virtual_machines_controller.rb
index 10b4bd8..e176348 100644
--- a/services/api/app/controllers/arvados/v1/virtual_machines_controller.rb
+++ b/services/api/app/controllers/arvados/v1/virtual_machines_controller.rb
@@ -1,12 +1,8 @@
class Arvados::V1::VirtualMachinesController < ApplicationController
skip_before_filter :find_object_by_uuid, :only => :get_all_logins
skip_before_filter :render_404_if_no_object, :only => :get_all_logins
- skip_before_filter(:require_auth_scope_all,
- :only => [:logins, :get_all_logins])
before_filter(:admin_required,
:only => [:logins, :get_all_logins])
- before_filter(:require_auth_scope_for_get_all_logins,
- :only => [:logins, :get_all_logins])
def logins
get_all_logins
@@ -44,16 +40,4 @@ class Arvados::V1::VirtualMachinesController < ApplicationController
end
render json: { kind: "arvados#HashList", items: @response }
end
-
- protected
-
- def require_auth_scope_for_get_all_logins
- if @object
- # Client wants all logins for a single VM.
- require_auth_scope(['all', arvados_v1_virtual_machine_url(@object.uuid)])
- else
- # ...for a non-existent VM, or all VMs.
- require_auth_scope(['all'])
- end
- end
end
diff --git a/services/api/db/migrate/20140423133559_new_scope_format.rb b/services/api/db/migrate/20140423133559_new_scope_format.rb
new file mode 100644
index 0000000..5b69e95
--- /dev/null
+++ b/services/api/db/migrate/20140423133559_new_scope_format.rb
@@ -0,0 +1,48 @@
+# At the time we introduced scopes everywhere, VirtualMachinesController
+# recognized scopes that gave the URL for a VM to grant access to that VM's
+# login list. This migration converts those VM-specific scopes to the new
+# general format, and back.
+
+class NewScopeFormat < ActiveRecord::Migration
+ include CurrentApiClient
+
+ VM_PATH_REGEX =
+ %r{(/arvados/v1/virtual_machines/[0-9a-z]{5}-[0-9a-z]{5}-[0-9a-z]{15})}
+ OLD_SCOPE_REGEX = %r{^https?://[^/]+#{VM_PATH_REGEX.source}$}
+ NEW_SCOPE_REGEX = %r{^GET #{VM_PATH_REGEX.source}/logins$}
+
+ def fix_scopes_matching(regex)
+ act_as_system_user
+ ApiClientAuthorization.find_each do |auth|
+ auth.scopes = auth.scopes.map do |scope|
+ if match = regex.match(scope)
+ yield match
+ else
+ scope
+ end
+ end
+ auth.save!
+ end
+ end
+
+ def up
+ fix_scopes_matching(OLD_SCOPE_REGEX) do |match|
+ "GET #{match[1]}/logins"
+ end
+ end
+
+ def down
+ case Rails.env
+ when 'test'
+ hostname = 'www.example.com'
+ else
+ require 'socket'
+ hostname = Socket.gethostname
+ end
+ fix_scopes_matching(NEW_SCOPE_REGEX) do |match|
+ Rails.application.routes.url_for(controller: 'virtual_machines',
+ uuid: match[1].split('/').last,
+ host: hostname, protocol: 'https')
+ end
+ end
+end
diff --git a/services/api/db/schema.rb b/services/api/db/schema.rb
index 988cb87..034ee35 100644
--- a/services/api/db/schema.rb
+++ b/services/api/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20140422011506) do
+ActiveRecord::Schema.define(:version => 20140423133559) do
create_table "api_client_authorizations", :force => true do |t|
t.string "api_token", :null => false
diff --git a/services/api/test/fixtures/api_client_authorizations.yml b/services/api/test/fixtures/api_client_authorizations.yml
index 77e5048..f772c4f 100644
--- a/services/api/test/fixtures/api_client_authorizations.yml
+++ b/services/api/test/fixtures/api_client_authorizations.yml
@@ -42,7 +42,7 @@ admin_vm:
api_token: adminvirtualmachineabcdefghijklmnopqrstuvwxyz12345
expires_at: 2038-01-01 00:00:00
# scope refers to the testvm fixture.
- scopes: ["https://www.example.com/arvados/v1/virtual_machines/zzzzz-2x53u-382brsig8rp3064"]
+ scopes: ["GET /arvados/v1/virtual_machines/zzzzz-2x53u-382brsig8rp3064/logins"]
admin_noscope:
api_client: untrusted
commit 0eb59e3acf9f13e89bd010f7f65a4d31554183fc
Author: Brett Smith <brett at curoverse.com>
Date: Tue Apr 22 17:45:46 2014 -0400
api: Introduce path-based API token scopes.
Refs #1904, #2662 for background discussion.
diff --git a/services/api/app/controllers/application_controller.rb b/services/api/app/controllers/application_controller.rb
index 713f2cf..a86e35b 100644
--- a/services/api/app/controllers/application_controller.rb
+++ b/services/api/app/controllers/application_controller.rb
@@ -7,7 +7,7 @@ class ApplicationController < ActionController::Base
around_filter :thread_with_auth_info, :except => [:render_error, :render_not_found]
before_filter :remote_ip
- before_filter :require_auth_scope_all, :except => :render_not_found
+ before_filter :require_auth_scope, :except => :render_not_found
before_filter :catch_redirect_hint
before_filter :find_object_by_uuid, :except => [:index, :create,
@@ -405,12 +405,9 @@ class ApplicationController < ActionController::Base
end
end
- def require_auth_scope_all
- require_login and require_auth_scope(['all'])
- end
-
- def require_auth_scope(ok_scopes)
- unless current_api_client_auth_has_scope(ok_scopes)
+ def require_auth_scope
+ return false unless require_login
+ unless current_api_client_auth_has_scope("#{request.method} #{request.path}")
render :json => { errors: ['Forbidden'] }.to_json, status: 403
end
end
diff --git a/services/api/app/controllers/arvados/v1/keep_disks_controller.rb b/services/api/app/controllers/arvados/v1/keep_disks_controller.rb
index 3d91916..47018d4 100644
--- a/services/api/app/controllers/arvados/v1/keep_disks_controller.rb
+++ b/services/api/app/controllers/arvados/v1/keep_disks_controller.rb
@@ -1,5 +1,5 @@
class Arvados::V1::KeepDisksController < ApplicationController
- skip_before_filter :require_auth_scope_all, :only => :ping
+ skip_before_filter :require_auth_scope, :only => :ping
def self._ping_requires_parameters
{
diff --git a/services/api/app/controllers/arvados/v1/nodes_controller.rb b/services/api/app/controllers/arvados/v1/nodes_controller.rb
index eda8b07..d7a477d 100644
--- a/services/api/app/controllers/arvados/v1/nodes_controller.rb
+++ b/services/api/app/controllers/arvados/v1/nodes_controller.rb
@@ -1,5 +1,5 @@
class Arvados::V1::NodesController < ApplicationController
- skip_before_filter :require_auth_scope_all, :only => :ping
+ skip_before_filter :require_auth_scope, :only => :ping
skip_before_filter :find_object_by_uuid, :only => :ping
skip_before_filter :render_404_if_no_object, :only => :ping
diff --git a/services/api/app/controllers/arvados/v1/schema_controller.rb b/services/api/app/controllers/arvados/v1/schema_controller.rb
index 1cc8496..625519e 100644
--- a/services/api/app/controllers/arvados/v1/schema_controller.rb
+++ b/services/api/app/controllers/arvados/v1/schema_controller.rb
@@ -2,7 +2,7 @@ class Arvados::V1::SchemaController < ApplicationController
skip_before_filter :find_objects_for_index
skip_before_filter :find_object_by_uuid
skip_before_filter :render_404_if_no_object
- skip_before_filter :require_auth_scope_all
+ skip_before_filter :require_auth_scope
def index
expires_in 24.hours, public: true
@@ -69,7 +69,7 @@ class Arvados::V1::SchemaController < ApplicationController
schemas: {},
resources: {}
}
-
+
ActiveRecord::Base.descendants.reject(&:abstract_class?).each do |k|
begin
ctl_class = "Arvados::V1::#{k.to_s.pluralize}Controller".constantize
@@ -175,7 +175,7 @@ class Arvados::V1::SchemaController < ApplicationController
description:
%|List #{k.to_s.pluralize}.
- The <code>list</code> method returns a
+ The <code>list</code> method returns a
<a href="/api/resources.html">resource list</a> of
matching #{k.to_s.pluralize}. For example:
diff --git a/services/api/app/controllers/static_controller.rb b/services/api/app/controllers/static_controller.rb
index fda0880..c71b850 100644
--- a/services/api/app/controllers/static_controller.rb
+++ b/services/api/app/controllers/static_controller.rb
@@ -3,7 +3,7 @@ class StaticController < ApplicationController
skip_before_filter :find_object_by_uuid
skip_before_filter :render_404_if_no_object
- skip_before_filter :require_auth_scope_all, :only => [ :home, :login_failure ]
+ skip_before_filter :require_auth_scope, :only => [ :home, :login_failure ]
def home
if Rails.configuration.respond_to? :workbench_address
diff --git a/services/api/app/controllers/user_sessions_controller.rb b/services/api/app/controllers/user_sessions_controller.rb
index a7391bd..3d4b05a 100644
--- a/services/api/app/controllers/user_sessions_controller.rb
+++ b/services/api/app/controllers/user_sessions_controller.rb
@@ -1,5 +1,5 @@
class UserSessionsController < ApplicationController
- before_filter :require_auth_scope_all, :only => [ :destroy ]
+ before_filter :require_auth_scope, :only => [ :destroy ]
skip_before_filter :find_object_by_uuid
skip_before_filter :render_404_if_no_object
diff --git a/services/api/lib/current_api_client.rb b/services/api/lib/current_api_client.rb
index bbba4dc..0803d54 100644
--- a/services/api/lib/current_api_client.rb
+++ b/services/api/lib/current_api_client.rb
@@ -29,14 +29,17 @@ module CurrentApiClient
Thread.current[:api_client_ip_address]
end
- # Does the current API client authorization include any of ok_scopes?
- def current_api_client_auth_has_scope(ok_scopes)
- auth_scopes = current_api_client_authorization.andand.scopes || []
- unless auth_scopes.index('all') or (auth_scopes & ok_scopes).any?
- logger.warn "Insufficient auth scope: need #{ok_scopes}, #{current_api_client_authorization.inspect} has #{auth_scopes}"
- return false
- end
- true
+ # Is the current API client authorization scoped for the request?
+ def current_api_client_auth_has_scope(req_s)
+ (current_api_client_authorization.andand.scopes || []).select { |scope|
+ if scope == 'all'
+ true
+ elsif scope.end_with? '/'
+ req_s.start_with? scope
+ else
+ req_s == scope
+ end
+ }.any?
end
def system_user_uuid
diff --git a/services/api/test/fixtures/api_client_authorizations.yml b/services/api/test/fixtures/api_client_authorizations.yml
index 5a715e3..77e5048 100644
--- a/services/api/test/fixtures/api_client_authorizations.yml
+++ b/services/api/test/fixtures/api_client_authorizations.yml
@@ -51,6 +51,28 @@ admin_noscope:
expires_at: 2038-01-01 00:00:00
scopes: []
+active_userlist:
+ api_client: untrusted
+ user: active
+ api_token: activeuserlistabcdefghijklmnopqrstuvwxyz1234568900
+ expires_at: 2038-01-01 00:00:00
+ scopes: ["GET /arvados/v1/users"]
+
+active_specimens:
+ api_client: untrusted
+ user: active
+ api_token: activespecimensabcdefghijklmnopqrstuvwxyz123456890
+ expires_at: 2038-01-01 00:00:00
+ scopes: ["GET /arvados/v1/specimens/"]
+
+active_apitokens:
+ api_client: trusted_workbench
+ user: active
+ api_token: activeapitokensabcdefghijklmnopqrstuvwxyz123456789
+ expires_at: 2038-01-01 00:00:00
+ scopes: ["GET /arvados/v1/api_client_authorizations",
+ "POST /arvados/v1/api_client_authorizations"]
+
spectator:
api_client: untrusted
user: spectator
diff --git a/services/api/test/integration/api_client_authorizations_scopes_test.rb b/services/api/test/integration/api_client_authorizations_scopes_test.rb
index 7269d38..ba91670 100644
--- a/services/api/test/integration/api_client_authorizations_scopes_test.rb
+++ b/services/api/test/integration/api_client_authorizations_scopes_test.rb
@@ -20,7 +20,6 @@ class Arvados::V1::ApiTokensScopeTest < ActionController::IntegrationTest
end
def request_with_auth(method, path, params={})
- https!
send(method, path, @token.merge(params))
end
@@ -32,6 +31,51 @@ class Arvados::V1::ApiTokensScopeTest < ActionController::IntegrationTest
request_with_auth(:post_via_redirect, *args)
end
+ test "user list token can only list users" do
+ auth_with :active_userlist
+ get_with_auth v1_url('users')
+ assert_response :success
+ get_with_auth v1_url('users', '') # Add trailing slash.
+ assert_response :success
+ get_with_auth v1_url('users', 'current')
+ assert_response 403
+ get_with_auth v1_url('virtual_machines')
+ assert_response 403
+ end
+
+ test "specimens token can see exactly owned specimens" do
+ auth_with :active_specimens
+ get_with_auth v1_url('specimens')
+ assert_response 403
+ get_with_auth v1_url('specimens', specimens(:owned_by_active_user).uuid)
+ assert_response :success
+ get_with_auth v1_url('specimens', specimens(:owned_by_spectator).uuid)
+ assert_includes(403..404, @response.status)
+ end
+
+ test "token with multiple scopes can use them all" do
+ def get_token_count
+ get_with_auth v1_url('api_client_authorizations')
+ assert_response :success
+ token_count = JSON.parse(@response.body)['items_available']
+ assert_not_nil(token_count, "could not find token count")
+ token_count
+ end
+ auth_with :active_apitokens
+ # Test the GET scope.
+ token_count = get_token_count
+ # Test the POST scope.
+ post_with_auth(v1_url('api_client_authorizations'),
+ api_client_authorization: {user_id: users(:active).id})
+ assert_response :success
+ assert_equal(token_count + 1, get_token_count,
+ "token count suggests POST was not accepted")
+ # Test other requests are denied.
+ get_with_auth v1_url('api_client_authorizations',
+ api_client_authorizations(:active_apitokens).uuid)
+ assert_response 403
+ end
+
test "token without scope has no access" do
# Logs are good for this test, because logs have relatively
# few access controls enforced at the model level.
commit 915de6c854cd559ebd029b24939149e37b18c8cf
Author: Brett Smith <brett at curoverse.com>
Date: Tue Apr 22 14:44:34 2014 -0400
api: Test VM login scopes.
The virtual machine controller is the only one doing anything
interesting with API token scopes right now. I'm writing this test
for that functionality to make sure it stays effective through
refactoring.
diff --git a/services/api/test/fixtures/api_client_authorizations.yml b/services/api/test/fixtures/api_client_authorizations.yml
index 5cada90..5a715e3 100644
--- a/services/api/test/fixtures/api_client_authorizations.yml
+++ b/services/api/test/fixtures/api_client_authorizations.yml
@@ -36,6 +36,21 @@ active_trustedclient:
api_token: 27bnddk6x2nmq00a1e3gq43n9tsl5v87a3faqar2ijj8tud5en
expires_at: 2038-01-01 00:00:00
+admin_vm:
+ api_client: untrusted
+ user: admin
+ api_token: adminvirtualmachineabcdefghijklmnopqrstuvwxyz12345
+ expires_at: 2038-01-01 00:00:00
+ # scope refers to the testvm fixture.
+ scopes: ["https://www.example.com/arvados/v1/virtual_machines/zzzzz-2x53u-382brsig8rp3064"]
+
+admin_noscope:
+ api_client: untrusted
+ user: admin
+ api_token: adminnoscopeabcdefghijklmnopqrstuvwxyz123456789012
+ expires_at: 2038-01-01 00:00:00
+ scopes: []
+
spectator:
api_client: untrusted
user: spectator
diff --git a/services/api/test/integration/api_client_authorizations_scopes_test.rb b/services/api/test/integration/api_client_authorizations_scopes_test.rb
new file mode 100644
index 0000000..7269d38
--- /dev/null
+++ b/services/api/test/integration/api_client_authorizations_scopes_test.rb
@@ -0,0 +1,59 @@
+# The v1 API uses token scopes to control access to the REST API at the path
+# level. This is enforced in the base ApplicationController, making it a
+# functional test that we can run against many different controllers.
+
+require 'test_helper'
+
+class Arvados::V1::ApiTokensScopeTest < ActionController::IntegrationTest
+ fixtures :all
+
+ def setup
+ @token = {}
+ end
+
+ def auth_with(name)
+ @token = {api_token: api_client_authorizations(name).api_token}
+ end
+
+ def v1_url(*parts)
+ (['arvados', 'v1'] + parts).join('/')
+ end
+
+ def request_with_auth(method, path, params={})
+ https!
+ send(method, path, @token.merge(params))
+ end
+
+ def get_with_auth(*args)
+ request_with_auth(:get_via_redirect, *args)
+ end
+
+ def post_with_auth(*args)
+ request_with_auth(:post_via_redirect, *args)
+ end
+
+ test "token without scope has no access" do
+ # Logs are good for this test, because logs have relatively
+ # few access controls enforced at the model level.
+ auth_with :admin_noscope
+ get_with_auth v1_url('logs')
+ assert_response 403
+ get_with_auth v1_url('logs', logs(:log1).uuid)
+ assert_response 403
+ post_with_auth(v1_url('logs'), log: {})
+ assert_response 403
+ end
+
+ test "VM login scopes work" do
+ # A system administration script makes an API token with limited scope
+ # for virtual machines to let it see logins.
+ def vm_logins_url(name)
+ v1_url('virtual_machines', virtual_machines(name).uuid, 'logins')
+ end
+ auth_with :admin_vm
+ get_with_auth vm_logins_url(:testvm)
+ assert_response :success
+ get_with_auth vm_logins_url(:testvm2)
+ assert(@response.status >= 400, "getting testvm2 logins should have failed")
+ end
+end
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list