| This configuration is not supported. Please see USER-105. |
Instructions here relate to use of the command line 'ldapsearch' utility to check that mappings between Atlassian User and your LDAP system are correct.
Mappings between LDAP and Atlassian User.
Here is an explanation of each property in the atlassian-user.xml file.
| Property Key | Example Value | Description | Link |
|---|---|---|---|
| baseUserNamespace | ou=users | This namespace should identify your DIT's (Directory Information Tree) base context holding user accounts. This is absolute, not relative to baseContext. | see below |
| baseGroupNamespace | ou=groups | This namespace should identify your DIT's base context holding groups. This is absolute, not relative to baseContext. | see below |
| userSearchAllDepths | false | true to search all subtrees beneath baseUserNamespace, false to search one level beneath it only | see below |
| groupSearchAllDepths | false | true to search all subtrees beneath baseGroupNamespace, false to search one level beneath it only | see below |
| usernameAttribute | uid | This attribute should identify the RDN (Relative Distinguished Name) of the user entry | see below |
| groupnameAttribute | gid | This attribute should identify the RDN of the group entry | see below |
| firstnameAttribute | givenname | This attribute should identify the first name of the user | see below |
| surnameAttribute | sn | This attribute should identify the surname of the user | see below |
| emailAttribute | This attribute should identify the email address of the user | see below | |
| membershipAttribute | atlassianGroupMemberOf | This attribute should identify which groups the user belongs to. | see below |
| userSearchFilter | (objectClass=inetorgperson) | This property represents an additional search filter ANDed to each query for a user (see RFC 2254) | see below |
| groupSearchFilter | (objectClass=group) | This property represents an additional search filter ANDed to each query for a group (ibid) | see below |
Also read below to learn how to specify a group adaptor, LDAP user and group factories, and a LDAP user searcher.
Converting Special Characters
There are 5 special characters that you must escape when saving search filters to the atlassian-user.xml file.
| LDAP Character | XML Equivalent | Description |
|---|---|---|
| < | < | less than |
| > | > | greater than |
| & | & | ampersand |
| ' | ' | apostrophe |
| " | " | quotation mark |
User Mappings
1. Identifying the baseUserNamespace and the userSearchAllDepths mappings
The baseUserNamespace indicates the top level of a tree in your LDAP system which holds your users. The userSearchAllDepths property can either be set to true or false. True indicates that only the level directly beneath the baseUserNamespace should be searched, false indicates that all additional sub-levels of the tree should be searched.
For example, if you wanted to include users beneath 'cn=contractors,cn=employees,cn=acme,cn=org' and users beneath 'cn=permanent,cn=employees,cn=acme,cn=org' in an Atlassian application you would specify a baseUserNamespace of 'cn=employees,cn=acme,cn=org' with a userSearchAllDepths value of 'true'. Otherwise, if all users are grouped in one level of your tree, set userSearchAllDepths to false.
[nickf@little-creatures dls]$ ldapsearch -h 'localhost' -p 389 -D 'cn=admin,dc=atlassian,dc=private' -x -w secret -b 'ou=people,dc=atlassian,dc=private' -s sub # extended LDIF # # LDAPv3 # base <ou=people,dc=atlassian,dc=private> with scope sub # filter: (objectclass=*) # requesting: ALL # # people, atlassian.private dn: ou=people,dc=atlassian,dc=private objectClass: top objectClass: organizationalUnit ou: people ... etc.
Would lead to the following values for baseUserNamespace , userSearchAllDepths, and usernameAttribute:
baseUserNamespace=cn=employees,cn=acme,cn=org userSearchAllDepths=true
[nickf@little-creatures dls]$ ldapsearch -h 'localhost' -p 389 -D 'cn=admin,dc=atlassian,dc=private' -x -w secret -b 'ou=people,dc=atlassian,dc=private' -s one # extended LDIF # # LDAPv3 # base <ou=people,dc=atlassian,dc=private> with scope one # filter: (objectclass=*) # requesting: ALL # # ldapusera, people, atlassian.private dn: cn=ldapusera,ou=people,dc=atlassian,dc=private objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson cn: ldapusera sn: ldapuseraSN givenName: ldapuseraGN mail: ldapusera@testingarea.org userPassword:: cGFzc2E= ... etc.
Would lead to the following values for baseUserNamespace and userSearchAllDepths:
baseUserNamespace=cn=employees,cn=acme,cn=org userSearchAllDepths=false
Here, also, the usernameAttribute property is identified as being 'cn'. The property mapping therefore becomes
usernameAttribute=cn
2. Identifying the userSearchFilter
The userSearchFilter allows for an extra condition to be placed on search results. This is useful if a search on the baseUserNamespace is returning results which will not equate to User objects. Use it to specify a search criteria which will identify users.
[nickf@little-creatures dls]$ ldapsearch -h 'localhost' -p 389 -D 'cn=admin,dc=atlassian,dc=private' -x -w secret -b 'ou=people,dc=atlassian,dc=private' -s sub '(objectClass=inetorgperson)' # extended LDIF # # LDAPv3 # base <ou=people,dc=atlassian,dc=private> with scope sub # filter: (objectClass=inetorgperson) # requesting: ALL # # ldapusera, people, atlassian.private dn: cn=ldapusera,ou=people,dc=atlassian,dc=private objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson cn: ldapusera sn: ldapuseraSN givenName: ldapuseraGN mail: ldapusera@testingarea.org userPassword:: cGFzc2E=
Here, we specify userSearchFilter as '(objectClass=inetorgperson)'. That is, we are saying our users are identified by an objectClass of inetorgperson (given our search result above, we could have also used organizationalPerson or person). Please note that inetorgperson is an LDAP objectClass. It does not exist in Active Directory. You will need to specify a different class if using AD.
3. Identifying the firstnameAttribute, surnameAttribute, and emailAttribute
As with the identification of username property search above, similar mappings can be found for firstnameAttribute, surnameAttribute, and emailAttribute.
firstnameAttribute=givenname surnameAttribute=sn emailAttribute=mail
Group Related Mappings
4. Identifying the groupnameAttribute and the baseGroupNamespace mappings
The tactic here is similar identifying the baseUserNamespace and userSearchAllDepths attributes.
It is assumed that groups are entries in their own right within your LDAP system. If groups exist by virtue of being listed against user entries, or in some other way, please raise a support request to discuss an integration plan.
The baseGroupNamespace indicates the top level of a tree in your LDAP system which holds groups. As with userSearchAllDepths, setting groupSearchAllDepths to true instructs the search function to traverse all available subtrees beneath the baseGroupNamespace. Set it to false if all of your groups are contained in the level indicated by baseGroupNamespace.
Static vs Dynamic Groups
Groups are generally one of two types in LDAP systems - static or dynamic. A static group maintains its own membership list. A dynamic group records its membership on a user entry.
Here is an example of a search on an OpenLDAP DIT (Data Information Tree), which stores static groups.
[nickf@little-creatures ~]$ ldapsearch -h 'localhost' -p 389 -D 'cn=admin,dc=atlassian,dc=private' -x -w secret -b 'ou=groups,dc=atlassian,dc=private' -s sub # extended LDIF # # LDAPv3 # base <ou=groups,dc=atlassian,dc=private> with scope sub # filter: (objectclass=*) # requesting: ALL # # groups, atlassian.private dn: ou=groups,dc=atlassian,dc=private objectClass: top objectClass: organizationalUnit ou: groups # groupA, groups, atlassian.private dn: cn=groupA,ou=groups,dc=atlassian,dc=private objectClass: top objectClass: groupOfNames cn: groupA member: cn=ldapusera,ou=people,dc=atlassian,dc=private member: cn=ldapuserb,ou=people,dc=atlassian,dc=private
The baseGroupNamespace is identified as being 'ou=groups,dc=atlassian,dc=private', the groupSearchAllDepths is 'false', and the groupnameAttribute as being 'cn':
baseGroupNamespace=ou=groups,dc=atlassian,dc=private groupSearchAllDepths=false groupnameAttribute=cn
Here is an example of a search on an Apache Directory Server DIT (Data Information Tree), which stores dynamic groups.
[nickf@little-creatures user_standalone]$ ldapsearch -D 'uid=admin,ou=system' -h localhost -p 10389 -x -w secret -s one -b 'ou=groups,ou=system' '(objectclass=group)' # extended LDIF # # LDAPv3 # base <ou=groups,ou=system> with scope one # filter: (objectclass=group) # requesting: ALL # # groupA, groups, system dn: uid=groupA,ou=groups,ou=system ou: Teams ou: Human Resources cn: groupA objectclass: group objectclass: top uid: groupA l: groupA
Here the baseGroupNamespace is 'ou=groups', groupNameAttribute is 'cn', and groupSearchFilter is false.
baseGroupNamespace=ou=groups groupnameAttribute=uid groupSearchAllDepths=false
You will notice that for the baseGroupNamespace I drop the full path: <ou=groups,ou=system> . This is just for convenience with ApacheDS. Whereas OpenLDAP requires the baseGroupNamespace mapping to be the full DN of the node, ApacheDS uses the baseContext property specified in connection.properties to complete it.
5. Identifying the groupSearchFilter filter.
As with the userSearchFilter property, the groupSearchFilter allows you to specify an added search criteria to all search results. This is useful if your baseGroupNamespace holds data which cannot be modelled into a Group alongside data which can be.
Please see the discussion on userSearchFilter for an example of how to build this property.
| The default value for this filter is (objectClass=groupOfNames). If you are using Active Directory, please change it to (objectClass=group) or select another objectClass that exists in your instance |
Membership Mappings
6. Identifying a membership attribute
There are two requirements for membership mappings to work.
- The membership value must carry the DN of the user or group, for static and dynamic groups respectively.
- The search for membership is constructed by using the username or groupname, for static or dynamic groups, attribute and attribute value, along with the the baseContext. If these values do not match membership will not work.
The membershipAttribute property can be identified via the same search which identified the baseGroupNamespace . On a static group, an attribute will be present to identify a membership list.
For example, in the search result below, the membershipAttribute is 'member'.
# groupA, groups, atlassian.private dn: cn=groupA,ou=groups,dc=atlassian,dc=private objectClass: top objectClass: groupOfNames cn: groupA member: cn=ldapusera,ou=people,dc=atlassian,dc=private member: cn=ldapuserb,ou=people,dc=atlassian,dc=private
membershipAttribute=member
Whereas, in the example for dynamic above, the membershipAttribute is not on the group but, instead, on the user:
[nickf@little-creatures ~]$ ldapsearch -h 'localhost' -p 10389 -D 'uid=admin,ou=system' -x -w secret -b 'ou=users,ou=system' -s sub # extended LDIF # # LDAPv3 # base <ou=users,ou=system> with scope sub # filter: (objectclass=*) # requesting: ALL # # users, system dn: ou=users,ou=system ou: users objectClass: organizationalUnit objectClass: top # ldapusera, users, system dn: uid=ldapusera,ou=users,ou=system sn: Surname1 ou: People ou: Human Resources cn: ldapusera objectclass: atlassianPerson objectclass: inetOrgPerson objectclass: organizationalPerson objectclass: person objectclass: top uid: ldapusera userpassword:: cGFzc2E= givenname: ldapusera mail: ldapusera@testingarea.org member: cn=groupA,ou=groups,ou=system l: Atlassian test subject ... etc.
membershipAttribute=atlassianGroupMemberOf

Comments (11)
Feb 08, 2006
Amos Gouaux says:
Is there any significant performance differences between static and dynamic grou...Is there any significant performance differences between static and dynamic groups?
Feb 17, 2006
Andrew Miller says:
As far as Confluence is concerned, it should just be an LDAP query so performanc...As far as Confluence is concerned, it should just be an LDAP query so performance would really be dependent on your LDAP directory (some directories are faster with static groups than dynamic groups).
May 24, 2006
YL says:
Does this LDAP integration support nested group? I guess I need t...Does this LDAP integration support nested group? I guess I need to set groupSearchAllDepths to true? If I have group AB nested under group A, will member in group AB be recognized as a member of group A?
Aug 10, 2006
David Soul [Atlassian] says:
Sorry, nested groups are not supported, so group AB is not recognised as a membe...Sorry, nested groups are not supported, so group AB is not recognised as a member of A. You'll need to set groupSearchAllDepths to true.
May 17, 2007
Michael Redinger says:
This document explains in detail the difference between static and dynamic group...This document explains in detail the difference between static and dynamic groups.
However, Add LDAP Integration says that static groups are needed.
I found a JIRA issue which basically says that only static groups are suppported, but that dynamic groups should work somehow, too: http://jira.atlassian.com/browse/USER-105
So: Do dynamic groups work, although there seems to be no documentation except this page? And if yes, could someone give a quick example on how to use them?
Oct 22, 2007
John Allen says:
Yes dynamic groups workYes dynamic groups work
Aug 16, 2007
David Peterson [CustomWare] says:
Wow. This page is really hard to digest. In particular, it is really hard to und...Wow. This page is really hard to digest. In particular, it is really hard to understand how to get Confluence to use dynamic groups. Could the page be rearranged so that the static group instructions are together, and the dynamic group instructions are together. At the moment they are spread all over the place.
Also, it is really unclear how to specify that it should be getting group membership from the user (aka dynamic groups), as opposed to the group. The only clue above is the 'membershipAttribute=atlassianGroupMemberOf' entry above, which doesn't seem to relate to the example above it at all. What is this mysterious 'atlassianGroupMemberOf'? Is it a special attribute name which tells Atlassian User that it should use the user's 'memberOf' attribute to determine group membership? Or something else?
Nov 16, 2007
senthilraja says:
Hi, We have a requirement, where we have multiples of DL groups nested in...Hi,
We have a requirement, where we have multiples of DL groups nested in multiple order.
When we assign group permissions to a space, we require that even if the users belong to one of the sub-level groups, should be authenticated.
Will groupSearchAllDepths solve the problem?
Feb 08, 2008
John Allen says:
Are there any plans for adding support for pulling XMPP ids out of LDAP? Bamboo ...Are there any plans for adding support for pulling XMPP ids out of LDAP? Bamboo would obviouslybenefit
Mar 28, 2008
Nick Campbell says:
I have a couple of questions. The first is, does this support multiple group ty...I have a couple of questions.
The first is, does this support multiple group types in the same system? If so, how do we specify in the xml that groups can be dynamic or static?
My next question is with the dynamic groups. We have a few of them. Our dynamic groups are done with an actual search using the ldap protocol "ldap://<server>...(objectclass=*)". While thats an example, it's similar to how we have dynamic groups. Does confluence handle this kind of dynamic group setup or do the users need to have a specific attribute on their object where the values are their groups?
Let me know, thanks!
- Nick
Dec 05, 2008
Stephen Edwards says:
So, this document is not very good, but I did manage to figure out how to make d...So, this document is not very good, but I did manage to figure out how to make dynamic LDAP groups work. (Using 2.9.2 Standalone).
First of all as http://jira.atlassian.com/browse/USER-105 explains, you need to add a class to your atlassian-user.xml. So, inside of the <ldap> tags add this:
<classes> <groupAdaptor>com.atlassian.user.impl.ldap.adaptor.LDAPDynamicGroupAdaptor</groupAdaptor> </classes>Next, the example above of a user query in a dynamic group LDAP is wrong. Here's what the query results should look like:
This means that in atlassian-user.xml you want:
In this example my user account would then be recognized as a member of the helpdesk rbsgroup.
One other thing that I ran into was the groupSearchFilter, if you are unsure on this one set it to:
I hope that helps clarify.
-Steve