From 046863fce3eefdd8f2b4588855b2335dcb0215e1 Mon Sep 17 00:00:00 2001 From: Peter Amstutz Date: Wed, 12 Aug 2020 17:32:06 -0400 Subject: [PATCH] 16683: Permit granting permissions to remote users Arvados-DCO-1.1-Signed-off-by: Peter Amstutz --- services/api/app/models/arvados_model.rb | 25 ++++++++++++++--------- services/api/app/models/link.rb | 26 ++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/services/api/app/models/arvados_model.rb b/services/api/app/models/arvados_model.rb index 01a31adb91..eb2ea17317 100644 --- a/services/api/app/models/arvados_model.rb +++ b/services/api/app/models/arvados_model.rb @@ -749,6 +749,20 @@ class ArvadosModel < ApplicationRecord %r/[a-z0-9]{5}-#{uuid_prefix}-[a-z0-9]{15}/ end + def check_readable_uuid attr, attr_value + return if attr_value.nil? + if (r = ArvadosModel::resource_class_for_uuid attr_value) + unless skip_uuid_read_permission_check.include? attr + r = r.readable_by(current_user) + end + if r.where(uuid: attr_value).count == 0 + errors.add(attr, "'#{attr_value}' not found") + end + else + errors.add(attr, "'#{attr_value}' invalid uuid") + end + end + def ensure_valid_uuids specials = [system_user_uuid] @@ -757,16 +771,7 @@ class ArvadosModel < ApplicationRecord next if skip_uuid_existence_check.include? attr attr_value = send attr next if specials.include? attr_value - if attr_value - if (r = ArvadosModel::resource_class_for_uuid attr_value) - unless skip_uuid_read_permission_check.include? attr - r = r.readable_by(current_user) - end - if r.where(uuid: attr_value).count == 0 - errors.add(attr, "'#{attr_value}' not found") - end - end - end + check_readable_uuid attr, attr_value end end end diff --git a/services/api/app/models/link.rb b/services/api/app/models/link.rb index e4ba7f3de1..7f4433dd70 100644 --- a/services/api/app/models/link.rb +++ b/services/api/app/models/link.rb @@ -43,6 +43,27 @@ class Link < ArvadosModel protected + def check_readable_uuid attr, attr_value + if attr == 'tail_uuid' && + !attr_value.nil? && + self.link_class == 'permission' && + attr_value[0..4] != Rails.configuration.ClusterID && + ArvadosModel::resource_class_for_uuid(attr_value) == User + # Permission link tail is a remote user (the user permissions + # are being granted to), so bypass the standard check that a + # referenced object uuid is readable by current user. + # + # We could do a call to the remote cluster to check if the user + # in tail_uuid exists. This would detect copy-and-paste errors, + # but add another way for the request to fail, and I don't think + # it would improve security. It doesn't seem to be worth the + # complexity tradeoff. + true + else + super + end + end + def permission_to_attach_to_objects # Anonymous users cannot write links return false if !current_user @@ -76,6 +97,11 @@ class Link < ArvadosModel head_obj = ArvadosModel.find_by_uuid(head_uuid) + if head_obj.nil? + errors.add(:head_uuid, "does not exist") + return false + end + # No permission links can be pointed to past collection versions if head_obj.is_a?(Collection) && head_obj.current_version_uuid != head_uuid errors.add(:head_uuid, "cannot point to a past version of a collection") -- 2.30.2