Bookstack: v0.23.2 // (AD) LDAP & "Default user role"... also, multiple ldap_user_filter entries?

Created on 20 Aug 2018  路  5Comments  路  Source: BookStackApp/BookStack

Disclosure

I wasn't sure how to submit this, as a request or as a bug, so please flag accordingly. I have concerns/questions regarding using LDAP integration with AD. I may have overlooked something that's just not registering with me right now because my head is so deep in the weeds.

Goal

Match user roles to security groups without manually entering them in the admin UI. If the LDAP user is not a member of a group name matching any of the roles, then login should not be permitted.

Meat n' Potatoes

I'm not sure if this is more a BookStack concern or a MSFT concern, but are groups supported in the ldap_user_filter entries?

I see that adding users individually to the ldap_user_filter is supported, per @ssddanbrown's comment on issue #971 (reference).

Based on based on this, I don't think its an MSFT concern since we're running Server 2016 in our environment (domain function level 2012).

Active Directory in Windows 2000 operating system does not implement three-value logic for search filter evaluation as defined in [RFC2251] section 4.5.1. In Windows 2000, filters evaluate to either "true" or "false". Filters that would evaluate to "Undefined", as per the RFC, are instead evaluated to "false". Active Directory in Windows Server 2003 operating system and later uses three-value logic for evaluating search filters, in conformance with the RFC.

Observation

  • It seems that this is at least partially working, as;

    • I can successfully authenticate to a user found in either of my two configured ldap_user_filter entries.

    • I cannot authenticate to any other user (desired result) .

  • However it seems that the _Default user role after registration_ setting is being applied to LDAP users at first time login.
  • So it seems logical to deduce that the group name is not being appropriately matched when two ldap_user_filter entries exist.

Example

If the default role is configured to Docs_Public and a user in the group Docs_Viewer logs in for the first time, they are incorrectly assigned the Docs_Public role.

|User|AD Group|Role Assigned
|-|-|-
|test|Docs_Viewer|Docs_Public

Validation

$ ldapsearch -xLLL -b CN="test,OU=domain admins,OU=city,OU=users,OU=corp,DC=domain,DC=local" -h dc.domain.local -D [email protected] -W | grep memberOf
Enter LDAP Password: 
memberOf: CN=docs_viewer,OU=security,OU=groups,OU=corp,DC=domain,DC=local

Result

image

Configuration Details

|Detail|-
|-|-
|BookStack Version|0.23.2
|PHP Version|PHP 7.2.7-0ubuntu0.18.04.2
|Hosting Method|Apache (install script)

File /.env

# General auth
AUTH_METHOD=ldap

# LDAP Settings
LDAP_SERVER=dc.domain.local
LDAP_BASE_DN="OU=corp,DC=domain,DC=local"
LDAP_DN="CN=docs service,OU=service accounts,OU=corp,DC=domain,DC=local"
LDAP_PASS=*****
LDAP_USER_FILTER="(&(sAMAccountName=${user})(|(memberOf=CN=docs_admin,OU=security,OU=groups,OU=corp,DC=domain,DC=local)(memberOf=CN=docs_viewer,OU=security,OU=groups,OU=corp,DC=domain,DC=local)))"
LDAP_VERSION=3
# Do you want to sync LDAP groups to BookStack roles for a user
LDAP_USER_TO_GROUPS=true
# What is the LDAP attribute for group memberships
LDAP_GROUP_ATTRIBUTE="memberOf"
# Would you like to remove users from roles on BookStack if they do not match on LDAP
# If false, the ldap groups-roles sync will only add users to roles
LDAP_REMOVE_FROM_GROUPS=false

Notes

  • I tried changing the ldap_user_filter to use (objectClass=user) instead of (sAMAccountName=${user}), but then I can't even complete the first login.
  • It does not matter which order I arrange the groups in the LDAP_USER_FILTER string, the end result is the same.
Question

Most helpful comment

I did some experimenting this morning and have things working.

My interpretation of the LDAP authentication configuration

The LDAP_USER_FILTER field defines a CN for users or groups to merely _log in_ to BookStack. They also need to be a member of a security group whose name matches a role configured in BookStack; or the security group CN needs to be configured in the role's External Authentication ID field.

My configuration changes

  • LDAP user filter changed as follows;
    bash LDAP_USER_FILTER="(&(sAMAccountName=${user})(memberOf=CN=docs_login,OU=security,OU=groups,OU=corp,DC=domain,DC=local))"
  • Test user added to the following AD security groups (slash-delimited format);

    • domain.local/corp/groups/security/docs_login

    • domain.local/corp/groups/security/docs_admin

Results

  • The user was able to log in and was assigned the Docs_Admin role.
  • I created docs_editor and docs_viewer security groups and tested logging out and back in after moving the user between groups and the user was reassigned to roles as expected (with the LDAP_REMOVE_FROM_GROUPS=true set in .env).
  • I was also able to prevent the test user from logging in by removing it from the docs_login group.

I am confused as to why my previous configuration didn't work, because my test account was a member of the AD security group Docs_Admin which was defined in my LDAP_USER_FILTER string; so theoretically it should have worked. However, I'm not too concerned about it because it's working as desired/intended now, so I'll close this one out.

All 5 comments

Looked at this again with a semi-clear head and thought the LDAP_REMOVE_FROM_GROUPS configuration set to true might accomplish what I want to do.

  1. I turned that option on and tried to log into an LDAP user who had already been assigned the Docs_Admin role via LDAP match (the same user I've been using to admin thus far).

    • I was able to log in, but I wasn't an admin anymore.
  2. I then tried to log into a new LDAP (added to the Docs_Admin AD group).

    • I was able to log in, but was not an admin.
  3. I set the AUTH_METHOD=standard and logged in with a _local_ user and was able to confirm both LDAP matched accounts were now assigned the Docs_Public role.

I re-ran the ldapsearch again (each time) for good measure and the Docs_Admin group was returned successfully.

$ ldapsearch -xLLL -b CN="test,OU=domain admins,OU=city,OU=users,OU=corp,DC=domain,DC=local" -h dc.domain.local -D [email protected] -W | grep memberOf
Enter LDAP Password: 
memberOf: CN=Docs_Admin,OU=security,OU=groups,OU=corp,DC=domain,DC=local

Maybe this is a bug? or my head isn't as clear as I thought it was and I'm still missing something.

I took one last stab and added the DN for the Docs_Admin _AD group_ to the Docs_Admin role under _External Authentication IDs_: CN=docs_admin,OU=security,OU=groups,OU=corp,DC=domain,DC=local

I created another test user and was still assigned the Doc_Public role upon first login; as a reminder, the Doc_Public role is configured as the _Default user role after registration_ in the app settings.

Hi @derek-shnosh, Sorry for the lack of reply. I had missed this issue before so sorry if it's too late.
The above is quite a lot to take in and I'm not really certain what the issue is but hopefully this helps:

Ldap Group Sync Logic with 'remove_from_groups' Enabled

  • Upon every login
  • BookStack will talk to LDAP using user_filter & provided credentials and will reject login if user not found or if cannot bind to user dn with the given password.
  • BookStack will fetch groups for the user from LDAP.
  • LDAP groups are matched up with roles.

    • This is based on the role name and the first component of the LDAP group DN (Usually the CN).

    • If the role has a 'external auth id' value there are split out on comma and used to match instead of the role name.

  • Existing BookStack roles are removed and the found roles are added.
  • The default registration role is attached to the user if not already added.

I've bolded the part that may be relevant from reading the above. I think you may just need to set the External Authentication Ids of the bookstack admin role to be docs_admin instead of the whole DN.

Let me know if that helps or if I've missed the mark.

Thanks for the response @ssddanbrown.

Here is my LDAP_USER_FILTER, and how it is broken down;

LDAP_USER_FILTER="(&(sAMAccountName=${user})(|(memberOf=CN=docs_admin,OU=security,OU=groups,OU=corp,DC=domain,DC=local)(memberOf=CN=docs_viewer,OU=security,OU=groups,OU=corp,DC=domain,DC=local)))"

LDAP_USER FILTER objects;

  • sAMAccountName=${user}
  • memberOf=CN=docs_admin,OU=security,OU=groups,OU=corp,DC=domain,DC=local
  • memberOf=CN=docs_viewer,OU=security,OU=groups,OU=corp,DC=domain,DC=local

Per the documentation;

BookStack has the ability to sync LDAP user groups with BookStack roles. By default this will match LDAP group names with the BookStack role display names with casing ignored.

Hopefully I'm interpreting this correctly; i.e. (providing the account was found within any of the groups configured in the LDAP_USER_FILTER and BookStack was able to bind to the user DN) a user account that is a member of the AD group Docs_Admin should be assigned the BookStack user role Docs_Admin without entering docs_admin in the External Authentication ID field; correct?

I did some experimenting this morning and have things working.

My interpretation of the LDAP authentication configuration

The LDAP_USER_FILTER field defines a CN for users or groups to merely _log in_ to BookStack. They also need to be a member of a security group whose name matches a role configured in BookStack; or the security group CN needs to be configured in the role's External Authentication ID field.

My configuration changes

  • LDAP user filter changed as follows;
    bash LDAP_USER_FILTER="(&(sAMAccountName=${user})(memberOf=CN=docs_login,OU=security,OU=groups,OU=corp,DC=domain,DC=local))"
  • Test user added to the following AD security groups (slash-delimited format);

    • domain.local/corp/groups/security/docs_login

    • domain.local/corp/groups/security/docs_admin

Results

  • The user was able to log in and was assigned the Docs_Admin role.
  • I created docs_editor and docs_viewer security groups and tested logging out and back in after moving the user between groups and the user was reassigned to roles as expected (with the LDAP_REMOVE_FROM_GROUPS=true set in .env).
  • I was also able to prevent the test user from logging in by removing it from the docs_login group.

I am confused as to why my previous configuration didn't work, because my test account was a member of the AD security group Docs_Admin which was defined in my LDAP_USER_FILTER string; so theoretically it should have worked. However, I'm not too concerned about it because it's working as desired/intended now, so I'll close this one out.

Was this page helpful?
0 / 5 - 0 ratings