Tuesday Sep 01, 2009

Creating a SAML Assertion with OpenSAML (Part 2)

I migrated the code (see blog) from OpenSAML 1.0 to 2.3 with some help from here and here.
Here's the Java Source:
import org.opensaml.DefaultBootstrap;
import org.opensaml.Configuration;

import org.opensaml.saml1.core.Assertion;
import org.opensaml.saml1.core.Attribute;
import org.opensaml.saml1.core.AttributeValue;
import org.opensaml.saml1.core.NameIdentifier;
import org.opensaml.saml1.core.Subject;
import org.opensaml.saml1.core.SubjectConfirmation;
import org.opensaml.saml1.core.SubjectStatement;
import org.opensaml.saml1.core.AuthenticationStatement;
import org.opensaml.saml1.core.AttributeStatement;
import org.opensaml.saml1.core.ConfirmationMethod;
import org.opensaml.saml1.core.Conditions;
import org.opensaml.saml1.core.DoNotCacheCondition;

import org.opensaml.saml1.core.impl.AssertionBuilder;
import org.opensaml.saml1.core.impl.AssertionImpl;
import org.opensaml.saml1.core.impl.AssertionMarshaller;
import org.opensaml.saml1.core.impl.SubjectImpl;

import org.opensaml.common.SAMLVersion;
import org.opensaml.common.SAMLObjectBuilder;
import org.opensaml.common.xml.SAMLConstants;
import org.opensaml.xml.XMLObjectBuilder;
import org.opensaml.xml.XMLObjectBuilderFactory;
import org.opensaml.xml.util.XMLHelper;
import org.opensaml.xml.util.XMLHelper;

import org.opensaml.xml.schema.XSString;

import org.w3c.dom.Element;
import org.joda.time.DateTime;

import java.util.Date;
import java.util.HashSet;
import java.util.List;

public class AMUserAssertion {

   private static String strIssuer = "Example:FrontEnd";
   private static String strNameID = "testUserID";
   private static String strNameQualifier = "Example:FrontEnd";
   private static String strNamespace = "urn:bea:security:saml:groups";
   private static String strAttrName = "Groups";
   private static String strAuthMethod = "SunAccessManager";

   public static void main(String args[]) {
   
      try {
         // OpenSAML 2.3
         DefaultBootstrap.bootstrap();
         XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();

         // Create the NameIdentifier
         SAMLObjectBuilder nameIdBuilder = (SAMLObjectBuilder) builderFactory.getBuilder(NameIdentifier.DEFAULT_ELEMENT_NAME);
         NameIdentifier nameId = nameIdBuilder.buildObject();
         nameId.setNameIdentifier(strNameID);
         nameId.setNameQualifier(strNameQualifier);
         nameId.setFormat(NameIdentifier.UNSPECIFIED);

         // Create the SubjectConfirmation
         SAMLObjectBuilder confirmationMethodBuilder = (SAMLObjectBuilder)  builderFactory.getBuilder(ConfirmationMethod.DEFAULT_ELEMENT_NAME);
         ConfirmationMethod confirmationMethod = confirmationMethodBuilder.buildObject();
         confirmationMethod.setConfirmationMethod("urn:oasis:names:tc:SAML:1.0:cm:sender-vouches");

         SAMLObjectBuilder subjectConfirmationBuilder = (SAMLObjectBuilder) builderFactory.getBuilder(SubjectConfirmation.DEFAULT_ELEMENT_NAME);
         SubjectConfirmation subjectConfirmation = subjectConfirmationBuilder.buildObject();
                                 subjectConfirmation.getConfirmationMethods().add(confirmationMethod);
         // Create the Subject
         SAMLObjectBuilder subjectBuilder = (SAMLObjectBuilder) builderFactory.getBuilder(Subject.DEFAULT_ELEMENT_NAME);
         Subject subject = subjectBuilder.buildObject();

         subject.setNameIdentifier(nameId);
         subject.setSubjectConfirmation(subjectConfirmation);

         // Create Authentication Statement
         SAMLObjectBuilder authStatementBuilder = (SAMLObjectBuilder) builderFactory.getBuilder(AuthenticationStatement.DEFAULT_ELEMENT_NAME);
         AuthenticationStatement authnStatement = authStatementBuilder.buildObject();
         authnStatement.setSubject(subject);
         authnStatement.setAuthenticationMethod(strAuthMethod);
         authnStatement.setAuthenticationInstant(new DateTime());

         // Create the attribute statement
         SAMLObjectBuilder attrBuilder = (SAMLObjectBuilder) builderFactory.getBuilder(Attribute.DEFAULT_ELEMENT_NAME);
         Attribute attrGroups = attrBuilder.buildObject();
         attrGroups.setAttributeName("Groups");

         XMLObjectBuilder stringBuilder = builderFactory.getBuilder(XSString.TYPE_NAME);
         XSString attrNewValue = (XSString) stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME);
         attrNewValue.setValue("AssetManager");

         attrGroups.getAttributeValues().add(attrNewValue);

         SAMLObjectBuilder attrStatementBuilder = (SAMLObjectBuilder) builderFactory.getBuilder(AttributeStatement.DEFAULT_ELEMENT_NAME);
         AttributeStatement attrStatement = attrStatementBuilder.buildObject();
         attrStatement.getAttributes().add(attrGroups);
         // attrStatement.setSubject(subject);

         // Create the do-not-cache condition
         SAMLObjectBuilder doNotCacheConditionBuilder = (SAMLObjectBuilder) builderFactory.getBuilder(DoNotCacheCondition.DEFAULT_ELEMENT_NAME);
         DoNotCacheCondition condition = doNotCacheConditionBuilder.buildObject();

         SAMLObjectBuilder conditionsBuilder = (SAMLObjectBuilder) builderFactory.getBuilder(Conditions.DEFAULT_ELEMENT_NAME);
         Conditions conditions = conditionsBuilder.buildObject();
         conditions.getConditions().add(condition);
         
         // Create the assertion
         SAMLObjectBuilder assertionBuilder = (SAMLObjectBuilder) builderFactory.getBuilder(Assertion.DEFAULT_ELEMENT_NAME);
         Assertion assertion = assertionBuilder.buildObject();
         assertion.setIssuer(strIssuer);
         assertion.setIssueInstant(new DateTime());
         assertion.setVersion(SAMLVersion.VERSION_10);

         assertion.getAuthenticationStatements().add(authnStatement);
         assertion.getAttributeStatements().add(attrStatement);
         assertion.setConditions(conditions);

         // Print the assertion to standard output
         AssertionMarshaller marshaller = new AssertionMarshaller();
         Element element = marshaller.marshall(assertion);
         System.out.println("AMUserAssertion (SAML 1):\\n");
         System.out.println(XMLHelper.prettyPrintXML(element));

      }
      catch (Exception e) {
                e.printStackTrace();
        }
   }
}
The output looks like:

<?xml version="1.0" encoding="UTF-8"?><saml1:Assertion xmlns:saml1="urn:oasis:names:tc:SAML:1.0:assertion" IssueInstant="2009-09-01T14:24:49.905Z" Issuer="Example:FrontEnd" MajorVersion="1" MinorVersion="0">
   <saml1:Conditions>
      <saml1:DoNotCacheCondition/>
   </saml1:Conditions>
   <saml1:AuthenticationStatement AuthenticationInstant="2009-09-01T14:24:49.581Z" AuthenticationMethod="SunAccessManager">
      <saml1:Subject>
         <saml1:NameIdentifierFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" NameQualifier="Example:FrontEnd">testUserIDlt;/saml1:NameIdentifier>
         <saml1:SubjectConfirmation>
            <saml1:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:sender-vouches</saml1:ConfirmationMethod>
         </saml1:SubjectConfirmation>
      </saml1:Subject>
   </saml1:AuthenticationStatement>
   <saml1:AttributeStatement>
      <saml1:Attribute AttributeName="Groups">
         <saml1:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">AssetManager</saml1:AttributeValue>
      </saml1:Attribute>
   </saml1:AttributeStatement>
</saml1:Assertion>

Wednesday Jul 01, 2009

VALid Authentication for OpenSSO

Validsoft's VALid provides out-of-band multi-factor Authentication. I allows for instance to validate a user's identity to ring back the individual on a registered phone number or send SMS in order to obtain a PIN code which needs to be entered in the login screen.
I made a first cut of a VALid authentication module available as an OpenSSO extension. It allows 2nd-factor authentication through mobile callback and SMS. It doesn't however cater for the display of progress messages in the login process and the flexibility to let the user pick the callback type.
In order to compile and run it you need to get the VALid client libraries from ValidSoft (enquiries@validsoft.com) - of which you probably got the VALid server in the first place.

Here's the source code:
https://opensso.dev.java.net/source/browse/opensso/extensions/authnvalid/

Creating a SAML Assertion with OpenSAML

Here's handy way to create a SAML assertion programmatically using OpenSAML (www.opensaml.org).

Dependencies:
xalan.jar (2.7.1), xercesImpl.jar, xml-apis.jar,
opensaml-1.1.jar, xmlsec-20050514.jar,
log4j-1.2.5.jar, commons-logging-1.03.jar, commons-codec-1.3.jar
Here's the Java Source:
import org.opensaml.SAMLAssertion;
import org.opensaml.SAMLException;
import org.opensaml.\*;

import java.util.Date;
import java.util.HashSet;

public class AMUserAssertion {

   private static String strIssuer = "Example:FrontEnd";
   private static String strNameID = "testUserID";
   private static String strNameQualifier = "Example:FrontEnd";
   // private static String strNamespace = "urn:oasis:names:tc:SAML:1.0:assertion";
   private static String strNamespace = "urn:bea:security:saml:groups";
   private static String strAttrName = "Groups";
   private static String strAuthMethod = "SunAccessManager";

   public static void main(String args[]) {
      try {
          // Crate the assertion
         SAMLAssertion assertion = new SAMLAssertion(strIssuer, null, null, null, null, null);
         // Create the subject
         SAMLSubject subject = new SAMLSubject(new SAMLNameIdentifier(strNameID, strNameQualifier, SAMLNameIdentifier.FORMAT_UNSPECIFIED), null, null, null);

         subject.addConfirmationMethod(SAMLSubject.CONF_SENDER_VOUCHES);

         // Create the authentication statement
         Date date = new Date();
         SAMLAuthenticationStatement authStatement = new SAMLAuthenticationStatement(subject, strAuthMethod, date, null, null, null);

         assertion.addStatement(authStatement);

         // Create the attribute statement
         SAMLAttribute attrGroups = new SAMLAttribute(strAttrName, strNamespace, null, 0, null);
         // Here some hardcoded values for the groups attributes
         attrGroups.addValue("AssetManager");
         attrGroups.addValue("Employee");

         HashSet set = new HashSet();
         set.add(attrGroups);

         SAMLSubject subject2 = (SAMLSubject) subject.clone();
         SAMLAttributeStatement attrStatement = new SAMLAttributeStatement(subject2, set);

         assertion.addStatement(attrStatement);

         SAMLDoNotCacheCondition condition = new SAMLDoNotCacheCondition();
         assertion.addCondition(condition);

         System.out.println("AMUserAssertion 1:\\n"+assertion.toString());
      }
      catch (Exception e) {
         e.printStackTrace();
      }
   }
}
The output looks like:
<Assertion xmlns="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" AssertionID="_4e138dee03e2e826b58b9310e2d8a1e5" IssueInstant="2009-07-01T10:03:06.103Z" Issuer="PND:FrontEnd" MajorVersion="1" MinorVersion="1">
   <Conditions>
      <DoNotCacheCondition></DoNotCacheCondition>
   </Conditions>
   <AuthenticationStatement AuthenticationInstant="2009-07-01T10:03:07.078Z" AuthenticationMethod="SunAccessManager">
      <Subject>
         <NameIdentifier Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" NameQualifier="PND:FrontEnd">testUserID</NameIdentifier>
         <SubjectConfirmation>
            <ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:sender-vouches</ConfirmationMethod>
         </SubjectConfirmation>
      </Subject>
   </AuthenticationStatement>
   <AttributeStatement>
      <Subject>
         <NameIdentifier Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" NameQualifier="PND:FrontEnd">testUserID</NameIdentifier>
         <SubjectConfirmation>
            <ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:sender-vouches</ConfirmationMethod>
         </SubjectConfirmation>
      </Subject>
      <Attribute AttributeName="Groups" AttributeNamespace="urn:bea:security:saml:groups">
         <AttributeValue>AssetManager</AttributeValue>
         <AttributeValue>Employee</AttributeValue>
      </Attribute>
   </AttributeStatement>
</Assertion>"


Monday Jan 26, 2009

Identity Management for Virtual Desktop Infrastructure (VDI): A Demo

Simply speaking, a virtual desktop is a desktop in form of a virtual image (e.g. VMWare, xVM Virtual Box) and virtual desktop infrastructure are the means to deliver the virtual desktop to the user.

With desktops and a smart cards (e.g. for Sun Ray access) being user assets, Sun's Identity Management provides a number benefits for managing them. It allows for instance the assignment of desktops and smart cards as part of a typical HR driven user on-boarding process with approvals, notifications and reports. Another crucial element in the user life cycle is de-activation, where Sun IdM provides the platform to assure that when a user is disabled, the user assigned assets are disabled or even unassigned as well.

Paul Walker and myself put together a demo around these use cases which is at https://slx.sun.com/1179272877

The products integrated in this demo include Sun VDI (xVM Virtual Box, Sun Ray Server, Virtual Desktop Connector, Secure Global Desktop, MySQL) and Sun Identity Management (Identity Manager, OpenSSO, OpenDS, DSEE, MySQL).

Friday Oct 03, 2008

Secure Global Desktop and OpenSSO Single Sign-On

Sun Secure Global Desktop can be nicely integrated in a web access management infrastructure based on OpenSSO for single sign-on and authorization. Here's a paper I published with the OpenSSO community on how to do this:
https://opensso.dev.java.net/files/documents/3676/112554/SecureGlobalDesktop-OpenSSO-Integration.pdf
http://wikis.sun.com/display/OpenSSO/Technical+Articles

Wednesday Jan 23, 2008

[Solaris] Which process is bound to a given port ?

Again I was faced with the problem of a port being busy and needed to determine what process was bound to it. The little script below I picked up some time ago from the internet came in handy. I unfortunately cannot remember though to whom I owe credits. Here it is:

#!/bin/ksh

line='---------------------------------------------'
pids=$(/usr/bin/ps -ef -o pid=)

if [ $# -eq 0 ]; then
read ans?"Enter port you would like to know pid for: "
else
ans=$1
fi

for f in $pids
do
/usr/proc/bin/pfiles $f 2>/dev/null | /usr/xpg4/bin/grep -q "port: $ans"
if [ $? -eq 0 ]; then
echo $line
echo "Port: $ans is being used by PID:\\c"
pargs -l $f
#/usr/bin/ps -o pid,args -p $f
fi
done
exit 0

Thursday Dec 13, 2007

OpenSSO, WS-Federation & IBM DataPower

I wrote-up the procedure I used in a recent PoC to setup OpenSSO/FAM as a multi-protocol federation hub for single sign-on with ADFS (through WS-Federation) and IBM DataPower (through SAML1.1 and SAML2). This contains a lot more detail than my last blog entries.

The document is available as part of the OpenSSO project at:
https://opensso.dev.java.net/servlets/ProjectDocumentList?folderID=8475

It is also linked of the articles and procedures pages:
https://opensso.dev.java.net/public/use/docs/opensso/index.html

The direct link to the .pdf is: https://opensso.dev.java.net/files/documents/3676/79106/OpenSSO-WS-Fed-DataPower-FederationPoC.pdf

Enjoy and let me know your comments.

Monday Dec 10, 2007

OpenSSO and WS-Federation: PoC ready and more !

It was surprisingly easy to setup FAM/OpenSSO Build 1 for single sign-on with ADFS through WS-Federation. The HowTo-Guide from OpenSSO and especially the ADFS Step-by-step guide (referenced in the document) were really helpful.
The biggest pain turned out to be the setup of the ADFS forest through the ADFS GUI (granted, I am wasn't familiar with it beforehand). The configuration of FAM/OpenSSO through metadata was however very straightforward.

Friday Dec 07, 2007

OpenSSO (FAM) Single Sign-On with IBM DataPower

In a recent customer proof-of-concept/prototype I integrated with my esteemed colleague Sergio O., OpenSSO and IBM DataPower for single sign-on. It appeared to be easier and quicker than I initially thought. Here's how it worked for us:

IBM DataPower can be configured in many different ways. In our case it is used a an XML firewall which exposes endpoints that asserting parties can post SAML assertions to (SAML 1.1 and SAML2). DataPower proceeds as follows :
1.) Receive SAML assertion (through HTTP-POST)
2.) Verify assertion signature
3.) Extract user name from the NameIdentifier (SAML1.1) or NameID (SAML2) field
4.) Issue appropriate LTPA token to user

IBM DataPower was also configured to POST SAML (1.1 and 2.0) to specific endpoints (relying parties, here FAM) upon initiation by user (e.g. click a link or button).

In order to achives bi-directional SSO based on SAML, we were faced with the following challenges:

- Certificates
DataPower needs to be configured so that it can validate the signature by FAM. FAM in turn needs to be configure with the asserting parties signature key (through metadata).

- User name mapping
The NameIdentifier (SAML1.1) and NameID (SAML2) tags had to match the Websphere username that DataPower issues an LTPA token for. This requires a custom NameIdentifier mapper for SAML1.1 that injects only the RDN attribute value rather than the user DN in the NameIdentifier tag. For SAML2 it had to be a custom IDP account mapper that does the same and sets the NameIDFormat to urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified.

- Craft DataPower Metadata
This is relativly easy from a template generated by famdadm. It is important to include the correct certificate though.

- Correct DataPower's Assertions
We had to correct some elements in the SAMLResponse sent by DataPower like the presence of the ResponseTo field of an unsolicited response. The debug logs (when log level set to message) really helped here (files libSAML and libSAML2).

Hopefully getting this in a more detailed paper soon.

Thursday Oct 11, 2007

The value of OpenSSO to build Access Manager prototypes and PoCs !

Over the last couple of months I built various prototypes and PoCs for customers to evaluate Sun Access Manager. The fact that the Access Manager source code repository is public provided and provides significant advantages in this process. And here's how.

\* Rapid and controlled customization
Situation: Before authenticating a user against an LDAP authentication module, it needs to be verified with the identity management system in place if the user is active. This translates into a custom authentication module with an API call to the external identity management system.
The value of OpenSSO: Developping a custom LDAP authentication module with the additional functionality is the traditionally supported way. However this introduces the risk that comes with re-writing a core piece of the security infrastructure (the LDAP authentication module). OpenSSO provides the source code of the standard LDAP authentication module (along with a build environment). Adding 10 lines of code and rebuilding the module from OpenSSO is not only a rapid but more importantly a low risk approach to customization here.

\* Technology Partner Integration
Situation: For a prototype a custom authentication module for a particular strong authentication provider was build. Following this exercise, various parties volunteered to own and maintain the element. However we quickly figured that the right way to maintain this is inside OpenSSO. The technology partner gets great visibility within OpenSSO and to the community. The commity gets the obvious benefit of more functionality.

\* Prototypes with "Early Access" software
With OpenSSO and a community strongly backed by Sun engineering, we build prototypes with much better early access bits (than before) while still getting some level of support (through the community).

I'll bump across further elements - and will post them here.

Wednesday Oct 03, 2007

FAM 8 Build 1 Available Now !

The first build of Sun Federated Access Manager (FAM) 8.0 off the OpenSSO code base is available at https://opensso.dev.java.net/public/use/index.html. A milestone in converging the code bases for Access Manager, Federation Manager and OpenSSO.

FAM 8.0 features and timeline are briefly described by the Daniel of the PM team at his blog http://blogs.sun.com/raskin/entry/part_ii

Friday May 04, 2007

Managing multiple directory instances is easy !

Setting up and managing a great number of instances in a directory deployment is easy - with Sun Directory Server (Enterprise Edition) 6.

For a benchmark for a 100M user entry directory deployment with Sun Directory Server 6 (shipped March 1st, 2007), generating the data, installing and configuring the software and loading the data was done in not more than a working day. Given that we partitioned the data in blocks of 25M entries with a multi-master pair for each partition, we had to manage 8 directory instances and 4 directory proxy instances. I was very impressed how little hassle this caused. Here's what I think are the key elements of DSEE6 that enabled this :

1.) Command line tools: DSEE6 provides a rather comprehensive set of command line tools for configuration (dsadm, dsconf, dpadm, dpconf). You have to run these tools with different parameters quite a few times, but this allows you to break up configuration in small and understandable steps. Much more pratical than crafting LDIF as for Sun Directory Server 5.2.

2.) Central Web-based Management Console: Yes, the management console is web based - finally. All directory and directory proxy instances can be managed from one place. An extremly useful feature is the ability to copy configuration (or parts of it) from one instance to others. This help avoiding many problems and save time if things had to be done individually for each instance.

3.) Replica initialization in parallel: With DS5.2, replica initialization was a 2 (or 3) step process where one master was initialized from the LDIF file and then in turn initialized other replicas either online or through LDIF export and LDIF import (in which case it was a 3 step process). Using the management console, 2 master replicas can be initialized from the same LDIF in parallel, which reduces topology initialization to one step that can be done in parallel on all systems. This represented an enourmous time gain.

That's for the management. The scalability aspects of DSEE6 are even more impressive - more on that later.

Wednesday Apr 25, 2007

Federation Bootcamp ...

I meant to write about it for some time, since this project kept me busy until autumn (2006). Since then Sun Microsystems is in the position to offer to internals, partners and customers (on arrangement) an in-depth training on identity federation and Sun's implementation (Sun Java System Access Manager and Federation Manager).
The aim is to depict first what identity federation is and what purpose it serves, then guide through the jungle of specifications and standards (without beeing an academic class on this topic and so far independant of any product) to enter the holy land of implementation where most of the course and lab time (~ 80 %) is spent.

The course agenda looks as follows:
Module 1: Identity Federation Concepts
Module 2: Identity Federation Standards and Specifications (incl. lab)
Module 3: Product Introduction, Access Manager and Federation Manager (incl. lab)
Module 4: Identity Federation (incl. lab bridging circles of trust)
Module 5: Identity Web Services with Liberty ID-WSF (incl. lab)
Module 6: Programming and Customization (incl. lab on customizing a SAML2 provider)
Module 7: Privacy with Liberty ID-WSF (incl. lab)
Module 8: Security (incl. lab on non-root install and fully secure configuration)
Module 9: LDAP Backend for Federation Manager (incl. lab)
Module 10: High Availability (incl. lab on a fully HA configuration).

For enrollment in the class, please send email to fm-bootcamp@sun.com.

One word on the training title - bootcamp. Well, there seems to be a fascination in corporate management with the concepts of leadership and organization as practiced by the military. This training could just as well be called 'training'. And trainings are aimed to the learning, not the teaching.

If you want to know what students say, check out this blog:
http://blogs.sun.com/hubertsblog/date/20061019
About

joachimandres

Search

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