Use Case Description
This article describes an advanced Tivoli Federated Identity Mananager configuration model concerning mapping modules for single sign-on federations. The article is applicable to readers who are already familiar with Tivoli Federated Identity Manager and it's federated SSO support. In particular I will present a technique to perform identity and attribute mapping via a second WS-Trust callout to another STS chain. It is important to understand circumstances when this might be useful to see if such a method might be applicable to your TFIM installation.
One option that I know some folks have explored is to make use of the Runtime Custom Property STS.showSSOChains = true, then use the console to modify the structure of the underlying built-in trust chains.
My advice: PLEASE AVOID MODIFYING THE BUILT-IN SSO CHAINS!!
There are several very good reasons why architecturally this is not a good approach:
- Modifications to the built-in SSO chain affect ALL federations of that type, and ALL partners of those federations. This would not meet the goal of having different chain functionality on a per-federation or per-partner basis.
- When you do modify a built-in SSO chain, you have no idea that the modification exists when you view the federation or partner properties in the console. The only place you can see the full chain and the module properties is in the Trust Service Chains management panels of the TFIM console.
About the only good use case I've seen for modifying a built-in SSO chain is to add the STSMessageLogger module as the very first module in a chain to do advanced audit logging.
The solution proposed in this article will work with either TFIM 6.2.0 or TFIM 6.2.1 and is to provide a custom java mapping module called STSMap which itself calls out to an STS (either the same STS or a different one), sending the current STSUniversalUser token (which is operated on for identity mapping) as the Base token in the RequestSecurityToken message to the STS. The STSMap module also expects an STSUniversalUser token to be returned from the callout, essentially delegating mapping operations on the STSUU to a second chain. Configuration allows one or more of the WS-Trust parameters TokenType, Issuer and AppliesTo to be modified from their original values in this second WS-Trust callout to ensure you invoke a different chain mapping and avoid an endless loop of calling your own chain mapping. You may then use the Trust Service management panels in the console to create and manage the second STS chain separate from the federation configuration. In this way the original chain structure used for federated single sign-on federations remains unmodified and you can use any number of different chains that you need for your partners' advanced identity and attribute mapping requirements. Partners that don't need a callout to a second STS chain may still use the simple XSLT mapping module in their federation configuration directly instead of using the custom STS module.
Logically, the configuration appears as shown in this diagram (click on the picture to view original size):
Now that the idea has been presented, let's walk through the actual deployment and configuration steps, then take a look at the code for the custom mapping module.
First, download this custom plugin jar which is ready to go. It may download as a .zip, but if that happens just rename it to .jar. It is a JAR file. The jar includes all example source code so you can also import it into Rational Application Developer for development and maintenance. More information will be given on the development enviornment later. Copy the jar to your <fim_install_root>/plugins directory, then use the TFIM console to Publish Plugins and Reload Configurations. If these steps don't sound familiar you should first read the STS Module Development Tutorial.
Now use the TFIM console to create a module instance of the com.tivoli.am.fim.demo.STSMap module, and set the init parameters for your module instance to point at the STS where you will configure the secondary chains. This will typically be the same STS as your federations, so the default URL of http://localhost:9080/TrustServer/SecurityTokenService will normally be ok. There are options available for basic-authentication and SSL configuration if needed. These options have exactly the same meaning as the properties for the STS client that is shipped as part of WSSM for TFIM and configured in the WSSM.properties file. If they don't seem obvious, you can read more about them in the InfoCenter here. You may also need to modify the role to user/group mapping for the TrustClientRole and TrustClientInternalRole of the ITFIMRuntime application in order for the module to be able to connect to the STS. Information about that requirement is documented in my blog article Using CURL to send requests to the TFIM Security Token Service.
Now when configuring your SAML partner properties in the TFIM Console, select the Custom Module as the Identity Mapping Module:
Next configure the partner properties for the module:
It is really important to establish best practices for configuration of the AppliesTo and Issuer addresses for using the STSMap module. In the example above which is for the partner of a SAML 1.1 Service Provider configuration, the incoming RST has an AppliesTo address set to our federation's ProtocolID and an Issuer Address set to the IDP-partner's ProtocolID. Because of this I've left the Issuer address intact (it represents the actual partner involved) and modified the AppliesTo address to a static string which is different from the chain mapping used for the federation.
If this was an identity provider federation, the AppliesTo address for the current RST would be the SP-partner's ProtocolID and the Issuer address would be our IDP federation's ProtocolID. In that case I would have preserved the per-partner value of AppliesTo by using the value @APPLIESTO@ and modified the Issuer address to a static string like urn:custom:stsmap.
What you need to remember is that you want the RST attributes for Issuer and AppliesTo to:
- Be different from the RST that is used by the federation itself, and
- Have one of the values that is representative of the partner (if you want different chains / chain mappings for each partner)
You may have also noticed two checkbox configuration options. The first is to preserve WS-Trust Claims elements in the second RequestSecurityToken. This may or may not be necessary depending on what your advanced mapping rule requires. The second is to remove the RequestSecurityToken Attribute List from the STSUU before sending it to the second chain. This will greatly reduce the size of the STSUniversalUser token sent to the second trust chain, and is recommended unless you have a specific reason for being able to access that data in your mapping modules.
The final step in the configuration is to use the Trust Service management panels of the TFIM console to configure your custom chain that the federation mapping module will call. The rules for this chain are:
- The chain selection criteria (Issuer address, ApppliesTo address, etc) must match with the configuration you've performed for the STSMap module in the federation or partner configuration
- The chain structure should start with Default STSUU Token(validate) and end with Default STSUU Token(issue)
- You can have any number of map modules in between operating on the STSUU
Here is an example of the chain selection criteria which matches the SAML 1.1 IDP-partner that we've been using for illustration purposes:
When constructing the chain, you can have any number of map modules, including custom-developed map modules. Just be sure that it starts with STSUU(validate) and ends with STSUU(issue):
You may also be interested in protecting access to your special mapping trust chain using a technique like that described in my blog entry Protected Access to Individual TFIM STS Chains.
That concludes the configuration requirements for the federation, partner and the custom chain that will be called by the federation chain. As the example module is provided with source and is not part of the actual TFIM product, you would be responsible for any ongoing development and maintenance. Let's now discuss some of the internal development details of this module.
The STS Module Development Tutorial is compulsory reading before attempting to understand this section. The rest of this section highlights some key points about the source code in the module, and the development environment used to put it together.
Note: I used Rational Application Developer 7.5 as my development environment for the module, with the IBM WebSphere 6.1 test runtime.
The STSMap module at it is written is really just a WS-Trust proxy for externalizing manipulation of an STSUniversalUser XML token. To draw a parallel to existing TFIM functionality, this is very similar to what the Tivoli Directory Integrator mapping module does except that instead of calling out to an assembly line on a TDI server we are calling out to another STS chain via WS-Trust. The module uses a primitive JAX-RPC WebSphere web services client for WS-Trust (this provided the smallest code footprint for execution in the STS environment) and all the generated stub code and helper classes have been provided.
The com.tivoli.am.fim.demo.sts.client.stubs package contains all the generated stubs from the wsdl2java that we performed on the ws-trust.wsdl. This wsdl is really a skeleton ws-trust 1.2 wsdl, but perfectly adequate for our needs.
The com.tivoli.am.fim.demo.stsclient package contains a set of helper classes that are used to invoke the WS-Trust web services client. The main entry point into this package is the class STSClientHelper. Due to the fact that the JAX-RPC runtime uses SOAPFactory, we did have to make use of the J2EEContainerAction pattern described in the STS Module Development tutorial. You can see this in action in the class J2EEHelper.
The com.tivoli.am.fim.demo.stsmap package contains the actual mapping module class as well as a message bundle class and a configuration helper.
When building the module yourself, you will most definitely need the com.tivoli.am.fim.sdk project described in the STS Module development tutorial. This will be needed to resolve a bunch of WebSphere-provided classes used byt the web services client runtime. In particular you will need to included these jars in the com.tivoli.am.fim.sdk classpath:
Then you will need to export the following packages from the com.tivoli.am.fim.sdk bundle as they are imported as dependencies by the com.tivoli.am.fim.demo.stsmap manifest:
As you can see from this example, there is a massive amount of flexibility in what is possible within the framework of the TFIM Security Token Service, and even complex customer requirements for per-partner identity and attribute mapping can be met without radical departure from normal installation and configuration operations.
For those thinking beyond the capabilities described here, it is also possible to modify the module as it is presented to go beyond just delegating mapping operations to another chain. For example you could use the same technique to delegate SAML token creation to another external STS instance (eg one that you don't have the signing keys for). The possibilities are quite endless and the best thing to keep in mind is that the options exist. Focus on your requirements and then apply the technology that works best.
If you have found this article useful, or believe this module is valuable enough to be considered for inclusion in the next GA release of TFIM, please contact me and give me your feedback.
If you have skipped to the bottom looking for the download link, here it is: Download the custom STSMap module. Remember to rename it as a .jar file if it downloads as a zip.