Configuration and usage of Gldapo in a Grails project

Configuration and usage of Gldapo in a Grails project

Gldapo is a groovy library for object oriented LDAP access. “The Gldapo is to LDAP what GORM is to SQL”.

Gldapo is packaged in Grails LDAP plugin, its installation is easy. In the root of your Grails project run command:

grails install-plugin ldap

Configuration

The Gldapo is configured in the Config.groovy file. Here follows an example.

ldap {
    directories {
        user { 
            url = "ldap://ldap.zmok.net"
            base = "OU=Users,DC=zmok,DC=net"
            userDn = "CN=usernameToLogToLdap,OU=Users,DC=zmok,DC=net"
            password = "passwordToLogToLdap" 
            searchControls { 
                countLimit = 40 
                timeLimit = 600 
                searchScope = "subtree" 
            }
        }
        group { 
            url = "ldap://ldap.zmok.net"
            base = "OU=Groups,DC=zmok,DC=net"
            userDn = "CN=usernameToLogToLdap,OU=Users,DC=zmok,DC=net"
            password = "passwordToLogToLdap"
            searchControls { 
                countLimit = 40 
                timeLimit = 600 
                searchScope = "subtree" 
            }
        }
    }

    schemas = [ 
        net.zmok.ldap.User,
        net.zmok.ldap.Group
    ]

}

The configuration is self-explaining, except of the schemas part. This is where the magic starts. The classes are object representation of the LDAP entities. So, let’s look how the classes are defined.

package net.zmok.ldap
import gldapo.schema.annotation.GldapoNamingAttribute

class User{
	@GldapoNamingAttribute
	String cn
	String title
	String displayName
	Set memberOf
}
package net.zmok.ldap
import gldapo.schema.annotation.GldapoNamingAttribute

class Group{
	@GldapoNamingAttribute
	String cn
	Set members
	@GldapoSynonymFor("mgr")
	String manager
}

Here, @GldapoNamingAttribute is mandatory and defines the key of the entity. The @GldapoSynonymFor redefines the LDAP names to human-readable format. In our case mgr will be translated to manager.

Manipulation

Usually, one needs to find a few records in an LDAP directory and do something with them. Lets say we need to find members of groups named like “Groovy*” (means GroovyProgrammers, GroovyFans, GroovyHaters) and their managers.
The Gldapo offers findAll method similar to GORM. So, here is the code to list them:

Group.findAll( directory: "group", filter: "(cn=Groovy*)" ).each{ group ->
	def groupName = group.cn
	group.members.each{ member ->
		def user = User.find( directory:"user", filter:"(cn=${member})")
		println "User ${user.displayName} managed by ${group.manager} is member of ${groupName}."
	}
}

Pretty easy, isn’t it? The User and Group classes are similar to GORM classes, so one can create, update, move, replace, delete… and much more. For details see http://http://gldapo.codehaus.org/schemaclasses/entries.html.

14 comments

  1. I am not sure what kind of LDAP directory structures you have, but these examples does not work. I think trying to use these example is almost like apply Java syntax to C#. The example look great, but unless the LDAP structure is set up similar, these example will actually confuse the crap out of everyone who uses it.

  2. This article is really good. I am new to grails and groovy. Can you please provide article with example for ldap authentication with Gldapo ?

  3. Please append the grails command for adding gldapo to the grails project at: “In the root of your Grails project run command:”

    Thanks

  4. We have a grails app nearing production that uses the Gldapo plugin. When we use a filter of “OU=CRP” for example, we can find/locate those employees. But when we broaden the filter to the base of “DC=mycompany,DC=com”, we cannot locate anyone. Any idea what would cause this? It is very frustrating. We have our config.groovy and manipulation set up almost identical to your example(s) above? Could it be a restriction in our Active Directory or something we are missing in the config or manipulation/search?

  5. Maybe the scope of your search is set to “one” or “base” and not “sub” as it should be if you want to descend in each branch to find the entries.

  6. This may sound like a dumb question but where do the class files go? In the domain folder or in the LDAP folder? Can someone show an example of their project layout using gladpo?
    Thanks

  7. I am also having problems with a simple example, as it does not say where to place class files.

    I have created a User class and placed it in the src/groovy directory. I have created a simple controller to do the following
    class TestController {

    def index = {
    def user = User.find( directory:”directory1″, filter:”(uid=Harry,cn=agent,cn=Users,dc=somewhere,dc=org)”)
    ….

    }
    }

    I am getting:
    Executing action [index] of controller [ldap.pi.TestController] caused exception: groovy.lang.MissingPropertyException: No such property: User for class: ldap.pi.TestController

    Any ideas?

  8. This is my configuration file entry
    ldap {
    directories {
    directory1 {
    defaultDirectory = true
    url = “ldap://xxxyyyy.somewhere”
    port = 8899
    userDn = “cn=admin,cn=Users,dc=somewhere,dc=org”
    password = “somepwd”
    searchControls {
    countLimit = 40
    timeLimit = 600
    searchScope = “subtree”
    }
    }
    }

    schemas = [
    User
    ]

    }

  9. How do you specify the authentication method (java.naming.security.authentication)
    I always receive a connection timeout error and i don’t understand why

  10. Thank you for this tutorial! I found it very useful and it got me going.
    A couple of gotchas that i missed were:
    1. Only strings can be used as datatypes for the schemas (or thats all ive discovered so far)
    2. the directory attribute in the find() method refers to the directory defined in the configuration file (had a big duh moment when i saw that)
    3. If you try to specify @GldapoNamingAttribute as an attribute that doesnt exist (i was using ldapsearch which shows a dn attribute) you get an infinite loop!

    Thanks again!

Comments are closed.