The Shibboleth V1 software has reached its End of Life and is no longer supported. This documentation is available for historical purposes only.

LoadBalancedIdP

Deploying the IdP in a Load Balanced Environment

If you want to deploy multiple Shibboleth 1.3 IdPs and load balance across them, either for performance or fail-over reasons, there are several things you have to consider. First, the IdP contains some state that maintained in memory, this means that when a client makes an initial request to one IdP node the next request, which will likely end up at a different node, will fail because the second node does not have the necessary state information. This is true for a lot of load balanced applications and so almost all the load balancing solutions have a setting that allows subsequent requests from a client to be directed back to the same server that the original request went to. This solves the first problem but not the second issue, namely that the client isn't the only one contacting the IdP. The service provider also contacts the IdP to make attribute requests or resolve artifacts. This request comes from an IP that is different than the clients and thus will likely be sent to a different node than the client is talking to which again won't have the needed state information to act on the request. These problems can be addressed by dealing with the areas on the IdP as discussed next.

Authentication

Since the IdP does not currently handle user authentication directly, you first need to consider the load balancing implications of the software you're using for that purpose. Since such systems often track users with a cookie, this may be simple, but if there is in-memory state, it may not be so simple. For those using Tomcat itself (or Apache) for authentication, version 1.3.1 now contains an option to enable cookie-based SSO as an extension of your regular authentication mechanism. The Crypto Handle mapping plugin described below is used to read and write an encrypted cookie containing the principal name and an expiration. This allows one server in a cluster to authenticate a user and then create the cookie, while the other servers read it later.

SSO Configuration

Prerequisites to enabling SSO include:

  • Installing and configuring the Crypto Handle Name Identifier Mapping plugin as described below. Note that you do not have to enable the plugin for actual use in generating identifiers for use by SPs, although this is typically done as well to support clustering.
  • Configuring two separate paths to invoke the IdP SSO handler. Both are configured identically in web.xml and IdPXml except that one path is left unprotected and the other path is protected by the authentication mechanism in use. The location you publish in your metadata to SPs is the unprotected location.

To enable the SSO option, you add the following attributes to the <IdPConfig> element in IdPXml:

<IdPConfig ... authHeaderName="COOKIE" cryptoHandleId="crypto" protectedPath="/AuthSSO" ... >

The reference to the Crypto Handle must match the identifier of the mapping definition in the file, and the protected path depends on how you decide to set up your locations.

The lifetime of the SSO session will be dictated by the handleTTL value of the Crypto Handle mapping definition.

Name Identifier Mapping

The Shibboleth IdP needs a way to translate a handle back in to the ID of the user it was generated for. This is accomplished by the Name Identifier Mapping whose default implementation simply uses an in-memory Map. Obviously this suffers from the problem discussed above. There are three ways to address this.

Crypto Handle

Instead of using the standard handle, which is just a generated random string you can use a handle generated by encrypting the principal's ID (with some random data). This way it is still opaque to the service provider but the principal can be reclaimed from the handle itself, by decrypting it, even if the handle is sent to a different IdP node than the one that created it. Setting this up is pretty simple, just follow these steps:

  1. Create a JCEKS symmetric keystore, which is a special kind of keystore file that contains symmetric keys. The Shibboleth ant script can be run from the root of the unpacked source:
    > ./ant genSecret
  2. Place the handle.jks file that was just generated (in src/conf) in the etc directory of your Shibboleth IdP configuration directory (this is where you idp.xml file is) for each node participating in the cluster. There will be a sample handle.jks file there, overwrite it.
  3. Edit your idp.xml, on each node, in the following manner:
    1. Locate the existing NameMapping element and make a copy of it
    2. Set the value of the id attribute to some descriptive name (e.g. cryptohandle)
    3. Set the value of the type attribute to CryptoHandleGenerator
    4. Add, as a child element of the NameMapping element, a KeyStorePath element with the absolute path to the handle.jks file as its content
    5. Add, as a child element of the NameMapping element, a KeyStorePassword element with the keystore's password as its content (default is shibhs)
    6. Add, as a child element of the NameMapping element, a KeyStoreKeyPassword element with the secret key's password as its content (default is shibhs)
    7. Add, as a child element of the NameMapping element, a KeyStoreKeyAlias element with the alias you assigned the secret key as its content (default is handleKey)
    8. If you are using something other than the standard Java keystore type you may add, as a child element of the NameMapping element, a KeyStoreType element with the appropriate type identifier as its content
    9. Locate the RelyingParty element(s) that you want to use the crypto handle with
    10. Set the value of the nameMapping attribute on the RelyingParty child element NameID to the name mapping ID you enerted in step ii.
  4. Restart each IdP node (probably just means restarting Tomcat+Apache)

Note if you want to modify the default passwords or key alias, you can edit the build.xml ant script and modify the properties in the genSecret command.

Principal Handle

Another option is to use the principal's ID as the handle. Before doing this consider whether the loss of anonymity provided by an opaque identifier is acceptable. If this is acceptable you can enable this handle mechanism by editing your idp.xml file as follows. Located the NameMapping element and change the type attribute to Principal (it's probably currently set to SharedMemoryShibHandle unless you've changed it before). Remember to do this on each IdP node.

Implement Your Own Handle Mechanism

This is certainly the most complicated method as it requires you to implement custom code. If you're going to pursue this route it is strongly recommended that you use the Shibboleth extension mechanism provided instead of placing your custom code directly in the Shibboleth source tree. Here's how to use your own handle mechanism.

  1. Create a class that extends edu.internet2.middleware.shibboleth.common.provider.BaseNameIdentifierMapping and implement the getPrincipal() and getNameIdentifier() methods. The getNameIdentifier method should create the mapping from principal ID to SAML name identifier (the handle in Shib parlance) some place that can be accessed by every node, perhaps in a database. The getPrincipal method should reverse the process.
  2. Run ant so that your class(es) get built and bundled with the IdP war and place this WAR on each IdP node
  3. Edit your idp.xml file, on each node, in the following manner:
    1. Locate the NameMapping attribute and make a copy of it.
    2. Replace the type attribute with an attribute called class that contains the full class name of the name identifier map you created in step 1.
    3. Give this name mapping a unique id by editing the id attribute. It doesn't matter what this is, just remember it for the next step.
    4. Located the RelyingParty element and its NameId child element
    5. Change nameMapping attribute to whatever id you gave your custom name mapping two steps ago.
  4. Restart each IdP node (probably just means restarting Tomcat+Apache)

Artifact Mappings

Like the name mappings the IdP keeps the Map of artifacts to the SAML documents they resolve to in memory, by default. Unfortunately, at this time, there is no easy way to deal with this. The easiest thing to do is to not use Artifacts yet. If you need to use Artifacts and you need to deploy in a load balanced environment you can implement and use a custom Artifact mapper. If you're going to pursue this route it is strongly recommended that you use the Shibboleth extension mechanism provided instead of placing your custom code directly in the Shibboleth source tree. Here's how:

  1. Create a class that implements edu.internet2.middleware.shibboleth.artifact.ArtifactMapper such that the artifact <-> SAML document mapping is stored somewhere accessible by all your IdP, perhaps a database
  2. Run ant so that your class(es) get built and bundled with the IdP war and place this WAR on each IdP node
  3. Edit your idp.xml file, on each node, in the following manner:
    i. Locate the ArtifactMapper element
    i. Change the implementation attribute to the full name of the class you created in step
  4. Restart each IdP node (probably just means restarting Tomcat+Apache)

eduPersonTargetedID

Current versions of the IdP include a plugin that generates eduPersonTargetedID values dynamically by hashing various pieces of data. While this approach does work in a load-balanced environment, deployers are strongly cautioned that this plugin is merely for experimentation and is not suitable for production use. Proper use of persistent identifiers like this attribute requires more permanent storage, the ability to easily update the values, and the ability to map from them back to actual users when needed. They also shouldn't change just because other identifiers change. Deployers are strongly urged to consider developing a more robust plugin suitable for their environment before supporting this attribute.

HA-Shib Extension

HA-Shib is an IdP 1.3 extension that provides Name Identifier and Artifact Mapping implementations that replicate state across nodes within a cluster. This solves the issues described with these mappers in a load balanced environment.