Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LDAP Sync Problems (is_admin, is_restricted and is_active) #13419

Open
2 of 6 tasks
lcnittl opened this issue Nov 3, 2020 · 13 comments
Open
2 of 6 tasks

LDAP Sync Problems (is_admin, is_restricted and is_active) #13419

lcnittl opened this issue Nov 3, 2020 · 13 comments

Comments

@lcnittl
Copy link

lcnittl commented Nov 3, 2020

Description

We are encountering 2/3 main issues with LDAP authentication:

  1. is_admin is set correctly on account creation (fist login to Gitea) but is not updated anymore on subsequent logins
  2. is_restricted is not updated anymore on subsequent logins (have not tested on account creation yet, sry)
  3. Although "AllowDeactivateAll": false is set ( Add option to prevent LDAP from deactivating everything on empty search #9879 ) each user's is_active attribute is set to false (cf. https://gist.github.com/lcnittl/60045a167285b50d72f0037f8a37cc2e#file-gitea-trace-0-log-L177-L178 ff.) when using Synchronize external user data in admin/monitor in the web UI (and also on cron started synchronizations).

This is our configuration of the authentication method:

# SELECT * FROM gitea.login_source WHERE id=2;
id: 2
type: 2
name: ldap.our.domain.com
is_actived: 1
is_sync_enabled: 1
cfg:
  Name: ldap.our.domain.com
  Host: ldap.lxc0
  Port: 389
  SecurityProtocol: 0
  SkipVerify: false
  BindDN: ''
  BindPassword: ''
  UserBase: OU=users,DC=our,DC=domain,DC=com
  UserDN: ''
  AttributeUsername: ''
  AttributeName: givenName
  AttributeSurname: sn
  AttributeMail: mail
  AttributesInBind: true
  AttributeSSHPublicKey: ''
  SearchPageSize: 0
  Filter: (&(objectClass=posixAccount)(UID=%s)(!(memberOf=CN=disabled,OU=roles,DC=our,DC=domain,DC=com)))
  AdminFilter: (memberOf=CN=admin,OU=roles,DC=our,DC=domain,DC=com)
  RestrictedFilter: (&(memberOf=CN=ext,OU=roles,DC=our,DC=domain,DC=com)(!(memberOf=CN=gitea,OU=roles,DC=our,DC=domain,DC=com)))
  Enabled: true
  AllowDeactivateAll: false
created_unix: 1603901943
updated_unix: 1604430791

This is the list of our users (probably important for the log gist):

user00: [admin]
user01: [admin]
user02: []
user03: []
user04: []
user05: [ext]
user06: [disabled]
user07: []
user08: [ext]
user09: []
user10: []
user11: []
user12: [ext]
user13: []
user14: []
user15: []
user16: []
user17: [disabled]
user18: []
user19: []
user20: [disabled]
user21: [disabled]
user22: []
user23: []
user24: []
user25: []
user26: [disabled]
user27: [disabled]
user28: [disabled]
user29: [disabled]
user30: [disabled]
user31: [disabled]
user32: [disabled]
user33: []
user34: []
user35: []
user36: [ext]
user37: [disabled, ext]
user38: [ext]
user39: [ext]
user40: [ext]
user41: []
user42: []
user43: []
user44: []
user45: []
user46: []

The values after the user keys are the roles each user has (eg user00 is admin and (memberOf=CN=admin,OU=roles,DC=our,DC=domain,DC=com) evaluates to true).

When the filters are run manually with ldapsearch they return the correct user entries.

Issue 1)

Should theoretically be fixed already (cf. #10538 (comment) ) but is not working for me: Is my admin filter wrong? If yes, why is the attribute correct on creation?

On subsequent login, LDAP seems to correctly filter for admin as it is not logging [T] LDAP Admin Search found no matching entries when the admin role is set:

2020/11/03 23:38:48 ...es/auth/ldap/ldap.go:161:checkAdmin() [T] Checking admin with filter (memberOf=CN=admin,OU=roles,DC=our,DC=domain,DC=com) and base uid=user08,ou=users,DC=our,DC=domain,DC=com
2020/11/03 23:38:48 ...es/auth/ldap/ldap.go:147:bindUser() [T] Binding with userDN: uid=user08,ou=users,DC=our,DC=domain,DC=com
2020/11/03 23:56:19 ...es/auth/ldap/ldap.go:161:checkAdmin() [T] Checking admin with filter (memberOf=CN=admin,OU=roles,DC=our,DC=domain,DC=com) and base uid=user08,ou=users,DC=our,DC=domain,DC=com
2020/11/03 23:56:19 ...es/auth/ldap/ldap.go:172:checkAdmin() [T] LDAP Admin Search found no matching entries.
2020/11/03 23:56:19 ...es/auth/ldap/ldap.go:186:checkRestricted() [T] Checking restricted with filter (&(memberOf=CN=ext,OU=roles,DC=our,DC=domain,DC=com)(!(memberOf=CN=gitea,OU=roles,DC=our,DC=domain,DC=com))) and base uid=user08,ou=users,DC=our,DC=domain,DC=com
2020/11/03 23:56:19 ...es/auth/ldap/ldap.go:197:checkRestricted() [T] LDAP Restricted Search found no matching entries.
2020/11/03 23:56:19 ...es/auth/ldap/ldap.go:147:bindUser() [T] Binding with userDN: uid=user08,ou=users,DC=our,DC=domain,DC=com
2020/11/03 23:56:19 ...es/auth/ldap/ldap.go:153:bindUser() [T] Bound successfully with userDN: uid=user08,ou=users,DC=our,DC=domain,DC=com

Yet, the is_admin flag remains unaltered.

Issue 2)

This was tested (for the log) by adding ext role to user08.

Here again, according to the log, LDAP seems to correctly apply the filter (No [T] LDAP Restricted Search found no matching entries login):

2020/11/04 00:10:27 ...es/auth/ldap/ldap.go:186:checkRestricted() [T] Checking restricted with filter (&(memberOf=CN=ext,OU=roles,DC=our,DC=domain,DC=com)(!(memberOf=CN=gitea,OU=roles,DC=our,DC=domain,DC=com))) and base uid=user08,ou=users,DC=our,DC=domain,DC=com
2020/11/04 00:10:27 ...es/auth/ldap/ldap.go:147:bindUser() [T] Binding with userDN: uid=user08,ou=users,DC=our,DC=domain,DC=com

Is is_restricted supposed to get updated on each login?

Issue 3)

I think this -- deactivation of all users -- should not happen in our case because

  1. The user search filter should, in our setup, not return an empty list for any user (the the best of my knowledge, all users exist in LDAP).
  2. Even if it would, AllowDeactivateAll is set to false (so it should never deactivate all users?)
  3. Only the admin and restricted filters are returning empty lists, for obvious reasons

But probably there is a filter problem here as well?

Any input welcome! If there is further info needed, please let me know!

Related

@lcnittl lcnittl changed the title LDAP Sync Problems (is_admin and is_active) LDAP Sync Problems (is_admin, is_restricted and is_active) Nov 3, 2020
@6543 6543 added the type/bug label Nov 5, 2020
@zeripath
Copy link
Contributor

zeripath commented Nov 8, 2020

This is very interesting. Why is it that the ldap is giving different results for the same query?

2020/11/03 23:38:48 ...es/auth/ldap/ldap.go:88:findUserDN() [T] Search for LDAP user: user08
2020/11/03 23:38:48 ...es/auth/ldap/ldap.go:96:findUserDN() [T] Searching for DN using filter (&(objectClass=posixAccount)(UID=user08)(!(memberOf=CN=disabled,OU=roles,DC=our,DC=domain,DC=com))) and base OU=users,DC=our,DC=domain,DC=com
2020/11/03 23:38:48 ...es/auth/ldap/ldap.go:286:SearchEntry() [T] Fetching attributes '', 'givenName', 'sn', 'mail', '' with filter (&(objectClass=posixAccount)(UID=user08)(!(memberOf=CN=disabled,OU=roles,DC=our,DC=domain,DC=com))) and base uid=user08,ou=users,DC=our,DC=domain,DC=com
2020/11/03 23:38:48 ...es/auth/ldap/ldap.go:161:checkAdmin() [T] Checking admin with filter (memberOf=CN=admin,OU=roles,DC=our,DC=domain,DC=com) and base uid=user08,ou=users,DC=our,DC=domain,DC=com
2020/11/03 23:38:48 ...es/auth/ldap/ldap.go:147:bindUser() [T] Binding with userDN: uid=user08,ou=users,DC=our,DC=domain,DC=com
020/11/03 23:56:19 ...es/auth/ldap/ldap.go:161:checkAdmin() [T] Checking admin with filter (memberOf=CN=admin,OU=roles,DC=our,DC=domain,DC=com) and base uid=user08,ou=users,DC=our,DC=domain,DC=com
2020/11/03 23:56:19 ...es/auth/ldap/ldap.go:172:checkAdmin() [T] LDAP Admin Search found no matching entries.

There's something very odd going on here. Is there request limiting? Are we sending some whitespace by accident?

@lcnittl
Copy link
Author

lcnittl commented Nov 9, 2020

Maybe I was not very clear, sorry for that:
The different results from the same query are expected, as in the first case the admin role was set (user08 has the memberOf=CN=admin,OU=roles,DC=our,DC=domain,DC=com attribute set) and in the second case that attribute was removed. This was done to rule out that a failed LDAP query is the reason for the is_admin flag being not altered. But indeed, Gitea's LDAP query correctly found whether the user is supposed to be admin or not.

@SnailShea
Copy link

SnailShea commented Dec 29, 2020

May be unrelated to the cause of issues others have had (I've seen at least one screenshot showing my fix would not help them on other related issues) but I was having issues with user deactivation after a sync. Turns out if you have, in my example a User Filter of (&(objectClass=posixAccount)(uid=%s)) but leave the Username Attribute field blank, deactivation of any previously signed in users will occur. Adding uid to Username Attribute resolved the issue I was having. It was strange, I was able to sign in just fine but the user list would only populate with that name after signing in, and no other names from the LDAP instance. And, of course, upon sync that account would then be locked. After applying the fix as it pertained to my issue, all users in the LDAP show up in the account list on gitea.

Hoping this helps someone.

@SirIntellegence
Copy link

This issue is happening for me as well. I don't know if it is related to me leaving the "Username Attribute" field empty since out LDAP apparently doesn't support the UID attribute and the closest thing I can use "userPrincipalName" is effectively their domain email address.

@SnailShea
Copy link

SnailShea commented Mar 29, 2021

This issue is happening for me as well. I don't know if it is related to me leaving the "Username Attribute" field empty since out LDAP apparently doesn't support the UID attribute and the closest thing I can use "userPrincipalName" is effectively their domain email address.

Is your user attribute cn instead of uid perhaps? Essentially I think the field should be populated with whatever attribute indicates a unique user entry.

@SirIntellegence
Copy link

SirIntellegence commented Mar 29, 2021

From what I can tell by running queries, cn contains the user's name ("Billy Bob"), not the username ("bbob").

@SnailShea
Copy link

From what I can tell by running queries, cn contains the user's name ("Billy Bob"), not the username ("bbob").

If you're directly referencing a user object in your LDAP structure how do you do so? For me it would be like uid=mxlinux,cn=Users,dc=domain,dc=tld the part where I have uid might be different for you but I think still an expected part of any LDAP structure.

@SirIntellegence
Copy link

SirIntellegence commented Mar 29, 2021

I am using userPrincipalName for the filter and I haven' gotten the group filter field to work, so I am using (&(&(&(objectClass=person)(memberOf:=CN=Programming,CN=Users,DC=domain,DC=com)(userPrincipalName=%s))))
Also, I am not sure if this is related entirely to the issue and if this discussion should be held here. Don't want to hijack an issue...

@youngmit
Copy link

May be unrelated to the cause of issues others have had (I've seen at least one screenshot showing my fix would not help them on other related issues) but I was having issues with user deactivation after a sync. Turns out if you have, in my example a User Filter of (&(objectClass=posixAccount)(uid=%s)) but leave the Username Attribute field blank, deactivation of any previously signed in users will occur. Adding uid to Username Attribute resolved the issue I was having. It was strange, I was able to sign in just fine but the user list would only populate with that name after signing in, and no other names from the LDAP instance. And, of course, upon sync that account would then be locked. After applying the fix as it pertained to my issue, all users in the LDAP show up in the account list on gitea.

Hoping this helps someone.

This is extremely helpful! I had left this option blank, because the "Leave empty to use the username entered in Gitea" guidance implies that all it is used for is to determine the Gitea-internal username for the user. Adding sAMAccountName (we use AD) fixed it for me. I'm wondering if just making more explicit that this is also important for the sync operation to work correctly would clear up a lot of confusion for folks?

@Alexey-I
Copy link

Hi!
I can probably add a bit. We've just experienced the sync issue with Gitea Version: 1.15.0+dev-358-gfb6c6895f (Docker image).
Users who were able to register via LDAP yesterday, became Deactivated today.
After a bit of experimenting I was able to fix this issue by changing Username Attribute = samaccountname to Username Attribute = sAMAccountName on Authentication Source settings.
This is probably my fault, I should have used correct spelling from the very beginning but with user registration it worked. It's synchronization which seems to insist to be case sensitive.

@Oasis6604
Copy link

Hi! I can probably add a bit. We've just experienced the sync issue with Gitea Version: 1.15.0+dev-358-gfb6c6895f (Docker image). Users who were able to register via LDAP yesterday, became Deactivated today. After a bit of experimenting I was able to fix this issue by changing Username Attribute = samaccountname to Username Attribute = sAMAccountName on Authentication Source settings. This is probably my fault, I should have used correct spelling from the very beginning but with user registration it worked. It's synchronization which seems to insist to be case sensitive.

Same here!
Login works even with lowercase writing and tools like ldapsearch work aswell. But the issue that my users become disabled is gone since I use the correct writing.

@night-gold
Copy link

night-gold commented Nov 15, 2022

Hello, just find out that there is a solution that works for us here . You have to put a valid value username attribute. CN is an example in the post, I had to put 'uid' as the 'cn' is empty in our ldap.

@lunny lunny added the issue/workaround it is or has a workaround label Nov 21, 2022
@Samachi
Copy link

Samachi commented May 31, 2024

1.22.0, the issue still exist, while using LDAP (via BindDN) as authentication source, Gitea deactivates LDAP users almost once a day or when you run “Synchronize external user data”.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests