Best practice for configuring an external DS instance for the Core Token Service (CTS) in AM 6.0.x
The purpose of this article is to provide best practice advice on configuring an external DS instance for CTS in AM as a non-admin user. CTS is used to provide session failover in AM.
7 readers recommend this article
Note
This article does not apply to AM 6.5 and later, because DS 6.5 added support for setup profiles to greatly simplify initial configuration, and DS 7 and later requires secure connections by default. As a result, you should follow the steps in the documentation for AM 6.5 and later:
- AM 7 and later: Configuring CTS Token Stores
- AM 6.5: Configuring CTS in AM
Introduction
AM uses the CTS as the enabling technology for Session Failover (SFO). CTS leverages DS to provide persistent and highly available storage for sessions, OAuth 2.0 tokens and SAML 2.0 tokens.
DS is the only supported directory for CTS. By default CTS uses the same instances of DS that holds the AM configuration. However, due to the very different profile of token data, an external DS instance dedicated to CTS traffic is highly recommended as CTS traffic is ~90%+ writes and ~10% reads (unlike most LDAP traffic). Furthermore, the data is highly volatile and hence requires different sizing and tuning parameters to typical LDAP servers, which tend to host fairly static data optimized for reads.
This article guides you on how to configure such an external repository for CTS and integrate with AM using a non-admin user (that is, not the Directory Manager) in AM 6.
Note
Tuning, replication design and sizing is considered out of scope of this article, but must be considered in your environments.
Overview of deployment steps
The deployment is broken down into the following steps:
- DS base build and CTS data (container and schema) import
- Non-admin user creation and ACI import
- CTS index import and rebuild
- AM admin UI configuration
- Testing session failover
In a replicated setup, you need to complete steps 2 and 3 on all servers as the ACI is a global-aci and the index is local to each server. Step 1 is only needed on one server as the schema is replicated by default.
Note
If you are using Amazon Web Services (AWS) to host AM and DS, you should ensure your DS servers are replicating prior to installing and configuring AM. If you configure replication after installing AM, you will need to restart AM before your setup functions as expected.
DS base build and CTS data import
- Download the latest DS zip file from Backstage.
- Unzip the DS zip file and run the setup program. The following parameters have been used for the purpose of this article: Initial Root User DN for the Directory Server: cn=Directory Manager Password for the Initial Root User: [password] Fully Qualified Hostname: cts.example.com LDAP Listening Port: 3389 Administration Connector Port: 5444 Create Base DNs: yes Backend Type*: JE Backend ([1]) Base DN for Directory Data: dc=cts,dc=example,dc=com Option for Populating Database: Option 2 - Only create base entry Do You Want to Enable SSL: no Do You Want to Enable Start TLS: no Do You Want To Start The Server: yes What Would You Like To Do: Set up server with parameters above
Note
Depending on your requirements, you may need to enable SSL and/or Start TLS.
- Check that the DS instance is operational once the installation has finished.
- Navigate to: /path/to/tomcat/webapps/am/WEB-INF/template/ldif/sfha, open the cts-container.ldif file and do a find and replace; find: @SM_CONFIG_ROOT_SUFFIX@ and replace with the Base DN defined during the DS installation procedure (for example, dc=cts,dc=example,dc=com).
- Update each entry in the cts-container.ldif file to include the following: changetype: addFor example, an updated entry would look similar to this: dn: ou=tokens,dc=cts,dc=example,dc=com changetype: add objectClass: organizationalUnit objectClass: top ou: tokens
- Import the CTS container configuration using the following command$ ./ldapmodify --port 1636 --bindDN "cn=Directory Manager" --bindPassword password --UseSSL --trustALL /path/to/tomcat/webapps/am/WEB-INF/template/ldif/sfha/cts-container.ldifYou should see the following output:Processing ADD request for ou=tokens,dc=cts,dc=example,dc=com ADD operation successful for DN ou=tokens,dc=cts,dc=example,dc=com Processing ADD request for ou=openam-session,ou=tokens,dc=cts,dc=example,dc=com ADD operation successful for DN ou=openam-session,ou=tokens,dc=cts,dc=example,dc=com Processing ADD request for ou=famrecords,ou=openam-session,ou=tokens,dc=cts,dc=example,dc=com ADD operation successful for DN ou=famrecords,ou=openam-session,ou=tokens,dc=cts,dc=example,dc=com
- Add the CTS schema into the repository using the following command:$ ./ldapmodify --port 1636 --bindDN "cn=Directory Manager" --bindPassword password --UseSSL --trustALL /path/to/tomcat/webapps/am/WEB-INF/template/ldif/sfha/cts-add-schema.ldifYou should see the following output:Processing MODIFY request for cn=schema MODIFY operation successful for DN cn=schema
Note
If AM is binding to CTS as the admin user (Directory Manager), you can skip the next section and proceed straight to the section: CTS index import and rebuild.
Non-admin user creation and ACI import
For best practice the use of the admin user is not recommended. Instead, a new and less privileged user than Directory Manager should be created and ACIs applied to allow the user read, search, modify and delete entries. You can also create a different user per AM instance if required.
The following section documents these step.
- Create an LDIF file called cts_user.ldif with the CTS user defined. The following sample LDIF creates a user called openam_cts: dn: ou=admins,dc=cts,dc=example,dc=com changetype: add objectClass: top objectClass: organizationalunit ou: OpenAM Administrator dn: uid=openam_cts,ou=admins,dc=cts,dc=example,dc=com changetype: add objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson cn: OpenAM Administrator sn: OpenAM userPassword: [password] ds-privilege-name: update-schema ds-privilege-name: subentry-write ds-privilege-name: password-resetEnsure you replace the [password] tag with the actual password value if you use this sample as the basis of your LDIF file.
- Add the new user to the CTS repository using the following command:$ ./ldapmodify --port 1636 --bindDN "cn=Directory Manager" --bindPassword password --UseSSL --trustALL .../cts_user.ldifYou should see the following output:Processing ADD request for ou=admins,dc=cts,dc=example,dc=com ADD operation successful for DN ou=admins,dc=cts,dc=example,dc=com Processing ADD request for uid=openam_cts,ou=admins,dc=cts,dc=example,dc=com ADD operation successful for DN uid=openam_cts,ou=admins,dc=cts,dc=example,dc=com
- Add a global ACI to allow the openam_cts user to modify schema using the following command: $ ./dsconfig set-access-control-handler-prop --hostname cts.example.com --port 5444 --bindDN "cn=Directory Manager" --bindPassword password --no-prompt --trustAll --add 'global-aci:(target = "ldap:///cn=schema")(targetattr = "attributeTypes || objectClasses")(version 3.0; acl "Modify schema"; allow (write) userdn = "ldap:///uid=openam_cts,ou=admins,dc=cts,dc=example,dc=com";)'
- Check the Global ACI has been applied using the following command: $ ./dsconfig get-access-control-handler-prop --hostname cts.example.com --port 5444 --bindDN "cn=Directory Manager" --bindPassword password --no-prompt --trustAll --property global-aciThe following entry should be present: "(target = "ldap:///cn=schema")(targetattr = "attributeTypes || objectClasses")(version 3.0; acl "Modify schema"; allow (write) userdn = "ldap:///uid=openam_cts,ou=admins,dc=cts,dc=example,dc=com";)",
- Create an LDIF file called cts_acis.ldif to add the ACIs to allow the CTS user to create, search, modify, delete and allow persistent search to the CTS repository. A sample LDIF file for this is: dn: dc=cts,dc=example,dc=com changetype: modify add: aci aci: (targetattr="*")(version 3.0;acl "Allow entry search"; allow (search, read)(userdn = "ldap:///uid=openam_cts,ou=admins,dc=cts,dc=example,dc=com");) aci: (targetattr="*")(version 3.0;acl "Modify entries"; allow (write)(userdn = "ldap:///uid=openam_cts,ou=admins,dc=cts,dc=example,dc=com");) aci: (targetcontrol="2.16.840.1.113730.3.4.3")(version 3.0;acl "Allow persistent search"; allow (search, read)(userdn = "ldap:///uid=openam_cts,ou=admins,dc=cts,dc=example,dc=com");) aci: (version 3.0;acl "Add config entry"; allow (add)(userdn = "ldap:///uid=openam_cts,ou=admins,dc=cts,dc=example,dc=com");) aci: (version 3.0;acl "Delete entries"; allow (delete)(userdn = "ldap:///uid=openam_cts,ou=admins,dc=cts,dc=example,dc=com");)
- Import the ACIs into the CTS repository using the following command:$ ./ldapmodify --hostname cts.example.com --port 1636 --bindDN "cn=Directory Manager" --bindPassword password --UseSSL --trustALL .../cts_acis.ldifYou should see the following output:Processing MODIFY request for dc=cts,dc=example,dc=com MODIFY operation successful for DN dc=cts,dc=example,dc=com
CTS index import and rebuild
- Navigate to: /path/to/tomcat/webapps/am/WEB-INF/template/ldif/sfha, open the cts-indices.ldif file and do a find and replace; find: @DB_NAME@ and replace with the actual DB name (for example, userRoot).
- Update each entry in the cts-indices.ldif file to include the following: changetype: addFor example, an updated entry would look similar to this: dn: ds-cfg-attribute=coreTokenExpirationDate,cn=Index,ds-cfg-backend-id=userRoot,cn=Backends,cn=config changetype: add objectClass: top objectClass: ds-cfg-backend-index ds-cfg-attribute: coreTokenExpirationDate ds-cfg-index-type: ordering
- Apply the new indexes to the CTS repository:$ ./ldapmodify --port 5444 --bindDN "cn=Directory Manager" --bindPassword password --UseSSL --trustALL /path/to/tomcat/webapps/am/WEB-INF/template/ldif/sfha/cts-indices.ldifYou should see the following output:Processing ADD request for ds-cfg-attribute=coreTokenExpirationDate,cn=Index,ds-cfg-backend-id=userRoot,cn=Backends,cn=config ADD operation successful for DN ds-cfg-attribute=coreTokenExpirationDate,cn=Index,ds-cfg-backend-id=userRoot,cn=Backends,cn=config Processing ADD request for ds-cfg-attribute=coreTokenUserId,cn=Index,ds-cfg-backend-id=userRoot,cn=Backends,cn=config ADD operation successful for DN ds-cfg-attribute=coreTokenUserId,cn=Index,ds-cfg-backend-id=userRoot,cn=Backends,cn=config …………… …………… …………… …………… ds-cfg-attribute=coreTokenDate04,cn=Index,ds-cfg-backend-id=userRoot,cn=Backends,cn=config Processing ADD request for ds-cfg-attribute=coreTokenDate05,cn=Index,ds-cfg-backend-id=userRoot,cn=Backends,cn=config ADD operation successful for DN ds-cfg-attribute=coreTokenDate05,cn=Index,ds-cfg-backend-id=userRoot,cn=Backends,cn=config
Note
These indexes may require further tuning subject to environmental load testing when used in production.
- Stop the DS server so that you can perform the next step offline.
- Rebuild all indexes and verify using the following commands:$ ./rebuild-index --baseDN "dc=cts,dc=example,dc=com" --rebuildAll --offline $ ./verify-index --baseDN "dc=cts,dc=example,dc=com"
- Restart the DS server and continue on to the AM admin UI configuration.
AM admin UI configuration
Complete the following configuration steps in the admin UI to integrate the new CTS repository with AM. Alternatively, you can perform these configuration steps using ssoadm as described in How do I configure an external CTS token store in AM (All versions) using Amster or ssoadm?
Assumptions
- It is assumed at least two AM instances have been deployed and configured under a site. If not, complete the steps detailed in this document before continuing: Configuring Load Balancing for a Site.
- It is also assumed that both AM instances can communicate with the CTS instance (for example, cts.example.com on port 3389). If this is not the case, rectify before continuing.
Configuration
- Configure the CTS repository in AM by navigating to: Configure > Server Defaults > CTS and complete the required details on both tabs. The following settings have been used for the purpose of this article; see CTS Token Store for further information on these settings:Root Suffix: dc=cts,dc=example,dc=com SSL/TLS Enabled: leave this option switched off Connection String(s): cts.example.com:3389 Login Id: uid=openam_cts,ou=admins,dc=cts,dc=example,dc=com Password: password Max Connections: 10 (this is the default value and should be tuned for Production depending on the authentication profile) Heartbeat: 10 (this is the default value and should be tuned for Production depending on the network and physical architecture) Affinity Enabled: leave this option switched off
- Click Save to save these changes.
- Restart all AM servers in the site and test your configuration.
By default, the AM to DS CTS connection string is inherited by all AM instances. It can also be configured on an instance by instance basis as discussed below, although in an Affinity deployment, all instances must share the same connection string.
Instance specific Connection String (active/passive deployments only)
You can configure the connection string on an instance by instance basis by navigating to: Deployment > Servers > [Server Name] > CTS > External Store Configuration, click the padlock against Connection String(s) to remove inheritance and set the connection string for this server. The connection string can also be multi-valued and ordered (using commas) to split CTS traffic by instances, limit traffic by geography and/or specify failover servers. You must repeat this on all instances.
For example:
- Single CTS DS instance or LB: cts.example.com:3389In this scenario, all instances of AM will use this address - this address could be a server or a load balancer intelligently managing traffic to multiple DS CTS instances.
- Single CTS DS Instance no LB: cts-1.example.com:3389, cts-2.example.com:3389In this scenario, all instances of AM will go to cts-1 unless that DS server goes down; in which case, all AM instances will go to cts-2.
- Multi-DS Instance per AM Limited to Site: cts-1.example.com:3389|server1|site1, cts-2.example.com:3389|server1|site1, cts-2.example.com:3389|server2|site1, cts-1.example.com:3389|server2|site1, cts-3.example.com:3389|server1|site2, ...In this scenario, server 1 of site 1 will go to cts-1 as it's the primary DS CTS server with cts-2 as its failover. Server 2 in site 1 will go to cts-2 as it's the primary server with cts-1 as its failover. Server 1 in site 2 will go to cts-3 as it's the primary server and so on.
It is clear from these examples that the connection string value is highly configurable and flexible depending on the target environment.
Testing session failover
This article uses two browsers to test failover: Chrome™ and Firefox®. You can use any two browsers or browsers running in incognito mode. Other approaches, such as viewing tokens using an LDAP browser, could also be used.
- In Chrome, log into the second AM instance with the amadmin user and click on Sessions.
- In Firefox, log into the first AM instance with a test user.
- In Chrome, verify the test user exists in the first AM instance’s session list and not in the second instance.
- Shutdown the first AM instance.
- In Firefox, rewrite the URL to point to the second AM instance. If successful, the browser should not prompt for login.
- Confirm the session has failed over - in Chrome, list the sessions on the second instance and verify that the test user’s session is present.
- Restart the first AM instance to complete the testing.
See Also
Best practice for using Core Token Service (CTS) Affinity based load balancing in AM (All versions)
How do I configure an external CTS token store in AM (All versions) using Amster or ssoadm?
FAQ: Core Token Service (CTS) and session high availability in AM
Core Token Service (CTS) and sessions in AM
Implementing the Core Token Service
Related Training
ForgeRock Access Management Deep Dive (AM-410)
Related Issue Tracker IDs
OPENAM-9738 (Enable CTS segregation to allow each token type to write to a different CTS instance)
OPENAM-7466 (Get CTS total tokens using SNMP monitoring fails )