How to Use Apache Cassandra as User and Session DataStore in OpenAM - OpenIdentityPlatform/OpenAM GitHub Wiki

How to Use Apache Cassandra as User and Session DataStore in OpenAM

Introduction

One of the performance bottlenecks of authentication is User DataStore. This becomes noticeable when the total number of user accounts exceeds 4 000 000.

To maintain acceptable performance, the most obvious solution is to scale User DataStore horizontally or vertically. But with an increasing amount of data, DataStore scaling does not affect performance.

With the increasing load on the authentication system, the most obvious solution is to scale horizontally or vertically the number of user repository nodes.

Another alternative solution is to use storage specifically designed for working with large amounts of data. One of such storages is Apache Cassandra. It has proved itself as a high-availability and high-performance datastore.

Prepare Apache Cassandra

Allow materialized views for Cassandra 4+ (in version 3 enabled by default) in conf/cassandra.yaml:

# Enables materialized view creation on this node.
# Materialized views are considered experimental and are not recommended for production use.
enable_materialized_views: true

Prepare Apache Cassandra to use as User DataStore

Сreate the corresponding Keyspaces and tables, for each OpenAM realm, from template import.cql

bin/cqlsh -f import.cql

Prepare Apache Cassandra to use as CTS

Сreate the corresponding Keyspaces and tables, for OpenAM CTS, from template schema.cqlsh

bin/cqlsh -f schema.cqlsh

OpenAM Setup

Add cassandra contact-points info in bin/setenv.sh and restart OpenAM:

export CATALINA_OPTS=" ... \
-Ddatastax-java-driver.basic.contact-points.0=ip1:9042 \
-Ddatastax-java-driver.basic.contact-points.1=ip2:9042 \
-Ddatastax-java-driver.basic.load-balancing-policy.local-datacenter=datacenter1 \
-Ddatastax-java-driver.advanced.auth-provider.class=PlainTextAuthProvider \
-Ddatastax-java-driver.advanced.auth-provider.username=user \
-Ddatastax-java-driver.advanced.auth-provider.password=password \
"

OpenAM create DataStore

Open OpenAM administration console, goto Realms select target realm, then goto DataStores and create new DataStore.

OpenAM Create Cassandra DataStore

Then setup following settings:

Server settings

Setting Value
Servers don't use (leave blank)
User name don't use (leave blank)
Password don't use (leave blank)
Password (confirm) don't use (leave blank)
Keyspace Cassandra keyspace for this realm realm_name

Plugin configuration

Setting Value
Database Repository Plugin Class Name org.openidentityplatform.openam.cassandra.Repo
Tables group=groupuser=userrealm=realm
Operations realm=read,create,edit,delete,service group=read,create,edit,delete user=read,create,edit,delete,service

User Configuration

Setting Value
TTL realm:attr1=86400 user:attr2=86400 group:attr3=86400
Attribute Name of User Status inetuserstatus
User Status Active Value Active

Group Configuration

Setting Value
Attribute Name for Group Membership memberOf

Click the Save button

You can check datastore. Goto Subjects -> Users and create a new user account. For example:

OpenAM Create Cassandra User Account

Click Save and make sure, the record exists in Cassandra:

cassandra@cqlsh:realm_name> SELECT * FROM realm_name.values ;

OpenAM CTS Setup

Add cassandra external CTS settings in bin/setenv.sh:

export CATALINA_OPTS=" ... \
-Dorg.forgerock.openam.sm.datalayer.module.CTS_ASYNC=org.openidentityplatform.openam.cassandra.CTSAsyncConnectionModule  \
-Dorg.forgerock.openam.sm.datalayer.module.CTS_MAX_SESSION_TIMEOUT_WORKER=org.openidentityplatform.openam.cassandra.CTSConnectionModule  \
-Dorg.forgerock.openam.sm.datalayer.module.CTS_SESSION_IDLE_TIMEOUT_WORKER=org.openidentityplatform.openam.cassandra.CTSConnectionModule  \
-Dorg.forgerock.openam.sm.datalayer.module.CTS_EXPIRY_DATE_WORKER=org.openidentityplatform.openam.cassandra.CTSConnectionModule  \
-Dorg.forgerock.services.cts.store.root.suffix=cts.tokens  \
"

restart OpenAM, login and check session info in Cassandra

cassandra@cqlsh:cts> SELECT * FROM cts.tokens ;