18277: Add RoleGroupsVisibleToAll config, default true.
authorTom Clegg <tom@curii.com>
Fri, 10 Dec 2021 14:46:00 +0000 (09:46 -0500)
committerTom Clegg <tom@curii.com>
Fri, 10 Dec 2021 14:46:00 +0000 (09:46 -0500)
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom@curii.com>

doc/admin/upgrading.html.textile.liquid
lib/config/config.default.yml
lib/config/export.go
lib/config/generated_config.go
sdk/go/arvados/config.go
services/api/app/models/arvados_model.rb
services/api/config/arvados_config.rb
services/api/test/functional/arvados/v1/groups_controller_test.rb
services/api/test/integration/remote_user_test.rb
services/api/test/unit/permission_test.rb

index 517c2dd0cde0014f44bd03e077048c459a191ef2..411e2ea0ff3cf3d4d4b0e8bd1c7852b336f6ae58 100644 (file)
@@ -39,6 +39,10 @@ h2(#main). development main (as of 2021-11-10)
 
 "previous: Upgrading from 2.3.0":#v2_3_0
 
+h3. Role groups are visible to all users by default
+
+The permission model has changed such that all role groups are visible to all active users. This enables users to share objects with groups they don't belong to. To preserve the previous behavior, where role groups are only visible to members and admins, add @RoleGroupsVisibleToAll: false@ to the @Users@ section of your configuration file.
+
 h3. Default LSF arguments have changed
 
 If you use LSF and your configuration specifies @Containers.LSF.BsubArgumentsList@, you should update it to include the new arguments (@"-R", "select[mem>=%MMB]", ...@, see "configuration reference":{{site.baseurl}}/admin/config.html). Otherwise, containers that are too big to run on any LSF host will remain in the LSF queue instead of being cancelled.
index a84dc5d31673b58b152645f3b73f3efa514ea767..7f859822537dfe440ebf7c8064400d11193a9cbe 100644 (file)
@@ -319,6 +319,14 @@ Clusters:
         Thanks,
         Your Arvados administrator.
 
+      # If RoleGroupsVisibleToAll is true, all role groups are visible
+      # to all active users.
+      #
+      # If false, users must be granted permission to role groups in
+      # order to see them. This is more appropriate for a multi-tenant
+      # cluster.
+      RoleGroupsVisibleToAll: true
+
     AuditLogs:
       # Time to keep audit logs, in seconds. (An audit log is a row added
       # to the "logs" table in the PostgreSQL database each time an
index 4c4e341f5a34c8608e554f407aab4869da88a8f6..cfc4cb6272d522d0505c909a82906c2723fea323 100644 (file)
@@ -234,6 +234,7 @@ var whitelist = map[string]bool{
        "Users.UserNotifierEmailBcc":                          false,
        "Users.UserProfileNotificationAddress":                false,
        "Users.UserSetupMailText":                             false,
+       "Users.RoleGroupsVisibleToAll":                        false,
        "Volumes":                                             true,
        "Volumes.*":                                           true,
        "Volumes.*.*":                                         false,
index 567ac30a9b7d855cfabdc10374dcf55b8f9694c7..485273e1b0ed0409f07f058959c45a8f739b5f08 100644 (file)
@@ -325,6 +325,14 @@ Clusters:
         Thanks,
         Your Arvados administrator.
 
+      # If RoleGroupsVisibleToAll is true, all role groups are visible
+      # to all active users.
+      #
+      # If false, users must be granted permission to role groups in
+      # order to see them. This is more appropriate for a multi-tenant
+      # cluster.
+      RoleGroupsVisibleToAll: true
+
     AuditLogs:
       # Time to keep audit logs, in seconds. (An audit log is a row added
       # to the "logs" table in the PostgreSQL database each time an
index 474ce33b0ee4e9b2262bbe1b16f9ed36c0c2af38..6d5156e765c07cb580f695b3e83b03bf996172be 100644 (file)
@@ -241,6 +241,7 @@ type Cluster struct {
                UserProfileNotificationAddress        string
                PreferDomainForUsername               string
                UserSetupMailText                     string
+               RoleGroupsVisibleToAll                bool
        }
        StorageClasses map[string]StorageClassConfig
        Volumes        map[string]Volume
index af226cde821399a0d115fdddfc698ec57b39ace9..54b1394ffd06245e6d7fc7c7fd97f004abbde3b4 100644 (file)
@@ -384,6 +384,14 @@ class ArvadosModel < ApplicationRecord
         direct_check = " OR " + direct_check
       end
 
+      if Rails.configuration.Users.RoleGroupsVisibleToAll &&
+         sql_table == "groups" &&
+         users_list.select { |u| u.is_active }.any?
+        # All role groups are readable (but we still need the other
+        # direct_check clauses to handle non-role groups).
+        direct_check += " OR #{sql_table}.group_class = 'role'"
+      end
+
       links_cond = ""
       if sql_table == "links"
         # 1) Match permission links incoming or outgoing on the
index 49865039c4649a8a8b7270682b97fd073b742504..c5db6e6b9e443a54550a577db32594e71194afc8 100644 (file)
@@ -100,6 +100,7 @@ arvcfg.declare_config "Users.UserNotifierEmailFrom", String, :user_notifier_emai
 arvcfg.declare_config "Users.UserNotifierEmailBcc", Hash
 arvcfg.declare_config "Users.NewUserNotificationRecipients", Hash, :new_user_notification_recipients, ->(cfg, k, v) { arrayToHash cfg, "Users.NewUserNotificationRecipients", v }
 arvcfg.declare_config "Users.NewInactiveUserNotificationRecipients", Hash, :new_inactive_user_notification_recipients, method(:arrayToHash)
+arvcfg.declare_config "Users.RoleGroupsVisibleToAll", Boolean
 arvcfg.declare_config "Login.LoginCluster", String
 arvcfg.declare_config "Login.TrustedClients", Hash
 arvcfg.declare_config "Login.RemoteTokenRefresh", ActiveSupport::Duration
index 4dbccc5eb24edd07cdb09e6f2e400faa9c4f0c81..0819c2306717f08cfac634494d1e55a1e6a677d4 100644 (file)
@@ -6,12 +6,19 @@ require 'test_helper'
 
 class Arvados::V1::GroupsControllerTest < ActionController::TestCase
 
-  test "attempt to delete group without read or write access" do
+  test "attempt to delete group that cannot be seen" do
+    Rails.configuration.Users.RoleGroupsVisibleToAll = false
     authorize_with :active
     post :destroy, params: {id: groups(:empty_lonely_group).uuid}
     assert_response 404
   end
 
+  test "attempt to delete group without read or write access" do
+    authorize_with :active
+    post :destroy, params: {id: groups(:empty_lonely_group).uuid}
+    assert_response 403
+  end
+
   test "attempt to delete group without write access" do
     authorize_with :active
     post :destroy, params: {id: groups(:all_users).uuid}
@@ -553,6 +560,30 @@ class Arvados::V1::GroupsControllerTest < ActionController::TestCase
     end
   end
 
+  [
+    [false, :inactive, :private_role, false],
+    [false, :spectator, :private_role, false],
+    [false, :admin, :private_role, true],
+    [true, :inactive, :private_role, false],
+    [true, :spectator, :private_role, true],
+    [true, :admin, :private_role, true],
+    # project (non-role) groups are invisible even when RoleGroupsVisibleToAll is true
+    [true, :inactive, :private, false],
+    [true, :spectator, :private, false],
+    [true, :admin, :private, true],
+  ].each do |visibleToAll, userFixture, groupFixture, visible|
+    test "with RoleGroupsVisibleToAll=#{visibleToAll}, #{groupFixture} group is #{visible ? '' : 'in'}visible to #{userFixture} user" do
+      Rails.configuration.Users.RoleGroupsVisibleToAll = visibleToAll
+      authorize_with userFixture
+      get :show, params: {id: groups(groupFixture).uuid, format: :json}
+      if visible
+        assert_response :success
+      else
+        assert_response 404
+      end
+    end
+  end
+
   ### trashed project tests ###
 
   #
index 568d5088d9d708fdc166dc04564106d81b27f108..179d30f3cbf3c255a1570ba3227b732603dd8ef9 100644 (file)
@@ -304,6 +304,7 @@ class RemoteUsersTest < ActionDispatch::IntegrationTest
   end
 
   test "list readable groups with salted token" do
+    Rails.configuration.Users.RoleGroupsVisibleToAll = false
     salted_token = salt_token(fixture: :active, remote: 'zbbbb')
     get '/arvados/v1/groups',
       params: {
index 128d0ebaa6f6f255ce54add5e8aac9b39ecca208..647139d9ec9d38d4d5570a19e658b866bd609544 100644 (file)
@@ -218,6 +218,7 @@ class PermissionTest < ActiveSupport::TestCase
   end
 
   test "manager user gets permission to minions' articles via can_manage link" do
+    Rails.configuration.Users.RoleGroupsVisibleToAll = false
     Rails.configuration.Users.ActivatedUsersAreVisibleToOthers = false
     manager = create :active_user, first_name: "Manage", last_name: "Er"
     minion = create :active_user, first_name: "Min", last_name: "Ion"