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.
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.
Well, knowing the LDAP structure is the must.
This article is really good. I am new to grails and groovy. Can you please provide article with example for ldap authentication with Gldapo ?
Something like this should work.
if (MySchemaClass.find(directory: “example”, filter: “(&(cn=NotSoNew)(sn=User))”)?.authenticate(“passw0rd”))
{
// Do authenticated stuff
}
else
{
// Do non authenticated stuff
}
see http://gldapo.codehaus.org/schemaclasses/entries.html
Please append the grails command for adding gldapo to the grails project at: “In the root of your Grails project run command:”
Thanks
Sorry, a small mistake in formatting. It is fixed now.
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?
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.
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
The classes should be stored in src/groovy.
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?
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
]
}
How do you specify the authentication method (java.naming.security.authentication)
I always receive a connection timeout error and i don’t understand why
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!