PingDS 7.5.1

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.

Actions

Before you start, download:

  • The AM .war file

  • An appropriate version of Apache Tomcat

  • The DS .zip file

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.

Sample deployment of AM with DS
  • 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

  1. 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.

  2. 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

  3. 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: 8989

    ds2

    LDAP: 11389
    LDAPS: 11636
    Admin: 14444
    Replication: 18989

    Tomcat

    HTTPS: 8080

    When installing each DS server on a different host, use the same port numbers everywhere.

  4. Set the JAVA_HOME environment variable to a supported JDK home if it isn’t already set:

    $ export JAVA_HOME=<supported-jdk-home>
  5. 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>
  6. 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.

  1. 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
  2. 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

  1. 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
  2. Make the Tomcat scripts executable:

    $ chmod +x /path/to/tomcat/bin/*.sh
  3. 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.

  1. Copy the AM .war file to /path/to/tomcat/webapps/am1.war and /path/to/tomcat/webapps/am2.war.

  2. 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) from am1 to use when configuring am2.

    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

  3. Configure the CTS store with affinity load balancing to both DS servers.

    On the am1 servlet, make these configuration changes, which are shared with the am2 servlet:

    1. Log in to the AM admin UI at http://am.example.com/am1 as amadmin with Passw0rd.

    2. Browse to Configure > Server Defaults > CTS.

    3. 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

  4. Configure the identity store with affinity load balancing to both DS servers.

    In the am1 admin UI, while connected as amadmin:

    1. Browse to Top Level Realm > Identity Stores > ds1 > Server Settings.

    2. Update the following identity settings:

      Setting Choice

      LDAP Server

      Add localhost:11636.

      Affinity Enabled

      Enable

      Affinty Level

      Bind

    3. Save your changes.

  5. Configure the configuration store to use both DS servers.

    In the am1 admin UI, while connected as amadmin:

    1. Browse to Deployment > Servers.

    2. 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.

  6. Log out of the AM admin UI.

  7. 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.

  1. Log in to the AM admin UI at http://am.example.com/am1 as amadmin with Passw0rd.

  2. Browse to Top Level Realm > Identities and click + Add Identity.

  3. 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

  4. 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

  1. Log in to AM at http://am.example.com/am1 as bjensen with password hifalutin.

    The AM UI displays the user profile page:

    Profile page for the test user
  2. Switch AM servlets by updating the URL in the browser address bar, replacing am1 with am2.

    The AM UI displays the same user profile page again.

  3. 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

  1. Stop the first DS server to force AM to use the second DS server:

    $ /path/to/ds1/bin/stop-ds
  2. Verify you can still access both AM servlets as bjensen.

    For am1 and am2, the AM UI displays the user profile page.

  3. Start the first DS server and stop the second:

    $ /path/to/ds1/bin/start-ds
    $ /path/to/ds2/bin/stop-ds
  4. Verify again you can still access both AM servlets as bjensen.

    For am1 and am2, 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.

Explore further

Reference material

Reference Description

In-depth information on setting up AM CTS with explanations of the tradeoffs

Details about DS for CTS

Details about DS for AM configuration

Details about DS for AM identities

Settings for letting DS reap expired tokens