diff --git a/molecule/quarkus_ha_remote/converge.yml b/molecule/quarkus_ha_remote/converge.yml index e31ad72..e62ae23 100644 --- a/molecule/quarkus_ha_remote/converge.yml +++ b/molecule/quarkus_ha_remote/converge.yml @@ -12,6 +12,7 @@ infinispan_jdbc_driver_version: 9.4.1212 infinispan_jdbc_user: keycloak infinispan_jdbc_pass: mysecretpass + infinispan_bind_address: "{{ ansible_default_ipv4.address }}" infinispan_users: - { name: 'testuser', password: 'test', roles: 'observer' } @@ -41,9 +42,16 @@ keycloak_quarkus_db_user: keycloak keycloak_quarkus_db_pass: mysecretpass keycloak_quarkus_db_url: jdbc:postgresql://postgres:5432/keycloak + keycloak_quarkus_cache_remote: true keycloak_quarkus_cache_remote_username: supervisor keycloak_quarkus_cache_remote_password: remembertochangeme - keycloak_quarkus_cache_remote_host: "infinispan1:11222" + keycloak_quarkus_cache_remote_host: "infinispan1" + keycloak_quarkus_cache_remote_port: 11222 keycloak_quarkus_cache_remote_tls_enabled: false + keycloak_quarkus_additional_env_vars: + - key: KC_FEATURES + value: clusterless + - key: KC_FEATURES_DISABLED + value: persistent-user-sessions roles: - role: keycloak_quarkus diff --git a/roles/keycloak_quarkus/README.md b/roles/keycloak_quarkus/README.md index 0da7272..c461203 100644 --- a/roles/keycloak_quarkus/README.md +++ b/roles/keycloak_quarkus/README.md @@ -147,9 +147,11 @@ Role Defaults | Variable | Description | Default | |:---------|:------------|:--------| +|`keycloak_quarkus_cache_remote` | Whether to connect to remote cache infinispan server | `false` | |`keycloak_quarkus_cache_remote_username` | Username for connecting to infinispan | `supervisor` | |`keycloak_quarkus_cache_remote_password` | Password for connecting to infinispan | `supervisor` | -|`keycloak_quarkus_cache_remote_host` | host name/port for connecting to infinispan, eg. host1:11222;host2:11222 | `localhost:11222` | +|`keycloak_quarkus_cache_remote_host` | Hostname for connecting to infinispan | `localhost` | +|`keycloak_quarkus_cache_remote_port`| Port for connecting to infinispan | `11222` | |`keycloak_quarkus_cache_remote_sasl_mechanism` | Infinispan auth mechanism | `SCRAM-SHA-512` | |`keycloak_quarkus_cache_remote_tls_enabled` | Whether infinispan uses TLS connection | `false` | diff --git a/roles/keycloak_quarkus/defaults/main.yml b/roles/keycloak_quarkus/defaults/main.yml index ee12214..d53c790 100644 --- a/roles/keycloak_quarkus/defaults/main.yml +++ b/roles/keycloak_quarkus/defaults/main.yml @@ -38,14 +38,21 @@ keycloak_quarkus_http_enabled: true keycloak_quarkus_http_port: 8080 keycloak_quarkus_https_port: 8443 keycloak_quarkus_http_management_port: 9000 -keycloak_quarkus_jgroups_ip: "{{ ansible_default_ipv4.address }}" keycloak_quarkus_jgroups_port: 7800 +keycloak_quarkus_jgroups_bind_address: "{{ ansible_default_ipv4.address }}" +keycloak_quarkus_jgroups_external_addr: "{{ keycloak_quarkus_jgroups_bind_address }}" +keycloak_quarkus_jgroups_external_port: "{{ keycloak_quarkus_jgroups_port }}" keycloak_quarkus_java_heap_opts: "-Xms1024m -Xmx2048m" -keycloak_quarkus_java_jvm_opts: "-XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 +keycloak_quarkus_java_jvm_opts: > + -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.err.encoding=UTF-8 -Dstdout.encoding=UTF-8 -Dstderr.encoding=UTF-8 -XX:+ExitOnOutOfMemoryError -Djava.security.egd=file:/dev/urandom -XX:+UseParallelGC -XX:GCTimeRatio=4 - -XX:AdaptiveSizePolicyWeight=90 -XX:FlightRecorderOptions=stackdepth=512" -keycloak_quarkus_java_opts: "{{ keycloak_quarkus_java_heap_opts + ' ' + keycloak_quarkus_java_jvm_opts }}" + -XX:AdaptiveSizePolicyWeight=90 -XX:FlightRecorderOptions=stackdepth=512 +keycloak_quarkus_jgroups_opts: > + -Djgroups.bind.address={{ keycloak_quarkus_jgroups_bind_address }} + -Djgroups.external_port={{ keycloak_quarkus_jgroups_external_port }} + -Djgroups.external_addr={{ keycloak_quarkus_jgroups_external_addr }} +keycloak_quarkus_java_opts: "{{ ' '.join((keycloak_quarkus_jgroups_opts, keycloak_quarkus_java_heap_opts, keycloak_quarkus_java_jvm_opts)) }}" keycloak_quarkus_additional_env_vars: [] ### TLS/HTTPS configuration @@ -110,10 +117,33 @@ keycloak_quarkus_spi_sticky_session_encoder_infinispan_should_attach_route: true keycloak_quarkus_metrics_enabled: false keycloak_quarkus_health_enabled: true +### caches; must read: https://www.keycloak.org/2024/12/storing-sessions-in-kc26 +### embedded caches +# https://www.keycloak.org/server/caching +keycloak_quarkus_cache_metrics_enabled: false +keycloak_quarkus_cache_embedded_authorization_max_count: +keycloak_quarkus_cache_embedded_client_sessions_max_count: +keycloak_quarkus_cache_embedded_crl_max_count: +keycloak_quarkus_cache_embedded_keys_max_count: +keycloak_quarkus_cache_embedded_offline_client_sessions_max_count: +keycloak_quarkus_cache_embedded_offline_sessions_max_count: +keycloak_quarkus_cache_embedded_realms_max_count: +keycloak_quarkus_cache_embedded_sessions_max_count: +keycloak_quarkus_cache_embedded_users_max_count: +keycloak_quarkus_cache_embedded_mtls_enabled: true +keycloak_quarkus_cache_embedded_mtls_key_store_file: "{{ keycloak.home }}/conf/cache_key_store.p12" +keycloak_quarkus_cache_embedded_mtls_key_store_password: '' +keycloak_quarkus_cache_embedded_mtls_rotation_interval_days: 30 +keycloak_quarkus_cache_embedded_mtls_trust_store_file: "{{ keycloak.home }}/conf/cache_trust_store.p12" +keycloak_quarkus_cache_embedded_mtls_trust_store_password: '' + ### infinispan remote caches access (hotrod) +# https://www.keycloak.org/server/caching#_remote_cache +keycloak_quarkus_cache_remote: false keycloak_quarkus_cache_remote_username: supervisor keycloak_quarkus_cache_remote_password: supervisor -keycloak_quarkus_cache_remote_host: "localhost:11222" +keycloak_quarkus_cache_remote_host: localhost +keycloak_quarkus_cache_remote_port: 11222 keycloak_quarkus_cache_remote_tls_enabled: false keycloak_quarkus_cache_remote_sasl_mechanism: SCRAM-SHA-512 diff --git a/roles/keycloak_quarkus/meta/argument_specs.yml b/roles/keycloak_quarkus/meta/argument_specs.yml index 95d42f4..1683321 100644 --- a/roles/keycloak_quarkus/meta/argument_specs.yml +++ b/roles/keycloak_quarkus/meta/argument_specs.yml @@ -195,14 +195,6 @@ argument_specs: default: 9000 description: "Port of the management interface. Relevant only when something is exposed on the management interface - see the guide for details." type: "int" - keycloak_quarkus_jgroups_ip: - default: "{{ ansible_default_ipv4.address }}" - description: Host jgroups IP. If changing this variable you must make sure it is always set for all hosts in your cluster. - type: "str" - keycloak_quarkus_jgroups_port: - default: 7800 - description: "jgroups cluster tcp port" - type: "int" keycloak_quarkus_java_heap_opts: default: "-Xms1024m -Xmx2048m" description: "Heap memory JVM setting" @@ -215,7 +207,7 @@ argument_specs: description: "Other JVM settings" type: "str" keycloak_quarkus_java_opts: - default: "{{ keycloak_quarkus_java_heap_opts + ' ' + keycloak_quarkus_java_jvm_opts }}" + default: "{{ ' '.join((keycloak_quarkus_jgroups_opts, keycloak_quarkus_java_heap_opts, keycloak_quarkus_java_jvm_opts)) }}" description: "JVM arguments, by default heap_opts + jvm_opts, if overriden it takes precedence over them" type: "str" keycloak_quarkus_additional_env_vars: @@ -263,6 +255,10 @@ argument_specs: default: true description: "If the server should expose health check endpoints on the management interface" type: "bool" + keycloak_quarkus_cache_remote: + description: "Whether to connect to remote cache infinispan server" + default: false + type: 'bool' keycloak_quarkus_cache_remote_username: default: "supervisor" description: "Username for connecting to infinispan" @@ -272,8 +268,12 @@ argument_specs: description: "Password for connecting to infinispan" type: "str" keycloak_quarkus_cache_remote_host: - default: "localhost:11222" - description: "host name/port for connecting to infinispan, eg. host1:11222;host2:11222" + default: "localhost" + description: "Hostname for connecting to infinispan" + type: "str" + keycloak_quarkus_cache_remote_port: + default: "11222" + description: "Port for connecting to infinispan" type: "str" keycloak_quarkus_cache_remote_sasl_mechanism: default: "SCRAM-SHA-512" @@ -472,6 +472,90 @@ argument_specs: description: "Path local to controller for offline/download of install archives" default: "{{ lookup('env', 'PWD') }}" type: "str" + keycloak_quarkus_cache_metrics_enabled: + description: 'Enable histograms for metrics for the embedded caches' + default: false + type: 'bool' + keycloak_quarkus_cache_embedded_authorization_max_count: + description: 'The maximum number of entries that can be stored in-memory by the authorization cache' + required: false + type: "int" + keycloak_quarkus_cache_embedded_client_sessions_max_count: + description: 'The maximum number of entries that can be stored in-memory by the clientSessions cache' + required: false + type: "int" + keycloak_quarkus_cache_embedded_crl_max_count: + description: 'The maximum number of entries that can be stored in-memory by the crl cache' + required: false + type: "int" + keycloak_quarkus_cache_embedded_keys_max_count: + description: 'The maximum number of entries that can be stored in-memory by the keys cache' + required: false + type: "int" + keycloak_quarkus_cache_embedded_offline_client_sessions_max_count: + description: 'The maximum number of entries that can be stored in-memory by the offlineClientSessions cache' + required: false + type: "int" + keycloak_quarkus_cache_embedded_offline_sessions_max_count: + description: 'The maximum number of entries that can be stored in-memory by the offlineSessions cache' + required: false + type: "int" + keycloak_quarkus_cache_embedded_realms_max_count: + description: 'The maximum number of entries that can be stored in-memory by the realms cache' + required: false + type: "int" + keycloak_quarkus_cache_embedded_sessions_max_count: + description: 'The maximum number of entries that can be stored in-memory by the sessions cache' + required: false + type: "int" + keycloak_quarkus_cache_embedded_users_max_count: + description: 'The maximum number of entries that can be stored in-memory by the users cache' + required: false + type: 'int' + keycloak_quarkus_cache_embedded_mtls_enabled: + description: 'Encrypts the network communication between Keycloak servers' + default: true + type: 'bool' + keycloak_quarkus_cache_embedded_mtls_key_store_file: + description: 'The Keystore file path' + default: "{{ keycloak.home }}/conf/cache_key_store.p12" + type: "str" + keycloak_quarkus_cache_embedded_mtls_key_store_password: + description: 'The password to access the Keystore' + default: '' + type: "str" + keycloak_quarkus_cache_embedded_mtls_rotation_interval_days: + description: 'Rotation period in days of automatic JGroups MTLS certificates' + default: 30 + type: 'int' + keycloak_quarkus_cache_embedded_mtls_trust_store_file: + description: 'The Truststore file path' + default: "{{ keycloak.home }}/conf/cache_trust_store.p12" + type: "str" + keycloak_quarkus_cache_embedded_mtls_trust_store_password: + description: 'The password to access the Truststore.' + default: '' + type: "str" + keycloak_quarkus_jgroups_port: + description: 'jgroups bind port' + default: 7800 + type: "int" + keycloak_quarkus_jgroups_bind_address: + description: 'jgroups bind address' + default: "{{ ansible_default_ipv4.address }}" + type: "str" + keycloak_quarkus_jgroups_external_addr: + description: 'IP address that other instances in the Keycloak should use to contact this node' + default: "{{ keycloak_quarkus_jgroups_bind_address }}" + type: "str" + keycloak_quarkus_jgroups_external_port: + description: 'Port that other instances in the Keycloak cluster should use to contact this node' + default: "{{ keycloak_quarkus_jgroups_port }}" + type: "int" + keycloak_quarkus_jgroups_opts: + description: "JVM arguments for jgroups configuration" + default: "-Djgroups.bind.address={{ keycloak_quarkus_jgroups_bind_address }} -Djgroups.external_port={{ keycloak_quarkus_jgroups_external_port }} -Djgroups.external_addr={{ keycloak_quarkus_jgroups_external_addr }}" + type: "str" downstream: options: rhbk_version: diff --git a/roles/keycloak_quarkus/templates/keycloak.conf.j2 b/roles/keycloak_quarkus/templates/keycloak.conf.j2 index 99790c3..7642715 100644 --- a/roles/keycloak_quarkus/templates/keycloak.conf.j2 +++ b/roles/keycloak_quarkus/templates/keycloak.conf.j2 @@ -59,8 +59,12 @@ hostname-backchannel-dynamic={{ keycloak_quarkus_hostname_backchannel_dynamic | {% if keycloak_quarkus_ha_enabled %} cache=ispn cache-config-file=cache-ispn.xml -{% if keycloak_quarkus_ha_enabled and keycloak_quarkus_ha_discovery == 'TCPPING' %} -# cache-stack=tcp # configured directly in `cache-ispn.xml` +{% if keycloak_quarkus_cache_remote %} +cache-remote-username={{ keycloak_quarkus_cache_remote_username }} +cache-remote-password={{ keycloak_quarkus_cache_remote_password }} +cache-remote-host={{ keycloak_quarkus_cache_remote_host }} +cache-remote-port={{ keycloak_quarkus_cache_remote_port }} +cache-remote-tls-enabled={{ keycloak_quarkus_cache_remote_tls_enabled | lower }} {% endif %} {% endif %}