Cassandra storage extension for Keycloak
Uses Apache Cassandra to store and retrieve entities of all storage areas except authorization and events. Requires Keycloak 22.0.x with enabled Map-Storage feature.
How to use
- Download the JAR from Maven Central: https://repo1.maven.org/maven2/de/arbeitsagentur/opdt/keycloak-cassandra-extension/1.1.0-22.0.1/keycloak-cassandra-extension-1.1.0-22.0.1.jar
- Put the JAR in Keycloak's providers folder
- Set "cassandra-map" as implementation for the "datastore"-SPI, for example via ENV-variable:
KC_SPI_DATASTORE_PROVIDER=cassandra-map
(for alternatives see the Keycloak configuration guide) - Set the necessary configuration options like cassandra endpoints (see the overview below)
- (optional) Override some areas with different storage providers, for example
KC_STORAGE_AREA_CLIENT=file
and disable this area in the cassandra-datastoreKC_SPI_DATASTORE_CASSANDRA_MAP_CLIENT_ENABLED=false
Use for caching only (Replace Infinispan)
This extensions enables users to get rid of Infinispan for caching and use Cassandra instead! The benefits are much easier operations and a proven way for multi-site setups, where Cassandra handles all the Cross-DC Synchronizations.
Set KC_SPI_DATASTORE_CASSANDRA_MAP_CACHE_MODE=true
(or equivalent keycloak configuration mechanisms) and configure
the default map-storage (for example via KC_STORAGE=file
) to use this extension for cache areas (authSession, userSession, singleUseObject) only.
Configuration options
CLI-Parameter | Description |
---|---|
--spi-cassandra-connection-default-port | Cassandra CQL-Port |
--spi-cassandra-connection-default-contact-points | Comma-separated list of cassandra node-endpoints |
--spi-cassandra-connection-default-local-datacenter | Local datacenter name |
--spi-cassandra-connection-default-username | Username |
--spi-cassandra-connection-default-passwort | Password |
--spi-cassandra-connection-default-keyspace | Keyspace-name (will be generated by the extension if it does not exist at startup-time) |
--spi-cassandra-connection-default-replication-factor | Replication factor used if the extension creates the keyspace with simple strategy |
Deviations from standard storage providers
User Lookup
Due to Cassandras query first nature, users can only be looked up by specific fields.
UserProvider::searchForUserStream
supports the following subset of Keycloaks standard search attributes:
keycloak.session.realm.users.query.search
for a case insensitive username searchkeycloak.session.realm.users.query.include_service_account
to include service accountsemail
for an email search
UserProvider::searchForUserByUserAttributeStream
by default iterates all users in the entire database to filter for the requested attribute in-memory.
For efficient searches, attributes can be defined as indexed attributes by prefixing their name with indexed., e.g. indexed.businessKey
Conditional updates / optimistic locking
All write-queries are done conditionally via Cassandra Lightweight Transactions. Therefore we store a version column in each of the tables. To be able to use this to get notified if a conflicting change occured after data was read, the entityVersion is exposed via a readonly attribute readonly.entityVersion. In order to pass a version in update operations, one can use the corresponding attribute internal.entityVersion.
Uniqueness across username and password
This extension supports additional checks to prevent setting username to a value that is already as email of another user and setting email to a value used as username.
To enable these checks for a realm, set its attribute enableCheckForDuplicatesAcrossUsernameAndEmail
to true
(default when not set: false
)
Development
Private image registries
If you use a private image registry, you can use the .testcontainers file in your user directory to override all image-registries used by the tests. See https://www.testcontainers.org/features/image_name_substitution/
Example:
docker.client.strategy=org.testcontainers.dockerclient.EnvironmentAndSystemPropertyClientProviderStrategy
hub.image.name.prefix=private-registry/3rd-party/
Debugging
Debugging can be enabled via mvn -Dmaven.surefire.debug verify
(Port 5005).
Using an external cassandra instance
If you want to use an external cassandra instance on localhost (Port 9042) you can
use mvn -Dkeycloak.testsuite.start-cassandra-container=false verify