This provider adds some functionality to the standard OSUser LDAP credentials provider included with Jira 4.0:
- automatic creation of a user in Jira's database upon successful login
- automatic synchronization of the user's LDAP attributes into Jira's profile (via a custom mapping scheme)
- static membership (all LDAP users get automatically added to a Jira group)
- automatic mapping of LDAP group membership to Jira groups (via a custom regex mapping scheme)
- automatic mapping of LDAP OUs to Jira groups (via a custom regex mapping scheme)
- TLS support
- Full caching of LDAP results using ehcache
- Better usage of LDAP connection pool
- Better error handling
- Better code :)
History
- 1.0.3 - Do not remove groups which are also being added, close enumeration which may remain open because of paging
- 1.0.2 - Allow anonymous bind, bug-fixes
- 1.0.1 - Users are now removed from Jira groups when the regexes don't match
- 1.0.0 - Initial release
Installation
Installation of the provider is simple:
- enable external password management in Jira's Administration -> Global Preferences
- put the osuser-autoldap-provider-x.y.z.jar file in Jira's WEB-INF/lib folder (find it in the Download area at the bottom of this page)
- modify the file WEB-INF/classes/osuser.xml to enable the new provider
<opensymphony-user> <authenticator class="com.opensymphony.user.authenticator.SmartAuthenticator"/> <provider class="com.sourcesense.jira.osuser.ldap.AutoLDAPCredentialsProvider"> <property name="java.naming.factory.initial">com.sun.jndi.ldap.LdapCtxFactory</property> <property name="cacheTimeout">30</property> <property name="url">ldap://ldap.domain.com:389</property> <property name="searchBase">DC=domain,DC=com</property> <property name="uidAttribute">sAMAccountName</property> <property name="memberOfAttribute">memberOf</property> <property name="attributeMap">email=mail,fullName=displayName</property> <property name="staticGroups">jira-users</property> <property name="groupMap">jira-developers='CN=JiraDevelopers,.*'</property> <property name="ouMap">jira-managers='.*,OU=Managers,OU=Users,DC=domain,DC=com',jira-observers='.*,OU=Secretaries,OU=Users,DC=domain,DC=com'</property> <property name="principal">CN=jira,OU=Users,DC=domain,DC=com</property> <property name="credentials">secret</property> <property name="useTls">false</property> <property name="serverDateFormat">yyyyMMddHHmmss'.0Z'</property> <property name="exclusive-access">true</property> </provider> <provider class="com.atlassian.core.ofbiz.osuser.CoreOFBizCredentialsProvider"> <property name="exclusive-access">true</property> </provider> <provider class="com.opensymphony.user.provider.ofbiz.OFBizProfileProvider"> <property name="exclusive-access">true</property> </provider> <provider class="com.opensymphony.user.provider.ofbiz.OFBizAccessProvider"> <property name="exclusive-access">true</property> </provider> </opensymphony-user>
Attribute Mapping
attributeMap is a comma-separated list of mappings from LDAP attributes to Jira profile properties structured as follows:
jiraproperty_1=ldapattribute_1,jiraproperty_2=ldapattribute_2,...
It is recommended that this property contain at least the following mapping:
email=mail,fullName=displayName
Static Groups
staticGroups is a comma-separated list of groups which are automatically added to all users authenticated against the LDAP server
jiragroup1,jiragroup2,...
To enable automatic account creation and access to Jira, it is recommended that this property contain at least the following mapping:
jira-users
Group Mapping
groupMap is a comma-separated list of mappings from LDAP membership groups to Jira groups structured as follows:
jiragroup_1='ldapgroupregex_1',jiragroup_2='ldapgroupregex_2',...
LDAP groups are specified using a regular expression which will be matched against the user's membership field (memberOf in most LDAP servers)
DN Mapping
ouMap is a comma-separated list of mappings from LDAP DNs to Jira groups structured as follows:
jiragroup_1='dn_regex_1',jiragroup_2='dn_regex_2',...
Using this feature it is possible to add users to groups based on their location within the LDAP DIT. For example manager, employee and consultant accounts may exist in different subtrees and get different Jira groups added to them:
managers='.*,OU=Managers,.*',employees='.*,OU=Employees,.*',consultants='.*,OU=Consultants,.*'
Source and Binaries
The Subversion repository for this project lives at:
https://dev.sourcesense.com/svn/jira-osuser-autoldap-provider/trunk/
You can get sources and binaries from Sourcesense' public Maven repository at:
| Name | Size | Creator (Last Modifier) | Creation Date | Last Mod Date | Comment | ||
|---|---|---|---|---|---|---|---|
| 13 kB | Tristan Tarrant | Dec 03, 2009 | Dec 03, 2009 | osuser-autoldap-provider v1.0.0 JAR | |||
| 14 kB | Tristan Tarrant | Dec 11, 2009 | Dec 11, 2009 | osuser-autoldap-provider v1.0.1 JAR | |||
| 14 kB | Tristan Tarrant | Dec 15, 2009 | Dec 15, 2009 | osuser-autoldap-provider v1.0.2 JAR | |||
| 14 kB | Tristan Tarrant | Jan 26, 2010 | Jan 26, 2010 | osuser-autoldap-provider v1.0.3 JAR |
Comments (19)
Dec 04
Michael Friman says:
Hi Tristan, Would this work on 3.13.2 enterprise ed.? I´ve been trying to confi...Hi Tristan,
Would this work on 3.13.2 enterprise ed.?
I´ve been trying to configure the solution that Andy Brook made but unfortunately this was impossible, hope your code works better for us. Great job.
//Michael
Dec 09
Tristan Tarrant says:
Hi Michael, I don't think there should be any problems as I'm using only very ba...Hi Michael, I don't think there should be any problems as I'm using only very basic OSUser hooks which have been there forever. The only caveat is that the code is compiled against Java 5.
Dec 14
Andy Brook says:
Tristan, good job, its looking promising! Please review: Jira 3.13.5 osuser.xml...Tristan, good job, its looking promising! Please review:
Jira 3.13.5 osuser.xml
<!-- This is where JIRA's credentials checking can be configured. For instance, see http://www.atlassian.com/software/jira/docs/latest/ldap.html --> <opensymphony-user> <authenticator class="com.opensymphony.user.authenticator.SmartAuthenticator" /> <provider class="com.sourcesense.jira.osuser.ldap.AutoLDAPCredentialsProvider"> <property name="java.naming.factory.initial">com.sun.jndi.ldap.LdapCtxFactory</property> <property name="cacheTimeout">30</property> <property name="url">ldap://xxxxxxxx:3268</property> <property name="searchBase">DC=dolby,DC=net</property> <property name="uidAttribute">sAMAccountName</property> <property name="memberOfAttribute">memberOf</property> <property name="attributeMap">email=mail,fullName=displayName</property> <property name="staticGroups"></property> <property name="groupMap">jira-trustees='CN=UK_WSS_ITDevelopment_Administrator.*',jira-users='^CN=(?!UK_WSS_ITDevelopment_Administrator).*'</property> <property name="principal">CN=xxxxxxxxxxx</property> <property name="credentials">xxxxxxx</property> <property name="useTls">false</property> <property name="serverDateFormat">yyyyMMddHHmmss'.0Z'</property> <property name="java.naming.referral">follow</property> <property name="exclusive-access">true</property> </provider> <provider class="com.atlassian.core.ofbiz.osuser.CoreOFBizCredentialsProvider"> <property name="exclusive-access">true</property> </provider> <provider class="com.opensymphony.user.provider.ofbiz.OFBizProfileProvider"> <property name="exclusive-access">true</property> </provider> <provider class="com.opensymphony.user.provider.ofbiz.OFBizAccessProvider"> <property name="exclusive-access">true</property> </provider> </opensymphony-user>The above config enables users to be created but of two test users (one with UK_WSS_ITDevelopment_Administrator membership, one without) both got added with jira-users membership, I expected only one. Do you have an example config syntax for negation?, Ive tried the following to no avail, any thoughts?:
Stacks, impact: unknown
Also, an optimization, there are lots of logs like, say 200+, note that this only shows up during startup
Dec 14
Tristan Tarrant says:
I'd wrap the content of the <groupMap> node with <!CDATA[]>. I ...I'd wrap the content of the <groupMap> node with <!CDATA[]>.
I will look into reducing the logging.
Dec 14
Andy Brook says:
Hmm, this stuff is easy to get wrong, can you provide an example given the above...Hmm, this stuff is easy to get wrong, can you provide an example given the above data?
Dec 15
Tristan Tarrant says:
There was a serious bug in 1.0.1, grab 1.0.2 and tell me if it works.There was a serious bug in 1.0.1, grab 1.0.2 and tell me if it works.
Jan 11
vivek pulukuri says:
For some reason this plug-in seems to be affecting greenhopper performance. Gre...For some reason this plug-in seems to be affecting greenhopper performance.
Greenhopper runs extremely slow, when this plug-in is installed.
Jan 11
Tristan Tarrant says:
I'll have to try with greenhopper. I'll let you knowI'll have to try with greenhopper. I'll let you know
Jan 25
Alex says:
yeah it really seems to kill the speed of greenhopper. Its unfortunate because t...yeah it really seems to kill the speed of greenhopper. Its unfortunate because this plugin would be perfect for us.
When loading greenhopper, the browser sits there waiting for over a minute for a response from the server.
I got this crash in the logs:
Jan 26
Tristan Tarrant says:
It seems like some contexts/enumerations are not being closed and therefore exha...It seems like some contexts/enumerations are not being closed and therefore exhausting the LDAP connection pool. I am quite certain I've wrapped all of them with proper finally{} blocks which clean them up, but maybe I've missed something.
EDIT: please test 1.0.3 which should fix this
Feb 04
Alex says:
Thanks Tristan, 1.0.3 no longer crashing in the logs so thats good. However, l...Thanks Tristan,
1.0.3 no longer crashing in the logs so thats good.
However, loading up the Greenhopper Planning board takes about 20 seconds. While this has improved from before (over a minute), it takes only a second or two without this plugin.
So there still seems to be something going on that causing it to take so long...
full window
Jan 14
Klaus Kreuzwieser says:
There is a bug in version 1.0.2 evaluating the groupMap property. Example: User...There is a bug in version 1.0.2 evaluating the groupMap property.
Example: User u1 is member of multiple groups g1,g2,g3,g4 in the LDAP directory. All users of group g3 should be jira-developers, so groupMap is jira-developers='CN=g3,.*'. Currently your code below line 460 in AutoLDAPCredentialsProvider.java puts g3 in the item.addGroups as well as in the item.delGroups list. The user is removed from the jira-developers group.
I've created a Java snippet which solves the problem and evaluates the groupMap property correctly.
Please integrate a fix into your version.
Jan 26
Tristan Tarrant says:
I think I have a better solution, by just using java.util.Set.removeAll and remo...I think I have a better solution, by just using java.util.Set.removeAll and removing from delGroups all items which are also in addGroups.
I'll release a 1.0.3 with the fix included.
EDIT: please test 1.0.3 which should fix this
Jan 27
Klaus Kreuzwieser says:
Yes thanks, 1.0.3 fixes the problem.Yes thanks, 1.0.3 fixes the problem.
Jan 18
Joe Shomphe says:
While using version 1.02, we got the following error when bulk editing issues: ...While using version 1.02, we got the following error when bulk editing issues:
2010-01-18 09:50:20,174 http-80-Processor23 ERROR USER 35409x2043x1 ltomrg http://jiraserver/secure/views/bulkedit/BulkEditDetailsValidation.jspa [jira.osuser.ldap.AutoLDAPCredentialsProvider] LDAP Error
javax.naming.CommunicationException: LDAPSERVER:389 [Root exception is java.net.BindException: Address already in use: connect]
at com.sun.jndi.ldap.Connection.<init>(Connection.java:207)
at com.sun.jndi.ldap.LdapClient.<init>(LdapClient.java:118)
at com.sun.jndi.ldap.LdapClient.getInstance(LdapClient.java:1580)
at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2616)
at com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:287)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:175)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:193)
at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:136)
at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:66)
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:667)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288)
at javax.naming.InitialContext.init(InitialContext.java:223)
at javax.naming.ldap.InitialLdapContext.<init>(InitialLdapContext.java:134)
at com.sourcesense.jira.osuser.ldap.AutoLDAPCredentialsProvider.ldapSearch(AutoLDAPCredentialsProvider.java:396)
at com.sourcesense.jira.osuser.ldap.AutoLDAPCredentialsProvider.handles(AutoLDAPCredentialsProvider.java:232)
at com.opensymphony.user.UserManager.getProvider(UserManager.java:269)
at com.opensymphony.user.UserManager$Accessor.getCredentialsProvider(UserManager.java:347)
at com.opensymphony.user.Entity.getCredentialsProvider(Entity.java:59)
at com.opensymphony.user.User.<init>(User.java:52)
at com.opensymphony.user.UserManager$Type$1.create(UserManager.java:47)
at com.opensymphony.user.UserManager$Type$1.create(UserManager.java:45)
at com.opensymphony.user.UserManager.buildEntity(UserManager.java:295)
at com.opensymphony.user.UserManager.getEntity(UserManager.java:261)
Jan 26
Tristan Tarrant says:
Could you please test with 1.0.3 which should fix this problem ?Could you please test with 1.0.3 which should fix this problem ?
Jan 27
Klaus Kreuzwieser says:
I've found another problem (at least for us): The LDAP plug-in treats usernames ...I've found another problem (at least for us): The LDAP plug-in treats usernames case senstive. Since every user will be created, when it is not found in the JIRA database a user can be created multiple times. This is especially bad if a user is in a developer group, because you see the user multiple times in the assign-to field.
Example: user1, USER1, User1 = 3 users are created in the JIRA database
I've researched a bit and found a workaround for this problem: JIRA uses the class com.atlassian.seraph.filter.LoginFilter to extract the username and password from the HttpServletRequest. I'm converting the username to lowercase to avoid any following troubles.
To compile you've to add the following dependecies in pom.xml.
The atlassian-seraph classes are packaged into atlassian-seraph-2.0.1.jar file. To load the modified LoginFilter first, rename the plug-in jar file to aa-osuser-autoldap-provider-1.0.3.jar.
Feb 10
Andy Gonzales del Valle says:
Hi, This plugin work with JIRA 4.0?Hi,
This plugin work with JIRA 4.0?
Feb 15
Steve Warin says:
Hi Tristran, We are trying to limit the users who can login and automatically cr...Hi Tristran,
We are trying to limit the users who can login and automatically create a JIRA account to those who are members of a particular LDAP group. Lets say we want users in the "ourstaff" group who do not already have a JIRA account to be able to create one by logging in with their LDAP userame and password.
I've had your Jira OSUser automatic LDAP provider working fine when we simply allow any user in the LDAP directory to do this, with the following entry in the osuser.xml file:
<property name="searchBase">ou=users,dc=example,dc=com</property>
Using Softerra LDAP Browser, the following Base entry results in a list of all the users in the "ourstaff" group:
cn=ourstaff,ou=groups,dc=example,dc=com
but in Jira using the OSUser automatic LDAP provider this does not work when I attempt to login as an existing user name when the osuser.xml file has:
<property name="searchBase">cn=ourstaff,ou=groups,dc=example,dc=com</property>
If I enter this as BaseDN into the Jira "LDAP Configurer" page: "cn=ourstaff,ou=groups,dc=example,dc=com" it also does not work, giving the message: "Connected, but could not find any LDAP records where 'uid=username' below cn=ourstaff,ou=groups,dc=example,dc=com"
Do you know if there other properties in the osuser.xml file that need altering to limit users to a particular group? Has anyobody else experience of doing something similar and can give me some pointers?
Thanks.