Incorrect email set when authenticating via LDAP
Summary
This is a corner case when a customer is using LDAP to authenticate but doesn't want the emails to come from LDAP.
A customer has set the email
attribute in the LDAP settings to an attribute that doesn't exist in LDAP, for example:
gitlab_rails['ldap_servers'] = {
'main' => {
...
'attributes' => {
'email' => ['email'],
},
...
}
}
The LDAP server does have data for one of the default email attributes, for example mail
. This isn't the email needed, but is just in the LDAP server.
When a user authenticates to GitLab, their email is replaced by the mail
data. This is not their actual email, and it's not the email configured.
This does not occur during LDAP user sync, only during user authentication to GitLab.
Found in customer ticket https://gitlab.zendesk.com/agent/tickets/167623 (internal use only)
When an LDAP user doesn't have
Steps to reproduce
- Setup a GitLab instance with authentication via LDAP
- In the LDAP configuration, set the
email
attribute to one that doesn't return data. - In your LDAP, there is an data for the
mail
attribute - Authenticate as a user, the email is replaced with data from the
mail
attribute.
I tested this on the GDK, and ran the following in the rails console for the user:
# define LDAP configuration with different email attribute than is available
ldap_config = Gitlab::Auth::Ldap::Config.new('ldapmain')
=> #<Gitlab::Auth::Ldap::Config:0x00007fc49c3d7558
@options=
{"label"=>"LDAP",
"host"=>"127.0.0.1",
"port"=>3891,
"uid"=>"uid",
"encryption"=>"plain",
"verify_certificates"=>true,
"tls_options"=>{"ca_file"=>"", "ssl_version"=>"", "ciphers"=>"", "cert"=>"", "key"=>""},
"timeout"=>10,
"allow_username_or_email_login"=>false,
"block_auto_created_users"=>false,
"base"=>"dc=example,dc=com",
"user_filter"=>"",
"attributes"=>{"username"=>["uid", "userid", "sAMAccountName"], "email"=>["email"], "name"=>"cn", "first_name"=>"givenName", "last_name"=>"sn"},
"lowercase_usernames"=>false,
"group_base"=>"ou=groups,dc=example,dc=com",
"smartcard_auth"=>false,
"active_directory"=>true,
"provider_name"=>"ldapmain",
"provider_class"=>"Ldapmain",
"external_groups"=>[]},
@provider="ldapmain">
# Define authentication filter on UID
filter = Net::LDAP::Filter.equals('uid', 'Mary')
=> #<Net::LDAP::Filter:0x00007fc49bf6db70 @left="uid", @op=:eq, @right="Mary">
# Connect to LDAP to authenticate
adaptor = OmniAuth::LDAP::Adaptor.new(ldap_config.omniauth_options)
=> #<OmniAuth::LDAP::Adaptor:0x00007fc4abaaf510
@allow_anonymous=false,
@auth={:method=>:anonymous, :username=>nil, :password=>nil},
@base="dc=example,dc=com",
@bind_dn=nil,
@bind_method=:anonymous,
@ca_file=nil,
@configuration=
{:host=>"127.0.0.1",
:port=>3891,
:base=>"dc=example,dc=com",
:encryption=>"plain",
:filter=>"(uid=%{username})",
:name_proc=>#<Proc:0x00007fc4abaaf588@/Users/blairlunceford/gdk/gitlab/lib/gitlab/auth/ldap/config.rb:173>,
:disable_verify_certificates=>false,
:tls_options=>nil,
:allow_anonymous=>false},
@connection=#<Net::LDAP:0x00007fc4abaaeb88 ...>,
@disable_verify_certificates=false,
@encryption="plain",
@filter="(uid=%{username})",
@host="127.0.0.1",
@hosts=nil,
@logger=nil,
@method=nil,
@password=nil,
@port=3891,
@sasl_mechanisms=nil,
@ssl_version=nil,
@tls_options=nil,
@try_sasl=nil,
@uid=nil>
# authenticate as example user to LDAP server and get auth hash back - with mail attribute in it
result = adaptor.bind_as(filter: filter, size: 1, password: 'password')
=> #<Net::LDAP::Entry:0x00007fc4abc24440
@myhash=
{:dn=>["uid=mary,ou=people,dc=example,dc=com"],
:objectclass=>["inetOrgPerson", "posixAccount", "shadowAccount"],
:uid=>["Mary"],
:sn=>["Jane"],
:givenname=>["Mary Jane"],
:cn=>["Mary Jane"],
:displayname=>["Mary Jane"],
:uidnumber=>["1001"],
:gidnumber=>["10001"],
:userpassword=>["{SSHA}qqLFjamdd1cru4RV815+FiSxh/54rfbd"],
:mail=>["mary.jane@example.com"],
:gecos=>["Mary"],
:loginshell=>["/bin/bash"],
:homedirectory=>["/home/mary"],
:shadowexpire=>["-1"],
:shadowflag=>["0"],
:shadowwarning=>["7"],
:shadowmin=>["8"],
:shadowmax=>["999999"],
:shadowlastchange=>["10877"],
:postalcode=>["31000"],
:l=>["Toulouse"],
:o=>["Example"],
:mobile=>["+33 (0)6 xx xx xx xx"],
:homephone=>["+33 (0)5 xx xx xx xx"],
:title=>["System Administrator"],
:postaladdress=>[""],
:initials=>["JD"]}>
# get user with information from LDAP
user = Gitlab::Auth::Ldap::User.find_by_uid_and_provider(result.dn, 'ldapmain')
=> #<User id:46 @Mary>
Example Project
Can't reproduce on GitLab as it's a self-managed specific LDAP error.
What is the current bug behavior?
Email is set to data from a field that is explicitly NOT set as the email.
What is the expected correct behavior?
Email should only be set to data from a field that is configured as an email.
Output of checks
Results of GitLab environment info
Expand for output related to GitLab environment info
System information System: Ubuntu 16.04 Proxy: no Current User: git Using RVM: no Ruby Version: 2.6.6p146 Gem Version: 2.7.10 Bundler Version:1.17.3 Rake Version: 12.3.3 Redis Version: 5.0.9 Git Version: 2.27.0 Sidekiq Version:5.2.7 Go Version: unknown GitLab information Version: 13.1.4-ee Revision: 66acdb3d3e9 Directory: /opt/gitlab/embedded/service/gitlab-rails DB Adapter: PostgreSQL DB Version: 11.7 URL: https://blunceford-omnibus-test.do.gitlap.com HTTP Clone URL: https://blunceford-omnibus-test.do.gitlap.com/some-group/some-project.git SSH Clone URL: git@blunceford-omnibus-test.do.gitlap.com:some-group/some-project.git Elasticsearch: yes Geo: no Using LDAP: yes Using Omniauth: yes Omniauth Providers: saml, google_oauth2, openid_connect GitLab Shell Version: 13.3.0 Repository storage paths: - default: /var/opt/gitlab/git-data/repositories GitLab Shell path: /opt/gitlab/embedded/service/gitlab-shell Git: /opt/gitlab/embedded/bin/git
Results of GitLab application Check
Expand for output related to the GitLab application check
Checking GitLab subtasks ...
Checking GitLab Shell ...
GitLab Shell: ... GitLab Shell version >= 13.3.0 ? ... OK (13.3.0) Running /opt/gitlab/embedded/service/gitlab-shell/bin/check Internal API available: OK Redis available via internal API: OK gitlab-shell self-check successful
Checking GitLab Shell ... Finished
Checking Gitaly ...
Gitaly: ... default ... OK
Checking Gitaly ... Finished
Checking Sidekiq ...
Sidekiq: ... Running? ... yes Number of Sidekiq processes ... 1
Checking Sidekiq ... Finished
Checking Incoming Email ...
Incoming Email: ... Reply by email is disabled in config/gitlab.yml
Checking Incoming Email ... Finished
Checking LDAP ...
LDAP: ... Server: ldapmain Deprecation warning: Net::LDAP::ConnectionRefused will be deprecated. Use Errno::ECONNREFUSED instead. Deprecation warning: Net::LDAP::ConnectionRefused will be deprecated. Use Errno::ECONNREFUSED instead. Could not connect to the LDAP server: Connection refused - connect(2) for 127.0.0.1:389
Checking LDAP ... Finished
Checking GitLab App ...
Git configured correctly? ... yes Database config exists? ... yes All migrations up? ... yes Database contains orphaned GroupMembers? ... no GitLab config exists? ... yes GitLab config up to date? ... yes Log directory writable? ... yes Tmp directory writable? ... yes Uploads directory exists? ... yes Uploads directory has correct permissions? ... yes Uploads directory tmp has correct permissions? ... yes Init script exists? ... skipped (omnibus-gitlab has no init script) Init script up-to-date? ... skipped (omnibus-gitlab has no init script) Projects have namespace: ... 34/1 ... yes 34/2 ... yes 34/3 ... yes 34/4 ... yes 34/5 ... yes 34/6 ... yes 34/7 ... yes 34/8 ... yes 34/9 ... yes 34/10 ... yes 35/11 ... yes 35/12 ... yes 35/13 ... yes 35/14 ... yes 35/15 ... yes 35/16 ... yes 35/17 ... yes 35/18 ... yes 35/19 ... yes 35/20 ... yes 36/21 ... yes 36/22 ... yes 36/23 ... yes 36/24 ... yes 36/25 ... yes 37/26 ... yes 37/27 ... yes 37/28 ... yes 37/29 ... yes 37/30 ... yes 37/31 ... yes 37/32 ... yes 38/33 ... yes 38/34 ... yes 38/35 ... yes 38/36 ... yes 38/37 ... yes 38/38 ... yes 38/39 ... yes 38/40 ... yes 39/41 ... yes 39/42 ... yes 39/43 ... yes 39/44 ... yes 39/45 ... yes 39/46 ... yes 40/47 ... yes 40/48 ... yes 40/49 ... yes 40/50 ... yes 40/51 ... yes 40/52 ... yes 40/53 ... yes 40/54 ... yes 40/55 ... yes 40/56 ... yes 41/57 ... yes 41/58 ... yes 41/59 ... yes 41/60 ... yes 41/61 ... yes 41/62 ... yes 41/63 ... yes 41/64 ... yes 41/65 ... yes 42/66 ... yes 42/67 ... yes 42/68 ... yes 42/69 ... yes 42/70 ... yes 42/71 ... yes 42/72 ... yes 43/73 ... yes 43/74 ... yes 43/75 ... yes 43/76 ... yes 43/77 ... yes 43/78 ... yes 43/79 ... yes 43/80 ... yes 43/81 ... yes 43/82 ... yes 44/83 ... yes 44/84 ... yes 44/85 ... yes 44/86 ... yes 44/87 ... yes 44/88 ... yes 44/89 ... yes 44/90 ... yes 44/91 ... yes 44/92 ... yes 45/93 ... yes 45/94 ... yes 45/95 ... yes 45/96 ... yes 45/97 ... yes 45/98 ... yes 46/99 ... yes 46/100 ... yes 46/101 ... yes 47/102 ... yes 47/103 ... yes 48/104 ... yes 48/105 ... yes 48/106 ... yes 48/107 ... yes 48/108 ... yes 48/109 ... yes 48/110 ... yes 48/111 ... yes 1/112 ... yes Redis version >= 4.0.0? ... yes Ruby version >= 2.5.3 ? ... yes (2.6.6) Git version >= 2.22.0 ? ... yes (2.27.0) Git user has default SSH configuration? ... yes Active users: ... 46 Is authorized keys file accessible? ... yes GitLab configured to store new projects in hashed storage? ... yes All projects are in hashed storage? ... yes Elasticsearch version 5.6 - 6.x? ... yes (7.7.1)
Checking GitLab App ... Finished
Checking GitLab subtasks ... Finished
Possible fixes
I'm not sure if the issue lies with the OmniAuth LDAP gem or with the LDAP authentication code in GitLab. This isn't an issue for the sync, just user authentication.