[ARVADOS] created: 1.2.0-171-g3453440f9
Git user
git at public.curoverse.com
Thu Oct 11 18:33:42 EDT 2018
at 3453440f95dc76db1bd39fe8c85d9a898d474c6b (commit)
commit 3453440f95dc76db1bd39fe8c85d9a898d474c6b
Author: Peter Amstutz <pamstutz at veritasgenetics.com>
Date: Thu Oct 11 18:27:51 2018 -0400
14260: Added runtime_token to container record
* runtime_token, runtime_user_uuid and runtime_auth_scopes are now
part of container initialization and reuse decisions
* Determine runtime_user_uuid and runtime_auth_scopes as part of
Container.resolve
* Use runtime_user_uuid to create container token (when runtime_token
is not set)
* act_as runtime_user_uuid when resolving container request fields
* tokens used for runtime_token will be left untouched (remove expire_destroy)
* added/updated/fixed tests
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <pamstutz at veritasgenetics.com>
diff --git a/services/api/app/models/api_client_authorization.rb b/services/api/app/models/api_client_authorization.rb
index 0a2793ade..12ef8eb3e 100644
--- a/services/api/app/models/api_client_authorization.rb
+++ b/services/api/app/models/api_client_authorization.rb
@@ -92,27 +92,6 @@ class ApiClientAuthorization < ArvadosModel
uuid_prefix+".arvadosapi.com")
end
- # Delete token, if remote, attempt to delete on the host as well.
- def expire_destroy
- uuid_prefix = self.uuid[0..4]
- if uuid_prefix != Rails.configuration.uuid_prefix
- # remote token
- host = remote_host(uuid_prefix: uuid_prefix)
- begin
- clnt = HTTPClient.new
- if Rails.configuration.sso_insecure
- clnt.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
- end
- result = SafeJSON.load(
- clnt.delete('https://' + host + '/arvados/v1/users/current',
- {'Authorization' => 'Bearer ' + token}))
- rescue => e
- Rails.logger.warn "deleting remote token #{self.uuid} failed: #{e}"
- end
- end
- destroy
- end
-
def self.validate(token:, remote: nil)
return nil if !token
remote ||= Rails.configuration.uuid_prefix
diff --git a/services/api/app/models/container.rb b/services/api/app/models/container.rb
index ba5c1c28c..86201955a 100644
--- a/services/api/app/models/container.rb
+++ b/services/api/app/models/container.rb
@@ -37,7 +37,7 @@ class Container < ArvadosModel
after_validation :assign_auth
before_save :sort_serialized_attrs
before_save :update_secret_mounts_md5
- before_save :scrub_secret_mounts
+ before_save :scrub_secrets
before_save :clear_runtime_status_when_queued
after_save :update_cr_logs
after_save :handle_completed
@@ -91,15 +91,15 @@ class Container < ArvadosModel
end
def self.full_text_searchable_columns
- super - ["secret_mounts", "secret_mounts_md5"]
+ super - ["secret_mounts", "secret_mounts_md5", "runtime_token"]
end
def self.searchable_columns *args
- super - ["secret_mounts_md5"]
+ super - ["secret_mounts_md5", "runtime_token"]
end
def logged_attributes
- super.except('secret_mounts')
+ super.except('secret_mounts', 'runtime_token')
end
def state_transitions
@@ -146,17 +146,37 @@ class Container < ArvadosModel
# Create a new container (or find an existing one) to satisfy the
# given container request.
def self.resolve(req)
- c_attrs = {
- command: req.command,
- cwd: req.cwd,
- environment: req.environment,
- output_path: req.output_path,
- container_image: resolve_container_image(req.container_image),
- mounts: resolve_mounts(req.mounts),
- runtime_constraints: resolve_runtime_constraints(req.runtime_constraints),
- scheduling_parameters: req.scheduling_parameters,
- secret_mounts: req.secret_mounts,
- }
+ if req.runtime_token.nil?
+ runtime_user = if req.modified_by_user_uuid.nil?
+ current_user
+ else
+ User.find_by_uuid(req.modified_by_user_uuid)
+ end
+ runtime_auth_scopes = ["all"]
+ else
+ auth = ApiClientAuthorization.validate(token: req.runtime_token)
+ if auth.nil?
+ raise ArgumentError.new "Invalid runtime token"
+ end
+ runtime_user = User.find_by_id(auth.user_id)
+ runtime_auth_scopes = auth.scopes
+ end
+ c_attrs = act_as_user runtime_user do
+ {
+ command: req.command,
+ cwd: req.cwd,
+ environment: req.environment,
+ output_path: req.output_path,
+ container_image: resolve_container_image(req.container_image),
+ mounts: resolve_mounts(req.mounts),
+ runtime_constraints: resolve_runtime_constraints(req.runtime_constraints),
+ scheduling_parameters: req.scheduling_parameters,
+ secret_mounts: req.secret_mounts,
+ runtime_token: req.runtime_token,
+ runtime_user_uuid: runtime_user.uuid,
+ runtime_auth_scopes: runtime_auth_scopes
+ }
+ end
act_as_system_user do
if req.use_existing && (reusable = find_reusable(c_attrs))
reusable
@@ -259,6 +279,14 @@ class Container < ArvadosModel
candidates = candidates.where_serialized(:runtime_constraints, resolve_runtime_constraints(attrs[:runtime_constraints]), md5: true)
log_reuse_info(candidates) { "after filtering on runtime_constraints #{attrs[:runtime_constraints].inspect}" }
+ candidates = candidates.where('runtime_user_uuid = ? or (runtime_user_uuid is NULL and runtime_auth_scopes is NULL)',
+ attrs[:runtime_user_uuid])
+ log_reuse_info(candidates) { "after filtering on runtime_user_uuid #{attrs[:runtime_user_uuid].inspect}" }
+
+ candidates = candidates.where('runtime_auth_scopes = ? or (runtime_user_uuid is NULL and runtime_auth_scopes is NULL)',
+ SafeJSON.dump(attrs[:runtime_auth_scopes]))
+ log_reuse_info(candidates) { "after filtering on runtime_auth_scopes #{attrs[:runtime_auth_scopes].inspect}" }
+
log_reuse_info { "checking for state=Complete with readable output and log..." }
select_readable_pdh = Collection.
@@ -415,7 +443,8 @@ class Container < ArvadosModel
permitted.push(:owner_uuid, :command, :container_image, :cwd,
:environment, :mounts, :output_path, :priority,
:runtime_constraints, :scheduling_parameters,
- :secret_mounts)
+ :secret_mounts, :runtime_token,
+ :runtime_user_uuid, :runtime_auth_scopes)
end
case self.state
@@ -522,28 +551,30 @@ class Container < ArvadosModel
# already have one
return
end
- cr = ContainerRequest.
- where('container_uuid=? and priority>0', self.uuid).
- order('priority desc').
- first
- if !cr
- return errors.add :auth_uuid, "cannot be assigned because priority <= 0"
- end
- if cr.runtime_token.nil?
+ if self.runtime_token.nil?
+ if self.runtime_user_uuid.nil?
+ cr = ContainerRequest.
+ where('container_uuid=? and priority>0', self.uuid).
+ order('priority desc').
+ first
+ if !cr
+ return errors.add :auth_uuid, "cannot be assigned because priority <= 0"
+ end
+ self.runtime_user_uuid = cr.modified_by_user_uuid
+ self.runtime_auth_scopes = ["all"]
+ end
+
# generate a new token
self.auth = ApiClientAuthorization.
- create!(user_id: User.find_by_uuid(cr.modified_by_user_uuid).id,
- api_client_id: 0)
- self.runtime_user_uuid = cr.modified_by_user_uuid
- self.runtime_auth_scopes = self.auth.scopes
+ create!(user_id: User.find_by_uuid(self.runtime_user_uuid).id,
+ api_client_id: 0,
+ scopes: self.runtime_auth_scopes)
else
- # using cr.runtime_token
- self.auth = ApiClientAuthorization.validate(token: cr.runtime_token)
+ # using runtime_token
+ self.auth = ApiClientAuthorization.validate(token: self.runtime_token)
if self.auth.nil?
raise ArgumentError.new "Invalid runtime token"
end
- self.runtime_user_uuid = User.find_by_id(self.auth.user_id).uuid
- self.runtime_auth_scopes = self.auth.scopes
end
end
@@ -569,12 +600,13 @@ class Container < ArvadosModel
end
end
- def scrub_secret_mounts
+ def scrub_secrets
# this runs after update_secret_mounts_md5, so the
# secret_mounts_md5 will still reflect the secrets that are being
# scrubbed here.
if self.state_changed? && self.final?
self.secret_mounts = {}
+ self.runtime_token = nil
end
end
diff --git a/services/api/app/models/container_request.rb b/services/api/app/models/container_request.rb
index b75775c87..cd6851709 100644
--- a/services/api/app/models/container_request.rb
+++ b/services/api/app/models/container_request.rb
@@ -106,7 +106,7 @@ class ContainerRequest < ArvadosModel
end
def skip_uuid_read_permission_check
- # XXX temporary until permissions are sorted out.
+ # XXX temporary until permissions are sorted out.
%w(modified_by_client_uuid container_uuid requesting_container_uuid)
end
@@ -359,14 +359,7 @@ class ContainerRequest < ArvadosModel
def scrub_secrets
if self.state == Final
self.secret_mounts = {}
- if !self.runtime_token.nil?
- _, uuid, secret = self.runtime_token.split('/')
- tok = ApiClientAuthorization.find_by_uuid(uuid)
- if !tok.nil?
- tok.expire_destroy
- end
- self.runtime_token = nil
- end
+ self.runtime_token = nil
end
end
diff --git a/services/api/db/migrate/20181011184200_add_runtime_token_to_container.rb b/services/api/db/migrate/20181011184200_add_runtime_token_to_container.rb
new file mode 100644
index 000000000..09201f514
--- /dev/null
+++ b/services/api/db/migrate/20181011184200_add_runtime_token_to_container.rb
@@ -0,0 +1,5 @@
+class AddRuntimeTokenToContainer < ActiveRecord::Migration
+ def change
+ add_column :containers, :runtime_token, :text, :null => true
+ end
+end
diff --git a/services/api/db/structure.sql b/services/api/db/structure.sql
index d1eb8d8d0..636306f97 100644
--- a/services/api/db/structure.sql
+++ b/services/api/db/structure.sql
@@ -358,7 +358,8 @@ CREATE TABLE public.containers (
secret_mounts_md5 character varying DEFAULT '99914b932bd37a50b983c5e7c90ae93b'::character varying,
runtime_status jsonb DEFAULT '{}'::jsonb,
runtime_user_uuid text,
- runtime_auth_scopes jsonb
+ runtime_auth_scopes jsonb,
+ runtime_token text
);
@@ -3176,3 +3177,5 @@ INSERT INTO schema_migrations (version) VALUES ('20180917205609');
INSERT INTO schema_migrations (version) VALUES ('20181005192222');
+INSERT INTO schema_migrations (version) VALUES ('20181011184200');
+
diff --git a/services/api/lib/sweep_trashed_objects.rb b/services/api/lib/sweep_trashed_objects.rb
index 59008c0fc..162bebf51 100644
--- a/services/api/lib/sweep_trashed_objects.rb
+++ b/services/api/lib/sweep_trashed_objects.rb
@@ -48,6 +48,11 @@ module SweepTrashedObjects
where({group_class: 'project'}).
where('is_trashed = false and trash_at < statement_timestamp()').
update_all('is_trashed = true')
+
+ # Sweep expired tokens
+ ApiClientAuthorization.
+ where("expires_at <= statement_timestamp()").
+ destroy_all
end
end
diff --git a/services/api/test/fixtures/api_client_authorizations.yml b/services/api/test/fixtures/api_client_authorizations.yml
index 9074c5ffc..d8ef63120 100644
--- a/services/api/test/fixtures/api_client_authorizations.yml
+++ b/services/api/test/fixtures/api_client_authorizations.yml
@@ -345,6 +345,21 @@ foo_collection_sharing_token:
container_runtime_token:
uuid: zzzzz-gj3su-2nj68s291f50gd9
api_client: untrusted
- user: spectator
+ user: container_runtime_token_user
api_token: 2d19ue6ofx26o3mm7fs9u6t7hov9um0v92dzwk1o2xed3abprw
expires_at: 2038-01-01 00:00:00
+
+crt_user:
+ uuid: zzzzz-gj3su-3r47qqy5ja5d54v
+ api_client: untrusted
+ user: container_runtime_token_user
+ api_token: 13z1tz9deoryml3twep0vsahi4862097pe5lsmesugnkgpgpwk
+ expires_at: 2038-01-01 00:00:00
+
+runtime_token_limited_scope:
+ uuid: zzzzz-gj3su-2fljvypjrr4yr9m
+ api_client: untrusted
+ user: container_runtime_token_user
+ api_token: 1fwc3be1m13qkypix2gd01i4bq5ju483zjfc0cf4babjseirbm
+ expires_at: 2038-01-01 00:00:00
+ scopes: ["GET /"]
diff --git a/services/api/test/fixtures/containers.yml b/services/api/test/fixtures/containers.yml
index ce61c01ee..eefb0297c 100644
--- a/services/api/test/fixtures/containers.yml
+++ b/services/api/test/fixtures/containers.yml
@@ -271,6 +271,9 @@ runtime_token:
cwd: test
output_path: test
command: ["echo", "hello"]
+ runtime_token: v2/zzzzz-gj3su-2nj68s291f50gd9/2d19ue6ofx26o3mm7fs9u6t7hov9um0v92dzwk1o2xed3abprw
+ runtime_user_uuid: zzzzz-tpzed-l3skomkti0c4vg4
+ runtime_auth_scopes: ["all"]
runtime_constraints:
ram: 12000000000
vcpus: 4
diff --git a/services/api/test/fixtures/links.yml b/services/api/test/fixtures/links.yml
index 8a33f696a..2b247a960 100644
--- a/services/api/test/fixtures/links.yml
+++ b/services/api/test/fixtures/links.yml
@@ -597,6 +597,20 @@ active_user_permission_to_unlinked_docker_image_collection:
head_uuid: zzzzz-4zz18-d0d8z5wofvfgwad
properties: {}
+crt_user_permission_to_unlinked_docker_image_collection:
+ uuid: zzzzz-o0j2j-20zvdi9b4odcfz3
+ owner_uuid: zzzzz-tpzed-000000000000000
+ created_at: 2014-01-24 20:42:26 -0800
+ modified_by_client_uuid: zzzzz-ozdt8-brczlopd8u8d0jr
+ modified_by_user_uuid: zzzzz-tpzed-000000000000000
+ modified_at: 2014-01-24 20:42:26 -0800
+ updated_at: 2014-01-24 20:42:26 -0800
+ tail_uuid: zzzzz-tpzed-l3skomkti0c4vg4
+ link_class: permission
+ name: can_read
+ head_uuid: zzzzz-4zz18-d0d8z5wofvfgwad
+ properties: {}
+
docker_image_collection_hash:
uuid: zzzzz-o0j2j-dockercollhasha
owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
diff --git a/services/api/test/fixtures/users.yml b/services/api/test/fixtures/users.yml
index 8d2586921..7d6b1fc3a 100644
--- a/services/api/test/fixtures/users.yml
+++ b/services/api/test/fixtures/users.yml
@@ -165,6 +165,22 @@ spectator:
role: Computational biologist
getting_started_shown: 2015-03-26 12:34:56.789000000 Z
+container_runtime_token_user:
+ owner_uuid: zzzzz-tpzed-000000000000000
+ uuid: zzzzz-tpzed-l3skomkti0c4vg4
+ email: spectator at arvados.local
+ first_name: Spect
+ last_name: Ator
+ identity_url: https://spectator.openid.local
+ is_active: true
+ is_admin: false
+ username: containerruntimetokenuser
+ prefs:
+ profile:
+ organization: example.com
+ role: Computational biologist
+ getting_started_shown: 2015-03-26 12:34:56.789000000 Z
+
inactive_uninvited:
owner_uuid: zzzzz-tpzed-000000000000000
uuid: zzzzz-tpzed-rf2ec3ryh4vb5ma
diff --git a/services/api/test/unit/container_request_test.rb b/services/api/test/unit/container_request_test.rb
index 00c341f74..14fa5796d 100644
--- a/services/api/test/unit/container_request_test.rb
+++ b/services/api/test/unit/container_request_test.rb
@@ -1076,8 +1076,8 @@ class ContainerRequestTest < ActiveSupport::TestCase
end
test "using runtime_token" do
- set_user_from_auth :active
- spec = api_client_authorizations(:spectator)
+ set_user_from_auth :spectator
+ spec = api_client_authorizations(:active)
cr = create_minimal_req!(state: "Committed", runtime_token: spec.token, priority: 1)
cr.save!
c = Container.find_by_uuid cr.container_uuid
@@ -1096,13 +1096,13 @@ class ContainerRequestTest < ActiveSupport::TestCase
cr.reload
c.reload
assert_nil cr.runtime_token
- assert_nil ApiClientAuthorization.find_by_uuid(spec.uuid)
+ assert_nil c.runtime_token
end
test "invalid runtime_token" do
set_user_from_auth :active
spec = api_client_authorizations(:spectator)
- assert_raises(ActiveRecord::RecordInvalid) do
+ assert_raises(ArgumentError) do
cr = create_minimal_req!(state: "Committed", runtime_token: "#{spec.token}xx")
cr.save!
end
diff --git a/services/api/test/unit/container_test.rb b/services/api/test/unit/container_test.rb
index 11ae0bfe3..39fde79a3 100644
--- a/services/api/test/unit/container_test.rb
+++ b/services/api/test/unit/container_test.rb
@@ -33,14 +33,18 @@ class ContainerTest < ActiveSupport::TestCase
"var" => "val",
},
secret_mounts: {},
+ runtime_user_uuid: "zzzzz-tpzed-xurymjxw79nv3jz",
+ runtime_auth_scopes: ["all"]
}
+ def request_only attrs
+ attrs.reject {|k| [:runtime_user_uuid, :runtime_auth_scopes].include? k}
+ end
+
def minimal_new attrs={}
- cr = ContainerRequest.new DEFAULT_ATTRS.merge(attrs)
+ cr = ContainerRequest.new request_only(DEFAULT_ATTRS.merge(attrs))
cr.state = ContainerRequest::Committed
- act_as_user users(:active) do
- cr.save!
- end
+ cr.save!
c = Container.find_by_uuid cr.container_uuid
assert_not_nil c
return c, cr
@@ -220,6 +224,7 @@ class ContainerTest < ActiveSupport::TestCase
end
test "Container serialized hash attributes sorted before save" do
+ set_user_from_auth :active
env = {"C" => "3", "B" => "2", "A" => "1"}
m = {"F" => {"kind" => "3"}, "E" => {"kind" => "2"}, "D" => {"kind" => "1"}}
rc = {"vcpus" => 1, "ram" => 1, "keep_cache_ram" => 1}
@@ -236,6 +241,7 @@ class ContainerTest < ActiveSupport::TestCase
end
test "find_reusable method should select higher priority queued container" do
+ Rails.configuration.log_reuse_decisions = true
set_user_from_auth :active
common_attrs = REUSABLE_COMMON_ATTRS.merge({environment:{"var" => "queued"}})
c_low_priority, _ = minimal_new(common_attrs.merge({use_existing:false, priority:1}))
@@ -285,13 +291,13 @@ class ContainerTest < ActiveSupport::TestCase
log: 'ea10d51bcf88862dbcc36eb292017dfd+45',
}
- cr = ContainerRequest.new common_attrs
+ cr = ContainerRequest.new request_only(common_attrs)
cr.use_existing = false
cr.state = ContainerRequest::Committed
cr.save!
c_output1 = Container.where(uuid: cr.container_uuid).first
- cr = ContainerRequest.new common_attrs
+ cr = ContainerRequest.new request_only(common_attrs)
cr.use_existing = false
cr.state = ContainerRequest::Committed
cr.save!
@@ -312,7 +318,8 @@ class ContainerTest < ActiveSupport::TestCase
c_output2.update_attributes!({state: Container::Running})
c_output2.update_attributes!(completed_attrs.merge({log: log1, output: out2}))
- reused = Container.resolve(ContainerRequest.new(common_attrs))
+ set_user_from_auth :active
+ reused = Container.resolve(ContainerRequest.new(request_only(common_attrs)))
assert_equal c_output1.uuid, reused.uuid
end
@@ -507,7 +514,73 @@ class ContainerTest < ActiveSupport::TestCase
Container.find_reusable(REUSABLE_COMMON_ATTRS)
end
+ def runtime_token_attr tok
+ auth = api_client_authorizations(tok)
+ {runtime_user_uuid: User.find_by_id(auth.user_id).uuid,
+ runtime_auth_scopes: auth.scopes,
+ runtime_token: auth.token}
+ end
+
+ test "find_reusable method with same runtime_token" do
+ set_user_from_auth :active
+ common_attrs = REUSABLE_COMMON_ATTRS.merge({use_existing:false, priority:1, environment:{"var" => "queued"}})
+ c1, _ = minimal_new(common_attrs.merge({runtime_token: api_client_authorizations(:container_runtime_token).token}))
+ assert_equal Container::Queued, c1.state
+ reused = Container.find_reusable(common_attrs.merge(runtime_token_attr(:container_runtime_token)))
+ assert_not_nil reused
+ assert_equal reused.uuid, c1.uuid
+ end
+
+ test "find_reusable method with different runtime_token, same user" do
+ set_user_from_auth :active
+ common_attrs = REUSABLE_COMMON_ATTRS.merge({use_existing:false, priority:1, environment:{"var" => "queued"}})
+ c1, _ = minimal_new(common_attrs.merge({runtime_token: api_client_authorizations(:crt_user).token}))
+ assert_equal Container::Queued, c1.state
+ reused = Container.find_reusable(common_attrs.merge(runtime_token_attr(:container_runtime_token)))
+ assert_not_nil reused
+ assert_equal reused.uuid, c1.uuid
+ end
+
+ test "find_reusable method with nil runtime_token, then runtime_token with same user" do
+ set_user_from_auth :crt_user
+ common_attrs = REUSABLE_COMMON_ATTRS.merge({use_existing:false, priority:1, environment:{"var" => "queued"}})
+ c1, _ = minimal_new(common_attrs)
+ assert_equal Container::Queued, c1.state
+ assert_equal users(:container_runtime_token_user).uuid, c1.runtime_user_uuid
+ reused = Container.find_reusable(common_attrs.merge(runtime_token_attr(:container_runtime_token)))
+ assert_not_nil reused
+ assert_equal reused.uuid, c1.uuid
+ end
+
+ test "find_reusable method with different runtime_token, different user" do
+ set_user_from_auth :crt_user
+ common_attrs = REUSABLE_COMMON_ATTRS.merge({use_existing:false, priority:1, environment:{"var" => "queued"}})
+ c1, _ = minimal_new(common_attrs.merge({runtime_token: api_client_authorizations(:active).token}))
+ assert_equal Container::Queued, c1.state
+ reused = Container.find_reusable(common_attrs.merge(runtime_token_attr(:container_runtime_token)))
+ assert_nil reused
+ end
+
+ test "find_reusable method with nil runtime_token, then runtime_token with different user" do
+ set_user_from_auth :active
+ common_attrs = REUSABLE_COMMON_ATTRS.merge({use_existing:false, priority:1, environment:{"var" => "queued"}})
+ c1, _ = minimal_new(common_attrs.merge({runtime_token: nil}))
+ assert_equal Container::Queued, c1.state
+ reused = Container.find_reusable(common_attrs.merge(runtime_token_attr(:container_runtime_token)))
+ assert_nil reused
+ end
+
+ test "find_reusable method with different runtime_token, different scope, same user" do
+ set_user_from_auth :active
+ common_attrs = REUSABLE_COMMON_ATTRS.merge({use_existing:false, priority:1, environment:{"var" => "queued"}})
+ c1, _ = minimal_new(common_attrs.merge({runtime_token: api_client_authorizations(:runtime_token_limited_scope).token}))
+ assert_equal Container::Queued, c1.state
+ reused = Container.find_reusable(common_attrs.merge(runtime_token_attr(:container_runtime_token)))
+ assert_nil reused
+ end
+
test "Container running" do
+ set_user_from_auth :active
c, _ = minimal_new priority: 1
set_user_from_auth :dispatch1
@@ -527,6 +600,7 @@ class ContainerTest < ActiveSupport::TestCase
end
test "Lock and unlock" do
+ set_user_from_auth :active
c, cr = minimal_new priority: 0
set_user_from_auth :dispatch1
@@ -587,6 +661,7 @@ class ContainerTest < ActiveSupport::TestCase
end
test "Container queued cancel" do
+ set_user_from_auth :active
c, cr = minimal_new({container_count_max: 1})
set_user_from_auth :dispatch1
assert c.update_attributes(state: Container::Cancelled), show_errors(c)
@@ -596,10 +671,11 @@ class ContainerTest < ActiveSupport::TestCase
end
test "Container queued count" do
- assert_equal 1, Container.readable_by(users(:active)).where(state: "Queued").count
+ assert_equal 2, Container.readable_by(users(:active)).where(state: "Queued").count
end
test "Container locked cancel" do
+ set_user_from_auth :active
c, _ = minimal_new
set_user_from_auth :dispatch1
assert c.lock, show_errors(c)
@@ -608,6 +684,7 @@ class ContainerTest < ActiveSupport::TestCase
end
test "Container locked cancel with log" do
+ set_user_from_auth :active
c, _ = minimal_new
set_user_from_auth :dispatch1
assert c.lock, show_errors(c)
@@ -619,6 +696,7 @@ class ContainerTest < ActiveSupport::TestCase
end
test "Container running cancel" do
+ set_user_from_auth :active
c, _ = minimal_new
set_user_from_auth :dispatch1
c.lock
@@ -641,6 +719,7 @@ class ContainerTest < ActiveSupport::TestCase
end
test "Container only set exit code on complete" do
+ set_user_from_auth :active
c, _ = minimal_new
set_user_from_auth :dispatch1
c.lock
@@ -653,6 +732,7 @@ class ContainerTest < ActiveSupport::TestCase
end
test "locked_by_uuid can update log when locked/running, and output when running" do
+ set_user_from_auth :active
logcoll = collections(:real_log_collection)
c, cr1 = minimal_new
cr2 = ContainerRequest.new(DEFAULT_ATTRS)
@@ -698,6 +778,7 @@ class ContainerTest < ActiveSupport::TestCase
end
test "auth_uuid can set output, progress, runtime_status, state on running container -- but not log" do
+ set_user_from_auth :active
c, _ = minimal_new
set_user_from_auth :dispatch1
c.lock
@@ -718,6 +799,7 @@ class ContainerTest < ActiveSupport::TestCase
end
test "not allowed to set output that is not readable by current user" do
+ set_user_from_auth :active
c, _ = minimal_new
set_user_from_auth :dispatch1
c.lock
@@ -732,6 +814,7 @@ class ContainerTest < ActiveSupport::TestCase
end
test "other token cannot set output on running container" do
+ set_user_from_auth :active
c, _ = minimal_new
set_user_from_auth :dispatch1
c.lock
@@ -742,6 +825,7 @@ class ContainerTest < ActiveSupport::TestCase
end
test "can set trashed output on running container" do
+ set_user_from_auth :active
c, _ = minimal_new
set_user_from_auth :dispatch1
c.lock
@@ -755,6 +839,7 @@ class ContainerTest < ActiveSupport::TestCase
end
test "not allowed to set trashed output that is not readable by current user" do
+ set_user_from_auth :active
c, _ = minimal_new
set_user_from_auth :dispatch1
c.lock
@@ -774,20 +859,24 @@ class ContainerTest < ActiveSupport::TestCase
{state: Container::Complete, exit_code: 0, output: '1f4b0bc7583c2a7f9102c395f4ffc5e3+45'},
{state: Container::Cancelled},
].each do |final_attrs|
- test "secret_mounts is null after container is #{final_attrs[:state]}" do
+ test "secret_mounts and runtime_token are null after container is #{final_attrs[:state]}" do
+ set_user_from_auth :active
c, cr = minimal_new(secret_mounts: {'/secret' => {'kind' => 'text', 'content' => 'foo'}},
- container_count_max: 1)
+ container_count_max: 1, runtime_token: api_client_authorizations(:active).token)
set_user_from_auth :dispatch1
c.lock
c.update_attributes!(state: Container::Running)
c.reload
assert c.secret_mounts.has_key?('/secret')
+ assert_equal api_client_authorizations(:active).token, c.runtime_token
c.update_attributes!(final_attrs)
c.reload
assert_equal({}, c.secret_mounts)
+ assert_nil c.runtime_token
cr.reload
assert_equal({}, cr.secret_mounts)
+ assert_nil cr.runtime_token
assert_no_secrets_logged
end
end
commit 72513393310d7f22688afa93f51b05e1d42bae08
Author: Peter Amstutz <pamstutz at veritasgenetics.com>
Date: Thu Oct 11 10:08:08 2018 -0400
14260: runtime_token goes in container auth
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <pamstutz at veritasgenetics.com>
diff --git a/services/api/app/controllers/arvados/v1/containers_controller.rb b/services/api/app/controllers/arvados/v1/containers_controller.rb
index 393e00492..65d8385ad 100644
--- a/services/api/app/controllers/arvados/v1/containers_controller.rb
+++ b/services/api/app/controllers/arvados/v1/containers_controller.rb
@@ -17,15 +17,7 @@ class Arvados::V1::ContainersController < ApplicationController
if @object.locked_by_uuid != Thread.current[:api_client_authorization].uuid
raise ArvadosModel::PermissionDeniedError.new("Not locked by your token")
end
- if @object.auth.nil?
- cr = ContainerRequest.
- where('container_uuid=? and priority>0', @object.uuid).
- order('priority desc').
- first
- @object = ApiClientAuthorization.validate(token: cr.runtime_token)
- else
- @object = @object.auth
- end
+ @object = @object.auth
show
end
diff --git a/services/api/app/models/api_client_authorization.rb b/services/api/app/models/api_client_authorization.rb
index 12ef8eb3e..0a2793ade 100644
--- a/services/api/app/models/api_client_authorization.rb
+++ b/services/api/app/models/api_client_authorization.rb
@@ -92,6 +92,27 @@ class ApiClientAuthorization < ArvadosModel
uuid_prefix+".arvadosapi.com")
end
+ # Delete token, if remote, attempt to delete on the host as well.
+ def expire_destroy
+ uuid_prefix = self.uuid[0..4]
+ if uuid_prefix != Rails.configuration.uuid_prefix
+ # remote token
+ host = remote_host(uuid_prefix: uuid_prefix)
+ begin
+ clnt = HTTPClient.new
+ if Rails.configuration.sso_insecure
+ clnt.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
+ end
+ result = SafeJSON.load(
+ clnt.delete('https://' + host + '/arvados/v1/users/current',
+ {'Authorization' => 'Bearer ' + token}))
+ rescue => e
+ Rails.logger.warn "deleting remote token #{self.uuid} failed: #{e}"
+ end
+ end
+ destroy
+ end
+
def self.validate(token:, remote: nil)
return nil if !token
remote ||= Rails.configuration.uuid_prefix
diff --git a/services/api/app/models/container.rb b/services/api/app/models/container.rb
index 075510e35..ba5c1c28c 100644
--- a/services/api/app/models/container.rb
+++ b/services/api/app/models/container.rb
@@ -530,6 +530,7 @@ class Container < ArvadosModel
return errors.add :auth_uuid, "cannot be assigned because priority <= 0"
end
if cr.runtime_token.nil?
+ # generate a new token
self.auth = ApiClientAuthorization.
create!(user_id: User.find_by_uuid(cr.modified_by_user_uuid).id,
api_client_id: 0)
@@ -537,12 +538,12 @@ class Container < ArvadosModel
self.runtime_auth_scopes = self.auth.scopes
else
# using cr.runtime_token
- runtime_auth = ApiClientAuthorization.validate(token: cr.runtime_token)
- if runtime_auth.nil?
+ self.auth = ApiClientAuthorization.validate(token: cr.runtime_token)
+ if self.auth.nil?
raise ArgumentError.new "Invalid runtime token"
end
- self.runtime_user_uuid = User.find_by_id(runtime_auth.user_id).uuid
- self.runtime_auth_scopes = runtime_auth.scopes
+ self.runtime_user_uuid = User.find_by_id(self.auth.user_id).uuid
+ self.runtime_auth_scopes = self.auth.scopes
end
end
diff --git a/services/api/app/models/container_request.rb b/services/api/app/models/container_request.rb
index f3fb220b0..b75775c87 100644
--- a/services/api/app/models/container_request.rb
+++ b/services/api/app/models/container_request.rb
@@ -359,7 +359,14 @@ class ContainerRequest < ArvadosModel
def scrub_secrets
if self.state == Final
self.secret_mounts = {}
- self.runtime_token = nil
+ if !self.runtime_token.nil?
+ _, uuid, secret = self.runtime_token.split('/')
+ tok = ApiClientAuthorization.find_by_uuid(uuid)
+ if !tok.nil?
+ tok.expire_destroy
+ end
+ self.runtime_token = nil
+ end
end
end
diff --git a/services/api/test/unit/container_request_test.rb b/services/api/test/unit/container_request_test.rb
index 408df0dd8..00c341f74 100644
--- a/services/api/test/unit/container_request_test.rb
+++ b/services/api/test/unit/container_request_test.rb
@@ -1075,13 +1075,28 @@ class ContainerRequestTest < ActiveSupport::TestCase
assert_equal [:secret_mounts], cr.errors.messages.keys
end
- test "valid runtime_token" do
+ test "using runtime_token" do
set_user_from_auth :active
spec = api_client_authorizations(:spectator)
- cr = create_minimal_req!(state: "Committed", runtime_token: spec.token)
+ cr = create_minimal_req!(state: "Committed", runtime_token: spec.token, priority: 1)
cr.save!
c = Container.find_by_uuid cr.container_uuid
- assert_nil c.auth_uuid
+ lock_and_run c
+ assert_equal c.auth_uuid, spec.uuid
+
+ assert_not_nil ApiClientAuthorization.find_by_uuid(spec.uuid)
+
+ act_as_system_user do
+ c.update_attributes!(state: Container::Complete,
+ exit_code: 0,
+ output: '1f4b0bc7583c2a7f9102c395f4ffc5e3+45',
+ log: 'fa7aeb5140e2848d39b416daeef4ffc5+45')
+ end
+
+ cr.reload
+ c.reload
+ assert_nil cr.runtime_token
+ assert_nil ApiClientAuthorization.find_by_uuid(spec.uuid)
end
test "invalid runtime_token" do
commit 1df6b1005acfdc098f6f42a384924f6879543c7b
Author: Peter Amstutz <pamstutz at veritasgenetics.com>
Date: Wed Oct 10 15:58:21 2018 -0400
14260: Test container runtime_token
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <pamstutz at veritasgenetics.com>
diff --git a/services/api/app/controllers/arvados/v1/containers_controller.rb b/services/api/app/controllers/arvados/v1/containers_controller.rb
index e1a8a019a..393e00492 100644
--- a/services/api/app/controllers/arvados/v1/containers_controller.rb
+++ b/services/api/app/controllers/arvados/v1/containers_controller.rb
@@ -19,7 +19,7 @@ class Arvados::V1::ContainersController < ApplicationController
end
if @object.auth.nil?
cr = ContainerRequest.
- where('container_uuid=? and priority>0', self.uuid).
+ where('container_uuid=? and priority>0', @object.uuid).
order('priority desc').
first
@object = ApiClientAuthorization.validate(token: cr.runtime_token)
diff --git a/services/api/app/models/container_request.rb b/services/api/app/models/container_request.rb
index ede1dca7b..f3fb220b0 100644
--- a/services/api/app/models/container_request.rb
+++ b/services/api/app/models/container_request.rb
@@ -350,7 +350,7 @@ class ContainerRequest < ArvadosModel
errors.add :runtime_token, "not a v2 token"
return
end
- if ApiClientAuthorization.validate(token: cr.runtime_token).nil?
+ if ApiClientAuthorization.validate(token: runtime_token).nil?
errors.add :runtime_token, "failed validation"
end
end
diff --git a/services/api/test/fixtures/api_client_authorizations.yml b/services/api/test/fixtures/api_client_authorizations.yml
index 2073d8b1b..9074c5ffc 100644
--- a/services/api/test/fixtures/api_client_authorizations.yml
+++ b/services/api/test/fixtures/api_client_authorizations.yml
@@ -341,3 +341,10 @@ foo_collection_sharing_token:
- GET /arvados/v1/collections/zzzzz-4zz18-znfnqtbbv4spc3w
- GET /arvados/v1/collections/zzzzz-4zz18-znfnqtbbv4spc3w/
- GET /arvados/v1/keep_services/accessible
+
+container_runtime_token:
+ uuid: zzzzz-gj3su-2nj68s291f50gd9
+ api_client: untrusted
+ user: spectator
+ api_token: 2d19ue6ofx26o3mm7fs9u6t7hov9um0v92dzwk1o2xed3abprw
+ expires_at: 2038-01-01 00:00:00
diff --git a/services/api/test/fixtures/container_requests.yml b/services/api/test/fixtures/container_requests.yml
index 5d3531eea..dea98887e 100644
--- a/services/api/test/fixtures/container_requests.yml
+++ b/services/api/test/fixtures/container_requests.yml
@@ -764,6 +764,26 @@ cr_in_trashed_project:
vcpus: 1
ram: 123
+runtime_token:
+ uuid: zzzzz-xvhdp-11eklkhy0n4dm86
+ owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
+ name: queued
+ state: Committed
+ priority: 1
+ created_at: <%= 2.minute.ago.to_s(:db) %>
+ updated_at: <%= 1.minute.ago.to_s(:db) %>
+ modified_at: <%= 1.minute.ago.to_s(:db) %>
+ modified_by_user_uuid: zzzzz-tpzed-xurymjxw79nv3jz
+ container_image: test
+ cwd: test
+ output_path: test
+ command: ["echo", "hello"]
+ container_uuid: zzzzz-dz642-20isqbkl8xwnsao
+ runtime_token: v2/zzzzz-gj3su-2nj68s291f50gd9/2d19ue6ofx26o3mm7fs9u6t7hov9um0v92dzwk1o2xed3abprw
+ runtime_constraints:
+ vcpus: 1
+ ram: 123
+
# Test Helper trims the rest of the file
diff --git a/services/api/test/fixtures/containers.yml b/services/api/test/fixtures/containers.yml
index 757adcee1..ce61c01ee 100644
--- a/services/api/test/fixtures/containers.yml
+++ b/services/api/test/fixtures/containers.yml
@@ -259,3 +259,25 @@ running_to_be_deleted:
auth_uuid: zzzzz-gj3su-ty6lvu9d7u7c2sq
secret_mounts: {}
secret_mounts_md5: 99914b932bd37a50b983c5e7c90ae93b
+
+runtime_token:
+ uuid: zzzzz-dz642-20isqbkl8xwnsao
+ owner_uuid: zzzzz-tpzed-000000000000000
+ state: Queued
+ priority: 1
+ created_at: 2016-01-11 11:11:11.111111111 Z
+ updated_at: 2016-01-11 11:11:11.111111111 Z
+ container_image: test
+ cwd: test
+ output_path: test
+ command: ["echo", "hello"]
+ runtime_constraints:
+ ram: 12000000000
+ vcpus: 4
+ mounts:
+ /tmp:
+ kind: tmp
+ capacity: 24000000000
+ /var/spool/cwl:
+ kind: tmp
+ capacity: 24000000000
diff --git a/services/api/test/functional/arvados/v1/container_requests_controller_test.rb b/services/api/test/functional/arvados/v1/container_requests_controller_test.rb
index 282e09049..a3252ad7b 100644
--- a/services/api/test/functional/arvados/v1/container_requests_controller_test.rb
+++ b/services/api/test/functional/arvados/v1/container_requests_controller_test.rb
@@ -81,4 +81,21 @@ class Arvados::V1::ContainerRequestsControllerTest < ActionController::TestCase
req.reload
assert_equal 'bar', req.secret_mounts['/foo']['content']
end
+
+ test "runtime_token not in #create responses" do
+ authorize_with :active
+
+ post :create, {
+ container_request: minimal_cr.merge(
+ runtime_token: api_client_authorizations(:spectator).token)
+ }
+ assert_response :success
+
+ resp = JSON.parse(@response.body)
+ refute resp.has_key?('runtime_token')
+
+ req = ContainerRequest.where(uuid: resp['uuid']).first
+ assert_equal api_client_authorizations(:spectator).token, req.runtime_token
+ end
+
end
diff --git a/services/api/test/functional/arvados/v1/containers_controller_test.rb b/services/api/test/functional/arvados/v1/containers_controller_test.rb
index 8e2002c75..8880967ba 100644
--- a/services/api/test/functional/arvados/v1/containers_controller_test.rb
+++ b/services/api/test/functional/arvados/v1/containers_controller_test.rb
@@ -151,4 +151,15 @@ class Arvados::V1::ContainersControllerTest < ActionController::TestCase
end
end
end
+
+ test 'get runtime_token auth' do
+ authorize_with :dispatch1
+ c = containers(:runtime_token)
+ assert c.lock, show_errors(c)
+ get :auth, id: c.uuid
+ assert_response :success
+ assert_equal "v2/#{json_response['uuid']}/#{json_response['api_token']}", api_client_authorizations(:container_runtime_token).token
+ assert_equal 'arvados#apiClientAuthorization', json_response['kind']
+ end
+
end
diff --git a/services/api/test/integration/remote_user_test.rb b/services/api/test/integration/remote_user_test.rb
index c812348a2..84e8a9439 100644
--- a/services/api/test/integration/remote_user_test.rb
+++ b/services/api/test/integration/remote_user_test.rb
@@ -251,23 +251,36 @@ class RemoteUsersTest < ActionDispatch::IntegrationTest
assert_equal 'barney', json_response['username']
end
- test "validate unsalted token for remote cluster zbbbb" do
+ test "validate unsalted v2 token for remote cluster zbbbb" do
auth = api_client_authorizations(:active)
token = "v2/#{auth.uuid}/#{auth.api_token}"
get '/arvados/v1/users/current', {format: 'json', remote: 'zbbbb'}, {
"HTTP_AUTHORIZATION" => "Bearer #{token}"
}
- assert_response 200
+ assert_response :success
assert_equal(users(:active).uuid, json_response['uuid'])
end
-
- # test 'container request with remote runtime_token' do
- # auth = api_client_authorizations(:active)
- # token = "v2/#{auth.uuid.sub('zzzzz-', 'zbbbb-')}/#{auth.api_token}"
-
- # post '/arvados/v1/container_requests', {"container_request": {}}, {"HTTP_AUTHORIZATION" => "Bearer #{token}"}
- # assert_response :success
- # end
+ test 'container request with runtime_token' do
+ [["valid local", "v2/#{api_client_authorizations(:active).uuid}/#{api_client_authorizations(:active).api_token}"],
+ ["valid remote", "v2/zbbbb-gj3su-000000000000000/abc"],
+ ["invalid local", "v2/#{api_client_authorizations(:active).uuid}/fakefakefake"]
+ ].each do |label, runtime_token|
+ post '/arvados/v1/container_requests', {
+ "container_request" => {
+ "command" => ["echo"],
+ "container_image" => "xyz",
+ "output_path" => "/",
+ "cwd" => "/",
+ "runtime_token" => runtime_token
+ }
+ }, {"HTTP_AUTHORIZATION" => "Bearer #{api_client_authorizations(:active).api_token}"}
+ if label.include? "invalid"
+ assert_response 422
+ else
+ assert_response :success
+ end
+ end
+ end
end
diff --git a/services/api/test/unit/container_request_test.rb b/services/api/test/unit/container_request_test.rb
index 81b49ff4f..408df0dd8 100644
--- a/services/api/test/unit/container_request_test.rb
+++ b/services/api/test/unit/container_request_test.rb
@@ -1074,4 +1074,22 @@ class ContainerRequestTest < ActiveSupport::TestCase
secret_mounts: sm)
assert_equal [:secret_mounts], cr.errors.messages.keys
end
+
+ test "valid runtime_token" do
+ set_user_from_auth :active
+ spec = api_client_authorizations(:spectator)
+ cr = create_minimal_req!(state: "Committed", runtime_token: spec.token)
+ cr.save!
+ c = Container.find_by_uuid cr.container_uuid
+ assert_nil c.auth_uuid
+ end
+
+ test "invalid runtime_token" do
+ set_user_from_auth :active
+ spec = api_client_authorizations(:spectator)
+ assert_raises(ActiveRecord::RecordInvalid) do
+ cr = create_minimal_req!(state: "Committed", runtime_token: "#{spec.token}xx")
+ cr.save!
+ end
+ end
end
commit 528e6554fbff9984bce411bdfeefc27ef15c62c8
Author: Peter Amstutz <pamstutz at veritasgenetics.com>
Date: Fri Oct 5 16:40:33 2018 -0400
14260: Container runtime token wip
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <pamstutz at veritasgenetics.com>
diff --git a/services/api/app/controllers/arvados/v1/containers_controller.rb b/services/api/app/controllers/arvados/v1/containers_controller.rb
index 65d8385ad..e1a8a019a 100644
--- a/services/api/app/controllers/arvados/v1/containers_controller.rb
+++ b/services/api/app/controllers/arvados/v1/containers_controller.rb
@@ -17,7 +17,15 @@ class Arvados::V1::ContainersController < ApplicationController
if @object.locked_by_uuid != Thread.current[:api_client_authorization].uuid
raise ArvadosModel::PermissionDeniedError.new("Not locked by your token")
end
- @object = @object.auth
+ if @object.auth.nil?
+ cr = ContainerRequest.
+ where('container_uuid=? and priority>0', self.uuid).
+ order('priority desc').
+ first
+ @object = ApiClientAuthorization.validate(token: cr.runtime_token)
+ else
+ @object = @object.auth
+ end
show
end
diff --git a/services/api/app/models/container.rb b/services/api/app/models/container.rb
index 079ac4c29..075510e35 100644
--- a/services/api/app/models/container.rb
+++ b/services/api/app/models/container.rb
@@ -529,9 +529,21 @@ class Container < ArvadosModel
if !cr
return errors.add :auth_uuid, "cannot be assigned because priority <= 0"
end
- self.auth = ApiClientAuthorization.
- create!(user_id: User.find_by_uuid(cr.modified_by_user_uuid).id,
- api_client_id: 0)
+ if cr.runtime_token.nil?
+ self.auth = ApiClientAuthorization.
+ create!(user_id: User.find_by_uuid(cr.modified_by_user_uuid).id,
+ api_client_id: 0)
+ self.runtime_user_uuid = cr.modified_by_user_uuid
+ self.runtime_auth_scopes = self.auth.scopes
+ else
+ # using cr.runtime_token
+ runtime_auth = ApiClientAuthorization.validate(token: cr.runtime_token)
+ if runtime_auth.nil?
+ raise ArgumentError.new "Invalid runtime token"
+ end
+ self.runtime_user_uuid = User.find_by_id(runtime_auth.user_id).uuid
+ self.runtime_auth_scopes = runtime_auth.scopes
+ end
end
def sort_serialized_attrs
diff --git a/services/api/app/models/container_request.rb b/services/api/app/models/container_request.rb
index bbec42108..ede1dca7b 100644
--- a/services/api/app/models/container_request.rb
+++ b/services/api/app/models/container_request.rb
@@ -38,7 +38,8 @@ class ContainerRequest < ArvadosModel
validate :validate_state_change
validate :check_update_whitelist
validate :secret_mounts_key_conflict
- before_save :scrub_secret_mounts
+ validate :validate_runtime_token
+ before_save :scrub_secrets
before_create :set_requesting_container_uuid
before_destroy :set_priority_zero
after_save :update_priority
@@ -88,7 +89,7 @@ class ContainerRequest < ArvadosModel
AttrsPermittedAlways = [:owner_uuid, :state, :name, :description, :properties]
AttrsPermittedBeforeCommit = [:command, :container_count_max,
:container_image, :cwd, :environment, :filters, :mounts,
- :output_path, :priority,
+ :output_path, :priority, :runtime_token,
:runtime_constraints, :state, :container_uuid, :use_existing,
:scheduling_parameters, :secret_mounts, :output_name, :output_ttl]
@@ -97,7 +98,7 @@ class ContainerRequest < ArvadosModel
end
def logged_attributes
- super.except('secret_mounts')
+ super.except('secret_mounts', 'runtime_token')
end
def state_transitions
@@ -165,7 +166,7 @@ class ContainerRequest < ArvadosModel
end
def self.full_text_searchable_columns
- super - ["mounts", "secret_mounts", "secret_mounts_md5"]
+ super - ["mounts", "secret_mounts", "secret_mounts_md5", "runtime_token"]
end
protected
@@ -343,9 +344,22 @@ class ContainerRequest < ArvadosModel
end
end
- def scrub_secret_mounts
+ def validate_runtime_token
+ if !self.runtime_token.nil?
+ if !runtime_token[0..2] == "v2/"
+ errors.add :runtime_token, "not a v2 token"
+ return
+ end
+ if ApiClientAuthorization.validate(token: cr.runtime_token).nil?
+ errors.add :runtime_token, "failed validation"
+ end
+ end
+ end
+
+ def scrub_secrets
if self.state == Final
self.secret_mounts = {}
+ self.runtime_token = nil
end
end
diff --git a/services/api/db/migrate/20181005192222_add_container_runtime_token.rb b/services/api/db/migrate/20181005192222_add_container_runtime_token.rb
index 007cbd00e..07151cd88 100644
--- a/services/api/db/migrate/20181005192222_add_container_runtime_token.rb
+++ b/services/api/db/migrate/20181005192222_add_container_runtime_token.rb
@@ -1,7 +1,7 @@
class AddContainerRuntimeToken < ActiveRecord::Migration
def change
add_column :container_requests, :runtime_token, :text, :null => true
- add_column :containers, :runtime_user_uuid, :text
- add_column :containers, :runtime_auth_scopes, :jsonb
+ add_column :containers, :runtime_user_uuid, :text, :null => true
+ add_column :containers, :runtime_auth_scopes, :jsonb, :null => true
end
end
diff --git a/services/api/test/integration/remote_user_test.rb b/services/api/test/integration/remote_user_test.rb
index c38c230b2..c812348a2 100644
--- a/services/api/test/integration/remote_user_test.rb
+++ b/services/api/test/integration/remote_user_test.rb
@@ -251,4 +251,23 @@ class RemoteUsersTest < ActionDispatch::IntegrationTest
assert_equal 'barney', json_response['username']
end
+ test "validate unsalted token for remote cluster zbbbb" do
+ auth = api_client_authorizations(:active)
+ token = "v2/#{auth.uuid}/#{auth.api_token}"
+ get '/arvados/v1/users/current', {format: 'json', remote: 'zbbbb'}, {
+ "HTTP_AUTHORIZATION" => "Bearer #{token}"
+ }
+ assert_response 200
+ assert_equal(users(:active).uuid, json_response['uuid'])
+ end
+
+
+ # test 'container request with remote runtime_token' do
+ # auth = api_client_authorizations(:active)
+ # token = "v2/#{auth.uuid.sub('zzzzz-', 'zbbbb-')}/#{auth.api_token}"
+
+ # post '/arvados/v1/container_requests', {"container_request": {}}, {"HTTP_AUTHORIZATION" => "Bearer #{token}"}
+ # assert_response :success
+ # end
+
end
commit cd17ba23970494028d62feb9f1b787c5e2466ca4
Author: Peter Amstutz <pamstutz at veritasgenetics.com>
Date: Fri Oct 5 15:31:08 2018 -0400
14260: Migration adding runtime_token, runtime_user_uuid, runtime_auth_scopes
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <pamstutz at veritasgenetics.com>
diff --git a/services/api/db/migrate/20181005192222_add_container_runtime_token.rb b/services/api/db/migrate/20181005192222_add_container_runtime_token.rb
new file mode 100644
index 000000000..007cbd00e
--- /dev/null
+++ b/services/api/db/migrate/20181005192222_add_container_runtime_token.rb
@@ -0,0 +1,7 @@
+class AddContainerRuntimeToken < ActiveRecord::Migration
+ def change
+ add_column :container_requests, :runtime_token, :text, :null => true
+ add_column :containers, :runtime_user_uuid, :text
+ add_column :containers, :runtime_auth_scopes, :jsonb
+ end
+end
diff --git a/services/api/db/structure.sql b/services/api/db/structure.sql
index f8d9b3f35..d1eb8d8d0 100644
--- a/services/api/db/structure.sql
+++ b/services/api/db/structure.sql
@@ -299,7 +299,8 @@ CREATE TABLE public.container_requests (
log_uuid character varying(255),
output_name character varying(255) DEFAULT NULL::character varying,
output_ttl integer DEFAULT 0 NOT NULL,
- secret_mounts jsonb DEFAULT '{}'::jsonb
+ secret_mounts jsonb DEFAULT '{}'::jsonb,
+ runtime_token text
);
@@ -355,7 +356,9 @@ CREATE TABLE public.containers (
scheduling_parameters text,
secret_mounts jsonb DEFAULT '{}'::jsonb,
secret_mounts_md5 character varying DEFAULT '99914b932bd37a50b983c5e7c90ae93b'::character varying,
- runtime_status jsonb DEFAULT '{}'::jsonb
+ runtime_status jsonb DEFAULT '{}'::jsonb,
+ runtime_user_uuid text,
+ runtime_auth_scopes jsonb
);
@@ -3171,3 +3174,5 @@ INSERT INTO schema_migrations (version) VALUES ('20180904110712');
INSERT INTO schema_migrations (version) VALUES ('20180917205609');
+INSERT INTO schema_migrations (version) VALUES ('20181005192222');
+
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list