Commit 47711f38 authored by Robert Speicher's avatar Robert Speicher Committed by Robert Speicher

Merge branch 'ldap-attributes' into 'master'

Allow configuration of LDAP attributes GitLab will use for the new user account.

Fixes #2412.

See merge request !1261
parent 7d59ba00
...@@ -56,6 +56,7 @@ v 7.14.3 ...@@ -56,6 +56,7 @@ v 7.14.3
v 7.14.2 v 7.14.2
- Upgrade gitlab_git to 7.2.15 to fix `git blame` errors with ISO-encoded files (Stan Hu) - Upgrade gitlab_git to 7.2.15 to fix `git blame` errors with ISO-encoded files (Stan Hu)
- Allow configuration of LDAP attributes GitLab will use for the new user account.
v 7.14.1 v 7.14.1
- Improve abuse reports management from admin area - Improve abuse reports management from admin area
......
...@@ -180,6 +180,26 @@ production: &base ...@@ -180,6 +180,26 @@ production: &base
# #
user_filter: '' user_filter: ''
# LDAP attributes that GitLab will use to create an account for the LDAP user.
# The specified attribute can either be the attribute name as a string (e.g. 'mail'),
# or an array of attribute names to try in order (e.g. ['mail', 'email']).
# Note that the user's LDAP login will always be the attribute specified as `uid` above.
attributes:
# The username will be used in paths for the user's own projects
# (like `gitlab.example.com/username/project`) and when mentioning
# them in issues, merge request and comments (like `@username`).
# If the attribute specified for `username` contains an email address,
# the GitLab username will be the part of the email address before the '@'.
username: ['uid', 'userid', 'sAMAccountName']
email: ['mail', 'email', 'userPrincipalName']
# If no full name could be found at the attribute specified for `name`,
# the full name is determined using the attributes specified for
# `first_name` and `last_name`.
name: 'cn'
first_name: 'givenName'
last_name: 'sn'
# GitLab EE only: add more LDAP servers # GitLab EE only: add more LDAP servers
# Choose an ID made of a-z and 0-9 . This ID will be stored in the database # Choose an ID made of a-z and 0-9 . This ID will be stored in the database
# so that GitLab can remember which LDAP server a user belongs to. # so that GitLab can remember which LDAP server a user belongs to.
......
...@@ -97,6 +97,7 @@ if Settings.ldap['enabled'] || Rails.env.test? ...@@ -97,6 +97,7 @@ if Settings.ldap['enabled'] || Rails.env.test?
server['block_auto_created_users'] = false if server['block_auto_created_users'].nil? server['block_auto_created_users'] = false if server['block_auto_created_users'].nil?
server['allow_username_or_email_login'] = false if server['allow_username_or_email_login'].nil? server['allow_username_or_email_login'] = false if server['allow_username_or_email_login'].nil?
server['active_directory'] = true if server['active_directory'].nil? server['active_directory'] = true if server['active_directory'].nil?
server['attributes'] = {} if server['attributes'].nil?
server['provider_name'] ||= "ldap#{key}".downcase server['provider_name'] ||= "ldap#{key}".downcase
server['provider_class'] = OmniAuth::Utils.camelize(server['provider_name']) server['provider_class'] = OmniAuth::Utils.camelize(server['provider_name'])
end end
......
...@@ -78,6 +78,26 @@ main: # 'main' is the GitLab 'provider ID' of this LDAP server ...@@ -78,6 +78,26 @@ main: # 'main' is the GitLab 'provider ID' of this LDAP server
# #
user_filter: '' user_filter: ''
# LDAP attributes that GitLab will use to create an account for the LDAP user.
# The specified attribute can either be the attribute name as a string (e.g. 'mail'),
# or an array of attribute names to try in order (e.g. ['mail', 'email']).
# Note that the user's LDAP login will always be the attribute specified as `uid` above.
attributes:
# The username will be used in paths for the user's own projects
# (like `gitlab.example.com/username/project`) and when mentioning
# them in issues, merge request and comments (like `@username`).
# If the attribute specified for `username` contains an email address,
# the GitLab username will be the part of the email address before the '@'.
username: ['uid', 'userid', 'sAMAccountName']
email: ['mail', 'email', 'userPrincipalName']
# If no full name could be found at the attribute specified for `name`,
# the full name is determined using the attributes specified for
# `first_name` and `last_name`.
name: 'cn'
first_name: 'givenName'
last_name: 'sn'
# GitLab EE only: add more LDAP servers # GitLab EE only: add more LDAP servers
# Choose an ID made of a-z and 0-9 . This ID will be stored in the database # Choose an ID made of a-z and 0-9 . This ID will be stored in the database
# so that GitLab can remember which LDAP server a user belongs to. # so that GitLab can remember which LDAP server a user belongs to.
......
# Class to parse and transform the info provided by omniauth
#
module Gitlab
module LDAP
class AuthHash < Gitlab::OAuth::AuthHash
private
def get_info(key)
attributes = ldap_config.attributes[key]
return super unless attributes
attributes = Array(attributes)
value = nil
attributes.each do |attribute|
value = get_raw(attribute)
break if value.present?
end
return super unless value
Gitlab::Utils.force_utf8(value)
value
end
def get_raw(key)
auth_hash.extra[:raw_info][key]
end
def ldap_config
@ldap_config ||= Gitlab::LDAP::Config.new(self.provider)
end
end
end
end
...@@ -84,6 +84,10 @@ module Gitlab ...@@ -84,6 +84,10 @@ module Gitlab
options['block_auto_created_users'] options['block_auto_created_users']
end end
def attributes
options['attributes']
end
protected protected
def base_config def base_config
Gitlab.config.ldap Gitlab.config.ldap
......
...@@ -71,6 +71,10 @@ module Gitlab ...@@ -71,6 +71,10 @@ module Gitlab
def ldap_config def ldap_config
Gitlab::LDAP::Config.new(auth_hash.provider) Gitlab::LDAP::Config.new(auth_hash.provider)
end end
def auth_hash=(auth_hash)
@auth_hash = Gitlab::LDAP::AuthHash.new(auth_hash)
end
end end
end end
end end
...@@ -16,16 +16,6 @@ module Gitlab ...@@ -16,16 +16,6 @@ module Gitlab
@provider ||= Gitlab::Utils.force_utf8(auth_hash.provider.to_s) @provider ||= Gitlab::Utils.force_utf8(auth_hash.provider.to_s)
end end
def info
auth_hash.info
end
def get_info(key)
value = info.try(key)
Gitlab::Utils.force_utf8(value) if value
value
end
def name def name
@name ||= get_info(:name) || "#{get_info(:first_name)} #{get_info(:last_name)}" @name ||= get_info(:name) || "#{get_info(:first_name)} #{get_info(:last_name)}"
end end
...@@ -44,9 +34,19 @@ module Gitlab ...@@ -44,9 +34,19 @@ module Gitlab
private private
def info
auth_hash.info
end
def get_info(key)
value = info[key]
Gitlab::Utils.force_utf8(value) if value
value
end
def username_and_email def username_and_email
@username_and_email ||= begin @username_and_email ||= begin
username = get_info(:nickname) || get_info(:username) username = get_info(:username) || get_info(:nickname)
email = get_info(:email) email = get_info(:email)
username ||= generate_username(email) if email username ||= generate_username(email) if email
......
require 'spec_helper'
describe Gitlab::LDAP::AuthHash do
let(:auth_hash) do
Gitlab::LDAP::AuthHash.new(
OmniAuth::AuthHash.new(
uid: '123456',
provider: 'ldapmain',
info: info,
extra: {
raw_info: raw_info
}
)
)
end
let(:info) do
{
name: 'Smith, J.',
email: 'johnsmith@example.com',
nickname: '123456'
}
end
let(:raw_info) do
{
uid: '123456',
email: 'johnsmith@example.com',
cn: 'Smith, J.',
fullName: 'John Smith'
}
end
context "without overridden attributes" do
it "has the correct username" do
expect(auth_hash.username).to eq("123456")
end
it "has the correct name" do
expect(auth_hash.name).to eq("Smith, J.")
end
end
context "with overridden attributes" do
let(:attributes) do
{
username: ['mail', 'email'],
name: 'fullName'
}
end
before do
allow_any_instance_of(Gitlab::LDAP::Config).to receive(:attributes).and_return(attributes)
end
it "has the correct username" do
expect(auth_hash.username).to eq("johnsmith@example.com")
end
it "has the correct name" do
expect(auth_hash.name).to eq("John Smith")
end
end
end
...@@ -11,7 +11,7 @@ describe Gitlab::LDAP::User do ...@@ -11,7 +11,7 @@ describe Gitlab::LDAP::User do
} }
end end
let(:auth_hash) do let(:auth_hash) do
double(uid: 'my-uid', provider: 'ldapmain', info: double(info)) OmniAuth::AuthHash.new(uid: 'my-uid', provider: 'ldapmain', info: info)
end end
describe :changed? do describe :changed? do
......
...@@ -3,11 +3,11 @@ require 'spec_helper' ...@@ -3,11 +3,11 @@ require 'spec_helper'
describe Gitlab::OAuth::AuthHash do describe Gitlab::OAuth::AuthHash do
let(:auth_hash) do let(:auth_hash) do
Gitlab::OAuth::AuthHash.new( Gitlab::OAuth::AuthHash.new(
double({ OmniAuth::AuthHash.new(
provider: provider_ascii, provider: provider_ascii,
uid: uid_ascii, uid: uid_ascii,
info: double(info_hash) info: info_hash
}) )
) )
end end
......
...@@ -5,7 +5,7 @@ describe Gitlab::OAuth::User do ...@@ -5,7 +5,7 @@ describe Gitlab::OAuth::User do
let(:gl_user) { oauth_user.gl_user } let(:gl_user) { oauth_user.gl_user }
let(:uid) { 'my-uid' } let(:uid) { 'my-uid' }
let(:provider) { 'my-provider' } let(:provider) { 'my-provider' }
let(:auth_hash) { double(uid: uid, provider: provider, info: double(info_hash)) } let(:auth_hash) { OmniAuth::AuthHash.new(uid: uid, provider: provider, info: info_hash) }
let(:info_hash) do let(:info_hash) do
{ {
nickname: '-john+gitlab-ETC%.git@gmail.com', nickname: '-john+gitlab-ETC%.git@gmail.com',
......
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