DS for AM CTS
Show how to replicate AM core token service (CTS) data and fail over when a DS server is unavailable.
Description
Estimated time to complete: 45 minutes
AM uses DS to store CTS data, such as session tokens, data for SAML v2.0 and OAuth 2.0 applications, and push notifications.
Replicate the CTS data as you would any other directory data for availability, but realize AM applications are not necessarily built with DS eventual consistency in mind. For this reason, configure AM to use affinity load balancing when connecting to the DS CTS store. Affinity load balancing ensures each request for the same entry goes to the same DS server. If the DS server becomes unavailable, AM fails over to another DS server.
Suppose an AM application makes several AM calls in quick succession, and each call requires AM to retrieve a CTS entry from DS. Without affinity, if AM updates the CTS entry on one DS then reads it from another DS, it’s possible replication won’t have had time to replay the changes between the update and the subsequent read. The application could get a confusing response when it appears AM "forgets" the update.
With affinity, both the update and the read target the same DS server. The AM client application gets the expected response each time.
In this use case, you:
-
Set up DS for AM CTS, configuration, and identity data.
-
Set up and configure AM to use the DS service with affinity and failover.
-
Show AM continues to work as expected when a DS server is unavailable.
Goals
In completing this use case, you learn to:
-
Set up DS and AM together.
-
Configure affinity and failover for AM connections to DS.
-
Replicate CTS data effectively while minimizing the impact on AM clients.
Example scenario
As a directory service administrator, Pat plans to deploy directory services for AM CTS data.
Pat knows AM has a number of configuration options for CTS, but wants to clarify the basic deployment principles before tuning the service for their specific deployment.
Pat plans to show the AM administrators the basic approach, and then discuss additional options.
Prerequisites
Knowledge
Before you start:
-
Make sure you are familiar with the command line on your operating system.
-
If you’re new to directory services, consider working through the examples to learn LDAP and to learn replication.
-
If you’re new to AM, consider working through the AM evaluation tasks.
Tasks
This sample deployment shows the steps to replicate CTS data on your computer. Use the same steps with geographically distributed computers or virtual machines for a real deployment.
-
Two AM servlets run in Apache Tomcat and serve HTTP requests from AM client applications.
-
Two replicated DS servers provide storage for AM.
-
Each AM servlet makes LDAP requests to DS for CTS data.
Task 1: Prepare for installation
-
Make sure there’s an FQDN for AM.
The cookie domain for AM session cookies depends on the FQDN, because the browser uses it to connect to AM.
This sample simulates DNS on your computer by updating the hosts file with an alias for each DS server:
# Simulate DNS with an FQDN alias for the loopback address: 127.0.0.1 am.example.com
When deploying in a production environment, make sure you have properly configured the DNS.
-
Unpack the server files once for each server to install.
This sample uses folder locations aligned with the hostnames:
Base path Description /path/to/ds1
First DS server
/path/to/ds2
Second DS server
/path/to/tomcat
Apache Tomcat server
-
Determine the port numbers for the service.
This sample uses different port numbers for each server because all the servers are on the same computer:
Sample server Port numbers ds1
LDAP: 1389
LDAPS: 1636
Admin: 4444
Replication: 8989ds2
LDAP: 11389
LDAPS: 11636
Admin: 14444
Replication: 18989Tomcat
HTTPS: 8080
When installing each DS server on a different host, use the same port numbers everywhere.
-
Set the
JAVA_HOME
environment variable to a supported JDK home if it isn’t already set:$ export JAVA_HOME=<supported-jdk-home>
-
Define how the DS servers trust DS server certificates.
This sample uses a private PKI based on the deployment ID. You generate a deployment ID for all DS servers using the
dskeymgr
command:$ /path/to/ds1/bin/dskeymgr \ create-deployment-id \ --deploymentIdPassword password <deployment-id>
The deployment ID is a string. To use it, you must have the deployment ID password.
Once you generate the ID, set a
DEPLOYMENT_ID
environment variable for use in other steps of this sample:$ export DEPLOYMENT_ID=<deployment-id>
-
Make sure Tomcat and AM trust DS server certificates for secure LDAPS connections.
This sample uses the private PKI based on the deployment ID you generated. Prepare a truststore with the DS CA certificate for Tomcat:
$ /path/to/ds1/bin/dskeymgr \ export-ca-cert \ --deploymentId $DEPLOYMENT_ID \ --deploymentIdPassword password \ --outputFile /path/to/ca-cert.pem $ keytool \ -importcert \ -trustcacerts \ -alias ca-cert \ -file /path/to/ca-cert.pem \ -keystore /path/to/truststore \ -storepass changeit \ -storetype JKS \ -noprompt $ export TRUSTSTORE=/path/to/truststore
Task 2: Set up DS
These sample commands prepare DS servers for AM CTS, configuration, and identities.
They depend on the DEPLOYMENT_ID
environment variable you set.
-
Set up the first DS server:
$ /path/to/ds1/setup \ --deploymentId $DEPLOYMENT_ID \ --deploymentIdPassword password \ --rootUserDN uid=admin \ --rootUserPassword password \ --monitorUserPassword password \ --hostname localhost \ --adminConnectorPort 4444 \ --ldapPort 1389 \ --enableStartTls \ --ldapsPort 1636 \ --replicationPort 8989 \ --bootstrapReplicationServer localhost:8989 \ --bootstrapReplicationServer localhost:18989 \ --profile am-config \ --set am-config/amConfigAdminPassword:5up35tr0ng \ --profile am-cts \ --set am-cts/amCtsAdminPassword:5up35tr0ng \ --profile am-identity-store \ --set am-identity-store/amIdentityStoreAdminPassword:5up35tr0ng \ --acceptLicense \ --start
-
Set up the second DS server:
$ /path/to/ds2/setup \ --deploymentId $DEPLOYMENT_ID \ --deploymentIdPassword password \ --rootUserDN uid=admin \ --rootUserPassword password \ --monitorUserPassword password \ --hostname localhost \ --adminConnectorPort 14444 \ --ldapPort 11389 \ --enableStartTls \ --ldapsPort 11636 \ --replicationPort 18989 \ --bootstrapReplicationServer localhost:8989 \ --bootstrapReplicationServer localhost:18989 \ --profile am-config \ --set am-config/amConfigAdminPassword:5up35tr0ng \ --profile am-cts \ --set am-cts/amCtsAdminPassword:5up35tr0ng \ --profile am-identity-store \ --set am-identity-store/amIdentityStoreAdminPassword:5up35tr0ng \ --acceptLicense \ --start
At this point, both DS servers are running and replicating changes to each other.
Task 3: Set up Tomcat
-
Update Tomcat settings for AM:
This command uses the
TRUSTSTORE
environment variable you set:echo "export CATALINA_OPTS=\"\$CATALINA_OPTS \ -Djavax.net.ssl.trustStore=${TRUSTSTORE} \ -Djavax.net.ssl.trustStorePassword=changeit \ -Djavax.net.ssl.trustStoreType=jks \ -server \ -Xmx2g \ -XX:MetaspaceSize=256m \ -XX:MaxMetaspaceSize=256m\"" > /path/to/tomcat/bin/setenv.sh
-
Make the Tomcat scripts executable:
$ chmod +x /path/to/tomcat/bin/*.sh
-
Start Tomcat:
$ /path/to/tomcat/bin/startup.sh
At this point, Tomcat is ready for you to set up AM.
Task 4: Set up AM
These steps prepare AM to use DS with affinity load balancing and failover.
-
Copy the AM .war file to
/path/to/tomcat/webapps/am1.war
and/path/to/tomcat/webapps/am2.war
. -
Configure AM at http://am.example.com:8080/am1 and http://am.example.com:8080/am2.
Use the following configuration settings:
Setting Choice Configuration Options
Create New Configuration.
Server Settings > Default User Password
Passw0rd
Server Settings > Server URL
http://am.example.com:8080
Server Settings > Cookie Domain
example.com
Server Settings > Platform Locale
en_US
Server Settings > Configuration Directory
/path/to/am1
or/path/to/am2
Configuration Data Store Settings > Configuration Data Store
External DS
Configuration Data Store Settings > SSL/TLS Enabled
Enable
Configuration Data Store Settings > Host Name
localhost
Configuration Data Store Settings > Port
1636
Configuration Data Store Settings > Encryption Key
Save the generated key (example:
w72dwbuhsLQzFNcUftA8eMCaw3a5ayhL
) fromam1
to use when configuringam2
.Configuration Data Store Settings > Root Suffix
ou=am-config
Configuration Data Store Settings > Login ID
uid=am-config,ou=admins,ou=am-config
Configuration Data Store Settings > Password
5up35tr0ng
Configuration Data Store Settings > Server configuration
New deployment (
am1
) or Additional server for existing deployment (am2
)The
am2
server uses the same stores as those of the existing deployment.This choice causes the configurator to skip to the Site Configuration settings for
am2
.User Data Store Settings > User Data Store Type
ForgeRock Directory Services (DS)
User Data Store Settings > SSL/TLS Enabled
Enable
User Data Store Settings > Directory Name
localhost
User Data Store Settings > Port
1636
User Data Store Settings > Root Suffix
ou=identities
User Data Store Settings > Login ID
uid=am-identity-bind-account,ou=admins,ou=identities
User Data Store Settings > Password
5up35tr0ng
Site Configuration
No
-
Configure the CTS store with affinity load balancing to both DS servers.
On the
am1
servlet, make these configuration changes, which are shared with theam2
servlet:-
Log in to the AM admin UI at http://am.example.com/am1 as
amadmin
withPassw0rd
. -
Browse to Configure > Server Defaults > CTS.
-
Use the following CTS settings, saving changes before switching tabs:
Setting Choice CTS Token Store > Store Mode
External Token Store
CTS Token Store > Root Suffix
ou=famrecords,ou=openam-session,ou=tokens
External Store Configuration > SSL/TLS Enabled
Enable
External Store Configuration > Connection String(s)
localhost:1636,localhost:11636
External Store Configuration > Login Id
uid=openam_cts,ou=admins,ou=famrecords,ou=openam-session,ou=tokens
External Store Configuration > Password
5up35tr0ng
External Store Configuration > Affinity Enabled
Enable
-
-
Configure the identity store with affinity load balancing to both DS servers.
In the
am1
admin UI, while connected asamadmin
:-
Browse to Top Level Realm > Identity Stores > ds1 > Server Settings.
-
Update the following identity settings:
Setting Choice LDAP Server
Add
localhost:11636
.Affinity Enabled
Enable
Affinty Level
Bind
-
Save your changes.
-
-
Configure the configuration store to use both DS servers.
In the
am1
admin UI, while connected asamadmin
:-
Browse to Deployment > Servers.
-
For each AM servlet:
-
Browse to Server URL > Directory Configuration > Server.
-
Add an entry for the second DS server and save the changes:
Setting Choice NAME
ds2
HOST NAME
localhost
PORT NUMBER
11636
CONNECTION TYPE
SSL
-
Save your changes.
-
-
-
Log out of the AM admin UI.
-
Restart Tomcat to take the configuration changes into account:
$ /path/to/tomcat/bin/shutdown.sh # Wait a moment for Tomcat to shut down cleanly before starting it again. $ /path/to/tomcat/bin/startup.sh
At this point, AM is ready to use.
Task 5: Create a test user
You will use this account for validation.
-
Log in to the AM admin UI at http://am.example.com/am1 as
amadmin
withPassw0rd
. -
Browse to Top Level Realm > Identities and click + Add Identity.
-
Use the following settings for the test user:
Setting Choice User ID
bjensen
Password
hifalutin
Email Address
bjensen@example.com
First Name
Babs
Last Name
Jensen
Full Name
Barbara Jensen
-
Log out of the AM admin UI.
Validation
To validate your work, check:
-
A user can log in to one AM servlet and access the other with the same session while all servers are up.
-
The session is still honored when a CTS store is unavailable.
The following sections show how to do this in detail.
Access AM as the test user
-
Log in to AM at http://am.example.com/am1 as
bjensen
with passwordhifalutin
.The AM UI displays the user profile page:
-
Switch AM servlets by updating the URL in the browser address bar, replacing
am1
witham2
.The AM UI displays the same user profile page again.
-
On the command line, find the associated CTS token in DS:
$ /path/to/ds1/bin/ldapsearch \ --hostname localhost \ --port 1636 \ --useSsl \ --useJavaTrustStore "${TRUSTSTORE}" \ --trustStorePassword changeit \ --bindDn uid=openam_cts,ou=admins,ou=famrecords,ou=openam-session,ou=tokens \ --bindPassword 5up35tr0ng \ --baseDn ou=famrecords,ou=openam-session,ou=tokens \ "(coreTokenUserId=id=bjensen,ou=user,ou=am-config)" \ coreTokenObject dn: coreTokenId=<token-id>,ou=famrecords,ou=openam-session,ou=tokens coreTokenObject: {"clientDomain":"ou=am-config","clientID":"id=bjensen,ou=user,ou=am-config","...":...}
Notice the CTS does not reference the test user account by its DN, but instead by its AM universal ID.
Show sample core token object
{ "clientDomain": "ou=am-config", "clientID": "id=bjensen,ou=user,ou=am-config", "creationTimeInMillis": 1706087705386, "listeners": { "8f51ba31-a2e8-4f44-a998-91b411ffde3e": true, "f0e6df25-2a9c-4be7-a5bb-1ae22c834190": true }, "maxCachingTimeInMinutes": 3, "maxIdleTimeInMinutes": 30, "maxSessionTimeInMinutes": 120, "restrictedTokensBySessionID": {}, "sessionEventURLs": {}, "sessionID": { "encryptedString": "ecJSF_y5EMdaJhQ4oJ01JGiXAyU.*AAJTSQACMDEAAlNLABxraFNLaytaenFKMlBtYjNmelpBdG9JTUU3ZEE9AAR0eXBlAANDVFMAAlMxAAA.*" }, "sessionProperties": { "Locale": "en_GB", "authInstant": "2024-01-24T09:15:05Z", "Organization": "ou=am-config", "UserProfile": "Required", "Principals": "bjensen", "successURL": "/am1/console", "CharSet": "UTF-8", "Service": "ldapService", "Host": "127.0.0.1", "FullLoginURL": "/am1/UI/Login?realm=%2F", "AuthLevel": "0", "clientType": "genericHTML", "AMCtxId": "4cc3e651-f4eb-4bd6-9355-03b2b0abb45b-319", "loginURL": "/am1/UI/Login", "UserId": "bjensen", "AuthType": "DataStore", "sun.am.UniversalIdentifier": "id=bjensen,ou=user,ou=am-config", "HostName": "127.0.0.1", "amlbcookie": "01", "Principal": "id=bjensen,ou=user,ou=am-config", "UserToken": "bjensen" }, "sessionState": "VALID", "sessionType": "USER", "timedOutTimeInSeconds": 0 }
You have shown the test user session works for either AM servlet.
Test CTS failover
-
Stop the first DS server to force AM to use the second DS server:
$ /path/to/ds1/bin/stop-ds
-
Verify you can still access both AM servlets as
bjensen
.For
am1
andam2
, the AM UI displays the user profile page. -
Start the first DS server and stop the second:
$ /path/to/ds1/bin/start-ds $ /path/to/ds2/bin/stop-ds
-
Verify again you can still access both AM servlets as
bjensen
.For
am1
andam2
, the AM UI displays the user profile page.
You have demonstrated how AM can use DS as a CTS store with affinity load balancing and failover.
What’s next
After successfully showing the sample to AM administrators, Pat leads a discussion to review the tradeoffs they can choose to make for the production deployment. Some of the questions to discuss include the following:
-
Do we back up CTS data?
If CTS data is lost, users must authenticate again.
If that’s acceptable, then we won’t back up CTS data, which is volatile and potentially large.
-
Should there be a separate DS service for CTS data?
CTS access patterns are very different from identity store access patterns. They cause DS to fill and empty its database cache in very different ways.
In a high-volume deployment, it may make sense to split the data up.
-
What AM features are in use?
Could we have DS reap expired tokens (optional) instead of AM (default)?
AM administrators can bring their own questions to the discussion.