Keycloak on Distributed SQL (CockroachDB) - Part 1/2

Keycloak on Distributed SQL (CockroachDB) - Part 1/2

With data breaches and cyber attacks becoming increasingly common, modern organisations require a robust security system in place that is also highly available. Keycloak is a popular open-source IAM solution that not only provides robust security features but also high availability between nodes by using a shared cache. It's built to be scalable and fault-tolerant, ensuring that your organisation's authentication and authorization services are always available when you need them. Keycloak can handle large user volumes and can be deployed in a distributed environment, making it suitable for businesses of all sizes.

The data within Keycloak is persisted in a database, however, and if that database does not provide the same level of resilience and availability as Keycloak then this compromises the solution. Traditional database backends such as postgres and MS SQL cannot provide the multi-region, multi-active capabilities and provide a single point of failure.

CockroachDB is a distributed SQL database designed for resilience and scalability. It's built to handle massive amounts of data and provide ACID transactions and distributed SQL for global scale. With CockroachDB, you can ensure that your data is always available, even in the face of network outages or hardware failures. Additionally because cockroach is postgres wire-compatible it is possible to configure Keycloak to connect to a CockroachDB. Below we will provide an example of how to implement Keycloak on a distributed CockroachDB on AWS EC2 instances.

This is the first half of a two-part post. In this post we will cover how to configure Keycloak to store data in Cockroach. In the subsequent post we will configure Keycloak to discover and share caches with other nodes by registering themselves on CockroachDB.

Target Architecture

For this implementation, the target architecture will be as shown below:


In this post we will only be looking at the first region (us-west-1).

The CockroachDB has been set up in advance on c5d.xlarge EC2 nodes with VPC peering used to allow connectivity between cockroach nodes in the disparate regions.

The keycloak nodes will also be c5d.xlarge nodes, with the following prerequisites:

  • Openssl installed (sudo apt install openssl)
  • Java installed (sudo apt install default-jdk)
  • Ports 8080, 8443 and 7800 open between keycloak nodes
  • Port 26257 open between keycloak nodes and the internal load balancers
  • UDP buffers resized:

Edit /etc/sysctl.com

# Allow a 25MB UDP receive buffer for JGroups
net.core.rmem_max = 26214400
# Allow a 1MB UDP send buffer for JGroups
net.core.wmem_max = 1048576

Run the following:

sudo sysctl -p


Additionally, one Keycloak node will also require:

  • Postgres database installed (sudo apt install postgresql)
  • Links2 browser (or similar) installed (sudo apt install links2)

Basic Keycloak installation (Node1)

The first stage is to download Keycloak to the first node (in us-west-1 in this example):

wget https://github.com/keycloak/keycloak/releases/download/20.0.3/keycloak-20.0.3.tar.gz
gunzip ./keycloak-20.0.3.tar.gz
tar xvf ./keycloak-20.0.3.tar

Once Keycloak is downloaded, we will launch this is “dev” mode to check all is running as expected:

cd keycloak
nohup bin/kc.sh start-dev > keycloak.log 2> keycloak.err &
ubuntu@keycloak01: —Ikeycloak-20.O.3 
tail —f keycloak. log 
2023-02-17 WARN [org.infinispan.CONFIG] (keycloak-cache-init) ISPN000569: Unable to 
aches as no global state enabled 
2023-02-17 WARN [org.infinispan.PERSISTENCE] (keycloak-cache-init) ISPN000554: jboss 
d planned for removal 
2023-02-17 17:43:50, 647 INFO [org.-infinispan.CONTAINER] (keycloak-cache-init) ISPN000556: Startin 
span. j boss. marshalli ng. core. JBossUserMarsha11er 
2023-02-17 17:43:51, 002 INFO [org.infinispan.CONTAINER] (keycloak-cache-init) ISPN000128: Infinis 
kai dekaphobia' 13.0.10. Final 
2023—02—17 17 INFO [org.keycloak.connections.infinispan.Defau1tInfinispanConnectionProv 
. node _ 121259, Site name: null 
2023—02—17 17 INFO [org. keycloak.broker. der. AbstractldentityProviderMapper] (main) 
ak. broker. provi der. mappersync. Confi gSyncEventLi stener 
2023—02—17 17:43:52, 058 INFO [io.quarkus] (main) Keycloak 20.0.3 on JVM (powered by Quarkus 2.13. 
istening on: http://O.O.O.O:8@80 
2023—02—17 17:43:52, 058 INFO [io.quarkus] (main) Profile dev activated. 
2023—02—17 17 INFO [io.quarkus] (main) Installed features: [agroal, cdi, hibernate—orm, 
mssql, jdbc—mysql, jdbc—oracle, jdbc—postgresql, keycloak, logging—gelf, narayana—jta, reactive—ro 
son, smallrye—health, smallrye—metrics, vault, vertx] 
2023—02—17 17 062 WARN [org. keycloak. quarkus. runtime. Keyc10akMain] (main) Running the serve 
use this confi guration in production.

Once Keycloak is running in development mode we can then configure admin password using a browser on the local host:

links2 http://localhost:8080
ubuntu@keycloak01: —Ikeycloak-20.O.3 
Keycloak 
Welcome to Keycloak 
Admi nistration Console 
Please create an initial admin user to get started. 
Username admin 
Password 
Password confi rmation 
Create 
[IMG]Administration Console 
Centrally manage all aspects of the Keycloak server 
[ING] Documentati on 
User Guide, Admin REST API and Javadocs 
[ING] Keycloak Project
ubuntu@keycloak01: —Ikeycloak-20.O.3 
eycloak 
Welcome to Keycloak 
User created 
[IMG]Administration Console 
Centrally manage all aspects of the Keycloak server 
[ING] Documentati on 
User Guide, Admin REST API and Javadocs 
[ING] Keycloak Project 
[IMG]Mai1ing List 
[ING] Report an issue

The Keycloak Admin console can now be accessed:

Welcome to Keycloak 
A Not secure 
keycloak01 :8080 
Keycloak 
Welcome to 
Administration Console > 
Centrally manage all aspects of the Keycloak 
ajs-GUl-Bastion 
Documentation > 
user Guide. Admin REST API and Javadocs 
@ Keycloak Project > 
g Mailing List > 
Report an issue >
ajs-GUl-Bastion 
Sign in to Keycloak 
C A Not secure I keycloak01:8080/realms/master/protocol/openid-connect/auth?client_id=security-admin-console&redirect_uri=http%3A%2F%2Fkeycloak01%3AE 
«DKEYCLOAV 
Sign in to your account 
Username or email 
admin 
Password 
.....l 
Sign In
ajs-GUl-Bastion 
Keycloak Administration Console X + 
C A Not secure I 
master 
Manage 
Clients 
Client scopes 
Realm roles 
Users 
Groups 
Sessions 
Events 
Configure 
Realm settings 
Authentication 
Identity providers 
master realm 
Admin UI version 285a5572183c923ed4ec1daa702840b11b05ccb9 
Realm info 
Server Info 
Version 
20.0.3 
Product 
Default 
Provider info 
Profile 
Enabled features O 
Disabled features 
ADMIN Supported Preview 
Preview DOCKER Supported 
DYNAMIC_SCOPE! 
MAP_STORAGE Experimental 
TOKEN_EXCHANGE Preview 
OPENSHIFT INTEGRATION Preview RECOVERY 
UPDATE_EMAIL Preview

This verifies the Keycloak server is functioning. We will now configure the server to be ready for production.

Configure Node1 for Production

The first stage will be to secure the interface with SSL, we will then configure Keycloak to use postgres as an interim step. Finally, we will configure Keycloak to connect to a CockroachDB. We require the interim step of using postgres to generate the schema as this cannot currently be generated directly in cockroach from Keycloak.

First off, we stop the running keycloak server.

To generate self-signed certificates, in the keycloak directory run the following commands:

mkdir ssl_certs
cd ssl_certs
openssl req -new > cert.csr
openssl rsa -in privkey.pem -out key.pem
openssl x509 -in cert.csr -out cert.pem -req -signkey key.pem -days 3650
cat key.pem>>cert.pem
ubuntu@keyctoakel : -/keyctoak-20. O. 3/sst_certs 
total 16K 
ubuntu@keycIoak01: —Ikeycloak-20.O.3/ssl_certs 
$ Is -ltrh 
1 ubuntu ubuntu 1.9K 
-rw—rw—r—— 1 ubuntu ubuntu 1.2K 
1 ubuntu ubuntu 1.7K 
, 1 ubuntu ubuntu 3. IK 
Feb 17 18:00 privkey .pem 
Feb 17 18:00 cert.csr 
Feb 17 18:01 key.pem 
Feb 17 18:02 cert.pem 
ubuntu@keycloak€l : -/keyctoak-20. O. 3/ sst_certs$

We now change the Keycloak server to use https, edit conf/keycloak.conf to include the following values for:

# If the server should expose healthcheck endpoints.
health-enabled=true
# If the server should expose metrics endpoints.
metrics-enabled=true
# HTTP
# The file path to a server certificate or certificate chain in PEM format.
https-certificate-file=${kc.home.dir}/ssl_certs/cert.pem
# The file path to a private key in PEM format.
https-certificate-key-file=${kc.home.dir}/ssl_certs/key.pem
# Hostname for the Keycloak server.
hostname=keycloak01

Once this has been done, we build and run the keycloak server again:

bin/kc.sh build
nohup bin/kc.sh start > keycloak.log 2>keycloak.err &
ubuntu@keycloak01: —Ikeycloak-20.O.3 
tail —f keycloak. log 
2023—02—17 18:34:59, 688 INFO [org. keycloak.quarkus. runtime. hostname. DefaultHostnameProvider] (mai 
L: <unset>, Hostname: keycIoak01, Strict HTTPS: true, Path: <request>, Strict BackChanneI: false, 
equest>, Port: —1, Proxied: false 
2023—02—17 18:35:01, 030 WARN [io.quarkus.agroal. runtime. DataSources] (main) Datasource <default> 
covery is not enabled. Please enable transaction recovery by setting quarkus.transaction—manager.e 
e data may be lost if the application is terminated abruptly 
2023-02-17 WARN [org.infinispan.PERSISTENCE] (keycloak-cache-init) ISPN000554: jboss 
d planned for removal 
2023-02-17 WARN [org.infinispan.CONFIG] (keycloak-cache-init) ISPN000569: Unable to 
aches as no global state enabled 
2023-02-17 INFO [org.infinispan.CONTAINER] (keycloak-cache-init) ISPN000556: Startin 
span. j boss. marshalli ng. core. JBossUserMarsha11er 
2023-02-17 INFO [org.infinispan.CONTAINER] (keycloak-cache-init) ISPN000128: Infinis 
kai dekaphobia' 13.0.10. Final 
2023-02-17 INFO [org.infinispan.CLUSTER] (keycloak-cache-init) ISPN000078: Starting 
2023-02-17 INFO [org.infinispan.CLUSTER] (keycloak-cache-init) ISPN000088: Unable to 
n mechanisms provided in properties { } . Using default JGroups confi guration! 
2023—02—17 , 604 INFO [org.jgroups.protocols.pbcast. GMS] keyc10ak01- 
after 2005 ms: creating cluster as coordinator 
2023-02-17 INFO [org.-infinispan.CLUSTER] (keycloak-cache--in-it) ISPN000094: Received 
ISPN: [keyc10ak01-6251910] (1) [keyc10ak01-62519] 
2023-02-17 INFO [org.infinispan.CLUSTER] (keycloak-cache-init) ISPN000079: Channel 
oak01-62519S 
, physical addresses are 
2023—02—17 18:35:05, 016 INFO [org. keycloak. connections. infinispan.Defau1tInfinispanConnectionProv 
keyc10ak01—62519, Site name: null 
2023—02—17 024 INFO [org. keycloak.broker. provider. AbstractldentityProviderMapper] (main) 
ak. broker. provi der. mappersync. Confi gSyncEventLi stener 
2023—02—17 18:35:05, 625 INFO [io.quarkus] (main) Keycloak 20.0.3 on JVM (powered by Quarkus 2.13. 
istening on: https://O.O.O.O:8443 
2023—02—17 18:35:05, 625 INFO [io.quarkus] (main) Profile prod activated. 
2023—02—17 625 INFO [io.quarkus] (main) Installed features: [agroal, cdi, hibernate—orm, 
mssql, jdbc—mysql, jdbc—oracle, jdbc—postgresql, keycloak, logging—gelf, narayana—jta, reactive—ro

Ensure port 8443 is open between the browser and the Keycloak node, and connect to the admin interface.

Welcome to Keycloak 
Not secure 
k*ps//keycloak01 :8443 
Keycloa 
Welcome to 
Administration Conso 
Centrally manage all aspects of the K' 
ajs-GUl-Bastion 
Certificate Viewer: keycloak01 
Issued To 
Common Name (CN) 
Organization (O) 
Organizational Unit (OU) 
Issued By 
Common Name (CN) 
Organization (O) 
Organizational Unit (OU) 
keycloak01 
Cockroach Labs 
S. Engineering 
keycloak01 
Cockroach Labs 
S. Engineering 
Friday. February 17, 2023 at PM 
Monday, February 14, 2033 at 6:01:48 PM 
VaEdiV Penod 
Issued On 
Expires On 
Firgerpönts 
SHA-256 Fingerprint 
SHA-I Fingerprint 
F6 Fl 5A 20 7F 3E 63 67 4282 C 
50 13 54C8C9BE4FB1 ADD 5B 45 EFA4 IA 40 
BE 1871 70 DB4E 1B 63 70 IC FEC4898861C2 
4AEF88E6 
oak Project > 
•g List > 
rt an issue >


Now we have an encrypted connection to keycloak, we can configure the database backend.

stop keycloak and then setup the postgres databases and user:

sudo su postgres
psql
postgres=# create database keycloak;
postgres=# create user keycloak with password 'keycloak';
postgres=# grant all on database keycloak to keycloak;
postgres=# create database jgroups;
postgres=# grant all on database jgroups to keycloak;
ubuntu@keycloak01: —Ikeycloak-20.O.3 
sudo su postgres 
psql 
could not change di rectory to "/home/ubuntu/keycIoak—20.O.3": Permission denied 
psql (14.6 (Ubuntu 14.6—0ubuntuO.22.04.1)) 
Type "help" for help. 
postgres=# create database keycloak; 
CREATE DATABASE 
postgres=# create user keycloak with password 'keycloak' • 
CREATE ROLE 
postgres=# grant all on database keycloak to keycloak; 
GRANT 
postgres=# create database j groups; 
CREATE DATABASE 
postgres=# grant all on database j groups to keycloak; 
GRANT 
postgres=#

Confirm can log on from keycloak user to both dbs:

ubuntu@keycloak01: —Ikeycloak-20.O.3 
psql 
——host=localhost —U keycloak —d keycloak 
Password for user keycloak: 
psql (14.6 (Ubuntu 14.6—0ubuntuO.22.04.1)) 
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: 
Type "help" for help. 
keycloak=> \q 
psql ——host=localhost —U keycloak —d jgroups 
Password for user keycloak: 
psql (14.6 (Ubuntu 14.6—0ubuntuO.22.04.1)) 
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: 
Type "help" for help. 
off) 
off)

Now we change the database backend to postgres. Again edit the conf/keycloak.conf file and ensure the following values are set:

# The database vendor.
db=postgres
# The username of the database user.
db-username=keycloak
# The password of the database user.
db-password=keycloak
# The full database JDBC URL. If not provided, a default URL is set based on the selected database vendor.
db-url=jdbc:postgresql://localhost/keycloak

Again build the Keycloak configuration and start the server. Once this has been done check to confirm database created.

ubuntu@keycloak01: —Ikeycloak-20.O.3 
psql 
——host=localhost —U keycloak —d keycloak 
Password for user keycloak: 
psql (14.6 (Ubuntu 14.6—0ubuntuO.22.04.1)) 
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: 
Type "help" for help. 
keycloak=> \d 
off)
List of 
Schema 
Name 
public 
admi ty 
public 
associ ated_poli cy 
publi c 
public 
public 
public 
public 
publi c 
public 
public 
publi c 
public 
public 
cli ent_scope 
publi c 
public 
public 
publi c 
cli ent_sessi on 
public 
public 
publi c 
public 
public 
publi c 
public 
public 
publi c 
public 
public 
publi c 
relati ons 
authenti cati on_executi on 
authenti cati on _ f Iow 
authenti cator_confi g 
authenti cator_confi g_entry 
broker _ link 
cli ent 
cli ent_attri butes 
cli ent_auth_ flow_bi ndi ngs 
cli ent_i ni ti al _ access 
cli strati ons 
cli butes 
cli ent 
cli ng 
cli ent_sessi on_auth_status 
cli ent_sessi on_note 
cli ent_sessi on_prot_mapper 
cli ent_sessi on_role 
cli on_note 
component 
component_confi g 
composi te_role 
credenti al 
databasechangelog 
databasechangeloglock 
default_cli ent_scope 
Type 
table 
table 
table 
table 
table 
table 
table 
table 
table 
table 
table 
table 
table 
table 
table 
table 
table 
table 
table 
table 
table 
table 
table 
table 
table 
table 
table 
table 
table 
ubuntu@keycloak01: -Ikeycloak-20.O.3 
Owner 
keycloak 
keycloak 
keycloak 
keycloak 
keycloak 
keycloak 
keycloak 
keycloak 
keycloak 
keycloak 
keycloak 
keycloak 
keycloak 
keycloak 
keycloak 
keycloak 
keycloak 
keycloak 
keycloak 
keycloak 
keycloak 
keycloak 
keycloak 
keycloak 
keycloak 
keycloak 
keycloak 
keycloak 
keycloak

As per the Keycloak documentation (https://www.keycloak.org/getting-started/getting-started-zip) we will create a new realm and a new user to ensure the database is being populated.

_J Keycloak Administration Console X + 
Not secure I 
new-realm 
master 
new-realm 
Create Realm 
Users 
Groups 
Sessions 
Events 
Configure 
Realm settings 
Authentication 
Identity providers 
Users 
Users are the users in the current realm. 
Learn more 
User list 
Permissions 
ajs-GUl-Bastion 
No users found 
Change your search criteria or add a user 
Create new user
ajs-GUl-Bastion 
_J Keycloak Administration Console X + 
Not secure I 
new-realm 
Manage 
Clients 
Client scopes 
Realm roles 
Users 
Groups 
Sessions 
Events 
Configure 
Realm settings 
Authentication 
Identity providers 
Users > Create user 
Create user 
Username 
Email 
Email verified O 
First name 
Last name 
Required user actions 
O 
Groups O 
user.kcl 
spindler@cockroachlabs.corq 
Off 
Adam 
Spindler 
Select action 
Join Groups

Setting the new users password:

ajs-GUl-Bastion 
_J Keycloak Administration Console X + 
Not secure I 
(O'KEYCLOAK 
new-realm 
Manage 
Clients 
Client scopes 
Realm roles 
Users 
Groups 
Sessions 
Events 
Configure 
Realm settings 
Authentication 
Identity providers 
Users User details 
user.kcl 
Details 
Attributes 
Credentials 
Role mapping 
Groups 
Zonsents 
Set password for user.kcl 
Password confirmation * 
Temporary O 
Cancel 
Key-cloak Account Management • Gccgle Chrome 
Identity provider links 
ord for this user.

Once this has been done, we can test we can log in with the new user:

ajs-GUl-Bastion 
I Keycloak Administration Console Sign in to new-realm 
Not secure I Å#ps//keycloak01:8443/realms/new-realm/protocol/openid-connect/auth?client_id=security-admin-console&redirect_uri=https%3A%2F%2FkeycloakOV 
NEW-REALM 
Sign in to your account 
Username or email 
user.kcl 
Pa ssword 
Sign •n 
o
ajs-GUl-Bastion 
I Keycloak Administration Console X J K$oakAccountManagement X 
Not secure I Bkps//keycloak01:8443/realms/new-realm/account/?referrer=security-admin-console&referrer_uri=https%3A%2F%2Fkeycloak01%3A8443%2Fadmin%21 
Back to security a 
Personal info 
Account security 
Applications 
Personal info 
Manage your basic information. 
All fields are required. 
Username 
user.kcl 
Email 
spindler@cockroachlabs.com 
First name 
Adam 
Last name 
Spindler

We then confirm that the data is being created in the database. This can be done via the psql command line tool:

psql –host=localhost -U keycloak -d keycloak
postgres=# select from realm;
postgres=# select * from user_entity;
ubuntu@keycloak01: —Ikeycloak-20.O.3 
psql 
——host=localhost —U keycloak —d keycloak 
Password for user keycloak: 
psql (14.6 (Ubuntu 14.6—0ubuntuO.22.04.1)) 
SSL connection (protocol: 
Type "help" for help. 
keycloak=> select * from 
keycloak=> select * from 
1 
TLSv1.3, cipher: bits: 256, compression: 
realm; 
user_enti ty ; 
off)
ubuntu@keycloak01: —Ikeycloak-20.O.3 
I fespan I fespan I access _ token 
dmin_theme I email _ theme I enabled I events_enabled I events_expi ration I login_theme I 
name 
y I registration _ allowed I remember_me I reset _ password _ allowed I social I ssl_requi red I sso_idle 
update_profile_on_soc_login I veri fy_email I 
I login_li fespa 
led I default _ locale I reg_email_as_username I admin_events_enabled I 
p _ policy _ counter I I I gits I I ot 
rowser_flow 
regi strati on _ flow 
di rect_grant_ flow 
I meout I revoke_refre 
s _ flow 
implicit I I duplicate _ emails _ allowed I 
docker_auth_flow 
I allow_user_managed_access I I I 
dd4a6ddb—c5b5—4aa@— 
If 
01 
a663- 
If 
dbc281a207cc I 
60 | 
300 | 
It 
If 
If 
If 
If 
Il 
07d3- 
-9889 
If 
01 
If 
I EXTERNAL 
I coale621-975f-465e-9437-88eecbc99816 1 
master 
18€ 
—4bac—af1f—12@bbbb6f9d2 1 b18c899d— 
-f3b343f23097 1 488c4320-c905-440a 
900 | t 
If 
b9 
If 
30 | 
48fc-a295-22a21f118d04 1 
-07a1d31728fd I 
01 
If 
6 | HmacSHA1 
4b74fd8a—d3cO—4dc5—a9cd—bc9fc3b59 
2592000 | f 
657e1069-706a-4a9c-9acb-49f21f74b 
0 1 9c8c8
ubuntu@keycloak01: 
emai 1 
abled I federation_link 
I fi rst_name 
not _ before 
I last _ 
name 
-Ikeycloak-20.O.3 
realm_i d 
emai I_constraint 
I username 
2dcf4005-ab1e-4aOf-aa5b-2611b6053f4d 
18f66d2a-ac52-4c12-84ec-dc69e32756ce 
I Adam 
(2 rows) 
(END) 
1 2130206b-84a9-4f49-bae7-24e72 
I dd4a6ddb—c5b5—4aaO—a663—dbc281a207cc I admin 
I spindler@cockroachlabs.com I spindler@cockroachlabs.com 
Spindler I able94cb—Ocde—4d8f—99b5—69e50322592e I user. kcl

Now to change the connection to use the Cockroach Distributed database, we first need to stop keycloak and then use pg_dump to extract the data from postgres:

pg_dump –host=localhost -U keycloak -d keycloak > keycloak.dmp

Once we have the output we can put this into cockroach. We first need to create the databases and the user. Using your preferred sql client (in this example I am using the cockroach sql command from the database node), connect to CockroachDB and issue the following commands:

create user keycloak with password 'keycloak';
create database keycloak;
create database jgroups;
grant all on database keycloak to keycloak;
grant all on database jgroups to keycloak;
ubuntu@ajs-db01: —Icockroach 
sql ——host=aj s—db01: 
26257 
a semicolon. 
# Welcome to the 
# All statements 
# To exit, type: 
# Server version: 
n as client) 
cockroach 
CockroachDB SQL shell. 
must be terminated by 
\q. 
——certs—di r=certs 
CockroachDB CCL v22.2.2 
-gnu, built 2023/01/04 
# Cluster ID: 130db927-c130-47c4-9d69-cf14b36ca70d 
# Organization: Adam. Spindler 
No entry for terminal type "xterm—256c010r" • 
using dumb terminal settings. 
# Enter \ ? for a brief introduction. 
root@ajs—db01:26257/defau1tdb> create user keycloak with password 'keycloak' ; 
CREATE ROLE 
Time: 2.381s total (execution 2.381s / network 0.000s) 
root@ajs—db01:26257/defau1tdb> create database keycloak; 
CREATE DATABASE 
Time: 315ms total (execution 314ms / network Oms) 
root@ajs—db01:26257/defau1tdb> create database jgroups; 
CREATE DATABASE 
Time: 314ms total (execution 313ms / network Oms) 
root@ajs—db01:26257/defau1tdb> grant all on database keycloak to keycloak; 
GRANT

We then verify that we can connect as the newly created user:

——certs—di r=certs —d k 
# Welcome to the 
# All statements 
# To exit, type: 
cockroach 
CockroachDB SQL shell. 
must be terminated by 
\q. 
ubuntu@ajs-db01: —Icockroach 
sql ——host=aj s—db01: 
26257 
a semicolon. 
Connecting to server as user "keycloak" . 
Enter password: 
# Server version: CockroachDB CCL v22.2.2 
n as client) 
# Cluster ID: 130db927-c130-47c4-9d69-cf14b36ca70d 
# Organization: Adam. Spindler 
No entry for terminal type "xterm—256c010r" • 
using dumb terminal settings. 
# Enter \ ? for a brief introduction. 
gnu, built 2023/01/04
——certs—di r=certs —d J 
# Welcome to the 
# All statements 
# To exit, type: 
cockroach 
CockroachDB SQL shell. 
must be terminated by 
\q. 
ubuntu@ajs-db01: —Icockroach 
sql ——host=aj s—db01: 
26257 
a semicolon. 
Connecting to server as user "keycloak" . 
Enter password: 
# Server version: CockroachDB CCL v22.2.2 
n as client) 
# Cluster ID: 130db927-c130-47c4-9d69-cf14b36ca70d 
# Organization: Adam. Spindler 
No entry for terminal type "xterm—256c010r" • 
using dumb terminal settings. 
# Enter \ ? for a brief introduction. 
gnu, built 2023/01/04

We now populate the Cockroach database from pg_dump output.

cockroach sql --host=ajs-db01:26257 --certs-dir=certs -d keycloak -u keycloak -f keycloak.dmp

Verify data has been created by querying the “realm” and “user_entity_ tables.

ubuntu@ajs-db01: —Icockroach 
—d keycloak —u keycloak 
cockroach sq1 
--host-aj s-db€l : 26257 
# Welcome to the CockroachDB SQL shell. 
# All statements must be terminated by a semicolon. 
# To exit, type: 
Connecting to server "ajs-db01:26257" as user 
Enter password: 
# Server version: CockroachDB CCL v22.2.2 (x86_64-pc-1inux-gnu, built 2023/01/04 17:23:00, gol.19.1) (same version as client) 
# Cluster ID: 130db927-c13e-47c4-9d69-cf14b36ca70d 
# Organization: Adam. Spindler 
No entry for terminal type "xterm—256coIort• ; 
using dumb terminal setti ngs. 
# Enter \ ? for a brief introduction. 
keyctoak@ajs-db01:26257/keyctoak> select * from realm; 
id 
I I I I account _ theme I admin_theme I email _ theme I en 
gin_theme I name I not_before I password_policy I registration_allowed I remember_me I I social I ssl_required I 
in I verify_emait I 
master_admin_ctient 
I login_lifespan I internationalization_enabled I defautt_locale I I admin_eve 
I otp_policy_counter I otp_policy_window I I I I otp_poticy_type I 
browser 
reset_credenti a Is_flow 
licit I I duplicate_emai ts_altowed I 
client _ auth _ flow 
I refresh_token_max_reuse I I ss 
emember_me I 
default_role 
able94cb-ecde-4d8f-99b5-69e50322592e I 
I new—realm I 
e I NULL 
60 | 
300 | 
30 | 
300 | NULL 
I NULL 
6 | HmacSHA1 
I totp 
I NULL 
1 EXTERNAL 
I NULL 
1 23ab7baa-f59a-4842-9ø21-62fcecfac5fb I 
11 
1800 | 
7cda2ab6b 1 21ecbda6-1394-49dd-9724-27f498øce4bd 1 ac1e4ed4-4fe6-41d5-be02-cec1ab4f92b8 1 89f3918ø-ee2d-493b-ac92-585f5e64b242 1 
900 | 
e 1 14fa5b72-07b7-443e-a58f-89af4fa5c766 
dd4a6ddb-c5b5-4aaø-a663-dbc281a207cc I 
I master 
e I NULL 
1 7f61988a-81b9-4faf-b763-d2e1824b64d2 1 
60 | 
3øe I 
60 | NULL 
I NULL 
1 EXTERNAL 
1806 
186010ac-5ebd-42df- 
2592eee 
I NULL 
18ee
—d keyctoak 
# Welcome to the 
# Alt statements 
# To exit, type: 
cockroach 
CockroachDB SQL shell. 
must be terminated by 
ubuntu@ajs-db01: —Icockroach 
sq1 ——host=ajs—db01:26257 
——certs—di r=certs 
a semicolon. 
—u keyctoa 
Connecting to server as user "keyctoak" . 
Enter password: 
# Server version: CockroachDB CCL v22.2.2 built 2023/01/04 17:23:00, gol.19.I) (sam 
# Cluster ID: 130db927-c130-47c4-9d69-cf14b36ca70d 
# Organization: Adam. Spindler 
No entry for terminal type "xterm—256cotor" • 
using dumb terminal settings. 
# Enter \ ? for a brief introduction. 
keycloak@aj s—db01 : 26257 /keycloak> select 
from 
user _ enti ty ; 
emai 
reatm_id 
federation 
_ link I fi rst_name I last _ name 
link I not_ 
before 
NULL 
2dcf4005- 
NULL 
(2 rows) 
emai t _ constrai nt 
I username I created _ time 
18f66d2a-ac52-4c12-84ec- 
I Adam 
I NULL 
dc69e32756ce I 
I Spindter 
2611b6053f4d I 
I NULL 
spi ndter@cockroachlabs.com I spindter@cockroachtabs . com 
I able94cb-Ocde-4d8f-99b5-69e50322592e I user.kcl I 
16766608 
1 2130206b-84a9-4f49-bae7-24e726d04a5 
NULL 
I dd4a6ddb—c5b5—4aaO—a663—dbc281a207cc I admin 
16766607

We now need to put the Cockroach DB ca.crt file on the keycloak node as cockroach requires ssl secured communications.

We stop Keycloak server and configure keycloak to connect to the CockroachDB by editing conf/keycloak.conf to edit the database url and disable XA transactions as Cockroach does not support XA transactions. Include the following lines:

# The full database JDBC URL. If not provided, a default URL is set based on the selected database vendor.
# db-url=jdbc:postgresql://localhost/keycloak
db-url=jdbc:postgresql://ajs-db-demo-int-1b85bcdea0b73e74.elb.us-west-1.amazonaws.com:26257/keycloak?sslmode=require&amp;sslrootcert=${kc.home.dir}/crdb_certs/ca.crt
# disable XA transactions
transaction-xa-enabled=false

We can now start keycloak again and confirm login and data being created by creating a new user and checking the “user_entity” table in CockroachDB.

ajs-GUl-Bastion 
_J Keycloak Administration Console X K%doakAccwntMargemert X I + 
Not secure I 
new-realm 
Manage 
Clients 
Client scopes 
Realm roles 
Users 
Groups 
Sessions 
Events 
Configure 
Realm settings 
Authentication 
Identity providers 
Users 
Users are the users in the current realm. 
User list 
Q Search user 
Username 
userkcl 
userkc2 
Permissions 
Email 
Learn more 
Add user 
Delete user 
Last name 
Spindler 
O spindler@cockroachlabs.com 
O dh@cockroachlabs.com
To exit, type: 
Client version: 
Server version: 
ubuntu@ajs-bastion: 
CockroachDB CCL v22.2.5 (x86_64-app1e-darw-in19, built 2023/02/16 16:31:39, gol.19.4) 
CockroachDB CCL v22.2.2 (x86_64-pc-t-inux-gnu, built 2023/01/04 gol.19.1) 
warning: server version older than client! proceed with caution; some features may not be available. 
# Cluster ID: 130db927-c130-47c4-9d69-cf14b36ca7@d 
# Organization: Adam. Spindler 
# Enter \ ? for a brief introduction. 
root@ajs-demo-tb-ObeeeOcdc649d47c.e1b.eu-west-2.amazonaws.com:26257/defau1tdb> use keycloak; 
warning: cannot save command-tine history: write _ history: illegal byte sequence 
SET 
Time: 93ms total 
(execution 80ms / network 12ms) 
root@aj s-demo-tb-ObeeeOcdc649d47c. elb. eu-west-2. amazonaws . com : 
ederation_link I 
nk I 
not _ before 
26257/keyc10ak> 
I last _ name 
fi rst_name 
email 
realm_id 
select * from user _ entity; 
emai 1 _ constrai nt 
created _ times 
username 
ULL 
2dcf4005- 
ULL 
18f66d2a-ac52-4c12-84ec-dc69e32756ce 
I Adam 
able-4aOf-aa5b- 
I NULL 
I Spindler 
2611b6053f4d 
I NULL 
spindler@cockroachtabs.com I spindler@cockroachlabs.com 
I able94cb-Ocde-4d8f-99b5-69e50322592e I 
user. kcl I 
167666087 
1 2130206b-84a9-4f49-bae7-24e726d04a5 
NULL 
I dd4a6ddb-c5b5-4aaO-a663-dbc281a207cc 
I admin 
167666076

In part 2 we will cover how to add more nodes to the cluster and ensure that the keycloak nodes are able to register themselves on CockroachDB which, then allows Keycloak to share cache information.