Commit 3f3ac780 authored by Thong Kuah's avatar Thong Kuah

Merge branch 'dblessing_sso_update_enterprise_users' into 'master'

Update user attributes for Group SAML enterprise users

See merge request gitlab-org/gitlab!72792
parents 883ad665 d1db69ca
...@@ -245,8 +245,9 @@ On subsequent visits, you should be able to go [sign in to GitLab.com with SAML] ...@@ -245,8 +245,9 @@ On subsequent visits, you should be able to go [sign in to GitLab.com with SAML]
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/263661) in GitLab 13.7. > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/263661) in GitLab 13.7.
GitLab allows setting certain user attributes based on values from the SAML response. GitLab allows setting certain user attributes based on values from the SAML response.
This affects users created on first sign-in via Group SAML. Existing users' Existing users will have these attributes updated if the user was originally
attributes are not affected regardless of the values sent in the SAML response. provisioned by the group. Users are provisioned by the group when the account was
created via [SCIM](scim_setup.md) or by first sign-in with SAML SSO for GitLab.com groups.
#### Supported user attributes #### Supported user attributes
......
...@@ -4,15 +4,22 @@ module Gitlab ...@@ -4,15 +4,22 @@ module Gitlab
module Auth module Auth
module GroupSaml module GroupSaml
class AuthHash < Gitlab::Auth::Saml::AuthHash class AuthHash < Gitlab::Auth::Saml::AuthHash
include Gitlab::Utils::StrongMemoize
ALLOWED_USER_ATTRIBUTES = %w(can_create_group projects_limit).freeze ALLOWED_USER_ATTRIBUTES = %w(can_create_group projects_limit).freeze
def groups def groups
Array.wrap(get_raw('groups') || get_raw('Groups')) Array.wrap(get_raw('groups') || get_raw('Groups'))
end end
ALLOWED_USER_ATTRIBUTES.each do |attribute| # Access user attributes by hash.
define_method(attribute) do #
Array(get_raw(attribute)).first # auth_hash.user_attributes['can_create_group']
def user_attributes
strong_memoize(:user_attributes) do
ALLOWED_USER_ATTRIBUTES.to_h do |attr|
[attr, Array(get_raw(attr)).first]
end
end end
end end
end end
......
...@@ -18,6 +18,7 @@ module Gitlab ...@@ -18,6 +18,7 @@ module Gitlab
override :find_and_update! override :find_and_update!
def find_and_update! def find_and_update!
add_or_update_user_identities add_or_update_user_identities
set_provisioned_user_attributes!(gl_user)
save("GroupSaml Provider ##{@saml_provider.id}") save("GroupSaml Provider ##{@saml_provider.id}")
# Do not return un-persisted user so user is prompted # Do not return un-persisted user so user is prompted
...@@ -61,14 +62,6 @@ module Gitlab ...@@ -61,14 +62,6 @@ module Gitlab
super.tap do |user| super.tap do |user|
user.provisioned_by_group_id = saml_provider.group_id user.provisioned_by_group_id = saml_provider.group_id
user.skip_confirmation_notification! user.skip_confirmation_notification!
# rubocop:disable GitlabSecurity/PublicSend
AuthHash::ALLOWED_USER_ATTRIBUTES.each do |attribute|
next unless value = auth_hash.public_send(attribute)
user.public_send("#{attribute}=", value)
end
# rubocop:enable GitlabSecurity/PublicSend
end end
end end
...@@ -99,6 +92,12 @@ module Gitlab ...@@ -99,6 +92,12 @@ module Gitlab
MembershipUpdater.new(gl_user, saml_provider, auth_hash).execute MembershipUpdater.new(gl_user, saml_provider, auth_hash).execute
end end
def set_provisioned_user_attributes!(user)
return unless user.provisioned_by_group_id == saml_provider.group_id
user.assign_attributes(auth_hash.user_attributes.compact)
end
override :block_after_signup? override :block_after_signup?
def block_after_signup? def block_after_signup?
false false
......
...@@ -41,11 +41,11 @@ RSpec.describe Gitlab::Auth::GroupSaml::AuthHash do ...@@ -41,11 +41,11 @@ RSpec.describe Gitlab::Auth::GroupSaml::AuthHash do
let(:raw_info_attr) { { 'can_create_group' => %w(true), 'projects_limit' => %w(20) } } let(:raw_info_attr) { { 'can_create_group' => %w(true), 'projects_limit' => %w(20) } }
it 'returns the proper can_create_groups value' do it 'returns the proper can_create_groups value' do
expect(saml_auth_hash.can_create_group).to eq "true" expect(saml_auth_hash.user_attributes['can_create_group']).to eq "true"
end end
it 'returns the proper projects_limit value' do it 'returns the proper projects_limit value' do
expect(saml_auth_hash.projects_limit).to eq "20" expect(saml_auth_hash.user_attributes['projects_limit']).to eq "20"
end end
end end
...@@ -53,11 +53,11 @@ RSpec.describe Gitlab::Auth::GroupSaml::AuthHash do ...@@ -53,11 +53,11 @@ RSpec.describe Gitlab::Auth::GroupSaml::AuthHash do
let(:raw_info_attr) { { 'can_create_group' => 'false', 'projects_limit' => '20' } } let(:raw_info_attr) { { 'can_create_group' => 'false', 'projects_limit' => '20' } }
it 'returns the proper can_create_groups value' do it 'returns the proper can_create_groups value' do
expect(saml_auth_hash.can_create_group).to eq "false" expect(saml_auth_hash.user_attributes['can_create_group']).to eq "false"
end end
it 'returns the proper projects_limit value' do it 'returns the proper projects_limit value' do
expect(saml_auth_hash.projects_limit).to eq "20" expect(saml_auth_hash.user_attributes['projects_limit']).to eq "20"
end end
end end
...@@ -65,11 +65,11 @@ RSpec.describe Gitlab::Auth::GroupSaml::AuthHash do ...@@ -65,11 +65,11 @@ RSpec.describe Gitlab::Auth::GroupSaml::AuthHash do
let(:raw_info_attr) { {} } let(:raw_info_attr) { {} }
it 'returns nil for can_create_group' do it 'returns nil for can_create_group' do
expect(saml_auth_hash.can_create_group).to eq nil expect(saml_auth_hash.user_attributes['can_create_group']).to eq nil
end end
it 'returns nil for can_create_groups' do it 'returns nil for can_create_groups' do
expect(saml_auth_hash.projects_limit).to eq nil expect(saml_auth_hash.user_attributes['projects_limit']).to eq nil
end end
end end
end end
......
...@@ -58,6 +58,25 @@ RSpec.describe Gitlab::Auth::GroupSaml::User do ...@@ -58,6 +58,25 @@ RSpec.describe Gitlab::Auth::GroupSaml::User do
expect(find_and_update.provisioned_by_group).to be_nil expect(find_and_update.provisioned_by_group).to be_nil
end end
context 'when user attributes are present but the user is not provisioned' do
before do
identity.user.update!(can_create_group: false, projects_limit: 10)
auth_hash[:extra][:raw_info] =
OneLogin::RubySaml::Attributes.new(
'can_create_group' => %w(true), 'projects_limit' => %w(20)
)
end
it 'does not update the user can_create_group attribute' do
expect(find_and_update.can_create_group).to eq(false)
end
it 'does not update the user projects_limit attribute' do
expect(find_and_update.projects_limit).to eq(10)
end
end
context 'when the user has multiple group saml identities' do context 'when the user has multiple group saml identities' do
let(:saml_provider2) { create(:saml_provider) } let(:saml_provider2) { create(:saml_provider) }
...@@ -140,10 +159,29 @@ RSpec.describe Gitlab::Auth::GroupSaml::User do ...@@ -140,10 +159,29 @@ RSpec.describe Gitlab::Auth::GroupSaml::User do
expect(find_and_update).to eq user expect(find_and_update).to eq user
end end
it 'updates idenitity' do it 'updates identity' do
expect { find_and_update }.to change { user.group_saml_identities.count }.by(1) expect { find_and_update }.to change { user.group_saml_identities.count }.by(1)
end end
context 'when user attributes are present' do
before do
user.update!(can_create_group: false, projects_limit: 10)
auth_hash[:extra][:raw_info] =
OneLogin::RubySaml::Attributes.new(
'can_create_group' => %w(true), 'projects_limit' => %w(20)
)
end
it 'updates the user with correct can_create_group attribute' do
expect(find_and_update.can_create_group).to eq(true)
end
it 'updates the user with correct projects_limit attribute' do
expect(find_and_update.projects_limit).to eq(20)
end
end
context 'without feature flag turned on' do context 'without feature flag turned on' do
before do before do
stub_feature_flags(block_password_auth_for_saml_users: false) stub_feature_flags(block_password_auth_for_saml_users: false)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment