diff --git a/app/policies/ci/runner_policy.rb b/app/policies/ci/runner_policy.rb index 6dfe9cc496bf99012d170520b01dc7f596cc807e..8a99f4d1a3e048404d5ff5243b94744e535b71d6 100644 --- a/app/policies/ci/runner_policy.rb +++ b/app/policies/ci/runner_policy.rb @@ -31,3 +31,5 @@ class RunnerPolicy < BasePolicy rule { ~admin & locked }.prevent :assign_runner end end + +Ci::RunnerPolicy.prepend_mod_with('Ci::RunnerPolicy') diff --git a/ee/app/policies/ee/ci/runner_policy.rb b/ee/app/policies/ee/ci/runner_policy.rb new file mode 100644 index 0000000000000000000000000000000000000000..014bf5d04a19b1869a3bc3429af239341211cc5e --- /dev/null +++ b/ee/app/policies/ee/ci/runner_policy.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +module EE + module Ci + module RunnerPolicy + extend ActiveSupport::Concern + + prepended do + condition(:is_group_runner) do + @subject.group_type? + end + + condition(:is_project_runner) do + @subject.project_type? + end + + condition(:enable_auditor_group_runner_access) do + ::Feature.enabled?(:auditor_group_runner_access) + end + + rule { enable_auditor_group_runner_access & auditor & (is_group_runner | is_project_runner) }.policy do + enable :read_runner + end + end + end + end +end diff --git a/ee/app/policies/ee/group_policy.rb b/ee/app/policies/ee/group_policy.rb index ec9198bf1715ef88ed9dfeb6140acf826f83f7c8..c4fe0471c606207489081b1b3abdaea0769dfea8 100644 --- a/ee/app/policies/ee/group_policy.rb +++ b/ee/app/policies/ee/group_policy.rb @@ -165,6 +165,10 @@ module GroupPolicy @user.banned_from_namespace?(root_namespace) end + condition(:enable_auditor_group_runner_access) do + ::Feature.enabled?(:auditor_group_runner_access) + end + rule { ~public_group & ~can?(:owner_access) & user_banned_from_group }.policy do prevent :read_group end @@ -207,6 +211,10 @@ module GroupPolicy enable :read_wiki end + rule { enable_auditor_group_runner_access & auditor }.policy do + enable :read_group_runners + end + rule { group_level_compliance_dashboard_enabled & auditor }.policy do enable :read_group_compliance_dashboard end diff --git a/ee/config/feature_flags/development/auditor_group_runner_access.yml b/ee/config/feature_flags/development/auditor_group_runner_access.yml new file mode 100644 index 0000000000000000000000000000000000000000..77db21aad3708f3a1fbcb98fd45093aef9b4a6a4 --- /dev/null +++ b/ee/config/feature_flags/development/auditor_group_runner_access.yml @@ -0,0 +1,8 @@ +--- +name: auditor_group_runner_access +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91553 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/368089 +milestone: '15.3' +type: development +group: group::runner +default_enabled: false diff --git a/ee/spec/policies/ee/ci/runner_policy_spec.rb b/ee/spec/policies/ee/ci/runner_policy_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..2cd539523dae68eaaa2bb2c515b4760bfc745fcd --- /dev/null +++ b/ee/spec/policies/ee/ci/runner_policy_spec.rb @@ -0,0 +1,81 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Ci::RunnerPolicy do + describe 'cicd runners' do + let_it_be(:group) { create(:group) } + let_it_be(:project) { create(:project, group: group) } + + subject(:policy) { described_class.new(user, runner) } + + context 'with auditor access' do + let_it_be(:user) { create(:auditor) } + let_it_be(:instance_runner) { create(:ci_runner, :instance) } + let_it_be(:group_runner) { create(:ci_runner, :group, groups: [group]) } + let_it_be(:project_runner) { create(:ci_runner, :project, projects: [project]) } + + context 'when auditor_group_runner_access FF disabled' do + before do + stub_feature_flags(auditor_group_runner_access: false) + end + + context 'with instance runner' do + let(:runner) { instance_runner } + + it 'disallows all permissions' do + expect_disallowed :read_runner, :assign_runner, :update_runner, :delete_runner + end + end + + context 'with group runner' do + let(:runner) { group_runner } + + it 'disallows all permissions' do + expect_disallowed :read_runner, :assign_runner, :update_runner, :delete_runner + end + end + + context 'with project runner' do + let(:runner) { project_runner } + + it 'disallows all permissions' do + expect_disallowed :read_runner, :assign_runner, :update_runner, :delete_runner + end + end + end + + context 'when auditor_group_runner_access FF enabled' do + before do + stub_feature_flags(auditor_group_runner_access: true) + end + + context 'with instance runner' do + let(:runner) { instance_runner } + + it 'disallows all permissions' do + expect_disallowed :read_runner, :assign_runner, :update_runner, :delete_runner + end + end + + context 'with group runner' do + let(:runner) { group_runner } + + it 'allows only read permissions' do + expect_allowed :read_runner + expect_disallowed :assign_runner, :update_runner, :delete_runner + end + end + + context 'with project runner' do + let(:runner) { project_runner } + + it 'allows only read permissions' do + expect_allowed :read_runner + expect_disallowed :assign_runner, :update_runner, :delete_runner + end + end + end + end + end +end diff --git a/ee/spec/policies/group_policy_spec.rb b/ee/spec/policies/group_policy_spec.rb index af1baec9905cb890d1f37b3b69f55e4bb3e55597..996427480d1a225c3984fa1c196019d8704f36c5 100644 --- a/ee/spec/policies/group_policy_spec.rb +++ b/ee/spec/policies/group_policy_spec.rb @@ -21,6 +21,7 @@ read_group read_group_security_dashboard read_cluster + read_group_runners ] end @@ -1244,7 +1245,7 @@ def stub_group_saml_config(enabled) expect_disallowed(*reporter_permissions) expect_disallowed(*(developer_permissions - auditor_permissions)) expect_disallowed(*maintainer_permissions) - expect_disallowed(*owner_permissions) + expect_disallowed(*(owner_permissions - auditor_permissions)) end end end @@ -2259,4 +2260,30 @@ def expect_private_group_permissions_as_if_non_member end end end + + describe 'group cicd runners' do + context 'auditor' do + let(:current_user) { auditor } + + context 'with auditor_group_runner_access FF disabled' do + before do + stub_feature_flags(auditor_group_runner_access: false) + end + + it { is_expected.to be_disallowed(:read_group_runners) } + it { is_expected.to be_disallowed(:admin_group_runners) } + it { is_expected.to be_disallowed(:register_group_runners) } + end + + context 'with auditor_group_runner_access FF enabled' do + before do + stub_feature_flags(auditor_group_runner_access: true) + end + + it { is_expected.to be_allowed(:read_group_runners) } + it { is_expected.to be_disallowed(:admin_group_runners) } + it { is_expected.to be_disallowed(:register_group_runners) } + end + end + end end