Skip to main content

Active Directory/LDAP Integration

Active Directory/LDAP Integration

Many of the commands and edits in this guide need to be performed as root. Use sudo where indicated or log in as root.

This section will assume the following:

  • BookStack is being deployed in an environment with Active Directory (AD)
  • There is an internal/local certificate authority (CA) which is handing out certificates to domain controllers (DCs)
  • You are currently logged in to BookStack with the default admin account
  • If there is a network firewall between BookStack and your DCs, you have configured it to allow LDAPS traffic (port 636/tcp) to pass

You will also need to add a service account user in AD for BookStack to use for LDAP queries. The default Domain Users group provides sufficient permissions/privileges for BookStack.

Install CA Certificate

For LDAPS to work, the BookStack server needs to trust the certificate from the DC. This is accomplished by installing the CA certificate to the server's trust store. If you do not do this, the SSL/TLS handshake with the DC will fail and BookStack will not be able to successfully run LDAP queries to authenticate users.

Copy the root CA certificate to the BookStack server and move it to /usr/local/share/ca-certificates/.

sudo mv /tmp/Root-CA.crt /usr/local/share/ca-certificates/

Then add the CA certificate to the trust store by running update-ca-certificates. This will add a symlink to the certificate file in /etc/ssl/certs/ and append the contents of the certificate to /etc/ssl/certs/ca-certificates.crt.

sudo update-ca-certificates

You can copy and install an intermediate CA certificate as well, but it is not necessary as long as the DC's certificate includes the chain of trust leading up to the root CA.

Edit .env File

LDAP Authentication Options

Append the following example section to the bottom of your .env file in /var/www/bookstack/ and update necessary values to match your environment. The example assumes the following:

  • There is a BookStack service account named bookstack in the default AD Users container
  • There is a BookStack Users group in the default AD Users container
Active Directory Configuration Options (click to expand)
#### Active Directory Integration ####
# Set authentication method to ldap
AUTH_METHOD=ldap

# Point to a domain controller for LDAP queries
# You can just point to the domain if you have multiple domain controllers. BookStack will query whichever server is resolved by DNS
# Note that if a domain controller goes down, DNS will still resolve to it some of the time, so this is not a perfect failover solution
# You might be able to configure an LDAP proxy using OpenLDAP to get around the above issue
# Make sure you are using LDAPS so that this traffic is encrypted
LDAP_SERVER=ldaps://example.com

# This is the path that BookStack will use to check for users
# If you have BookStack users in different OUs/containers in Active Directory, you can just specify the distinguished name of the domain
LDAP_BASE_DN="dc=example,dc=com"

# Distinguished name and password for the BookStack service account performing LDAP queries
LDAP_DN="cn=bookstack,cn=Users,dc=example,dc=com"
LDAP_PASS="ServiceAccountPassword"

# A filter to use when searching for users
# '${user}' resolves to the username being used at the login page
# If you're setting this option via other means, such as within a docker-compose.yml,
# you may need escape the $, often using $$ or \$ instead.
# Note: This option cannot be used with the docker-compose.yml `env_file` option.
LDAP_USER_FILTER="(&(sAMAccountName=${user})(memberOf:1.2.840.113556.1.4.1941:=cn=BookStack Users,cn=Users,dc=example,dc=com))"

# Server LDAP version
LDAP_VERSION=3

# Set the property to use as a unique identifier for users.
# Stored and used to match LDAP users with existing BookStack users.
# Prefixing the value with 'BIN;' will assume the LDAP service provides the attribute value as binary data and BookStack will convert the value to a hexidecimal representation.
LDAP_ID_ATTRIBUTE=BIN;objectGUID

# LDAP attribute from which to pull an email address
LDAP_EMAIL_ATTRIBUTE=mail

# Set the property to use for a user's display name. Defaults to 'cn'
LDAP_DISPLAY_NAME_ATTRIBUTE=cn

# Don't use StartTLS because LDAPS should handle encryption
LDAP_START_TLS=false

# This can be set to true if the BookStack server doesn't trust the LDAP server
# It is always best to install necessary certificates to ensure that both parties on either side of a conversation are trusted before moving any service into production
LDAP_TLS_INSECURE=false

# If you need to debug the details coming from your LDAP server, uncomment this option
# Only set this option if debugging since it will block logins and potentially show private details.
#LDAP_DUMP_USER_DETAILS=true

# Enable LDAP group sync, Set to 'true' to enable.
# This feature matches BookStack roles with LDAP groups
LDAP_USER_TO_GROUPS=true

# LDAP user attribute containing groups, Defaults to 'memberOf'.
LDAP_GROUP_ATTRIBUTE="memberOf"

# Remove users from roles that don't match LDAP groups.
# Note: While this is enabled the "Default Registration Role", editable within the
# BookStack settings view, will be considered a matched role and assigned to the user.
LDAP_REMOVE_FROM_GROUPS=true

# If you need to debug the group details coming from your LDAP server, uncomment this option
# Only set this option if debugging since it will block logins and potentially show private details.
#LDAP_DUMP_USER_GROUPS=true

Read through the added options carefully. As you can see, there are plenty of comments to help describe what each option does. With that said, it is probably a good idea to break down what is happening with the LDAP_USER_FILTER value. This filter does a few things:

  • (sAMAccountName=${user}) queries AD for the username being used by the person who is trying to log in
  • (memberOf=cn=BookStack Users,cn=Users,dc=example,dc=com) checks if the user is in the BookStack Users group.
  • :1.2.840.113556.1.4.1941: is added to the memberOf condition to check any nested groups. This is useful for when you sync BookStack roles to AD groups because you can store multiple roles within a single BookStack Users group. Here are some examples of how you might use this:
    • BookStack Users group can log in to BookStack
    • BookStack Users/BookStack Admins group can log in and has admin privileges
    • BookStack Users/BookStack Editors group can log in and has editing privileges

Alternatively, you could add an OR statement to the filter and explicitly name each group with something like (|(group_one_DN)(group_two_DN)(group_three_DN)), but it is not as clean and would need to be extended every time a new role was added to BookStack.

It is worth noting that users will still be able to log in and groups will still sync without the additional filtering. However, it will allow all users in the base DN to authenticate to the server regardless of whether or not they are in one of the configured groups. This is not the most secure configuration.

Save your changes to .env, but do not log out of the default admin user yet. Your AD user account won't be able to modify BookStack settings until you map an admin BookStack role to an AD group that your user is in. If you need to log out temporarily to test whether LDAP authentication works at all, you can log back in to the default account later by commenting out the AUTH_METHOD option in .env.

Avatar Fetching

You can use the LDAP_THUMBNAIL_ATTRIBUTE option to pull user avatars from AD. To do this reliably, you should also disable automatic avatar fetching from external sources. The default service used for this is called Gravatar and can be disabled by adding the AVATAR_URL option and setting it to false. Add the following to .env

# Use custom avatar service, Sets fetch URL
# Possible placeholders: ${hash} ${size} ${email}
# If set, Avatars will be fetched regardless of DISABLE_EXTERNAL_SERVICES option.
# Example: AVATAR_URL=https://seccdn.libravatar.org/avatar/${hash}?s=${size}&d=identicon
AVATAR_URL=false

# Set the attribute to use for the user's avatar image.
# Must provide JPEG binary image data.
# Will be used upon login or registration when the user doesn't
# already have an avatar image set.
# Remove this option or set to 'null' to disable LDAP avatar import.
LDAP_THUMBNAIL_ATTRIBUTE=thumbnailPhoto

You can disable all default third-party services by setting the DISABLE_EXTERNAL_SERVICES option to true. Gravatar and draw.io/diagrams.net are the only default third-party services which are identified in the BookStack documentation, but it is possible that other services may be affected as well.

Role and Group Configuration

Create two groups in AD, BookStack Users and BookStack Admins, with the BookStack Admins group being nested inside the BookStack Users group (nesting allows us to take full advantage of the LDAP filter we defined in .env). Once you have created the groups, assign the account you wish to use for BookStack administration to the BookStack Admins group.

In BookStack, go to Settings/Roles and select the Viewer role. We'll be editing this role to match the BookStack Users group in AD. If the permissions applied to this role do not match your needs exactly, you can go back and edit them later.

dvlimage-1.png

Edit the Role Name and External Authentication IDs fields as shown below. BookStack uses the External Authentication IDs field to match BookStack roles to AD groups. You must replace any spaces in the Role Name with a dash/hyphen in the External Authentication IDs field. When you are finished, click the Save Role button at the bottom of the page.

nhVimage.png

sDximage.png

Ideally, the role name should match the group name, but you can really put whatever you want in the Role Name field as long as the External Authentication IDs field can find a match.

Go back to Settings/Roles, select the Admin role, edit the role to match the BookStack Admins group in AD, then save your changes. Once you complete this step, you will be able to log in and make settings changes with the AD user you added to the BookStack Admins group.

jXYimage.png

Cleanup

After confirming that your AD account can log in and has access to BookStack settings, it is a good idea to remove the default admin user in order to prevent potential abuse (example: attacker somehow manages to revert back to local authentication to use the default account credentials). At the very least, you should change the account password to something much more secure.

Go to Settings/Users and select the Admin user.

image.png

You will find the Delete User button toward the bottom of the Edit User page.

uoiimage.png

When given the option to migrate ownership of the Admin user's items, select your AD user's account from the dropdown menu, then click Confirm.

G99image.png

Repeat these steps for any other users and/or roles that you do not intend to use.