When you authenticate to the Identity Server using an authentication class that prompts for a password, you can reuse the password in policies such as Form Fill and Identity Injection. This way, you have single sign-on to the web servers that are configured as reverse proxy. When you authenticate to the Identity Server using a non-password-based authentication class such as X509, NMAS, Radius or Kerberos, the Identity Server will not prompt for a password. Because no password was entered during authentication, it can be a challenge to configure SSO. You should be able to read the password from somewhere, preferably in a secure way.
With NMAS, it is now possible to retrieve your password from an eDirectory tree. You can read Simple Password and Universal Password if you have the right configuration, appropriate eDirectory rights, and the NMAS toolkit. If we use this in combination with a custom Java Data Injection Module, we are able to configure SSO in a secure way.
To achieve this, I created a custom Java Data Injection Module that can read either the Simple Password or the Universal Password. This can be configured in a separate text file. For general information about the Java Data Injection Module, please consult the documentation at:
The first step is to copy two .jars and a configuration file to the Access Gateway. It is the Access Gateway that is responsible to retrieve the data from custom sources; the request is not passed to the Identity Server as with normal policies. This means you must make sure the Access Gateway can communicate with the eDirectory LDAP service and that the port is not blocked by a firewall.
1. Copy the fillpasword.jar and NMASToolkit.jar needs to the Access Gateway. NMASToolkit.jar can also be obtained from the Novell developer website. Put the files in “/var/opt/novell/tomcat4/webapps/nesp/WEB-INF/lib”.
2. In the configuration file “fillpassword.properties”, specify where the LDAP server is located and how to authenticate to it.
3. Place the configuration file in “/var/opt/novell/tomcat4/webapps/nesp/WEB-INF/classes/”.
Figure 1 – Configuration for Fill Password Java Data Injection Module
Here is a list of the Properties:
|url||The location of the ldap server. You must use SSL to read password attributes.|
|bindname||A user with enough rights to read the password properties, this doesn’t need to be an administrator.|
|bindpw||Password for the bind user. If you write and compile the JDIM modules yourself, it might be recommended to encrypt this password property or to compile it in the code to increase security.|
|tree||eDirectory tree name|
|universal||Universal password will be used if this property is set to “yes”; otherwise, the module will read the Simple Password.|
|debug||If the value is set to “yes”, the module will drop some debug lines in catalina.out to troubleshoot the module.|
Because Access Gateway will bind to the LDAP server using SSL, we need to add the LDAP server certificate, or the certificate from the CA that issued the ldap server certificate, to the Java keystore. You can find many methods on the Web to do this; I prefer the following procedure:
1. Use the following command to save the ldap server certificate to a file called ldapcert.der. Be sure to replace ldap.lab.ba:636 with your ldap server address, and if you run this command on your Access Gateway, there is no need to copy files:
NAM-LAG:~ #echo QUIT | openssl s_client -connect ldap.lab.ba:636 2>&1 | sed -ne '/BEGIN CERTIFICATE/,/END CERTIFICATE/p' > ldapcert.der
2. You can check whether the cert was successfully saved by issuing the following command. The subject name and issuer of the certificate will be displayed:
NAM-LAG:~ #openssl x509 -noout -in ldapcert.der -subject -issuer subject= /O=EMEA/CN=ldap.lab.ba issuer= /OU=Organizational CA/O=EMEA
3. Import the certificate into the Java keystore, providing confirmation when asked.
NAM-LAG:~ # /opt/novell/java/jre/bin/keytool -import -keystore /opt/novell/java/jre/lib/security/cacerts -storepass changeit -v -alias ldapcert -file ldapcert.der Owner: CN=ldap.lab.ba, O=EMEA Issuer: O=EMEA, OU=Organizational CA Serial number: 21c0562e55d35e13328defc7d449d45a8c2a6bc5e0975d83c406ff1b4e70201e9 Valid from: Thu Oct 19 13:34:44 CEST 2006 until: Sat Oct 18 13:34:44 CEST 2008 Certificate fingerprints: MD5: C9:7F:B2:BC:C9:38:55:AF:98:D1:5F:8C:C7:FE:0B:31 SHA1: 86:8B:79:C1:0A:33:02:4B:D9:4A:ED:00:8B:CE:BC:CB:0C:BE:14:24 Trust this certificate? [no]: yes Certificate was added to keystore [Saving /opt/novell/java/jre/lib/security/cacerts]
4. Restart Tomcat (or the server) after changing the Java keystore.
Next, create and configure the Identity Injection policy. Depending on where you want to inject the password, you need to create the corresponding Identity Injection Action. The most logical will be the authentication header.
1. Take the User Name from the Credential Profile.
2. For Password, choose “Java Data Injection Module” and set the value to the Java Class name “ba.policy.injection.FillPasswordFactory”.
3. Enable the Identity Injection Policy on the correct protected resource and Apply the configuration.
Figure 2 – Enabling the Identity Injection Policy
Troubleshooting can be divided in two sections: initialization errors and LDAP errors.
To find initialization errors in catalina.out, use the following command and go to the protected resource with a browser.
NAM-LAG:~ # tail -f /var/opt/novell/tomcat4/logs/catalina.out | grep ConfigInitializationError ~~PC~ActionID_1181051337119~~Document=(ou=xpemlPEP,ou=mastercdn,ou=ContentPublisherContainer, ou=Partition,ou=PartitionsContainer,ou=VCDN_Root,ou=accessManagerContainer,o=novell:romaContentCollectionXMLDoc), Policy=(II-Authentication),Rule=(1::RuleID_1181037116238), Action=(InjectCustomHeader::ActionID_1181051337119)~~~~ConfigInitializationError(3)
If you find a ConfigInitializationError in the policy you created, the cause will be most likely that the FillPasswordFactory Class could not be found. Check the location of the fillpassword.jar and check that the Class name is correct in the policy Actions. Another trick to find an initialization error is to check whether the header has been sent to the web server. If there is no header at all, something is wrong with the Class.
To find LDAP configuration errors, enable debug in the fillpassword.properties configuration file. Then you need to look for “BADEBUG” entries in catalina.out. When an LDAP error occur, the header will be send to the web server, but it will be empty.
Here is an example of where the fillpassword.properties configuration file is not found or is corrupt:
NAM-LAG:~ # tail -f /var/opt/novell/tomcat4/logs/catalina.out | grep BADEBUG BADEBUG - No configuration file found BADEBUG - Missing fields in configuration file BADEBUG - 
If the LDAP query was successful, the password should be injected into the header. If this is still not the case, check that the Bind User has enough rights to retrieve the authenticating user password, and that the authenticating user has a Simple or Universal Password set. You can use DSTrace on the LDAP server to troubleshoot this.
NAM-LAG:~ # tail -f /var/opt/novell/tomcat4/logs/catalina.out | grep BADEBUG BADEBUG - <== FillPassword JDIM version 0.99 ==> BADEBUG - LDAP url = ldaps://ldap.lab.ba:636/ BADEBUG - BindUser = cn=admin,o=testlab BADEBUG - Tree = EMEA BADEBUG - Universal = yes
For an LDAP connection error, check the LDAP communication to the server. Also check DSTrace on the LDAP server to find the exact cause of the error (user not found, wrong password, SSL error, etc.).
NAM-LAG:~ # tail -f /var/opt/novell/tomcat4/logs/catalina.out | grep BADEBUG BADEBUG - <== FillPassword JDIM version 0.99 ==> BADEBUG - LDAP url = ldaps://ldap.lab.ba:636/ BADEBUG - BindUser = cn=admin,o=testlab BADEBUG - Tree = EMEA BADEBUG - Universal = yes BADEBUG - LDAP connection error javax.naming.CommunicationException: ldap.lab.ba:636 [Root exception is java.net.ConnectException: Connection refused]
Using Simple Password
The first important prerequisite is that the Simple Password NMAS method is installed and that the authenticating user has the Simple Password set. Look in the documentation to learn more about Simple Password.
Minimum rights are needed for the Bind User operation. After assigning “read and write” rights to the “SAS:Login Configuration” and “SAS:Login Configuration Key” attributes of the object, a bind user should be able to read the Simple Password.
Using Universal Password
The first important prerequisite is that the Universal Password is configured and that the authenticating user has the Universal Password set. Look in the documentation to learn more about Universal Password. Also, the Universal Password should be configured as exportable. This can be done in the Password Policy Configuration – select “Allow admin to retrieve passwords”.
Figure 3 – Password configuration options
Rights Needed for Bind User: “Browse” rights to the authenticating users and “read and compare” rights to attributes of the authenticating users that has Universal Password enabled.
Disclaimer: As with everything else at NetIQ Cool Solutions, this content is definitely not supported by NetIQ, so Customer Support will not be able to help you if it has any adverse effect on your environment. It just worked for at least one person, and perhaps it will be useful for you too. Be sure to test in a non-production environment.