From 1ae26b6f28a603d0b1ebbc8dc36ccae6717bf977 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C5=82gorzata=20Ksionek?= <mksionek@gitlab.com> Date: Wed, 10 Mar 2021 19:22:05 +0100 Subject: [PATCH] Create session enforcer class for group saml to add to git check Refactor naming into more readable Add new database column Add specs and model method Add specs for group saml session enforcer class WIP on git access specs Refactor git access specs Add specs to git access Add new setting to view and form Add new setting to controller Add changelog entry Add translations file Refactor git access class Add method to find group Fix container method Add cr remarks Simplify spec example Change copy in saml sso form Add documentation regarding checking sso session on git activity Add cr remarks Reorganize code to make sso check more effective Add remarks to git check migration Add remarks about enforcing sso on Git activity docs Move check_additional_conditions method --- ...on-git-activity-and-direct-user-to-sso.yml | 5 + ...add_enforced_git_check_to_saml_provider.rb | 13 ++ db/schema_migrations/20210312174321 | 1 + db/structure.sql | 3 +- doc/user/group/saml_sso/index.md | 11 +- .../saml_providers/saml_settings_form.js | 5 + .../groups/saml_providers_controller.rb | 2 +- ee/app/models/saml_provider.rb | 12 ++ .../groups/saml_providers/_form.html.haml | 12 +- ee/lib/ee/gitlab/git_access.rb | 23 ++- .../auth/group_saml/session_enforcer.rb | 69 ++++++++ .../auth/group_saml/session_enforcer_spec.rb | 164 ++++++++++++++++++ ee/spec/lib/gitlab/git_access_spec.rb | 49 ++++++ ee/spec/models/saml_provider_spec.rb | 49 ++++++ lib/gitlab/git_access.rb | 5 + locale/gitlab.pot | 14 +- 16 files changed, 426 insertions(+), 11 deletions(-) create mode 100644 changelogs/unreleased/9152-check-sso-status-on-git-activity-and-direct-user-to-sso.yml create mode 100644 db/migrate/20210312174321_add_enforced_git_check_to_saml_provider.rb create mode 100644 db/schema_migrations/20210312174321 create mode 100644 ee/lib/gitlab/auth/group_saml/session_enforcer.rb create mode 100644 ee/spec/lib/gitlab/auth/group_saml/session_enforcer_spec.rb diff --git a/changelogs/unreleased/9152-check-sso-status-on-git-activity-and-direct-user-to-sso.yml b/changelogs/unreleased/9152-check-sso-status-on-git-activity-and-direct-user-to-sso.yml new file mode 100644 index 0000000000000..2b681363bfe17 --- /dev/null +++ b/changelogs/unreleased/9152-check-sso-status-on-git-activity-and-direct-user-to-sso.yml @@ -0,0 +1,5 @@ +--- +title: Group SAML - Check SSO status on Git activity +merge_request: 56867 +author: +type: added diff --git a/db/migrate/20210312174321_add_enforced_git_check_to_saml_provider.rb b/db/migrate/20210312174321_add_enforced_git_check_to_saml_provider.rb new file mode 100644 index 0000000000000..89553a53084a4 --- /dev/null +++ b/db/migrate/20210312174321_add_enforced_git_check_to_saml_provider.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class AddEnforcedGitCheckToSamlProvider < ActiveRecord::Migration[6.0] + DOWNTIME = false + + def up + add_column :saml_providers, :git_check_enforced, :boolean, default: false, null: false + end + + def down + remove_column :saml_providers, :git_check_enforced + end +end diff --git a/db/schema_migrations/20210312174321 b/db/schema_migrations/20210312174321 new file mode 100644 index 0000000000000..5126ab2675d1f --- /dev/null +++ b/db/schema_migrations/20210312174321 @@ -0,0 +1 @@ +4fa88193ae328f04465980210d9a43ce8cad978c157bda5e8ae9951538209268 \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 78f959a71f10f..0ad3a3aaeadb1 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -17270,7 +17270,8 @@ CREATE TABLE saml_providers ( enforced_sso boolean DEFAULT false NOT NULL, enforced_group_managed_accounts boolean DEFAULT false NOT NULL, prohibited_outer_forks boolean DEFAULT true NOT NULL, - default_membership_role smallint DEFAULT 10 NOT NULL + default_membership_role smallint DEFAULT 10 NOT NULL, + git_check_enforced boolean DEFAULT false NOT NULL ); CREATE SEQUENCE saml_providers_id_seq diff --git a/doc/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md index 6046258ee2970..6c3ffc4f6464d 100644 --- a/doc/user/group/saml_sso/index.md +++ b/doc/user/group/saml_sso/index.md @@ -95,6 +95,7 @@ Please note that the certificate [fingerprint algorithm](../../../integration/sa - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/9255) in GitLab 11.11 with ongoing enforcement in the GitLab UI. - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/292811) in GitLab 13.8, with an updated timeout experience. - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/211962) in GitLab 13.8 with allowing group owners to not go through SSO. +- [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/9152) in GitLab 13.11 with enforcing open SSO session to use Git if this setting is switched on. With this option enabled, users must go through your group's GitLab single sign-on URL. They may also be added via SCIM, if configured. Users can't be added manually, and may only access project/group resources via the UI by signing in through the SSO URL. @@ -102,9 +103,15 @@ However, users are not prompted to sign in through SSO on each visit. GitLab che has authenticated through SSO. If it's been more than 1 day since the last sign-in, GitLab prompts the user to sign in again through SSO. -We intend to add a similar SSO requirement for [Git and API activity](https://gitlab.com/gitlab-org/gitlab/-/issues/9152). +We intend to add a similar SSO requirement for [API activity](https://gitlab.com/gitlab-org/gitlab/-/issues/9152). -When SSO enforcement is enabled for a group, users can't share a project in the group outside the top-level group, even if the project is forked. +SSO has the following effects when enabled: + +- For groups, users can't share a project in the group outside the top-level group, + even if the project is forked. +- For a Git activity, users must be signed-in through SSO before they can push to or + pull from a GitLab repository. +<!-- Add bullet for API activity when https://gitlab.com/gitlab-org/gitlab/-/issues/9152 is complete --> ## Providers diff --git a/ee/app/assets/javascripts/saml_providers/saml_settings_form.js b/ee/app/assets/javascripts/saml_providers/saml_settings_form.js index 9bce0f7b674b7..f732a34f521cf 100644 --- a/ee/app/assets/javascripts/saml_providers/saml_settings_form.js +++ b/ee/app/assets/javascripts/saml_providers/saml_settings_form.js @@ -39,6 +39,11 @@ export default class SamlSettingsForm { el: this.form.querySelector('.js-group-saml-enforced-group-managed-accounts-toggle-area'), dependsOn: 'enforced-sso', }, + { + name: 'enforced-git-activity-check', + el: this.form.querySelector('.js-group-saml-enforced-git-check-toggle-area'), + dependsOn: 'enforced-sso', + }, { name: 'prohibited-outer-forks', el: this.form.querySelector('.js-group-saml-prohibited-outer-forks-toggle-area'), diff --git a/ee/app/controllers/groups/saml_providers_controller.rb b/ee/app/controllers/groups/saml_providers_controller.rb index 497cec1320966..63e9786c28ea7 100644 --- a/ee/app/controllers/groups/saml_providers_controller.rb +++ b/ee/app/controllers/groups/saml_providers_controller.rb @@ -47,7 +47,7 @@ def load_test_response end def saml_provider_params - allowed_params = %i[sso_url certificate_fingerprint enabled enforced_sso default_membership_role] + allowed_params = %i[sso_url certificate_fingerprint enabled enforced_sso default_membership_role git_check_enforced] if Feature.enabled?(:group_managed_accounts, group) allowed_params += [:enforced_group_managed_accounts, :prohibited_outer_forks] diff --git a/ee/app/models/saml_provider.rb b/ee/app/models/saml_provider.rb index 26fccaf61a997..86edd5c12f62f 100644 --- a/ee/app/models/saml_provider.rb +++ b/ee/app/models/saml_provider.rb @@ -10,6 +10,7 @@ class SamlProvider < ApplicationRecord validates :sso_url, presence: true, addressable_url: { schemes: %w(https), ascii_only: true } validates :certificate_fingerprint, presence: true, certificate_fingerprint: true validates :default_membership_role, presence: true + validate :git_check_enforced_allowed validate :access_level_inclusion after_initialize :set_defaults, if: :new_record? @@ -35,6 +36,10 @@ def enforced_sso? enabled? && super && group.feature_available?(:group_saml) end + def git_check_enforced? + super && enforced_sso? + end + def enforced_group_managed_accounts? super && enforced_sso? && Feature.enabled?(:group_managed_accounts, group) end @@ -92,6 +97,13 @@ def access_level_inclusion errors.add(:default_membership_role, "is not included in the list") end + def git_check_enforced_allowed + return unless git_check_enforced + return if enforced_sso? + + errors.add(:git_check_enforced, "is not allowed when SSO is not enforced.") + end + def set_defaults self.enabled = true end diff --git a/ee/app/views/groups/saml_providers/_form.html.haml b/ee/app/views/groups/saml_providers/_form.html.haml index 263956fbce63b..3a7eb6e2cbed0 100644 --- a/ee/app/views/groups/saml_providers/_form.html.haml +++ b/ee/app/views/groups/saml_providers/_form.html.haml @@ -10,10 +10,18 @@ %label.gl-mt-2.mb-0.js-group-saml-enforced-sso-toggle-area = render "shared/buttons/project_feature_toggle", is_checked: saml_provider.enforced_sso, disabled: !saml_provider.enabled?, label: s_("GroupSAML|Enforced SSO"), class_list: "js-project-feature-toggle js-group-saml-enforced-sso-toggle project-feature-toggle d-inline", data: { qa_selector: 'enforced_sso_toggle_button' } do = f.hidden_field :enforced_sso, { class: 'js-group-saml-enforced-sso-input js-project-feature-toggle-input'} - %span.form-text.d-inline.font-weight-normal.align-text-bottom.ml-3= s_('GroupSAML|Enforce SSO-only authentication for this group.') + %span.form-text.d-inline.font-weight-normal.align-text-bottom.ml-3= s_('GroupSAML|Enforce SSO-only authentication for web activity for this group.') .form-text.text-muted.js-helper-text{ style: "display: #{'none' if saml_provider.enabled?} #{'block' unless saml_provider.enabled?}" } %span - = s_('GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication.') + = s_('GroupSAML|Before enforcing SSO, enable SAML authentication.') + .form-group + %label.gl-mt-2.mb-0.js-group-saml-enforced-git-check-toggle-area + = render "shared/buttons/project_feature_toggle", is_checked: saml_provider.git_check_enforced, disabled: !saml_provider.enabled?, label: s_("GroupSAML|Check SSO on git activity"), class_list: "js-project-feature-toggle js-group-saml-enforced-git-check-toggle-area project-feature-toggle d-inline", data: { qa_selector: 'git_activity_check_toggle_button' } do + = f.hidden_field :git_check_enforced, { class: 'js-group-enforced-git-check-input js-project-feature-toggle-input'} + %span.form-text.d-inline.font-weight-normal.align-text-bottom.ml-3= s_('GroupSAML|Enforce SSO-access for Git in this group.') + .form-text.text-muted.js-helper-text{ style: "display: #{saml_provider.enabled? ? 'none' : 'block'}" } + %span + = s_('GroupSAML|Before enforcing SSO, enable SAML authentication.') - if Feature.enabled?(:group_managed_accounts, group) .form-group %label.gl-mt-2.mb-0.js-group-saml-enforced-group-managed-accounts-toggle-area diff --git a/ee/lib/ee/gitlab/git_access.rb b/ee/lib/ee/gitlab/git_access.rb index 25c9fc47b6c07..708661ccfaa0d 100644 --- a/ee/lib/ee/gitlab/git_access.rb +++ b/ee/lib/ee/gitlab/git_access.rb @@ -83,6 +83,13 @@ def check_active_user! super end + override :check_additional_conditions! + def check_additional_conditions! + check_sso_session! + + super + end + def check_geo_license! if ::Gitlab::Geo.secondary? && !::Gitlab::Geo.license_allows? raise ::Gitlab::GitAccess::ForbiddenError, 'Your current license does not have GitLab Geo add-on enabled.' @@ -104,12 +111,21 @@ def check_otp_session! if ::Gitlab::Auth::Otp::SessionEnforcer.new(actor).access_restricted? message = "OTP verification is required to access the repository.\n\n"\ - " Use: #{build_ssh_otp_verify_command}" + " Use: #{build_ssh_otp_verify_command}" raise ::Gitlab::GitAccess::ForbiddenError, message end end + def check_sso_session! + return true unless user && container + + return unless ::Gitlab::Auth::GroupSaml::SessionEnforcer.new(user, containing_group).access_restricted? + + group_saml_url = Rails.application.routes.url_helpers.sso_group_saml_providers_url(containing_group, token: containing_group.saml_discovery_token) + raise ::Gitlab::GitAccess::ForbiddenError, "Cannot find valid SSO session. Please login via your group's SSO at #{group_saml_url}" + end + def build_ssh_otp_verify_command user = "#{::Gitlab.config.gitlab_shell.ssh_user}@" unless ::Gitlab.config.gitlab_shell.ssh_user.empty? user_host = "#{user}#{::Gitlab.config.gitlab_shell.ssh_host}" @@ -155,6 +171,11 @@ def check_size_limit? size_checker.enabled? && super end end + + def containing_group + return group if group? + return project.group if project? + end end end end diff --git a/ee/lib/gitlab/auth/group_saml/session_enforcer.rb b/ee/lib/gitlab/auth/group_saml/session_enforcer.rb new file mode 100644 index 0000000000000..e3f44e3c4671a --- /dev/null +++ b/ee/lib/gitlab/auth/group_saml/session_enforcer.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +module Gitlab + module Auth + module GroupSaml + class SessionEnforcer + SESSION_STORE_KEY = :active_group_sso_sign_ins + + def initialize(user, group) + @user = user + @group = group + end + + def access_restricted? + return false if skip_check? + + latest_sign_in = find_session + + return true unless latest_sign_in + return SsoEnforcer::DEFAULT_SESSION_TIMEOUT.ago > latest_sign_in if ::Feature.enabled?(:enforced_sso_expiry, group) + + false + end + + private + + attr_reader :user, :group + + def skip_check? + return true if no_group_or_provider? + return true if user_allowed? + return true unless git_check_enforced? + + false + end + + def no_group_or_provider? + return true unless group + return true unless group.root_ancestor + return true unless saml_provider + + false + end + + def saml_provider + @saml_provider ||= group.root_ancestor.saml_provider + end + + def git_check_enforced? + saml_provider.git_check_enforced? + end + + def user_allowed? + return true if user.auditor? || user.can_read_all_resources? + return true if group.owned_by?(user) + + false + end + + def find_session + sessions = ActiveSession.list_sessions(user) + sessions.filter_map do |session| + Gitlab::NamespacedSessionStore.new(SESSION_STORE_KEY, session.with_indifferent_access)[saml_provider.id] + end.last + end + end + end + end +end diff --git a/ee/spec/lib/gitlab/auth/group_saml/session_enforcer_spec.rb b/ee/spec/lib/gitlab/auth/group_saml/session_enforcer_spec.rb new file mode 100644 index 0000000000000..af7fa279e4bb6 --- /dev/null +++ b/ee/spec/lib/gitlab/auth/group_saml/session_enforcer_spec.rb @@ -0,0 +1,164 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Auth::GroupSaml::SessionEnforcer do + describe '#access_restricted' do + let_it_be(:saml_provider) { create(:saml_provider, enforced_sso: true) } + let_it_be(:user) { create(:user) } + let_it_be(:identity) { create(:group_saml_identity, saml_provider: saml_provider, user: user) } + + let(:root_group) { saml_provider.group } + + subject { described_class.new(user, root_group).access_restricted? } + + before do + stub_licensed_features(group_saml: true) + end + + context 'when git check is enforced' do + before do + allow(saml_provider).to receive(:git_check_enforced?).and_return(true) + end + + context 'with an active session', :clean_gitlab_redis_shared_state do + let(:session_id) { '42' } + let(:session_time) { 5.minutes.ago } + let(:stored_session) do + { 'active_group_sso_sign_ins' => { saml_provider.id => session_time } } + end + + before do + Gitlab::Redis::SharedState.with do |redis| + redis.set("session:gitlab:#{session_id}", Marshal.dump(stored_session)) + redis.sadd("session:lookup:user:gitlab:#{user.id}", [session_id]) + end + end + + it { is_expected.to be_falsey } + + context 'with sub-group' do + let(:group) { create(:group, parent: root_group) } + + subject { described_class.new(user, group).access_restricted? } + + it { is_expected.to be_falsey } + end + + context 'with expired session' do + let(:session_time) { 2.days.ago } + + it { is_expected.to be_truthy } + end + + context 'with two active sessions', :clean_gitlab_redis_shared_state do + let(:second_session_id) { '52' } + let(:second_stored_session) do + { 'active_group_sso_sign_ins' => { create(:saml_provider, enforced_sso: true).id => session_time } } + end + + before do + Gitlab::Redis::SharedState.with do |redis| + redis.set("session:gitlab:#{second_session_id}", Marshal.dump(second_stored_session)) + redis.sadd("session:lookup:user:gitlab:#{user.id}", [session_id, second_session_id]) + end + end + + it { is_expected.to be_falsey } + end + + context 'without enforced_sso_expiry feature flag' do + let(:session_time) { 2.days.ago } + + before do + stub_feature_flags(enforced_sso_expiry: false) + end + + it { is_expected.to be_falsey } + end + + context 'without group' do + let(:root_group) { nil } + + it { is_expected.to be_falsey } + end + + context 'without saml_provider' do + let(:root_group) { create(:group) } + + it { is_expected.to be_falsey } + end + + context 'with admin', :enable_admin_mode do + let(:user) { create(:user, :admin) } + + it { is_expected.to be_falsey } + end + + context 'with auditor' do + let(:user) { create(:user, :auditor) } + + it { is_expected.to be_falsey } + end + + context 'with group owner' do + before do + root_group.add_owner(user) + end + + it { is_expected.to be_falsey } + end + end + + context 'without any session' do + it { is_expected.to be_truthy } + + context 'with admin', :enable_admin_mode do + let(:user) { create(:user, :admin) } + + it { is_expected.to be_falsey } + end + + context 'with auditor' do + let(:user) { create(:user, :auditor) } + + it { is_expected.to be_falsey } + end + + context 'with group owner' do + before do + root_group.add_owner(user) + end + + it { is_expected.to be_falsey } + end + end + end + + context 'when git check is not enforced' do + before do + allow(saml_provider).to receive(:git_check_enforced?).and_return(false) + end + + context 'with an active session', :clean_gitlab_redis_shared_state do + let(:session_id) { '42' } + let(:stored_session) do + { 'active_group_sso_sign_ins' => { saml_provider.id => 5.minutes.ago } } + end + + before do + Gitlab::Redis::SharedState.with do |redis| + redis.set("session:gitlab:#{session_id}", Marshal.dump(stored_session)) + redis.sadd("session:lookup:user:gitlab:#{user.id}", [session_id]) + end + end + + it { is_expected.to be_falsey } + end + + context 'without any session' do + it { is_expected.to be_falsey } + end + end + end +end diff --git a/ee/spec/lib/gitlab/git_access_spec.rb b/ee/spec/lib/gitlab/git_access_spec.rb index 0ee484696fc08..bb22c56d6dc4f 100644 --- a/ee/spec/lib/gitlab/git_access_spec.rb +++ b/ee/spec/lib/gitlab/git_access_spec.rb @@ -915,6 +915,55 @@ def stub_redis end end + describe '#check_sso_session!' do + before do + project.add_developer(user) + end + + context 'with project without group' do + it 'allows pull and push changes' do + expect(Gitlab::Auth::GroupSaml::SessionEnforcer).to receive(:new).with(user, nil).and_return(double(access_restricted?: false)) + pull_changes + end + end + + context 'with project with group' do + let_it_be(:group) { create(:group) } + + before do + project.update!(namespace: group) + end + + context 'user with a sso session' do + let(:access_restricted?) { false } + + it 'allows pull and push changes' do + expect(Gitlab::Auth::GroupSaml::SessionEnforcer).to receive(:new).with(user, group).twice.and_return(double(access_restricted?: access_restricted?)) + + expect { pull_changes }.not_to raise_error + expect { push_changes }.not_to raise_error + end + end + + context 'user without a sso session' do + let(:access_restricted?) { true } + + before do + expect(Gitlab::Auth::GroupSaml::SessionEnforcer).to receive(:new).with(user, group).twice.and_return(double(access_restricted?: access_restricted?)) + end + + it 'does not allow pull or push changes with proper url in the message' do + aggregate_failures do + address = "http://localhost/groups/#{group.name}/-/saml/sso" + + expect { pull_changes }.to raise_error(Gitlab::GitAccess::ForbiddenError, /#{Regexp.quote(address)}/) + expect { push_changes }.to raise_error(Gitlab::GitAccess::ForbiddenError, /#{Regexp.quote(address)}/) + end + end + end + end + end + describe '#check_maintenance_mode!' do let(:changes) { Gitlab::GitAccess::ANY } diff --git a/ee/spec/models/saml_provider_spec.rb b/ee/spec/models/saml_provider_spec.rb index a52adc30bfa9a..ea8224ac3a6ba 100644 --- a/ee/spec/models/saml_provider_spec.rb +++ b/ee/spec/models/saml_provider_spec.rb @@ -98,6 +98,27 @@ end end end + + describe 'git_check_enforced' do + let_it_be(:group) { create(:group) } + + context 'sso is enforced' do + it 'git_check_enforced is valid' do + expect(build(:saml_provider, group: group, enabled: true, enforced_sso: true, git_check_enforced: true)).to be_valid + expect(build(:saml_provider, group: group, enabled: true, enforced_sso: true, git_check_enforced: false)).to be_valid + end + end + + context 'sso is not enforced' do + it 'git_check_enforced is invalid when set to true' do + expect(build(:saml_provider, group: group, enabled: true, enforced_sso: false, git_check_enforced: true)).to be_invalid + end + + it 'git_check_enforced is valid when set to false' do + expect(build(:saml_provider, group: group, enabled: true, enforced_sso: false, git_check_enforced: false)).to be_valid + end + end + end end describe 'Default values' do @@ -216,6 +237,34 @@ end end + describe '#git_check_enforced?' do + context 'without enforced sso' do + before do + allow(subject).to receive(:enforced_sso?).and_return(false) + end + + it 'does not enforce git activity check' do + subject.git_check_enforced = true + expect(subject).not_to be_git_check_enforced + subject.git_check_enforced = false + expect(subject).not_to be_git_check_enforced + end + end + + context 'with enforced sso' do + before do + allow(subject).to receive(:enforced_sso?).and_return(true) + end + + it 'enforces git activity check when attribute is set to true' do + subject.git_check_enforced = true + expect(subject).to be_git_check_enforced + subject.git_check_enforced = false + expect(subject).not_to be_git_check_enforced + end + end + end + describe '#prohibited_outer_forks?' do context 'without enforced GMA' do it 'is false when prohibited_outer_forks flag value is true' do diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb index c5ca46827cbd9..31e4755192ee3 100644 --- a/lib/gitlab/git_access.rb +++ b/lib/gitlab/git_access.rb @@ -91,6 +91,7 @@ def check(cmd, changes) when *PUSH_COMMANDS check_push_access! end + check_additional_conditions! success_result end @@ -530,6 +531,10 @@ def check_size_limit? def size_checker container.repository_size_checker end + + # overriden in EE + def check_additional_conditions! + end end end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index ce9dadc16e8e6..16eb1e80911e0 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -14851,9 +14851,15 @@ msgstr "" msgid "GroupSAML|Are you sure you want to remove the SAML group link?" msgstr "" +msgid "GroupSAML|Before enforcing SSO, enable SAML authentication." +msgstr "" + msgid "GroupSAML|Certificate fingerprint" msgstr "" +msgid "GroupSAML|Check SSO on git activity" +msgstr "" + msgid "GroupSAML|Configuration" msgstr "" @@ -14869,7 +14875,10 @@ msgstr "" msgid "GroupSAML|Enable SAML authentication for this group." msgstr "" -msgid "GroupSAML|Enforce SSO-only authentication for this group." +msgid "GroupSAML|Enforce SSO-access for Git in this group." +msgstr "" + +msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group." msgstr "" msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group." @@ -14965,9 +14974,6 @@ msgstr "" msgid "GroupSAML|This will be set as the access level of users added to the group." msgstr "" -msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication." -msgstr "" - msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO." msgstr "" -- GitLab