Directory Services

The LDAP configuration has breaking changes between version 7.X and 8.X. The following instructions are for 8.X and higher. The guide for previous versions is available here.

Connecting to the server

Kantree supports LDAP authentication by adding the following to the config file:

extensions:
    - kantree.extensions.auth.ldap:
        server: ldap://localhost
        use_tls: false
        bind_dn: cn=admin,dc=example,dc=com
        bind_password: password

allow_signup: false # optional: disable user signups when using LDAP

Be aware that if you allow signups while using LDAP, this will create the user in Kantree’s database, not in LDAP.

Here is a rundown of the mentioned configuration options:

  • server: an LDAP url to connect to your server
  • use_tls: set to true if your server requires TLS

When a user logs in, Kantree will connect to the server using simple authentification, perform a search for the user object and attempt to connect as the user. Most likely, you will need to bind the connection as a user wich has enough privilege to search through the user directory. Use the following options to specify the bind credentials:

  • bind_dn: The user DN used to bind to the server. This user must have the permissions to query the directory of users
  • bind_password: password for the bind user

Matching users

By default, the query string to search for users is (&(objectClass=inetOrgPerson)(uid=%(user)s)) where %(user)s is replaced with the provided identifier from the login form. This means your user object must have the inetOrgPerson class and their username stored in the uid attribute. If this is not the case, you can use the following options to define the search query:

  • user_dn: base DN to search for users
  • user_filter: the search filter to match users. Use %(user)s as placeholder for the username.

Once the user has been found and that a bind is successful, an account will be created in Kantree. To perform this operation, Kantree needs to know which LDAP attribute to use for the username and email:

  • username_attr: (default: uid) name of the attribute which represents the username.
  • email_attr: (default: mail) name of the attribute which represents the email.
  • display_name_attr: (default: displayName) name of the attribute which represents the display name.

Using groups to define user type

When a user logins or signups, its user type (admin, observer, disabled) can be specified using group membership. If the user is not in any groups, it is considered a normal member.

You will need to provide the DN for the group under the following configuration key;

  • admin_group: users belonging to this ldap group will be Kantree administrators
  • observer_group: users belonging to this ldap group will be observers
  • disabled_group: users belonging to this ldap group will be disabled

Exemple:

extensions:
    - kantree.extensions.auth.ldap:
        # ...
        admin_group: cn=admin,ou=groups,dc=example,dc=com

By default, groups are considered of type groupOfNames. See below to use different types of groups.

Auto join teams

Users can auto-join teams based on their LDAP group memberships. Missing teams will be automatically created.

To define which groups reprensents teams, define the base DN for these groups under the orgs_groups_base_dn configuration key. The attribute for the name of the group can be defined using orgs_groups_name_attr (default: cn).

Exemple:

extensions:
    - kantree.extensions.auth.ldap:
        # ...
        orgs_groups_base_dn: ou=kantreeorgs,dc=example,dc=com

If your groups are not using groupOfNames, see options below.

All configuration options

Connection options

Key Type Default Description
server string   LDAP URL
use_tls bool false Whether to START TLS on connecting
bind_dn string   DN to bind too when connecting (optional)
bind_password string   Password for the binding user

Users options

Key Type Default Description
user_dn string   Base DN to find users
user_filter string (&(objectClass=inetOrgPerson)(uid=%(user)s)) Filter to match users under the base DN
username_attr string uid LDAP attribute representing the username
email_attr string mail LDAP attribute representing the email
display_name_attr string displayName LDAP attribute representing the display name
avatar_attr string jpegPhoto LDAP attribute representing the avatar picture
append_username_domain string   Append a domain to username (unless they already have one). Will append the domain name to the username separated by @

Permissions options

Key Type Default Description
admin_group string   DN of the group which membership will make the user a Kantree admin
observer_group string   DN of the group which membership will make the user an installation wide observer
disabled_group string   DN of the group which membership will disable the user
orgs_groups_base_dn string   Base DN for groups representing Kantree teams (must be specified to use auto-join)
orgs_groups_filter string (objectclass=groupOfNames) Filter to find groups matching orgs under the base DN
orgs_groups_name_attr string cn LDAP attribute used for the team name

Groups options

Key Type Default Description
group_member_attr string member LDAP attribute used to indicate membership in groups
group_member_uid_user_attr string   Attribute of the user object used to match group membership (null value = use DN, available options: username, email, display_name)

Exemple when using PosixGroup instead of groupOfNames:

orgs_groups_filter: "(objectclass=posixGroup)"
group_member_attr: memberUid
group_member_uid_user_attr: username

Active Directory

Active Directory is fully supported after setting the proper configuration options.

If you are trouble establishing a connection, add the following options:

opts:
    referrals: 0
    protocol_version: 3

Regarding users, we recommend the following options:

user_dn: "CN=Users,DC=example,DC=com"
user_filter: "(&(objectClass=user)(sAMAccountName=%(user)s))"
username_attr: sAMAccountName
display_name_attr: cn
avatar_attr: thumbnailPhoto

You will probably need to change the user_dn option (which should be the base DN to look for users).

If you are using userPrincipalName as your username attribute, you will need to set the append_username_domain option with your domain.

user_dn: "CN=Users,DC=example,DC=com"
user_filter: "(&(objectClass=user)(userPrincipalName=%(user)s))"
username_attr: userPrincipalName
append_username_domain: example.com

Note: the domain part of the userPrincipalName will be stripped when converted to a Kantree username

Regarding groups, admin_group, observer_group and disabled_group work as expected. Auto joining orgs need a custom filter if you are using groups which are member of other groups.

Let’s say you have a group name “CN=Kantree,CN=Users,DC=example,DC=com” and another group named “CN=TestOrg,CN=Users,DC=example,DC=com” which is a member of the first. You want users to auto join orgs according to groups which are member of the first. The following configuration can be used:

  orgs_groups_base_dn: "CN=Users,DC=example,DC=com"
  orgs_groups_filter: "(&(objectclass=group)(memberOf=CN=Kantree,CN=Users,DC=example,DC=com))"

Example

Consider the following LDAP directory:

dn: dc=example,dc=com
objectClass: top
objectClass: dcObject
objectClass: organization
o: Example
dc: example

dn: cn=admin,dc=example,dc=com
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator
userPassword: test

dn: ou=users,dc=example,dc=com
objectClass: organizationalUnit
ou: users

dn: ou=groups,dc=example,dc=com
objectClass: organizationalunit
ou: groups

dn: ou=kantreeorgs,dc=example,dc=com
objectClass: organizationalunit
ou: kantreeorgs

dn: cn=admins,ou=groups,dc=example,dc=com
objectClass: groupOfNames
description: Admins
member: uid=peter,ou=users,dc=example,dc=com
cn: admins

dn: cn=disabled,ou=groups,dc=example,dc=com
objectClass: groupOfNames
description: Disabled
member: uid=paul,ou=users,dc=example,dc=com
cn: disabled

dn: cn=Marketing,ou=kantreeorgs,dc=example,dc=com
objectClass: groupOfNames
description: Marketing team
member: uid=peter,ou=users,dc=example,dc=com
cn: Marketing

dn: uid=peter,ou=users,dc=example,dc=com
objectClass: organizationalPerson
objectClass: person
objectClass: inetOrgPerson
uid: peter
sn: Demo
givenName: Peter
cn: Peter Demo
displayName: Peter
userPassword: test
mail: peter@example.com

dn: uid=paul,ou=users,dc=example,dc=com
objectClass: organizationalPerson
objectClass: person
objectClass: inetOrgPerson
uid: paul
sn: Demo
givenName: Paul
cn: Paul Demo
displayName: Paul
userPassword: test
mail: paul@example.com

You can use the following Kantree config:

extensions:
    - kantree.extensions.auth.ldap:
        server: ldap://localhost
        use_tls: false
        bind_dn: "cn=admin,dc=example,dc=com"
        bind_password: test
        user_dn: "ou=users,dc=example,dc=com"
        user_filter: "(uid=%(user)s))"
        username_attr: uid
        email_attr: mail
        admin_group: cn=admins,ou=groups,dc=example,dc=com
        disabled_group: cn=disabled,ou=groups,dc=example,dc=com
        orgs_groups_base_dn: ou=kantreeorgs,dc=example,dc=com