Sunday Jul 19, 2009

Identity Manager: adding versioning information to your deployment

Identity Manager projects using the NetBeans IDE plugin usually face the problem that when deploying the application e.g. idm.war and loading the custom objects in the database repository (e.g. via lh import custom-init-full.xml). If you use Subversion or CVS, there is a quick and easy way to include a revision number with every build. There a two components which need a revision number:
  • the web application (here we include a page called 'about.html' which dislays the svn revision number)
  • the repository (here we add a dummy IDM object e.g. an E-Mail Template which contains the revision number of the working copy when building idm.war). If you import your custom-init-full.xml file, the E-Mail will be imported into the repository. We will use a JSP to retrieve the object from within the BUI
[Read More]

Friday Oct 24, 2008

The easiest OpenSSO install ever


I always found the Java webstart installation of OpenDS a nice thing for developers. A similar method now exists

for OpenSSO: simply click on OpenSSO JavaWebstart. It uses an the embedded version of (the not yet released) Glassfish v3 application server.


Any developer who simply need a running OpenSSO instance: this is the easiest way to get it.

Wednesday May 28, 2008

Cardspace compromised?

My colleague Jörg was listening to the radio when they broadcasted that a weakness in Microsoft's
Cardspace identity metasystem has been found. Here's the link http://demo.nds.rub.de/cardspace/.

From a quick look, the attack is rather an application to dynamic pharming (DNS pinning) and general
browser/user security than an attack on the CardSpace protocol itself. The only thing which is CardSpace related is the fact that a security token can be replayed and that CardSpace doesn't require an undeniable token: whoever possesses the token has access to the service provider. Sun Access Manager has a (weak) approach to undeniable tokens by tying them to an IP address. However, this might lead to problems as in many setups HTTP proxies are used.

The "CardSpace" attack again shows that two or three security issues can easily add up to a bigger problem.

Thursday Apr 10, 2008

Vaau, Roles and Identity

The acquisition of Vaau enriches our identity portfolio by a role mining and management tool. Tried to figure out the main differences and areas of application between RBACx and Sun's Identity Manager. First of all, Vaau's RBACx (Sun Role Manager) is more a configurable tool rather than a programmable tool as for example Sun's Identity Manager. Programmable means that the configuration language includes things like IF THEN ELSE, WHILE loops. So Identity Manager can be applied to many areas and programmed as desired.

Role Manager is quite static compared to Identity Manager. It has its fixed area of application which is compliance and role management (including role mining). This makes it more a management tool rather than an administration tool. Role Manager can talk to Identity Manager via SPML. So you can drag out all user data from Identity Manager and import it via SPML into Role Manager.

Which tool to start with? Apart from that there is no 'one size fits all' when it comes to enterprise apps, I would recommend to start with a privisioning tool which (IDM). First, you need data cleansing

  • find out stale data (accounts, attributes etc)
  • check for compliance violations, segregation of duties

Both tasks can be done with Identity Manager or with Role Manager. However, my personal view is that Identity Manager is more flexible because it accesses data online whereas Role Manager needs a CSV file for data loading if you don't drag out the data via SPML. Compliance tasks and attestation can be implemented in either.

Second, role mining is a nice feature when you haven't defined your roles yet. Role mining is not a black art. It uses a covering algorithm to help the role designer in a way a CAD system helps technical designers. The important point here is that the outcome of the mining process is where technology meets business: whether or not a mined role is useful depends on the business.

The mined roles can be amended to meet business criteria and then be exported to an identity management system (e.g. Sun's Identity Manager) from where the entitlements can be provisioned to the target systems (RACF, AD, LDAP etc). Overall impression: good tool. But beware it's called Role Manager and not sox.exe or security.exe.

Monday Mar 17, 2008

Single Sign On to Google using OpenSSO

Google has a SAML 2 capable single-sign-on service by which you can use Google as a service provider (SP). Google also provides a sample demo application. Rather than using Liberty Alliance's circle-of-trust model, Google uses a peered structure: if Google's SSO service (SP) receives a SAML response, it checks the signature of that request. If the signature is valid, the SAML assertion will be accepted.

Trying to use Google's demo code with OpenSSO as an identity provider (IDP) requires some tweaks.

Step 1: Making OpenSSO to accept Google's SAML request
  1. The SAML request sent out by Google's demo code cannot be understood by OpenSSO due to a compression (deflate) problem (from what I saw in the code, it seems that Google inflates according to RFC 1950 but SAML specification dictates RFC 1951 and that's also what OpenSSO implements). All you need to do to replace Google's RequestUtil.encodeMessage(String) code with OpenSSO's SAML2Utils.encodeForRedirect(String).
  2. Google's code uses a simple template for constructing the SAML request. In fact too simple for OpenSSO. Add a few XML elements to the AuthnRequestTemplate.xml
  3. <?xml version="1.0" encoding="UTF-8"?>
    <AuthnRequest xmlns="urn:oasis:names:tc:SAML:2.0:protocol"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="urn:oasis:names:tc:SAML:2.0:protocol file:/Documentation/Federation-SAML-Liberty/SAML%202.0/XSD/saml-2.0-os-xsd/saml-schema-protocol-2.0.xsd" 
        ID="<AUTHN_ID>" 
    	Version="2.0"
    	IssueInstant="<ISSUE_INSTANT>"
    	ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
    	ProviderName="<PROVIDER_NAME>"
                ForceAuthn="true"
    	AssertionConsumerServiceURL="<ACS_URL>">
    <Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion" format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">
    google
    </Issuer>
     <Subject xmlns="urn:oasis:names:tc:SAML:2.0:assertion">
            <NameID>google</NameID>
     </Subject>
    </AuthnRequest>
    
  4. Point ssoURL in CreateRequestServlet.doPost(HttpServletRequest, HttpServletResponse) to you OpenSSO instance (e.g. http://localhost:8080/opensso/idpSSOFederate/metaAlias/idp where 'idp' is your IDP entity.
Step 2: Making Google applications to accept OpenSSO's SAML response
  1. Import Google's sample private key to Java keystore. Since keytool cannot import arbitrary private keys, I convert Google's keys to PKCS#12 and then use one of the PKCS12Import classes (source can be found on the net) to import the key to JKS.
  2. Since Google's keys are DSA keys and are only good for signing, but not for encrypting you need to tell OpenSSO via browser GUI (Service Configuration > Global > Common Federation Configuration) to sign, but not to encrypt the SAML response.
  3. You also need an account mapper that generates the SAML response message. Pat Patterson posted a sample on the OpenSSO mailing list (check the OpenSSO archives). Google wants the email address as an identity ('demouser@psosamldemo.com' is the default one in case you don't own a Google apps premier account). You can use Pat's version out of the box if your OpenSSO user has ID='demouser@psosamldemo.com' or you can extend Pat's code returning the user's email adress (e.g. via OpenSSO's DataStoreProvider.getAttribute(String, String)).

Friday Mar 14, 2008

Identity Manager IDE 8.0 is open-source

The new IDE (https://identitymanageride.dev.java.net) comes as a NetBeans Plugin. Quick tests show that it's stable. Compared to the IDM 7.x IDE,
you can use the new version with NetBeans 6 and also Eclipse (if you like to work in the dark ;-).

Wednesday Nov 14, 2007

Leopard (Mac OS 10.5) / Mac OS X 10.4 and Java 6

In case, you're looking for Java 6 on Mac OS X (10.4/10.5): https://connect.apple.com

It's the roughly same 'old' build we've seen before:

teufelchen: steffo$ /System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home/bin/java -version
java version "1.6.0-dp"
Java(TM) SE Runtime Environment (build 1.6.0-dp-b88-34)
Java HotSpot(TM) Client VM (build 1.6.0-b88-17-release, mixed mode, sharing)

Monday Nov 05, 2007

Monitoring Identity Manager

Sun Java System Identity Manager has decent JMX capabilities which allows you to

  • check reconciliation status
  • check whether all connected systems (resources) are available
  • monitor the status of the server
  • many, many other things

In order to use these features, you only have to enable JMX (disabled by default) via "Configure > Servers" from the HTTPS admin interface. Additionally, you have to 'enable' JMX at the application server level. For Tomcat, you can add the following to the catalina.sh

JAVA_OPTS="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false
    -Dcom.sun.management.jmxremote.port=9002 
    -Dcom.sun.management.jmxremote.password.file=/System/Library/Frameworks/JavaVM.framework/Versions/1.5.0/Home/lib/management/management.jmxremote.password 
    -D java.rmi.server.hostname=localhost 
    -Dcom.sun.management.jmxremote.ssl=false"

You can see a bunch of JMX data at e.g. http://localhost:8080/idm/debug/Show_MBeanInfo.jsp. You could also tools like jconsole to set and query JMX attributes.

The big question is "How to integrate IDM into a system monitoring tool?" is quite easy to answer since there is a small Java program called 'jmxquery'. Unfortunately I do not know who the author is but all credits go to her or him. What we want to achieve is that IDM‘s status and the resources health check show in our monitoring tool. E.g. with nagios you'll get the following screen

Picture 2

The basic idea is that Nagios calls an external programm like a (modified) version of jmxquery which able to retrieve and set IDM's JMX objects. Three things are sufficient

  • jmxquery tool
  • a modification of Nagios' command.cfg
  • a modification of Nagios' localhost.cfg

You can find the modified jmxquery as a NetBeans project file here:

IDM-Nagios.zip
Add the following lines to command.cfg

##############################
#
#
# Sample commands for Sun Java System Identity Manager
#
##############################


define command{
        command_name     check-idm-resources
        command_line    /opt/lib/nagios/check_jmx -IDM resources
}

define command{
        command_name     check-idm-server-status
        command_line    /opt/lib/nagios/check_jmx -IDM serverStatus
}

Now modify localhost.cfg by adding
define service{
       use                             local-service         ; Name of service template to use
       host_name                       localhost
        service_description             IDM Status
        check_command                                           check-idm-server-status
        }

define service{
       use                             local-service         ; Name of service template to use
        host_name                       localhost
        service_description             IDM Connected Systems
        check_command                                           check-idm-resources
       }
Of course, this can only be used for demo purposes as there is no security wrt to JMX access.

Tuesday Sep 25, 2007

A standalone OpenSSO client

OpenSSO has a server part (deployed behind a /fam URI or similar) and a client part (e.g. a J2EE agent, or the OpenID extension). In any case you have ensure that the AMConfig.properties for each part do correspond w.r.t. encryption keys, agent IDs etc. Since debugging an J2EE agent or even OpenID extension might be unfeasible (at least as a first step), I use a stand-alone client which sources the AMAgent.properties used by e.g. the OpenID extension.

The following code is example and works well for OpenSSO, Sun Java System Access Manager (7.0 and 7.1) all deployed in realm mode.

To build the JAR, make sure that you include the OpenSSO Client SDK as well as the servlet.jar to your (NetBeans) project.

/\*
 \* OpenSSOConnect.java
 \*
 \* Created on November 2, 2006, 11:18 AM
 \*
 \* To change this template, choose Tools | Template Manager
 \* and open the template in the editor.
 \*/

/\*\*
 \*
 \* @author steffo
 \*/


// OpenSSO installation has a default realm 'init8' as well as an authentication chain 'init8'

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.ChoiceCallback;
import javax.security.auth.callback.ConfirmationCallback;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.TextInputCallback;
import javax.security.auth.callback.TextOutputCallback;
import javax.security.auth.callback.UnsupportedCallbackException;

import netscape.ldap.util.DN;

import com.iplanet.am.util.SystemProperties;
import com.iplanet.sso.SSOToken;
import com.sun.identity.authentication.AuthContext;
import com.sun.identity.idm.AMIdentity;
import com.sun.identity.idm.AMIdentityRepository;
import com.sun.identity.idm.IdRepoException;
import com.sun.identity.idm.IdSearchControl;
import com.sun.identity.idm.IdSearchOpModifier;
import com.sun.identity.idm.IdSearchResults;
import com.sun.identity.idm.IdType;
import com.sun.identity.idm.IdUtils;
import com.sun.identity.security.AdminTokenAction;


import com.sun.identity.authentication.spi.AuthLoginException;


public class OpenSSOConnect {

	public static void main(String[] argv) {
		boolean remote = false;
		if (argv.length > 0) {
			String r = argv[0];
			if (r.equalsIgnoreCase("remote")) {
				remote = true;
			}
		}
		Properties props = new Properties();

		try {
                        //Point this to the AMConfig.properties, you want to check
			FileInputStream amconfig = new FileInputStream("/Users/steffo/Projekte/OpenSSO/OpenID-Provider/src/opensso/extensions/openid/provider/resources/AMConfig.properties");
			
			props.load(amconfig);
		} catch (IOException e) {
			System.out.println("AMConfig.properties was not found");
		}

		props.setProperty("com.iplanet.services.debug.level", "message");
                props.setProperty("com.iplanet.am.naming.ignoreNamingService", "true");
		
                //remote=true;
		if (remote) {
			props.setProperty("com.iplanet.am.sdk.package", "com.iplanet.am.sdk.remote");
		} else {
			props.setProperty(AdminTokenAction.AMADMIN_MODE, "true");
		}
		System.out.println("Properties set");
		SystemProperties.initializeProperties(props);
		try {
			SSOToken token = getSSOToken();
			System.out.println("Getting AMIdentityRepository object");

			AMIdentityRepository idrepo = new AMIdentityRepository(token, "init8");
                        
                       

			System.out.println("Using TOKEN to get AMIdentity object " + "and read attrs");
			AMIdentity tmpId = IdUtils.getIdentity(token);
			System.out.println("Calling Attributes getting all attributes: " + tmpId.getAttributes());
						

		} catch (Exception ex) {
			ex.printStackTrace();
		}
		System.exit(0);
	}

	public static SSOToken getSSOToken() throws Exception {
                //We created a user 'steffo' with credenials 'password'
		return getSSOToken("init8", "steffo", "password");

	}

	protected static SSOToken getSSOToken(String org, String uid,
			String password) throws Exception {

		AuthContext ac = new AuthContext(org);
		ac.login(AuthContext.IndexType.SERVICE, "init8");
		Callback[] callbacks = null;
		if (ac.hasMoreRequirements()) {
			callbacks = ac.getRequirements();

			if (callbacks != null) {
				try {
					addLoginCallbackMessage(callbacks, uid, password);
					ac.submitRequirements(callbacks);
				} catch (Exception e) {
					debugMessage("Login failed!!");
                                        debugMessage("--> " + ac.getLoginException().getMessage());
					e.printStackTrace();
					return null;
				}
			}
		}
		if (ac.getStatus() == AuthContext.Status.SUCCESS) {
			debugMessage("Login success!!");
		} else if (ac.getStatus() == AuthContext.Status.FAILED) {
			debugMessage("Login has failed!!");
                        debugMessage("--> " + ac.getLoginException().getMessage());
		} else if( ac.getStatus() == AuthContext.Status.IN_PROGRESS ) {
                        // This may happen when the password is about to expire and must be reset.
                        // Analyze the error message to be sure what is going on.
			debugMessage( "Login is in progress !" );
                        //debugMessage("--> " + ac.getLoginException().getMessage());
                        if( ac.hasMoreRequirements() ) {
                                callbacks = ac.getRequirements();
                                if( callbacks != null ) {
                                    debugMessage( "Callbacks for new password will be processed !" );
                                    try {
                                            addNewPasswordCallbackMessage( callbacks, uid, password, "Geheim03" );
                                            ac.submitRequirements( callbacks );
                                    } catch( Exception e ) {
                                            debugMessage( "Login failed while processing new password callbacks." );
                                            debugMessage("--> " + ac.getLoginException().getMessage());
                                            e.printStackTrace();
                                            return null;
                                    }
                                }
                        }
                    if( ac.getStatus() == AuthContext.Status.SUCCESS )
                            debugMessage( "Login success after switch to new password!" );                           
                    else {
                            debugMessage( "Login failed after switch to new password!" );  
                            debugMessage("--> " + ac.getLoginException().getMessage());
                            }

                }
                   else {
			debugMessage("Unknown status: " + ac.getStatus());
                        debugMessage("--> " + ac.getLoginException().getMessage());
		}

		SSOToken token = ac.getSSOToken();
		return token;

	}

	// Get user's inputs and set them to callback array.
	static void addLoginCallbackMessage(Callback[] callbacks, String uid,
			String password) throws UnsupportedCallbackException {
		debugMessage("begin addLoginCallbackMessage()");
		int i = 0;
		try {
			for (i = 0; i < callbacks.length; i++) {
				if (callbacks[i] instanceof TextOutputCallback) {
					debugMessage("Got TextOutputCallback");
					// Display the message according to the specified type
					TextOutputCallback toc = (TextOutputCallback) callbacks[i];
					switch (toc.getMessageType()) {
					case TextOutputCallback.INFORMATION:
						debugMessage(toc.getMessage());
						break;
					case TextOutputCallback.ERROR:
						debugMessage("ERROR: " + toc.getMessage());
						break;
					case TextOutputCallback.WARNING:
						debugMessage("WARNING: " + toc.getMessage());
						break;
					default:
						debugMessage("Unsupported message type: "
								+ toc.getMessageType());
					}
				} else if (callbacks[i] instanceof NameCallback) {
					debugMessage("Got NameCallback");
					NameCallback nc = (NameCallback) callbacks[i];
					nc.setName(uid);
				} else if (callbacks[i] instanceof PasswordCallback) {
					debugMessage("Got PasswordCallback");
					PasswordCallback pc = (PasswordCallback) callbacks[i];
					pc.setPassword(new String(password).toCharArray());
				} else if (callbacks[i] instanceof TextInputCallback) {
					debugMessage("Got TextInputCallback");
					// prompt for text input
					TextInputCallback tic = (TextInputCallback) callbacks[i];
					// ignore the provided defaultValue
					System.err.print(tic.getPrompt());
					System.err.flush();
					tic.setText((new BufferedReader(new InputStreamReader(
							System.in))).readLine());

				} else if (callbacks[i] instanceof ChoiceCallback) {
					debugMessage("Got ChoiceCallback");
					// prompt for choice input
					ChoiceCallback cc = (ChoiceCallback) callbacks[i];
					System.err.print(cc.getPrompt());

					String[] strChoices = cc.getChoices();
					for (int j = 0; j < strChoices.length; j++) {
						System.err
								.print("choice[" + j + "] : " + strChoices[j]);
					}
					System.err.flush();
					cc.setSelectedIndex(Integer.parseInt((new BufferedReader(
							new InputStreamReader(System.in))).readLine()));
				}
			}
		} catch (Exception e) {
			throw new UnsupportedCallbackException(callbacks[i],
					"Callback exception: " + e);
		}
	}
        
        static void addNewPasswordCallbackMessage(  Callback[] callbacks,
                                                    String uid,
                                                    String oldPassword,
                                                    String newPassword ) throws UnsupportedCallbackException
        {
		int pwdCount    = 0;
		int i           = 0;
		try {
			for (i = 0; i < callbacks.length; i++) {
				if (callbacks[i] instanceof TextOutputCallback) {
					debugMessage( "Got TextOutputCallback while setting new password." );
					// simply display the message
					TextOutputCallback toc = (TextOutputCallback) callbacks[i];
					debugMessage(toc.getMessage() + " :" + toc.getMessage() );
				} else if (callbacks[i] instanceof NameCallback) {
					debugMessage( "Got NameCallback while setting new password - this should not happen !" );
                                        debugMessage( "Maybe you hit the next login module." );
				} else if (callbacks[i] instanceof PasswordCallback) {
					debugMessage( "Got PasswordCallback while setting new password." );
                                        
					PasswordCallback pc = (PasswordCallback) callbacks[i];

                                        // set first password callback with value of old password, the others with the new one
                                        if( pwdCount == 0 )
                                            pc.setPassword( new String( oldPassword ).toCharArray() );
                                        else
                                            pc.setPassword( new String( newPassword ).toCharArray() );
                                        
                                        pwdCount++;
                                            
				} else if (callbacks[i] instanceof ConfirmationCallback) {
					debugMessage( "Got ConfirmationCallback while setting new password !" );
					ConfirmationCallback cc = (ConfirmationCallback) callbacks[i];
                                        // "0" is the index of SUBMIT
                                        cc.setSelectedIndex( 0 );
				} else if (callbacks[i] instanceof TextInputCallback) {
					debugMessage( "Got TextInputCallback while setting new password - this should not happen !" );
				} else if (callbacks[i] instanceof ChoiceCallback) {
					debugMessage( "Got ChoiceCallback while setting new password - this should not happen !" );
				}
			}
		} catch( Exception e ) {
			throw new UnsupportedCallbackException( callbacks[i], "Callback exception: " + e );
		}
	}

	static void debugMessage(String msg) {
		System.out.println(msg);
	}

}

Monday Sep 24, 2007

OpenSSO with OpenID (on the Mac featuring Glassfish)

I've been asked for this a couple of times. Building and getting the OpenID extension for OpenSSO running
is no rocket science but there is no clear 'how to' document available. Here is what I do; the components I'm using are:

  • Sun Java System Directory Server 6 (from Java Enterprise System 5.1, running on Solaris 10U4 (Parallels))
  • Glassfish v2
  • Java "1.5.0_07" (Apple Build)
  • NetBeans 6.0M10 (to build the OpenID endpoint for OpenSSO)
  • OpenID Client (from the Python libs at http://www.openidenabled.com/)

I assume that you have already downloaded and deployed OpenSSO in the Glassfish application server. Also, you must be able to successfully login to OpenSSO's console as 'amadmin'.

Overall Scenario

We will setup 4 (HTTP) services:

  • A site-simulator for an OpenID enabled website (OpenID client) listening at openid.init8.net:8001 (openid.init.net is an alias for 127.0.0.1 - loopback)
  • An Apache server which serves your OpenID (http://teufelchen.init8.net/steffo). The 'index.html' delivered by this service contains a reference to the OpenID endpoint (i.e. OpenID extension for OpenSSO)
  • OpenID endpoint at teufelchen.init8.net:18080/openid/service
  • OpenSSO server at teufelchen.init8.net:8080/fam

The 4 components correspond to the ones used by Sun's deployment (as described in Hubert's blog: the relying party (Python client), the OpenID Identifier Server (Apache), OpenID Extension (OpenID Endpoint at 18080), Login (OpenSSO server at 8080). There is no registration component in our example. Users are either created from the OpenSSO console or privioned to an LDAP data source.

Step 1. Download and build the OpenID extension

First, login to OpenSSO's console and create an account to be used by the OpenID extension (the OpenID extension is an OpenSSO client which tries to authenticate against the OpenSSO server).

  1. Goto http://teufelchen.init8.net:8080/fam/UI/Login?service=ldapService
  2. Next select your realm and click on the Subjects tab.
  3. You should see different sub-tabs: User, Agent, Filtered-Role etc. Click on 'Agent'
  4. Click on 'New' and create a new agent of type Webservice Security Provider. Choose e.g. 'openid' and 'password' as ID and credentials.

Second, checkout the OpenSSO source code via

cvs -d :pserver:yourlogin@cvs.dev.java.net:/cvs checkout opensso

an save the result in e.g. ~/Projects/OpenSSO/src. Next, dowload the OpenSSO ClientSDK and save the JAR famclientsdk.jar in e.g. ~/Projects/OpenSSO/clientSDK/. The client SDK is needed by the OpenID extension.

The OpenID extension is at: opensso/extensions/openid/provider/ in the OpenSSO source tree. You'll also find a build.xml with all the necessary targets there. Now copy the following JARs to opensso/extensions/openid/provider/extlib:

  • commons-codec-1.3.jar (from Apache common codecs)
  • j2ee.jar (from Glassfish libs)
  • famclientsdk.jar (you've just downloaded this one)
  • jsf-facelets.jar (jave.net site)

Setup a NetBeans project; I used 'Java Project with existing Ant script'. Make sure you add the above JARs to your NetBeans project. There are two properties files which are crucial

  • AMConfig.properties
  • Provider.properties

More information can be found the extension's README

AMConfig.properties

AMConfig.properties contains configuration information required by the OpenSSO client SDK (do not mix up this one up with the OpenSSO server configuration file which has the same name but resides somewhere at /etc/OpenSSO or /etc/SUNWam - you've been asked for the exact location during the OpenSSO installation). Make sure that everything in this file is correct. Also check that the debug directity exists and that the naming URL is correct. Here are the keys that work for my setup:

com.iplanet.services.debug.level=warning
com.iplanet.services.debug.directory=/tmp
com.iplanet.am.notification.url=http://teufelchen.init8.net:8080/fam/notificationservice
# This is the ID of the Webservice Security Provider you created above
com.sun.identity.agents.app.username=openid
# And that's the password in clear text
com.iplanet.am.service.password=password
# And that's the encrypted password (obtained from running 'ampassword')
com.iplanet.am.service.secret=AQICJZXYu2vVsQ/WAwEdJh/x3+m2+daOUe3Y
# Check your sever's AMConfig.properties for the next value
am.encryption.pwd=AQICJZXYu2vVsQ/WAwEdJh/x3+m2+daOUe3Y
com.sun.identity.client.encryptionKey=AQICJZXYu2vVsQ/WAwEdJh/x3+m2+daOUe3Y
com.iplanet.security.encryptor=com.iplanet.services.util.JCEEncryption
com.sun.identity.idm.remote.notification.enabled=true
com.iplanet.am.sdk.remote.pollingTime=1
com.sun.identity.sm.notification.enabled=true
com.sun.identity.sm.cacheTime=1
com.iplanet.am.server.protocol=http
com.iplanet.am.server.host=teufelchen.init8.net
com.iplanet.am.server.port=8080
com.iplanet.am.cookie.name=iPlanetDirectoryPro
com.iplanet.am.session.client.polling.enable=true
com.iplanet.am.session.client.polling.period=180
com.iplanet.am.admin.cli.certdb.dir=@CONTAINER_CERTDB_DIR@
com.iplanet.am.admin.cli.certdb.prefix=@CONTAINER_CERTDB_PREFIX@
com.iplanet.am.admin.cli.certdb.passfile=@BASEDIR@/@PRODUCT_DIR@/config/.wtpass
com.sun.identity.agents.server.log.file.name=/tmp/amRemotePolicyLog
com.sun.identity.agents.logging.level=NONE
com.sun.identity.agents.notification.enabled=false
com.sun.identity.agents.notification.url=@NOTIFICATION_URL@
com.sun.identity.agents.polling.interval=3
com.sun.identity.policy.client.cacheMode=subtree
com.sun.identity.liberty.ws.soap.supportedActors=http://schemas.xmlsoap.org/soap/actor/next

Make sure, that in your setup, the values of the server's and client's AMConfig.properties match.

Provider.properties

There are only a few keys here.

openid.provider.service_url=http://teufelchen.init8.net:18080/openid/service
openid.provider.identity_pattern=http://teufelchen.init8.net/(.+)
# The next one is the Universal ID pattern of your OpenSSO installation
openid.provider.principal_pattern=id=(.+),ou=user,dc=init8,dc=net
openid.provider.encryption_key=mXiwLS8bsVBjQJ+dw13lTw==
openid.provider.login_url=http://teufelchen.init8.net:8080/fam/UI/Login?goto=
openid.provider.simple_registration=true
openid.provider.external_target=_blank
openid.provider.strict_protocol=false

You can now build the OpenID extension by selecting the target 'war'.

I deployed the 'provider.jar' at http://teufelchen.nit8.net:18080/openid. Browse to http://teufelchen.nit8.net:18080/openid and you should see the service end point.

Step 2. Configuring your OpenID URL and create a user in OpenSSO

The OpenID URL I want to use is: "http://teufelchen.init8.net/steffo". Browsing to this URL should retrieve the document at $DOCROOT/steffo/index.html. I used Apache's standard 'index.html' (the one that gives you the 'Seeing this instead of the website you expected?') and pasted the following between th HEAD tag:

<link rel="openid.server" href="http://teufelchen.init8.net:18080/openid/service"/>

You also have to create a user in OpenSSO. The ID of that user depends on the OpenID you want to use. If you want to use "http://teufelchen.init8.net/steffo", create a user "steffo". Note that this user might reside in an external LDAP (in which case you have to configure an appropriate authentication module and data source - but that's not required for this sample).

Step 3. Download and install the OpenID client

Download the Python libs at http://www.openidenabled.com/ . Follow the installation instructions and edit the file 'consumer.py' in the examples directory. Modify the following keys:

OPENID_PROVIDER_NAME = 'OpenSSOOpenID'
OPENID_PROVIDER_URL ='http://teufelchen.init8.net:18080/openid/service'

You can now start the consumer from the command shell: python consumer.py --port 8001

This sets up an HTTP service. The above command outputs something like:

Server running at:
http://openid.init8.net:8001/

I put a fake entry to /etc/hosts which assigns 127.0.0.1 the name "openid.init8.net". Direct your browser to this URL. You can now enter your OpenID (e.g. http://teufelchen.init8.net/steffo) into the box. Next, you'll be redirected to OPenSSO's login screen. After successfully entering your credential, you'll see a message like

The website http://openid.init8.net:8001/ is requesting confirmation that your OpenID identity is http://teufelchen.init8.net/steffo.

Done.

Tuesday Jul 10, 2007

Integration of IDM SPE and Access Manager

As announced, the PDF version of the paper (v3) is available on sharespace (login required) and on
bigadmin (no login required).

Tuesday Jun 26, 2007

Integration of Identity Manager and Access Manager

We have extended the whitepaper that describes how to integerate Sun Java Identity Manager and Sun Java Access Manager in Realm Mode. Also the shortly upcoming version will discuss an approach to Single-Sign On into the Service Provider Edition (SPE) of Identity Manager.

Wednesday May 16, 2007

Against 'Least Privilege'

The principle of 'least privilege' (LP) states that a subject should have access to the smallest number of objects necessary to perform some task (p. 242 of Security in Computing, by C. Pfleger, 1997 Prentice Hall). I never questioned this principle until I came in touch with Identity Management. The more I looked on the management side of security rather than on its technical side, I found that in most cases LP leads to systems whose security is more diffcult to manage. These systems are less secure than a system which doesn't follow the LP paradigm.

Tales from the field: a company with 5000 employees has 3000 AD groups (I didn't count the RACF groups but there are many). The big question is: how many business roles (e.g. sales rep, developer) do exists in this company (the sales rep role might imply memebership in 10 LDAP groups so the pure amount of LDAP groups doen't say anything about least privilege). The number of business roles vary from company to company. One my customers told me that an an organization having 1000 employees should have at most 50 (five percent!) business roles, otherwise there is no oranizational benefit from a role model.

I think if an organization's role amount is ten percent, that's still a good number. I met other customers who do not even have roles but maintain a list of privileges for each individual user (according to LP).

To me it seems that LP hinders organizations to achieve a low number of roles which in turn means that it hinders you in defining a proper security management structure. I'm willing to give up LP (and maybe use audit facilities to monitor access rather to prevent access) as a general principle. LP must be questioned under practical aspects and in many cases LP is a requirement that comes from regulations rather than from reality.

Thursday Apr 26, 2007

Identity Manager: Neogent's Rapid Deployment Tool

Sun acquired Neogent a couple of months ago. Neogent has an excellent tool which can ease deployment of IdM at customers. Velocity Identity Deployment Tool (VIDT) is a code generator that is able to generate code on the basis of use-cases. The implementor selects a use-case (e.g. create user) and an actor (e.g. a resource like HR Active Sync) and VIDT generates all the code that is required for a synchronization of the HR resource (e.g. SAP ot PeopleSoft) and IDM.

As with every tool VIDT has it's pros and cons. On the pro side we have

  • repeatable process
  • can be used by IDM newbies
  • produces a documentation (which can be used as a start for an appropriate documentation later on)
  • can export IDVT projects to CBE (common build environment) projects (very important if you're an experienced IDM code warrior)
  • can easily compete with Novell's and Oracle's build-in tools
  • can be extended to incorporate other use cases

And then there's certainly a downside of such a tool: like many tools, it tries to embrace the unexperienced user and loses the professional one. It's like YaST (anyone remembering this?) or Windows network configuration (what the hell is the difference between an office network and a home dial-up access?).

Is VIDT really another YaST? Not quite. VIDT has it's own 'logic' but fortunately, all it does it to produce XML files that can be read and modified if needed. Also, IDVT projects can be exported to a CBE structure (if you're not familiar with CBE, check out https://idm-cbe.dev.java.net). This allows a transition from a code base that was generated by a rapid deployment tool to a code base that can be used for a long term (> 6 months) projects.

VIDT currently aims at the following project phases or users:

  • proof of concept (PoC)
  • small projects
  • initial project phases
  • enablement of unexperienced users

My impression is that VIDT will currently not be used by experienced implementors throughout a longer project. The reason is that an experienced coder is faster using NetBeans or Oxygen than using VIDT. Does that mean that VIDT is useless for larger projects? No. VIDT can be used for rapid prototyping. Moreover, VIDT can be extended to incorporate additional uses cases (e.g. move and rename a user) and it depends on the community to share those new plugins.

Friday Apr 13, 2007

Weird modeling in X.500/LDAP and ActiveDirectory: cn in distinguished names

Over the last years I came across some common issues on the modeling in LDAP and ActiveDirectory, well, more on AD than LDAP. The first issue is on distinguished names.

I never understood why so many AD implementation use the cn rather than uid or employeeNumber as part of the distinguished name. The problem is that if there are employees with common common names like 'John Smith' the dn's look like


dn: cn=John Smith,ou=People,dc=company,dc=com
dn: cn=John J Smith,ou=People,dc=company,dc=com
dn: cn=John Smith 1,ou=People,dc=company,dc=com
dn: cn=John Smith 2,ou=People,dc=company,dc=com

This might not appear to be a problem from an LDAP perspective, but it is a problem from an identity management perspective. If John Smith gets married to Jane Miller and changes his name the key (dn) must be changed as well. Employee numbers don't change. Moreover, if the entries do not contain a company wide unique attribute at all it is difficult to tell whether 'jsmith5' on UNIX belongs to the same person as 'cn=John Smith 3' on LDAP/AD.

When an IDM is deployed, no enterprise infomation system can be anyl longer regarded as an island. Data quality is one major issue in identity management projects and improper naming convention do contribute this this issue.

About

steffo

Search

Top Tags
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today