diff --git a/ee/app/helpers/ee/saml_providers_helper.rb b/ee/app/helpers/ee/saml_providers_helper.rb index 01b9c78461719d3d0509725b636b52681919771b..68e101b1a42712d8a88ab50405eacf2e2b1a40be 100644 --- a/ee/app/helpers/ee/saml_providers_helper.rb +++ b/ee/app/helpers/ee/saml_providers_helper.rb @@ -2,18 +2,14 @@ module EE module SamlProvidersHelper - def group_saml_configured? - ::Gitlab::Auth::GroupSaml::Config.enabled? - end - def show_saml_in_sidebar?(group) - return false unless group_saml_configured? - return false unless group.feature_available?(:group_saml) - return false if group.subgroup? - can?(current_user, :admin_group_saml, group) end + def show_saml_group_links_in_sidebar?(group) + can?(current_user, :admin_saml_group_links, group) + end + def saml_link_for_provider(text, provider, **args) saml_link(text, provider.group.full_path, **args) end diff --git a/ee/app/policies/ee/group_policy.rb b/ee/app/policies/ee/group_policy.rb index ef4dbc1716e402b4a25f27e929de469bc26a6634..96107d4da65fc60320291fe6e0b2c2d0a9d9afd0 100644 --- a/ee/app/policies/ee/group_policy.rb +++ b/ee/app/policies/ee/group_policy.rb @@ -69,8 +69,16 @@ module GroupPolicy @subject.feature_available?(:cluster_deployments) end - condition(:group_saml_enabled) do - @subject.saml_provider&.enabled? + condition(:group_saml_config_enabled, scope: :global) do + ::Gitlab::Auth::GroupSaml::Config.enabled? + end + + condition(:group_saml_available, scope: :subject) do + !@subject.subgroup? && @subject.feature_available?(:group_saml) + end + + condition(:group_saml_enabled, scope: :subject) do + @subject.saml_enabled? end condition(:group_timelogs_available) do @@ -198,7 +206,9 @@ module GroupPolicy enable :read_group_security_dashboard end - rule { admin | owner }.enable :admin_group_saml + rule { group_saml_config_enabled & group_saml_available & (admin | owner) }.enable :admin_group_saml + + rule { group_saml_enabled & can?(:admin_group_saml) }.enable :admin_saml_group_links rule { admin | (can_owners_manage_ldap & owner) }.policy do enable :admin_ldap_group_links diff --git a/ee/spec/helpers/ee/saml_providers_helper_spec.rb b/ee/spec/helpers/ee/saml_providers_helper_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..5328a2925ccfe3eb2921ab51af466983d463276c --- /dev/null +++ b/ee/spec/helpers/ee/saml_providers_helper_spec.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe EE::SamlProvidersHelper do + def stub_can(permission, value) + allow(helper).to receive(:can?).with(user, permission, group).and_return(value) + end + + let_it_be(:group) { create(:group) } + let_it_be(:user) { create(:user) } + + before do + allow(helper).to receive(:current_user).and_return(user) + end + + describe '#show_saml_in_sidebar?' do + subject { helper.show_saml_in_sidebar?(group) } + + context 'when the user can admin group saml' do + before do + stub_can(:admin_group_saml, true) + end + + it { is_expected.to eq(true) } + end + + context 'when the user cannot admin group saml' do + before do + stub_can(:admin_group_saml, false) + end + + it { is_expected.to eq(false) } + end + end + + describe '#show_saml_group_links_in_sidebar?' do + subject { helper.show_saml_group_links_in_sidebar?(group) } + + context 'when the user can admin saml group links' do + before do + stub_can(:admin_saml_group_links, true) + end + + it { is_expected.to eq(true) } + end + + context 'when the user cannot admin saml group links' do + before do + stub_can(:admin_saml_group_links, false) + end + + it { is_expected.to eq(false) } + end + end +end diff --git a/ee/spec/policies/group_policy_spec.rb b/ee/spec/policies/group_policy_spec.rb index f713bf47aa1923af5e682a93f9e8ffffd445c897..a9240ba1311ffad982da5ca20c82941eb48ee6a9 100644 --- a/ee/spec/policies/group_policy_spec.rb +++ b/ee/spec/policies/group_policy_spec.rb @@ -285,62 +285,130 @@ end describe 'per group SAML' do - let(:current_user) { maintainer } - - it { is_expected.to be_disallowed(:admin_group_saml) } + context 'when group_saml is unavailable' do + def stub_group_saml_config(enabled) + allow(::Gitlab::Auth::GroupSaml::Config).to receive_messages(enabled?: enabled) + end - context 'owner' do let(:current_user) { owner } - it { is_expected.to be_allowed(:admin_group_saml) } - end + context 'when group saml config is disabled' do + before do + stub_group_saml_config(false) + end - context 'admin' do - let(:current_user) { admin } + it { is_expected.to be_disallowed(:admin_group_saml) } + end - it { is_expected.to be_allowed(:admin_group_saml) } - end + context 'when the group is a subgroup' do + let_it_be(:subgroup) { create(:group, :private, parent: group) } - context 'with sso enforcement enabled' do - let(:current_user) { guest } + before do + stub_group_saml_config(true) + end - let_it_be(:saml_provider) { create(:saml_provider, group: group, enforced_sso: true) } + subject { described_class.new(current_user, subgroup) } + it { is_expected.to be_disallowed(:admin_group_saml) } + end + + context 'when the feature is not licensed' do + before do + stub_group_saml_config(true) + stub_licensed_features(group_saml: false) + end + + it { is_expected.to be_disallowed(:admin_group_saml) } + end + end + + context 'when group_saml is available' do before do stub_licensed_features(group_saml: true) end - context 'when the session has been set globally' do - around do |example| - Gitlab::Session.with_session({}) do - example.run - end + context 'without an enabled SAML provider' do + context 'maintainer' do + let(:current_user) { maintainer } + + it { is_expected.to be_disallowed(:admin_group_saml) } + it { is_expected.to be_disallowed(:admin_saml_group_links) } end - it 'prevents access without a SAML session' do - is_expected.not_to be_allowed(:read_group) + context 'owner' do + let(:current_user) { owner } + + it { is_expected.to be_allowed(:admin_group_saml) } + it { is_expected.to be_disallowed(:admin_saml_group_links) } end - context 'as a group owner' do - before do - group.add_owner(current_user) + context 'admin' do + let(:current_user) { admin } + + it { is_expected.to be_allowed(:admin_group_saml) } + it { is_expected.to be_disallowed(:admin_saml_group_links) } + end + end + + context 'with an enabled SAML provider' do + let_it_be(:saml_provider) { create(:saml_provider, group: group, enabled: true) } + + context 'maintainer' do + let(:current_user) { maintainer } + + it { is_expected.to be_disallowed(:admin_saml_group_links) } + end + + context 'owner' do + let(:current_user) { owner } + + it { is_expected.to be_allowed(:admin_saml_group_links) } + end + + context 'admin' do + let(:current_user) { admin } + + it { is_expected.to be_allowed(:admin_saml_group_links) } + end + end + + context 'with sso enforcement enabled' do + let(:current_user) { guest } + + let_it_be(:saml_provider) { create(:saml_provider, group: group, enforced_sso: true) } + + context 'when the session has been set globally' do + around do |example| + Gitlab::Session.with_session({}) do + example.run + end end it 'prevents access without a SAML session' do - is_expected.not_to allow_action(:read_group) + is_expected.not_to be_allowed(:read_group) + end + + context 'as a group owner' do + before do + group.add_owner(current_user) + end + + it 'prevents access without a SAML session' do + is_expected.not_to allow_action(:read_group) + end end - end - it 'allows access with a SAML session' do - Gitlab::Auth::GroupSaml::SsoEnforcer.new(saml_provider).update_session + it 'allows access with a SAML session' do + Gitlab::Auth::GroupSaml::SsoEnforcer.new(saml_provider).update_session - is_expected.to be_allowed(:read_group) + is_expected.to be_allowed(:read_group) + end end - end - context 'when there is no global session or sso state' do - it "allows access because we haven't yet restricted all use cases" do - is_expected.to be_allowed(:read_group) + context 'when there is no global session or sso state' do + it "allows access because we haven't yet restricted all use cases" do + is_expected.to be_allowed(:read_group) + end end end end