Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
a8298021
Commit
a8298021
authored
May 18, 2018
by
Rémy Coutable
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Extract EE-specific lines to EE::Gitlab::Auth::LDAP::Access
Signed-off-by:
Rémy Coutable
<
remy@rymai.me
>
parent
a9f0b56c
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
390 additions
and
379 deletions
+390
-379
ee/lib/ee/gitlab/auth/ldap/access.rb
ee/lib/ee/gitlab/auth/ldap/access.rb
+122
-0
ee/spec/lib/gitlab/auth/ldap/access_spec.rb
ee/spec/lib/gitlab/auth/ldap/access_spec.rb
+261
-0
lib/gitlab/auth/ldap/access.rb
lib/gitlab/auth/ldap/access.rb
+7
-111
spec/lib/gitlab/auth/ldap/access_spec.rb
spec/lib/gitlab/auth/ldap/access_spec.rb
+0
-268
No files found.
ee/lib/ee/gitlab/auth/ldap/access.rb
0 → 100644
View file @
a8298021
module
EE
module
Gitlab
module
Auth
module
LDAP
module
Access
extend
ActiveSupport
::
Concern
extend
::
Gitlab
::
Utils
::
Override
override
:find_ldap_user
def
find_ldap_user
found_user
=
super
return
found_user
if
found_user
if
ldap_identity
::
Gitlab
::
Auth
::
LDAP
::
Person
.
find_by_email
(
user
.
email
,
adapter
)
end
end
override
:update_user
def
update_user
update_email
update_memberships
update_identity
update_ssh_keys
if
sync_ssh_keys?
update_kerberos_identity
if
import_kerberos_identities?
end
# Update user ssh keys if they changed in LDAP
def
update_ssh_keys
remove_old_ssh_keys
add_new_ssh_keys
end
# Add ssh keys that are in LDAP but not in GitLab
def
add_new_ssh_keys
keys
=
ldap_user
.
ssh_keys
-
user
.
keys
.
ldap
.
pluck
(
:key
)
keys
.
each
do
|
key
|
::
Rails
.
logger
.
info
"
#{
self
.
class
.
name
}
: adding LDAP SSH key
#{
key
.
inspect
}
to
#{
user
.
name
}
(
#{
user
.
id
}
)"
new_key
=
::
LDAPKey
.
new
(
title:
"LDAP -
#{
ldap_config
.
sync_ssh_keys
}
"
,
key:
key
)
new_key
.
user
=
user
unless
new_key
.
save
::
Rails
.
logger
.
error
"
#{
self
.
class
.
name
}
: failed to add LDAP SSH key
#{
key
.
inspect
}
to
#{
user
.
name
}
(
#{
user
.
id
}
)
\n
"
\
"error messages:
#{
new_key
.
errors
.
messages
}
"
end
end
end
# Remove ssh keys that do not exist in LDAP any more
def
remove_old_ssh_keys
keys
=
user
.
keys
.
ldap
.
where
.
not
(
key:
ldap_user
.
ssh_keys
)
keys
.
each
do
|
deleted_key
|
::
Rails
.
logger
.
info
"
#{
self
.
class
.
name
}
: removing LDAP SSH key
#{
deleted_key
.
key
}
from
#{
user
.
name
}
(
#{
user
.
id
}
)"
unless
deleted_key
.
destroy
::
Rails
.
logger
.
error
"
#{
self
.
class
.
name
}
: failed to remove LDAP SSH key
#{
key
.
inspect
}
from
#{
user
.
name
}
(
#{
user
.
id
}
)"
end
end
end
# Update user Kerberos identity with Kerberos principal name from Active Directory
def
update_kerberos_identity
# there can be only one Kerberos identity in GitLab; if the user has a Kerberos identity in AD,
# replace any existing Kerberos identity for the user
return
unless
ldap_user
.
kerberos_principal
.
present?
kerberos_identity
=
user
.
identities
.
where
(
provider: :kerberos
).
first
return
if
kerberos_identity
&&
kerberos_identity
.
extern_uid
==
ldap_user
.
kerberos_principal
kerberos_identity
||=
::
Identity
.
new
(
provider: :kerberos
,
user:
user
)
kerberos_identity
.
extern_uid
=
ldap_user
.
kerberos_principal
unless
kerberos_identity
.
save
::
Rails
.
logger
.
error
"
#{
self
.
class
.
name
}
: failed to add Kerberos principal
#{
principal
}
to
#{
user
.
name
}
(
#{
user
.
id
}
)
\n
"
\
"error messages:
#{
new_identity
.
errors
.
messages
}
"
end
end
# Update user email if it changed in LDAP
def
update_email
return
false
unless
ldap_user
.
try
(
:email
)
ldap_email
=
ldap_user
.
email
.
last
.
to_s
.
downcase
return
false
if
user
.
email
==
ldap_email
::
Users
::
UpdateService
.
new
(
user
,
user:
user
,
email:
ldap_email
).
execute
do
|
user
|
user
.
skip_reconfirmation!
end
end
def
update_identity
return
if
ldap_user
.
dn
.
empty?
||
ldap_user
.
dn
==
ldap_identity
.
extern_uid
unless
ldap_identity
.
update
(
extern_uid:
ldap_user
.
dn
)
::
Rails
.
logger
.
error
"Could not update DN for
#{
user
.
name
}
(
#{
user
.
id
}
)
\n
"
\
"error messages:
#{
user
.
ldap_identity
.
errors
.
messages
}
"
end
end
delegate
:sync_ssh_keys?
,
to: :ldap_config
def
import_kerberos_identities?
# Kerberos may be enabled for Git HTTP access and/or as an Omniauth provider
ldap_config
.
active_directory
&&
(
::
Gitlab
.
config
.
kerberos
.
enabled
||
::
AuthHelper
.
kerberos_enabled?
)
end
def
update_memberships
return
if
ldap_user
.
nil?
||
ldap_user
.
group_cns
.
empty?
group_ids
=
::
LdapGroupLink
.
where
(
cn:
ldap_user
.
group_cns
,
provider:
provider
)
.
distinct
(
:group_id
)
.
pluck
(
:group_id
)
::
LdapGroupSyncWorker
.
perform_async
(
group_ids
,
provider
)
if
group_ids
.
any?
end
end
end
end
end
end
ee/spec/lib/gitlab/auth/ldap/access_spec.rb
0 → 100644
View file @
a8298021
require
'spec_helper'
describe
Gitlab
::
Auth
::
LDAP
::
Access
do
include
LdapHelpers
let
(
:access
)
{
described_class
.
new
user
}
let
(
:user
)
{
create
(
:omniauth_user
)
}
describe
'#find_ldap_user'
do
it
'finds a user by email if the email came from LDAP'
do
expect
(
Gitlab
::
Auth
::
LDAP
::
Person
).
to
receive
(
:find_by_dn
).
and_return
(
nil
)
expect
(
Gitlab
::
Auth
::
LDAP
::
Person
).
to
receive
(
:find_by_email
)
access
.
find_ldap_user
end
end
describe
'#allowed?'
do
subject
{
access
.
allowed?
}
context
'when the user cannot be found'
do
before
do
allow
(
Gitlab
::
Auth
::
LDAP
::
Person
).
to
receive
(
:find_by_dn
).
and_return
(
nil
)
allow
(
Gitlab
::
Auth
::
LDAP
::
Person
).
to
receive
(
:find_by_email
).
and_return
(
nil
)
end
context
'when looking for a user by email'
do
let
(
:user
)
{
create
(
:omniauth_user
,
extern_uid:
'my-uid'
,
provider:
'my-provider'
)
}
it
{
is_expected
.
to
be_falsey
}
end
end
end
describe
'#update_user'
do
subject
{
access
.
update_user
}
let
(
:entry
)
do
Net
::
LDAP
::
Entry
.
from_single_ldif_string
(
"dn: cn=foo, dc=bar, dc=com"
)
end
before
do
allow
(
access
).
to
(
receive_messages
(
ldap_user:
Gitlab
::
Auth
::
LDAP
::
Person
.
new
(
entry
,
user
.
ldap_identity
.
provider
)
)
)
end
it
'updates email address'
do
expect
(
access
).
to
receive
(
:update_email
).
once
subject
end
it
'updates the group memberships'
do
expect
(
access
).
to
receive
(
:update_memberships
).
once
subject
end
it
'syncs ssh keys if enabled by configuration'
do
allow
(
access
).
to
receive_messages
(
group_base:
''
,
sync_ssh_keys?:
true
)
expect
(
access
).
to
receive
(
:update_ssh_keys
).
once
subject
end
it
'update_kerberos_identity'
do
allow
(
access
).
to
receive_messages
(
import_kerberos_identities?:
true
)
expect
(
access
).
to
receive
(
:update_kerberos_identity
).
once
subject
end
it
'updates the ldap identity'
do
expect
(
access
).
to
receive
(
:update_identity
)
subject
end
end
describe
'#update_kerberos_identity'
do
let
(
:entry
)
do
Net
::
LDAP
::
Entry
.
from_single_ldif_string
(
"dn: cn=foo, dc=bar, dc=com"
)
end
before
do
allow
(
access
).
to
receive_messages
(
ldap_user:
Gitlab
::
Auth
::
LDAP
::
Person
.
new
(
entry
,
user
.
ldap_identity
.
provider
))
end
it
"adds a Kerberos identity if it is in Active Directory but not in GitLab"
do
allow_any_instance_of
(
EE
::
Gitlab
::
Auth
::
LDAP
::
Person
).
to
receive_messages
(
kerberos_principal:
"mylogin@FOO.COM"
)
expect
{
access
.
update_kerberos_identity
}.
to
change
(
user
.
identities
.
where
(
provider: :kerberos
),
:count
).
from
(
0
).
to
(
1
)
expect
(
user
.
identities
.
where
(
provider:
"kerberos"
).
last
.
extern_uid
).
to
eq
(
"mylogin@FOO.COM"
)
end
it
"updates existing Kerberos identity in GitLab if Active Directory has a different one"
do
allow_any_instance_of
(
EE
::
Gitlab
::
Auth
::
LDAP
::
Person
).
to
receive_messages
(
kerberos_principal:
"otherlogin@BAR.COM"
)
user
.
identities
.
build
(
provider:
"kerberos"
,
extern_uid:
"mylogin@FOO.COM"
).
save
expect
{
access
.
update_kerberos_identity
}.
not_to
change
(
user
.
identities
.
where
(
provider:
"kerberos"
),
:count
)
expect
(
user
.
identities
.
where
(
provider:
"kerberos"
).
last
.
extern_uid
).
to
eq
(
"otherlogin@BAR.COM"
)
end
it
"does not remove Kerberos identities from GitLab if they are none in the LDAP provider"
do
allow_any_instance_of
(
EE
::
Gitlab
::
Auth
::
LDAP
::
Person
).
to
receive_messages
(
kerberos_principal:
nil
)
user
.
identities
.
build
(
provider:
"kerberos"
,
extern_uid:
"otherlogin@BAR.COM"
).
save
expect
{
access
.
update_kerberos_identity
}.
not_to
change
(
user
.
identities
.
where
(
provider:
"kerberos"
),
:count
)
expect
(
user
.
identities
.
where
(
provider:
"kerberos"
).
last
.
extern_uid
).
to
eq
(
"otherlogin@BAR.COM"
)
end
it
"does not modify identities in GitLab if they are no kerberos principal in the LDAP provider"
do
allow_any_instance_of
(
EE
::
Gitlab
::
Auth
::
LDAP
::
Person
).
to
receive_messages
(
kerberos_principal:
nil
)
expect
{
access
.
update_kerberos_identity
}.
not_to
change
(
user
.
identities
,
:count
)
end
end
describe
'#update_ssh_keys'
do
let
(
:ssh_key
)
{
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCrSQHff6a1rMqBdHFt+FwIbytMZ+hJKN3KLkTtOWtSvNIriGhnTdn4rs+tjD/w+z+revytyWnMDM9dS7J8vQi006B16+hc9Xf82crqRoPRDnBytgAFFQY1G/55ql2zdfsC5yvpDOFzuwIJq5dNGsojS82t6HNmmKPq130fzsenFnj5v1pl3OJvk513oduUyKiZBGTroWTn7H/eOPtu7s9MD7pAdEjqYKFLeaKmyidiLmLqQlCRj3Tl2U9oyFg4PYNc0bL5FZJ/Z6t0Ds3i/a2RanQiKxrvgu3GSnUKMx7WIX373baL4jeM7cprRGiOY/1NcS+1cAjfJ8oaxQF/1dYj"
}
let
(
:ssh_key_attribute_name
)
{
'altSecurityIdentities'
}
let
(
:entry
)
do
Net
::
LDAP
::
Entry
.
from_single_ldif_string
(
"dn: cn=foo, dc=bar, dc=com
\n
#{
ssh_key_attribute_name
}
: SSHKey:
#{
ssh_key
}
\n
#{
ssh_key_attribute_name
}
: KerberosKey:bogus"
)
end
before
do
allow_any_instance_of
(
Gitlab
::
Auth
::
LDAP
::
Config
).
to
receive_messages
(
sync_ssh_keys:
ssh_key_attribute_name
)
allow
(
access
).
to
receive_messages
(
sync_ssh_keys?:
true
)
end
it
"adds a SSH key if it is in LDAP but not in gitlab"
do
allow_any_instance_of
(
Gitlab
::
Auth
::
LDAP
::
Adapter
).
to
receive
(
:user
)
{
Gitlab
::
Auth
::
LDAP
::
Person
.
new
(
entry
,
'ldapmain'
)
}
expect
{
access
.
update_ssh_keys
}.
to
change
(
user
.
keys
,
:count
).
from
(
0
).
to
(
1
)
end
it
"adds a SSH key and give it a proper name"
do
allow_any_instance_of
(
Gitlab
::
Auth
::
LDAP
::
Adapter
).
to
receive
(
:user
)
{
Gitlab
::
Auth
::
LDAP
::
Person
.
new
(
entry
,
'ldapmain'
)
}
access
.
update_ssh_keys
expect
(
user
.
keys
.
last
.
title
).
to
match
(
/LDAP/
)
expect
(
user
.
keys
.
last
.
title
).
to
match
(
/
#{
access
.
ldap_config
.
sync_ssh_keys
}
/
)
end
it
"does not add a SSH key if it is invalid"
do
entry
=
Net
::
LDAP
::
Entry
.
from_single_ldif_string
(
"dn: cn=foo, dc=bar, dc=com
\n
#{
ssh_key_attribute_name
}
: I am not a valid key"
)
allow_any_instance_of
(
Gitlab
::
Auth
::
LDAP
::
Adapter
).
to
receive
(
:user
)
{
Gitlab
::
Auth
::
LDAP
::
Person
.
new
(
entry
,
'ldapmain'
)
}
expect
{
access
.
update_ssh_keys
}.
not_to
change
(
user
.
keys
,
:count
)
end
context
'user has at least one LDAPKey'
do
before
do
user
.
keys
.
ldap
.
create
key:
ssh_key
,
title:
'to be removed'
end
it
"removes a SSH key if it is no longer in LDAP"
do
entry
=
Net
::
LDAP
::
Entry
.
from_single_ldif_string
(
"dn: cn=foo, dc=bar, dc=com
\n
#{
ssh_key_attribute_name
}
:
\n
"
)
allow_any_instance_of
(
Gitlab
::
Auth
::
LDAP
::
Adapter
).
to
receive
(
:user
)
{
Gitlab
::
Auth
::
LDAP
::
Person
.
new
(
entry
,
'ldapmain'
)
}
expect
{
access
.
update_ssh_keys
}.
to
change
(
user
.
keys
,
:count
).
from
(
1
).
to
(
0
)
end
it
"removes a SSH key if the ldap attribute was removed"
do
entry
=
Net
::
LDAP
::
Entry
.
from_single_ldif_string
(
"dn: cn=foo, dc=bar, dc=com"
)
allow_any_instance_of
(
Gitlab
::
Auth
::
LDAP
::
Adapter
).
to
receive
(
:user
)
{
Gitlab
::
Auth
::
LDAP
::
Person
.
new
(
entry
,
'ldapmain'
)
}
expect
{
access
.
update_ssh_keys
}.
to
change
(
user
.
keys
,
:count
).
from
(
1
).
to
(
0
)
end
end
end
describe
'#update_user_email'
do
let
(
:entry
)
{
Net
::
LDAP
::
Entry
.
new
}
before
do
allow
(
access
).
to
receive_messages
(
ldap_user:
Gitlab
::
Auth
::
LDAP
::
Person
.
new
(
entry
,
user
.
ldap_identity
.
provider
))
end
it
"does not update email if email attribute is not set"
do
expect
{
access
.
update_email
}.
not_to
change
(
user
,
:email
)
end
it
"does not update the email if the user has the same email in GitLab and in LDAP"
do
entry
[
'mail'
]
=
[
user
.
email
]
expect
{
access
.
update_email
}.
not_to
change
(
user
,
:email
)
end
it
"does not update the email if the user has the same email GitLab and in LDAP, but with upper case in LDAP"
do
entry
[
'mail'
]
=
[
user
.
email
.
upcase
]
expect
{
access
.
update_email
}.
not_to
change
(
user
,
:email
)
end
it
"updates the email if the user email is different"
do
entry
[
'mail'
]
=
[
"new_email@example.com"
]
expect
{
access
.
update_email
}.
to
change
(
user
,
:email
)
end
end
describe
'#update_memberships'
do
let
(
:provider
)
{
user
.
ldap_identity
.
provider
}
let
(
:entry
)
{
ldap_user_entry
(
user
.
ldap_identity
.
extern_uid
)
}
let
(
:person_with_memberof
)
do
entry
[
'memberof'
]
=
[
'CN=Group1,CN=Users,DC=The dc,DC=com'
,
'CN=Group2,CN=Builtin,DC=The dc,DC=com'
]
Gitlab
::
Auth
::
LDAP
::
Person
.
new
(
entry
,
provider
)
end
it
'triggers a sync for all groups found in `memberof`'
do
group_link_1
=
create
(
:ldap_group_link
,
cn:
'Group1'
,
provider:
provider
)
group_link_2
=
create
(
:ldap_group_link
,
cn:
'Group2'
,
provider:
provider
)
group_ids
=
[
group_link_1
,
group_link_2
].
map
(
&
:group_id
)
allow
(
access
).
to
receive
(
:ldap_user
).
and_return
(
person_with_memberof
)
expect
(
LdapGroupSyncWorker
).
to
receive
(
:perform_async
)
.
with
(
a_collection_containing_exactly
(
*
group_ids
),
provider
)
access
.
update_memberships
end
it
"doesn't continue when there is no `memberOf` param"
do
allow
(
access
).
to
receive
(
:ldap_user
)
.
and_return
(
Gitlab
::
Auth
::
LDAP
::
Person
.
new
(
entry
,
provider
))
expect
(
LdapGroupLink
).
not_to
receive
(
:where
)
expect
(
LdapGroupSyncWorker
).
not_to
receive
(
:perform_async
)
access
.
update_memberships
end
it
"doesn't trigger a sync when there are no links for the provider"
do
_another_provider
=
create
(
:ldap_group_link
,
cn:
'Group1'
,
provider:
'not-this-ldap'
)
allow
(
access
).
to
receive
(
:ldap_user
).
and_return
(
person_with_memberof
)
expect
(
LdapGroupSyncWorker
).
not_to
receive
(
:perform_async
)
access
.
update_memberships
end
end
describe
'#update_identity'
do
it
'updates the external UID if it changed in the entry'
do
entry
=
ldap_user_entry
(
'another uid'
)
provider
=
user
.
ldap_identity
.
provider
person
=
Gitlab
::
Auth
::
LDAP
::
Person
.
new
(
entry
,
provider
)
allow
(
access
).
to
receive
(
:ldap_user
).
and_return
(
person
)
access
.
update_identity
expect
(
user
.
ldap_identity
.
reload
.
extern_uid
)
.
to
eq
(
'uid=another uid,ou=users,dc=example,dc=com'
)
end
end
end
lib/gitlab/auth/ldap/access.rb
View file @
a8298021
...
...
@@ -6,6 +6,8 @@ module Gitlab
module
Auth
module
LDAP
class
Access
prepend
::
EE
::
Gitlab
::
Auth
::
LDAP
::
Access
attr_reader
:provider
,
:user
,
:ldap_identity
def
self
.
open
(
user
,
&
block
)
...
...
@@ -33,7 +35,7 @@ module Gitlab
@adapter
=
adapter
@user
=
user
@ldap_identity
=
user
.
ldap_identity
@provider
=
adapter
&
.
provider
||
@
ldap_identity
&
.
provider
@provider
=
adapter
&
.
provider
||
ldap_identity
&
.
provider
end
def
allowed?
...
...
@@ -69,17 +71,12 @@ module Gitlab
end
def
find_ldap_user
return
unless
provider
found_user
=
Gitlab
::
Auth
::
LDAP
::
Person
.
find_by_dn
(
ldap_identity
.
extern_uid
,
adapter
)
return
found_user
if
found_user
if
ldap_identity
Gitlab
::
Auth
::
LDAP
::
Person
.
find_by_email
(
user
.
email
,
adapter
)
end
Gitlab
::
Auth
::
LDAP
::
Person
.
find_by_dn
(
ldap_identity
.
extern_uid
,
adapter
)
end
def
ldap_user
return
unless
provider
@ldap_user
||=
find_ldap_user
end
...
...
@@ -109,108 +106,7 @@ module Gitlab
end
def
update_user
update_email
update_memberships
update_identity
update_ssh_keys
if
sync_ssh_keys?
update_kerberos_identity
if
import_kerberos_identities?
end
# Update user ssh keys if they changed in LDAP
def
update_ssh_keys
remove_old_ssh_keys
add_new_ssh_keys
end
# Add ssh keys that are in LDAP but not in GitLab
def
add_new_ssh_keys
keys
=
ldap_user
.
ssh_keys
-
user
.
keys
.
ldap
.
pluck
(
:key
)
keys
.
each
do
|
key
|
logger
.
info
"
#{
self
.
class
.
name
}
: adding LDAP SSH key
#{
key
.
inspect
}
to
#{
user
.
name
}
(
#{
user
.
id
}
)"
new_key
=
LDAPKey
.
new
(
title:
"LDAP -
#{
ldap_config
.
sync_ssh_keys
}
"
,
key:
key
)
new_key
.
user
=
user
unless
new_key
.
save
logger
.
error
"
#{
self
.
class
.
name
}
: failed to add LDAP SSH key
#{
key
.
inspect
}
to
#{
user
.
name
}
(
#{
user
.
id
}
)
\n
"
\
"error messages:
#{
new_key
.
errors
.
messages
}
"
end
end
end
# Remove ssh keys that do not exist in LDAP any more
def
remove_old_ssh_keys
keys
=
user
.
keys
.
ldap
.
where
.
not
(
key:
ldap_user
.
ssh_keys
)
keys
.
each
do
|
deleted_key
|
logger
.
info
"
#{
self
.
class
.
name
}
: removing LDAP SSH key
#{
deleted_key
.
key
}
from
#{
user
.
name
}
(
#{
user
.
id
}
)"
unless
deleted_key
.
destroy
logger
.
error
"
#{
self
.
class
.
name
}
: failed to remove LDAP SSH key
#{
key
.
inspect
}
from
#{
user
.
name
}
(
#{
user
.
id
}
)"
end
end
end
# Update user Kerberos identity with Kerberos principal name from Active Directory
def
update_kerberos_identity
# there can be only one Kerberos identity in GitLab; if the user has a Kerberos identity in AD,
# replace any existing Kerberos identity for the user
return
unless
ldap_user
.
kerberos_principal
.
present?
kerberos_identity
=
user
.
identities
.
where
(
provider: :kerberos
).
first
return
if
kerberos_identity
&&
kerberos_identity
.
extern_uid
==
ldap_user
.
kerberos_principal
kerberos_identity
||=
Identity
.
new
(
provider: :kerberos
,
user:
user
)
kerberos_identity
.
extern_uid
=
ldap_user
.
kerberos_principal
unless
kerberos_identity
.
save
Rails
.
logger
.
error
"
#{
self
.
class
.
name
}
: failed to add Kerberos principal
#{
principal
}
to
#{
user
.
name
}
(
#{
user
.
id
}
)
\n
"
\
"error messages:
#{
new_identity
.
errors
.
messages
}
"
end
end
# Update user email if it changed in LDAP
def
update_email
return
false
unless
ldap_user
.
try
(
:email
)
ldap_email
=
ldap_user
.
email
.
last
.
to_s
.
downcase
return
false
if
user
.
email
==
ldap_email
Users
::
UpdateService
.
new
(
user
,
user:
user
,
email:
ldap_email
).
execute
do
|
user
|
user
.
skip_reconfirmation!
end
end
def
update_identity
return
if
ldap_user
.
dn
.
empty?
||
ldap_user
.
dn
==
ldap_identity
.
extern_uid
unless
ldap_identity
.
update
(
extern_uid:
ldap_user
.
dn
)
Rails
.
logger
.
error
"Could not update DN for
#{
user
.
name
}
(
#{
user
.
id
}
)
\n
"
\
"error messages:
#{
user
.
ldap_identity
.
errors
.
messages
}
"
end
end
delegate
:sync_ssh_keys?
,
to: :ldap_config
def
import_kerberos_identities?
# Kerberos may be enabled for Git HTTP access and/or as an Omniauth provider
ldap_config
.
active_directory
&&
(
Gitlab
.
config
.
kerberos
.
enabled
||
AuthHelper
.
kerberos_enabled?
)
end
def
update_memberships
return
if
ldap_user
.
nil?
||
ldap_user
.
group_cns
.
empty?
group_ids
=
LdapGroupLink
.
where
(
cn:
ldap_user
.
group_cns
,
provider:
provider
)
.
distinct
(
:group_id
)
.
pluck
(
:group_id
)
LdapGroupSyncWorker
.
perform_async
(
group_ids
,
provider
)
if
group_ids
.
any?
end
private
def
logger
Rails
.
logger
# no-op in CE
end
end
end
...
...
spec/lib/gitlab/auth/ldap/access_spec.rb
View file @
a8298021
...
...
@@ -23,13 +23,6 @@ describe Gitlab::Auth::LDAP::Access do
access
.
find_ldap_user
end
it
'finds a user by email if the email came from LDAP'
do
expect
(
Gitlab
::
Auth
::
LDAP
::
Person
).
to
receive
(
:find_by_dn
).
and_return
(
nil
)
expect
(
Gitlab
::
Auth
::
LDAP
::
Person
).
to
receive
(
:find_by_email
)
access
.
find_ldap_user
end
end
describe
'#allowed?'
do
...
...
@@ -48,12 +41,6 @@ describe Gitlab::Auth::LDAP::Access do
access
.
allowed?
end
context
'when looking for a user by email'
do
let
(
:user
)
{
create
(
:omniauth_user
,
extern_uid:
'my-uid'
,
provider:
'my-provider'
)
}
it
{
is_expected
.
to
be_falsey
}
end
end
context
'when the user is found'
do
...
...
@@ -146,34 +133,6 @@ describe Gitlab::Auth::LDAP::Access do
access
.
allowed?
end
end
context
'when user was previously ldap_blocked'
do
before
do
user
.
ldap_block
end
it
'unblocks the user if it exists'
do
expect
(
access
).
to
receive
(
:unblock_user
).
with
(
user
,
'is available again'
)
access
.
allowed?
end
end
end
end
context
'when the connection fails'
do
before
do
raise_ldap_connection_error
end
it
'does not block the user'
do
access
.
allowed?
expect
(
user
.
ldap_blocked?
).
to
be_falsey
end
it
'denies access'
do
expect
(
access
.
allowed?
).
to
be_falsey
end
end
...
...
@@ -235,231 +194,4 @@ describe Gitlab::Auth::LDAP::Access do
)
end
end
describe
'#update_user'
do
subject
{
access
.
update_user
}
let
(
:entry
)
do
Net
::
LDAP
::
Entry
.
from_single_ldif_string
(
"dn: cn=foo, dc=bar, dc=com"
)
end
before
do
allow
(
access
).
to
(
receive_messages
(
ldap_user:
Gitlab
::
Auth
::
LDAP
::
Person
.
new
(
entry
,
user
.
ldap_identity
.
provider
)
)
)
end
it
'updates email address'
do
expect
(
access
).
to
receive
(
:update_email
).
once
subject
end
it
'updates the group memberships'
do
expect
(
access
).
to
receive
(
:update_memberships
).
once
subject
end
it
'syncs ssh keys if enabled by configuration'
do
allow
(
access
).
to
receive_messages
(
group_base:
''
,
sync_ssh_keys?:
true
)
expect
(
access
).
to
receive
(
:update_ssh_keys
).
once
subject
end
it
'update_kerberos_identity'
do
allow
(
access
).
to
receive_messages
(
import_kerberos_identities?:
true
)
expect
(
access
).
to
receive
(
:update_kerberos_identity
).
once
subject
end
it
'updates the ldap identity'
do
expect
(
access
).
to
receive
(
:update_identity
)
subject
end
end
describe
'#update_kerberos_identity'
do
let
(
:entry
)
do
Net
::
LDAP
::
Entry
.
from_single_ldif_string
(
"dn: cn=foo, dc=bar, dc=com"
)
end
before
do
allow
(
access
).
to
receive_messages
(
ldap_user:
Gitlab
::
Auth
::
LDAP
::
Person
.
new
(
entry
,
user
.
ldap_identity
.
provider
))
end
it
"adds a Kerberos identity if it is in Active Directory but not in GitLab"
do
allow_any_instance_of
(
EE
::
Gitlab
::
Auth
::
LDAP
::
Person
).
to
receive_messages
(
kerberos_principal:
"mylogin@FOO.COM"
)
expect
{
access
.
update_kerberos_identity
}.
to
change
(
user
.
identities
.
where
(
provider: :kerberos
),
:count
).
from
(
0
).
to
(
1
)
expect
(
user
.
identities
.
where
(
provider:
"kerberos"
).
last
.
extern_uid
).
to
eq
(
"mylogin@FOO.COM"
)
end
it
"updates existing Kerberos identity in GitLab if Active Directory has a different one"
do
allow_any_instance_of
(
EE
::
Gitlab
::
Auth
::
LDAP
::
Person
).
to
receive_messages
(
kerberos_principal:
"otherlogin@BAR.COM"
)
user
.
identities
.
build
(
provider:
"kerberos"
,
extern_uid:
"mylogin@FOO.COM"
).
save
expect
{
access
.
update_kerberos_identity
}.
not_to
change
(
user
.
identities
.
where
(
provider:
"kerberos"
),
:count
)
expect
(
user
.
identities
.
where
(
provider:
"kerberos"
).
last
.
extern_uid
).
to
eq
(
"otherlogin@BAR.COM"
)
end
it
"does not remove Kerberos identities from GitLab if they are none in the LDAP provider"
do
allow_any_instance_of
(
EE
::
Gitlab
::
Auth
::
LDAP
::
Person
).
to
receive_messages
(
kerberos_principal:
nil
)
user
.
identities
.
build
(
provider:
"kerberos"
,
extern_uid:
"otherlogin@BAR.COM"
).
save
expect
{
access
.
update_kerberos_identity
}.
not_to
change
(
user
.
identities
.
where
(
provider:
"kerberos"
),
:count
)
expect
(
user
.
identities
.
where
(
provider:
"kerberos"
).
last
.
extern_uid
).
to
eq
(
"otherlogin@BAR.COM"
)
end
it
"does not modify identities in GitLab if they are no kerberos principal in the LDAP provider"
do
allow_any_instance_of
(
EE
::
Gitlab
::
Auth
::
LDAP
::
Person
).
to
receive_messages
(
kerberos_principal:
nil
)
expect
{
access
.
update_kerberos_identity
}.
not_to
change
(
user
.
identities
,
:count
)
end
end
describe
'#update_ssh_keys'
do
let
(
:ssh_key
)
{
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCrSQHff6a1rMqBdHFt+FwIbytMZ+hJKN3KLkTtOWtSvNIriGhnTdn4rs+tjD/w+z+revytyWnMDM9dS7J8vQi006B16+hc9Xf82crqRoPRDnBytgAFFQY1G/55ql2zdfsC5yvpDOFzuwIJq5dNGsojS82t6HNmmKPq130fzsenFnj5v1pl3OJvk513oduUyKiZBGTroWTn7H/eOPtu7s9MD7pAdEjqYKFLeaKmyidiLmLqQlCRj3Tl2U9oyFg4PYNc0bL5FZJ/Z6t0Ds3i/a2RanQiKxrvgu3GSnUKMx7WIX373baL4jeM7cprRGiOY/1NcS+1cAjfJ8oaxQF/1dYj"
}
let
(
:ssh_key_attribute_name
)
{
'altSecurityIdentities'
}
let
(
:entry
)
do
Net
::
LDAP
::
Entry
.
from_single_ldif_string
(
"dn: cn=foo, dc=bar, dc=com
\n
#{
ssh_key_attribute_name
}
: SSHKey:
#{
ssh_key
}
\n
#{
ssh_key_attribute_name
}
: KerberosKey:bogus"
)
end
before
do
allow_any_instance_of
(
Gitlab
::
Auth
::
LDAP
::
Config
).
to
receive_messages
(
sync_ssh_keys:
ssh_key_attribute_name
)
allow
(
access
).
to
receive_messages
(
sync_ssh_keys?:
true
)
end
it
"adds a SSH key if it is in LDAP but not in gitlab"
do
allow_any_instance_of
(
Gitlab
::
Auth
::
LDAP
::
Adapter
).
to
receive
(
:user
)
{
Gitlab
::
Auth
::
LDAP
::
Person
.
new
(
entry
,
'ldapmain'
)
}
expect
{
access
.
update_ssh_keys
}.
to
change
(
user
.
keys
,
:count
).
from
(
0
).
to
(
1
)
end
it
"adds a SSH key and give it a proper name"
do
allow_any_instance_of
(
Gitlab
::
Auth
::
LDAP
::
Adapter
).
to
receive
(
:user
)
{
Gitlab
::
Auth
::
LDAP
::
Person
.
new
(
entry
,
'ldapmain'
)
}
access
.
update_ssh_keys
expect
(
user
.
keys
.
last
.
title
).
to
match
(
/LDAP/
)
expect
(
user
.
keys
.
last
.
title
).
to
match
(
/
#{
access
.
ldap_config
.
sync_ssh_keys
}
/
)
end
it
"does not add a SSH key if it is invalid"
do
entry
=
Net
::
LDAP
::
Entry
.
from_single_ldif_string
(
"dn: cn=foo, dc=bar, dc=com
\n
#{
ssh_key_attribute_name
}
: I am not a valid key"
)
allow_any_instance_of
(
Gitlab
::
Auth
::
LDAP
::
Adapter
).
to
receive
(
:user
)
{
Gitlab
::
Auth
::
LDAP
::
Person
.
new
(
entry
,
'ldapmain'
)
}
expect
{
access
.
update_ssh_keys
}.
not_to
change
(
user
.
keys
,
:count
)
end
context
'user has at least one LDAPKey'
do
before
do
user
.
keys
.
ldap
.
create
key:
ssh_key
,
title:
'to be removed'
end
it
"removes a SSH key if it is no longer in LDAP"
do
entry
=
Net
::
LDAP
::
Entry
.
from_single_ldif_string
(
"dn: cn=foo, dc=bar, dc=com
\n
#{
ssh_key_attribute_name
}
:
\n
"
)
allow_any_instance_of
(
Gitlab
::
Auth
::
LDAP
::
Adapter
).
to
receive
(
:user
)
{
Gitlab
::
Auth
::
LDAP
::
Person
.
new
(
entry
,
'ldapmain'
)
}
expect
{
access
.
update_ssh_keys
}.
to
change
(
user
.
keys
,
:count
).
from
(
1
).
to
(
0
)
end
it
"removes a SSH key if the ldap attribute was removed"
do
entry
=
Net
::
LDAP
::
Entry
.
from_single_ldif_string
(
"dn: cn=foo, dc=bar, dc=com"
)
allow_any_instance_of
(
Gitlab
::
Auth
::
LDAP
::
Adapter
).
to
receive
(
:user
)
{
Gitlab
::
Auth
::
LDAP
::
Person
.
new
(
entry
,
'ldapmain'
)
}
expect
{
access
.
update_ssh_keys
}.
to
change
(
user
.
keys
,
:count
).
from
(
1
).
to
(
0
)
end
end
end
describe
'#update_user_email'
do
let
(
:entry
)
{
Net
::
LDAP
::
Entry
.
new
}
before
do
allow
(
access
).
to
receive_messages
(
ldap_user:
Gitlab
::
Auth
::
LDAP
::
Person
.
new
(
entry
,
user
.
ldap_identity
.
provider
))
end
it
"does not update email if email attribute is not set"
do
expect
{
access
.
update_email
}.
not_to
change
(
user
,
:email
)
end
it
"does not update the email if the user has the same email in GitLab and in LDAP"
do
entry
[
'mail'
]
=
[
user
.
email
]
expect
{
access
.
update_email
}.
not_to
change
(
user
,
:email
)
end
it
"does not update the email if the user has the same email GitLab and in LDAP, but with upper case in LDAP"
do
entry
[
'mail'
]
=
[
user
.
email
.
upcase
]
expect
{
access
.
update_email
}.
not_to
change
(
user
,
:email
)
end
it
"updates the email if the user email is different"
do
entry
[
'mail'
]
=
[
"new_email@example.com"
]
expect
{
access
.
update_email
}.
to
change
(
user
,
:email
)
end
end
describe
'#update_memberships'
do
let
(
:provider
)
{
user
.
ldap_identity
.
provider
}
let
(
:entry
)
{
ldap_user_entry
(
user
.
ldap_identity
.
extern_uid
)
}
let
(
:person_with_memberof
)
do
entry
[
'memberof'
]
=
[
'CN=Group1,CN=Users,DC=The dc,DC=com'
,
'CN=Group2,CN=Builtin,DC=The dc,DC=com'
]
Gitlab
::
Auth
::
LDAP
::
Person
.
new
(
entry
,
provider
)
end
it
'triggers a sync for all groups found in `memberof`'
do
group_link_1
=
create
(
:ldap_group_link
,
cn:
'Group1'
,
provider:
provider
)
group_link_2
=
create
(
:ldap_group_link
,
cn:
'Group2'
,
provider:
provider
)
group_ids
=
[
group_link_1
,
group_link_2
].
map
(
&
:group_id
)
allow
(
access
).
to
receive
(
:ldap_user
).
and_return
(
person_with_memberof
)
expect
(
LdapGroupSyncWorker
).
to
receive
(
:perform_async
)
.
with
(
a_collection_containing_exactly
(
*
group_ids
),
provider
)
access
.
update_memberships
end
it
"doesn't continue when there is no `memberOf` param"
do
allow
(
access
).
to
receive
(
:ldap_user
)
.
and_return
(
Gitlab
::
Auth
::
LDAP
::
Person
.
new
(
entry
,
provider
))
expect
(
LdapGroupLink
).
not_to
receive
(
:where
)
expect
(
LdapGroupSyncWorker
).
not_to
receive
(
:perform_async
)
access
.
update_memberships
end
it
"doesn't trigger a sync when there are no links for the provider"
do
_another_provider
=
create
(
:ldap_group_link
,
cn:
'Group1'
,
provider:
'not-this-ldap'
)
allow
(
access
).
to
receive
(
:ldap_user
).
and_return
(
person_with_memberof
)
expect
(
LdapGroupSyncWorker
).
not_to
receive
(
:perform_async
)
access
.
update_memberships
end
end
describe
'#update_identity'
do
it
'updates the external UID if it changed in the entry'
do
entry
=
ldap_user_entry
(
'another uid'
)
provider
=
user
.
ldap_identity
.
provider
person
=
Gitlab
::
Auth
::
LDAP
::
Person
.
new
(
entry
,
provider
)
allow
(
access
).
to
receive
(
:ldap_user
).
and_return
(
person
)
access
.
update_identity
expect
(
user
.
ldap_identity
.
reload
.
extern_uid
)
.
to
eq
(
'uid=another uid,ou=users,dc=example,dc=com'
)
end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment