summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-06-01 07:27:42 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-06-01 07:27:50 +0000
commit780afecf300254a98c8db6818f7a53db564740ec (patch)
tree5a6aa0e0eeaeccb8ba020f1a381593538cb57fe5
parentdadf501093010f76eda6fdc496ad8c3302a32892 (diff)
downloadgitlab-ce-780afecf300254a98c8db6818f7a53db564740ec.tar.gz
Add latest changes from gitlab-org/security/gitlab@14-10-stable-ee
-rw-r--r--app/controllers/groups/application_controller.rb6
-rw-r--r--app/controllers/groups/group_members_controller.rb1
-rw-r--r--app/policies/group_policy.rb9
-rw-r--r--doc/user/group/subgroups/index.md3
-rw-r--r--lib/api/helpers/members_helpers.rb4
-rw-r--r--lib/api/members.rb8
-rw-r--r--spec/features/security/group/private_access_spec.rb2
-rw-r--r--spec/requests/api/members_spec.rb15
8 files changed, 47 insertions, 1 deletions
diff --git a/app/controllers/groups/application_controller.rb b/app/controllers/groups/application_controller.rb
index bf72ade32d0..aec3247f4b2 100644
--- a/app/controllers/groups/application_controller.rb
+++ b/app/controllers/groups/application_controller.rb
@@ -67,6 +67,12 @@ class Groups::ApplicationController < ApplicationController
end
end
+ def authorize_read_group_member!
+ unless can?(current_user, :read_group_member, group)
+ render_403
+ end
+ end
+
def build_canonical_path(group)
params[:group_id] = group.to_param
diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb
index 51778f31f65..db26848a280 100644
--- a/app/controllers/groups/group_members_controller.rb
+++ b/app/controllers/groups/group_members_controller.rb
@@ -14,6 +14,7 @@ class Groups::GroupMembersController < Groups::ApplicationController
# Authorize
before_action :authorize_admin_group_member!, except: admin_not_required_endpoints
+ before_action :authorize_read_group_member!, only: :index
skip_before_action :check_two_factor_requirement, only: :leave
skip_cross_project_access_check :index, :update, :destroy, :request_access,
diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb
index 7a49ad3d4aa..bf70899ad79 100644
--- a/app/policies/group_policy.rb
+++ b/app/policies/group_policy.rb
@@ -22,6 +22,7 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
condition(:share_with_group_locked, scope: :subject) { @subject.share_with_group_lock? }
condition(:parent_share_with_group_locked, scope: :subject) { @subject.parent&.share_with_group_lock? }
condition(:can_change_parent_share_with_group_lock) { can?(:change_share_with_group_lock, @subject.parent) }
+ condition(:can_read_group_member) { can_read_group_member? }
desc "User is a project bot"
condition(:project_bot) { user.project_bot? && access_level >= GroupMember::GUEST }
@@ -127,6 +128,10 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
rule { ~public_group & ~has_access }.prevent :read_counts
+ rule { ~can_read_group_member }.policy do
+ prevent :read_group_member
+ end
+
rule { ~can?(:read_group) }.policy do
prevent :read_design_activity
end
@@ -308,6 +313,10 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
true
end
+ def can_read_group_member?
+ !(@subject.private? && access_level == GroupMember::NO_ACCESS)
+ end
+
def resource_access_token_creation_allowed?
resource_access_token_feature_available? && group.root_ancestor.namespace_settings.resource_access_token_creation_allowed?
end
diff --git a/doc/user/group/subgroups/index.md b/doc/user/group/subgroups/index.md
index 2cddbaa9723..5f3c859d15a 100644
--- a/doc/user/group/subgroups/index.md
+++ b/doc/user/group/subgroups/index.md
@@ -93,6 +93,9 @@ For more information, view the [permissions table](../../permissions.md#group-me
## Subgroup membership
+NOTE:
+There is a bug that causes some pages in the parent group to be accessible by subgroup members. For more details, see [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/340421).
+
When you add a member to a group, that member is also added to all subgroups. The user's permissions are inherited from
the group's parent.
diff --git a/lib/api/helpers/members_helpers.rb b/lib/api/helpers/members_helpers.rb
index f26ac1318b1..e0ccf2242c7 100644
--- a/lib/api/helpers/members_helpers.rb
+++ b/lib/api/helpers/members_helpers.rb
@@ -15,6 +15,10 @@ module API
public_send("find_#{source_type}!", id) # rubocop:disable GitlabSecurity/PublicSend
end
+ def authorize_read_source_member!(source_type, source)
+ authorize! :"read_#{source_type}_member", source
+ end
+
def authorize_admin_source!(source_type, source)
authorize! :"admin_#{source_type}", source
end
diff --git a/lib/api/members.rb b/lib/api/members.rb
index 01e859c94c4..7fd2dc4c347 100644
--- a/lib/api/members.rb
+++ b/lib/api/members.rb
@@ -30,6 +30,8 @@ module API
get ":id/members" do
source = find_source(source_type, params[:id])
+ authorize_read_source_member!(source_type, source)
+
members = paginate(retrieve_members(source, params: params))
present_members members
@@ -49,6 +51,8 @@ module API
get ":id/members/all" do
source = find_source(source_type, params[:id])
+ authorize_read_source_member!(source_type, source)
+
members = paginate(retrieve_members(source, params: params, deep: true))
present_members members
@@ -64,6 +68,8 @@ module API
get ":id/members/:user_id" do
source = find_source(source_type, params[:id])
+ authorize_read_source_member!(source_type, source)
+
members = source_members(source)
member = members.find_by!(user_id: params[:user_id])
@@ -81,6 +87,8 @@ module API
get ":id/members/all/:user_id" do
source = find_source(source_type, params[:id])
+ authorize_read_source_member!(source_type, source)
+
members = find_all_members(source)
member = members.find_by!(user_id: params[:user_id])
diff --git a/spec/features/security/group/private_access_spec.rb b/spec/features/security/group/private_access_spec.rb
index fc1fb3e3848..f733145b5e3 100644
--- a/spec/features/security/group/private_access_spec.rb
+++ b/spec/features/security/group/private_access_spec.rb
@@ -97,7 +97,7 @@ RSpec.describe 'Private Group access' do
it { is_expected.to be_allowed_for(:developer).of(group) }
it { is_expected.to be_allowed_for(:reporter).of(group) }
it { is_expected.to be_allowed_for(:guest).of(group) }
- it { is_expected.to be_allowed_for(project_guest) }
+ it { is_expected.to be_denied_for(project_guest) }
it { is_expected.to be_denied_for(:user) }
it { is_expected.to be_denied_for(:external) }
it { is_expected.to be_denied_for(:visitor) }
diff --git a/spec/requests/api/members_spec.rb b/spec/requests/api/members_spec.rb
index 6bacb3a59b2..ac077ea155d 100644
--- a/spec/requests/api/members_spec.rb
+++ b/spec/requests/api/members_spec.rb
@@ -184,6 +184,21 @@ RSpec.describe API::Members do
expect(json_response).to be_an Array
expect(json_response.map { |u| u['id'] }).to match_array [maintainer.id, developer.id, nested_user.id]
end
+
+ context 'with a subgroup' do
+ let(:group) { create(:group, :private)}
+ let(:subgroup) { create(:group, :private, parent: group)}
+ let(:project) { create(:project, group: subgroup) }
+
+ before do
+ subgroup.add_developer(developer)
+ end
+
+ it 'subgroup member cannot get parent group members list' do
+ get api("/groups/#{group.id}/members/all", developer)
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
end
shared_examples 'GET /:source_type/:id/members/(all/):user_id' do |source_type, all|