Neat Jira/Cocoon/LDAP tricks

I’m playing with Jira and Confluence lately. These guys managed to provide an impressive set of software indeed, and I’m amazed on how well it works. Yeah, I know, it’s not Open Source, but it’s licensed with a clue anyway (you get the source code, and you can modify it to itch your own scratches).

So far, Jira and Confluence have disappointed me only on a user management issue: they can be integrated with LDAP, but just for password checking purposes. Users have to be manually created and associated to groups, and this promised to be a serious pain, given that we are currently migrating a hundred users, and we might end up with thousands in a forthcoming setup.

Luckily enough, Jira supports Jelly tags to interact with their backend, and I discovered that they had tags to perform user creation and group association. Since all our users are on LDAP, I figured out it would have been enough to dump the user database as a properly formatted XML file with Jelly tags, and with Cocoon it was a piece of cake. Just add a new matcher in a sitemap that reads as follows:

    <map:match pattern="ldap2jira">
        <map:generate src="ldapquery.xml"/>
        <map:transform type="ldap"/>
        <map:transform src="ldap2jira.xsl"/>
        <map:serialize type="xml"/>
    </map:match>

write your LDAP query definition:

<?xml version="1.0" encoding="ISO-8859-1"?>
<LDAPUSER xmlns:ldap="http://apache.org/cocoon/LDAP/1.0">
      <ldap:execute-query>

         <ldap:initializer>com.sun.jndi.ldap.LdapCtxFactory</ldap:initializer>
         <ldap:authentication>simple</ldap:authentication>
         
         <ldap:version>3</ldap:version>
         
         <ldap:serverurl>ldap://ldapserver</ldap:serverurl>
         
         <ldap: port>389</ldap: port>
         <ldap:scope>SUBTREE_SCOPE</ldap:scope>
         
         <ldap:searchbase>ou=your,o=base,c=here</ldap:searchbase>

         <ldap:debug>FALSE</ldap:debug>

         <ldap:deref-link>TRUE</ldap:deref-link>

         <ldap:count-limit>0</ldap:count-limit>
         <ldap:time-limit>0</ldap:time-limit>
                  <ldap:filter>(objectClass=orgPerson)</ldap:filter>

         <ldap:show-attribute>TRUE</ldap:show-attribute>

         <ldap:doc-element>LDAP</ldap:doc-element>
         <ldap:row-element>LDAPSET</ldap:row-element>
                  <ldap:error-element>ELEMENT</ldap:error-element>

         <ldap:attribute>uid</ldap:attribute>
         <ldap:attribute>cn</ldap:attribute>
         <ldap:attribute>mail</ldap:attribute>

      </ldap:execute-query>
</LDAPUSER>

add an almost braindead XSLT:

<?xml version="1.0"?>

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:jira="jelly:com.atlassian.jira.jelly.JiraTagLib"
                xmlns:ldap="http://apache.org/cocoon/LDAP/1.0">

        <xsl:template match="/">
                <JiraJelly>
                        <xsl:apply-templates/>
                </JiraJelly>
        </xsl:template>

        <xsl:template match="ldap:LDAPSET">
                <jira:CreateUser  password="fakePwd" confirm="fakePwd">
                        <xsl:attribute name="username">
                                <xsl:value-of select="ldap:uid"/>
                        </xsl:attribute>
                        <xsl:attribute name="fullname">
                                <xsl:value-of select="ldap:cn"/>
                        </xsl:attribute>
                        <xsl:attribute name="email">
                                <xsl:value-of select="ldap:mail"/>
                        </xsl:attribute>
                        <jira:AddUserToGroup group-name="your-group"/>
                </jira:CreateUser>
        </xsl:template>

</xsl:stylesheet>

and, presto, you’re set! Execute the sitemap, save the output to a file and use it as the input for Jira’s Jelly Runner. This could be easily extended to create groups as well, and I can imagine a number of ways to make the whole process more efficient (python being a nice option). Next step is figuring out how to keep the LDAP directory in sync with Jira’s own user database (even though seamless LDAP integration seems to be in the official roadmap). Being relatively new to Jira, I strongly suspect there was an even easier way, but still it was good to see how this complex migration could be achieved without a single line of code and in 15 minutes flat. Moreover, it was fun, and this is a very good sign of good software quality by itself: rock on Atlassian!

Comments

comments

1 thought on “Neat Jira/Cocoon/LDAP tricks”

  1. Hi,

    I’m very glad you were successful with your user migration. That’s a useful technique. You might also think about sharing it on the JIRA forums (http://forums.atlassian.com/) or the JIRA wiki (http://confluence.atlassian.com/display/JIRACOM/).

    Also, we’re in the middle of a big project to better integrate JIRA and Confluence with LDAP. You can learn more about it here: http://confluence.atlassian.com/x/nt4B . Hopefully it will be bearing fruit soon.

    Cheers,
    jonathan@atlassian.com

Comments are closed.