diff options
author | Douwe Maan <douwe@gitlab.com> | 2015-06-05 13:34:25 +0200 |
---|---|---|
committer | Douwe Maan <douwe@gitlab.com> | 2015-06-05 13:34:25 +0200 |
commit | 3f59a8f0be101c2405372d05a304540beb1b6d01 (patch) | |
tree | 60db46574ab7f6c238ac8b0bd1a9ee5eee31628b | |
parent | 214f38c4223091ce37d41582feacae09120db5d9 (diff) | |
parent | 45e9150a517970d3782bed642b091ad60a46634f (diff) | |
download | gitlab-ce-3f59a8f0be101c2405372d05a304540beb1b6d01.tar.gz |
Merge branch 'cernvcs/gitlab-ce-feature/auto_link_ldap_omniauth'
-rw-r--r-- | CHANGELOG | 1 | ||||
-rw-r--r-- | config/gitlab.yml.example | 3 | ||||
-rw-r--r-- | config/initializers/1_settings.rb | 3 | ||||
-rw-r--r-- | lib/gitlab/o_auth/user.rb | 63 | ||||
-rw-r--r-- | spec/lib/gitlab/o_auth/user_spec.rb | 166 |
5 files changed, 221 insertions, 15 deletions
diff --git a/CHANGELOG b/CHANGELOG index 3df8e7ea516..08b879a2391 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -47,6 +47,7 @@ v 7.12.0 (unreleased) - When remove project - move repository and schedule it removal - Improve group removing logic - Trigger create-hooks on backup restore task + - Add option to automatically link omniauth and LDAP identities v 7.11.4 - Fix missing bullets when creating lists diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index c7f22b9388b..787b3ccfc56 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -192,6 +192,9 @@ production: &base allow_single_sign_on: false # Locks down those users until they have been cleared by the admin (default: true). block_auto_created_users: true + # Look up new users in LDAP servers. If a match is found (same uid), automatically + # link the omniauth identity with the LDAP account. (default: false) + auto_link_ldap_user: false ## Auth providers # Uncomment the following lines and fill in the data of the auth provider you want to use diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index c234bd69e9a..1bd14a3a89f 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -88,6 +88,9 @@ end Settings['omniauth'] ||= Settingslogic.new({}) Settings.omniauth['enabled'] = false if Settings.omniauth['enabled'].nil? Settings.omniauth['auto_sign_in_with_provider'] = false if Settings.omniauth['auto_sign_in_with_provider'].nil? +Settings.omniauth['allow_single_sign_on'] = false if Settings.omniauth['allow_single_sign_on'].nil? +Settings.omniauth['block_auto_created_users'] = true if Settings.omniauth['block_auto_created_users'].nil? +Settings.omniauth['auto_link_ldap_user'] = false if Settings.omniauth['auto_link_ldap_user'].nil? Settings.omniauth['providers'] ||= [] diff --git a/lib/gitlab/o_auth/user.rb b/lib/gitlab/o_auth/user.rb index ba5caed6131..c4971b5bcc6 100644 --- a/lib/gitlab/o_auth/user.rb +++ b/lib/gitlab/o_auth/user.rb @@ -46,6 +46,10 @@ module Gitlab def gl_user @user ||= find_by_uid_and_provider + if auto_link_ldap_user? + @user ||= find_or_create_ldap_user + end + if signup_enabled? @user ||= build_new_user end @@ -55,6 +59,46 @@ module Gitlab protected + def find_or_create_ldap_user + return unless ldap_person + + # If a corresponding person exists with same uid in a LDAP server, + # set up a Gitlab user with dual LDAP and Omniauth identities. + if user = Gitlab::LDAP::User.find_by_uid_and_provider(ldap_person.dn.downcase, ldap_person.provider) + # Case when a LDAP user already exists in Gitlab. Add the Omniauth identity to existing account. + user.identities.build(extern_uid: auth_hash.uid, provider: auth_hash.provider) + else + # No account in Gitlab yet: create it and add the LDAP identity + user = build_new_user + user.identities.new(provider: ldap_person.provider, extern_uid: ldap_person.dn) + end + + user + end + + def auto_link_ldap_user? + Gitlab.config.omniauth.auto_link_ldap_user + end + + def creating_linked_ldap_user? + auto_link_ldap_user? && ldap_person + end + + def ldap_person + return @ldap_person if defined?(@ldap_person) + + # looks for a corresponding person with same uid in any of the configured LDAP providers + @ldap_person = Gitlab::LDAP::Config.providers.find do |provider| + adapter = Gitlab::LDAP::Adapter.new(provider) + + Gitlab::LDAP::Person.find_by_uid(auth_hash.uid, adapter) + end + end + + def ldap_config + Gitlab::LDAP::Config.new(ldap_person.provider) if ldap_person + end + def needs_blocking? new? && block_after_signup? end @@ -64,7 +108,11 @@ module Gitlab end def block_after_signup? - Gitlab.config.omniauth.block_auto_created_users + if creating_linked_ldap_user? + ldap_config.block_auto_created_users + else + Gitlab.config.omniauth.block_auto_created_users + end end def auth_hash=(auth_hash) @@ -84,10 +132,19 @@ module Gitlab end def user_attributes + # Give preference to LDAP for sensitive information when creating a linked account + if creating_linked_ldap_user? + username = ldap_person.username + email = ldap_person.email.first + else + username = auth_hash.username + email = auth_hash.email + end + { name: auth_hash.name, - username: ::Namespace.clean_path(auth_hash.username), - email: auth_hash.email, + username: ::Namespace.clean_path(username), + email: email, password: auth_hash.password, password_confirmation: auth_hash.password, password_automatically_set: true diff --git a/spec/lib/gitlab/o_auth/user_spec.rb b/spec/lib/gitlab/o_auth/user_spec.rb index 44cdd1e4fab..2a982e8b107 100644 --- a/spec/lib/gitlab/o_auth/user_spec.rb +++ b/spec/lib/gitlab/o_auth/user_spec.rb @@ -13,6 +13,7 @@ describe Gitlab::OAuth::User do email: 'john@mail.com' } end + let(:ldap_user) { Gitlab::LDAP::Person.new(Net::LDAP::Entry.new, 'ldapmain') } describe :persisted? do let!(:existing_user) { create(:omniauth_user, extern_uid: 'my-uid', provider: 'my-provider') } @@ -32,31 +33,94 @@ describe Gitlab::OAuth::User do let(:provider) { 'twitter' } describe 'signup' do - context "with allow_single_sign_on enabled" do - before { Gitlab.config.omniauth.stub allow_single_sign_on: true } + shared_examples "to verify compliance with allow_single_sign_on" do + context "with allow_single_sign_on enabled" do + before { Gitlab.config.omniauth.stub allow_single_sign_on: true } - it "creates a user from Omniauth" do - oauth_user.save + it "creates a user from Omniauth" do + oauth_user.save - expect(gl_user).to be_valid - identity = gl_user.identities.first - expect(identity.extern_uid).to eql uid - expect(identity.provider).to eql 'twitter' + expect(gl_user).to be_valid + identity = gl_user.identities.first + expect(identity.extern_uid).to eql uid + expect(identity.provider).to eql 'twitter' + end + end + + context "with allow_single_sign_on disabled (Default)" do + before { Gitlab.config.omniauth.stub allow_single_sign_on: false } + it "throws an error" do + expect{ oauth_user.save }.to raise_error StandardError + end end end - context "with allow_single_sign_on disabled (Default)" do - it "throws an error" do - expect{ oauth_user.save }.to raise_error StandardError + context "with auto_link_ldap_user disabled (default)" do + before { Gitlab.config.omniauth.stub auto_link_ldap_user: false } + include_examples "to verify compliance with allow_single_sign_on" + end + + context "with auto_link_ldap_user enabled" do + before { Gitlab.config.omniauth.stub auto_link_ldap_user: true } + + context "and a corresponding LDAP person" do + before do + ldap_user.stub(:uid) { uid } + ldap_user.stub(:username) { uid } + ldap_user.stub(:email) { ['johndoe@example.com','john2@example.com'] } + ldap_user.stub(:dn) { 'uid=user1,ou=People,dc=example' } + allow(oauth_user).to receive(:ldap_person).and_return(ldap_user) + end + + context "and no account for the LDAP user" do + + it "creates a user with dual LDAP and omniauth identities" do + oauth_user.save + + expect(gl_user).to be_valid + expect(gl_user.username).to eql uid + expect(gl_user.email).to eql 'johndoe@example.com' + expect(gl_user.identities.length).to eql 2 + identities_as_hash = gl_user.identities.map { |id| { provider: id.provider, extern_uid: id.extern_uid } } + expect(identities_as_hash).to match_array( + [ { provider: 'ldapmain', extern_uid: 'uid=user1,ou=People,dc=example' }, + { provider: 'twitter', extern_uid: uid } + ]) + end + end + + context "and LDAP user has an account already" do + let!(:existing_user) { create(:omniauth_user, email: 'john@example.com', extern_uid: 'uid=user1,ou=People,dc=example', provider: 'ldapmain', username: 'john') } + it "adds the omniauth identity to the LDAP account" do + oauth_user.save + + expect(gl_user).to be_valid + expect(gl_user.username).to eql 'john' + expect(gl_user.email).to eql 'john@example.com' + expect(gl_user.identities.length).to eql 2 + identities_as_hash = gl_user.identities.map { |id| { provider: id.provider, extern_uid: id.extern_uid } } + expect(identities_as_hash).to match_array( + [ { provider: 'ldapmain', extern_uid: 'uid=user1,ou=People,dc=example' }, + { provider: 'twitter', extern_uid: uid } + ]) + end + end + end + + context "and no corresponding LDAP person" do + before { allow(oauth_user).to receive(:ldap_person).and_return(nil) } + + include_examples "to verify compliance with allow_single_sign_on" end end + end describe 'blocking' do let(:provider) { 'twitter' } before { Gitlab.config.omniauth.stub allow_single_sign_on: true } - context 'signup' do + context 'signup with omniauth only' do context 'dont block on create' do before { Gitlab.config.omniauth.stub block_auto_created_users: false } @@ -78,6 +142,64 @@ describe Gitlab::OAuth::User do end end + context 'signup with linked omniauth and LDAP account' do + before do + Gitlab.config.omniauth.stub auto_link_ldap_user: true + ldap_user.stub(:uid) { uid } + ldap_user.stub(:username) { uid } + ldap_user.stub(:email) { ['johndoe@example.com','john2@example.com'] } + ldap_user.stub(:dn) { 'uid=user1,ou=People,dc=example' } + allow(oauth_user).to receive(:ldap_person).and_return(ldap_user) + end + + context "and no account for the LDAP user" do + context 'dont block on create (LDAP)' do + before { Gitlab::LDAP::Config.any_instance.stub block_auto_created_users: false } + + it do + oauth_user.save + expect(gl_user).to be_valid + expect(gl_user).not_to be_blocked + end + end + + context 'block on create (LDAP)' do + before { Gitlab::LDAP::Config.any_instance.stub block_auto_created_users: true } + + it do + oauth_user.save + expect(gl_user).to be_valid + expect(gl_user).to be_blocked + end + end + end + + context 'and LDAP user has an account already' do + let!(:existing_user) { create(:omniauth_user, email: 'john@example.com', extern_uid: 'uid=user1,ou=People,dc=example', provider: 'ldapmain', username: 'john') } + + context 'dont block on create (LDAP)' do + before { Gitlab::LDAP::Config.any_instance.stub block_auto_created_users: false } + + it do + oauth_user.save + expect(gl_user).to be_valid + expect(gl_user).not_to be_blocked + end + end + + context 'block on create (LDAP)' do + before { Gitlab::LDAP::Config.any_instance.stub block_auto_created_users: true } + + it do + oauth_user.save + expect(gl_user).to be_valid + expect(gl_user).not_to be_blocked + end + end + end + end + + context 'sign-in' do before do oauth_user.save @@ -103,6 +225,26 @@ describe Gitlab::OAuth::User do expect(gl_user).not_to be_blocked end end + + context 'dont block on create (LDAP)' do + before { Gitlab::LDAP::Config.any_instance.stub block_auto_created_users: false } + + it do + oauth_user.save + expect(gl_user).to be_valid + expect(gl_user).not_to be_blocked + end + end + + context 'block on create (LDAP)' do + before { Gitlab::LDAP::Config.any_instance.stub block_auto_created_users: true } + + it do + oauth_user.save + expect(gl_user).to be_valid + expect(gl_user).not_to be_blocked + end + end end end end |