keycloakinfinispantranscodingdistributed-cache

Is x-Protostream encoding supported in Keycloak version 21.x


I have setup Keyclock v21.x on Kubernetes along with Infinispan v14.x.

In Infinispan, I have created distributed caches named sessions, offlineSessions, offlineClientSessions, actionTokens,loginFailures, authenticationSessions, clientSessions and replicated cache named work.

I have configured encoding media-type as "application/x-jboss-marshalling" for all caches.

Eg. of sessions cache.

"sessions": {
    "distributed-cache": {
      "owners": "2",
      "mode": "SYNC",
      "statistics": true,
      "encoding": {
        "media-type": "application/x-jboss-marshalling"
      },
      "locking": {
        "isolation": "REPEATABLE_READ"
      }
    }
  }
}

This worked ok in Keycloak v20.0. In that I faced different issues so switch to Keyclock v21.x.

In Keyclock 21,x we get transcoding error as below 2023-05-04 04:03:29,630 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: org.infinispan.commons.dataconversion.EncodingException: ISPN000492: Cannot find transcoder between 'application/x-protostream' to 'application/x-jboss-marshalling'

This states that Cache is using jboss-marshelling but getting data x-protostream from keycloak.

So after this tried updating sessions cache encoding as x-protostream, however I got below error: javax.security.sasl.SaslException: ELY05087: Client selected realm not offered by server (AllowScriptManager)

So what kind of cache encoding, I should configure in infinispan?

Also in cache-ispn-remote.xml, configured remote store for all caches. Eg.

      <distributed-cache name="sessions" owners="2">
            <expiration lifespan="-1"/>
            <remote-store cache="sessions" xmlns="urn:infinispan:config:store:remote:13.0"
                          fetch-state="false"
                          purge="false"
                          preload="false"
                          shared="true" segmented="false"
                          connect-timeout="${env.KEYCLOAK_REMOTE_ISPN_CONN_TIMEOUT:2000}">
                <remote-server host="${env.INFINISPAN_SERVER}" port="${infinispan.bind.port:11222}"/>

                <security>
                    <authentication>
                        <digest username="${env.KEYCLOAK_REMOTE_ISPN_USERNAME:keycloak}"
                                password="${env.KEYCLOAK_REMOTE_ISPN_PASSWORD:password}"
                                realm="default"/>
                    </authentication>
                </security>

                <property name="rawValues">true</property>
                <property name="marshaller">org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory</property>
            </remote-store>
        </distributed-cache>

And keycloak-values.yaml content

logging:
  level: DEBUG
replicaCount: 2
image:
  registry: docker.io
  repository: bitnami/keycloak
  tag: 21.0.2-debian-11-r0
production: true
resources:
  limits:
    cpu: 700m
    memory: 2048Mi
  requests:
    cpu: 700m
    memory: 2048Mi
tls:
  enabled: true
  autoGenerated: true
extraVolumeMounts: |
  - name: quarkus
    mountPath: /opt/bitnami/keycloak/conf/quarkus.properties
    subPath: quarkus.properties
  - name: keycloak
    mountPath: /opt/bitnami/keycloak/conf/cache-ispn.xml
    subPath: cache-ispn-remote.xml
extraVolumes: |
  - name: quarkus
    configMap:
      name: quarkus
      defaultMode: 0777
  - name: keycloak
    configMap:
      name: keycloak
      defaultMode: 0777
extraEnvVars:
   - name: KC_CACHE_STACK
     value: kubernetes
   - name: KC_PROXY
     value: edge
   - name: KEYCLOAK_PROXY
     value: edge
   - name: KEYCLOAK_PROXY_ADDRESS_FORWARDING
     value: "true"
   - name: QUARKUS_INFINISPAN_CLIENT_SERVER_LIST
     value: infinispan.keycloak.svc.cluster.local:11222
   - name: INFINISPAN_SERVER
     value: infinispan.keycloak.svc.cluster.local
   - name: KC_DB
     value: postgres
   - name: KC_DB_URL_HOST
     value: <RDS endpoint>
   - name: KC_DB_URL_DATABASE
     value: keycloak
   - name: KC_DB_USERNAME
     value: postgres
   - name:  KC_DB_PASSWORD
     value: <RDS Password>
   - name: KEYCLOAK_REMOTE_ISPN_USERNAME
     value: developer
   - name: KEYCLOAK_REMOTE_ISPN_PASSWORD
     value: <Infinispan developer password>
   - name: KC_CACHE
     value: ispn
   - name: JAVA_OPTS_APPEND
     value: -Djboss.site.name=site1 -Djgroups.dns.query=keycloak-headless.keycloak.svc.cluster.local -Dinfinispan.deserialization.allowlist.classes=org.keycloak.cluster.infinispan.WrapperClusterEvent -Dinfinispan.deserialization.allowlist.regexps=.*
   - name: KEYCLOAK_PRODUCTION
     value: "true"
   - name: KEYCLOAK_ENABLE_HTTPS
     value: "false"
   - name: KC_CACHE_CONFIG_FILE
     value: cache-ispn.xml
cache: 
  enabled: true
postgresql: 
  enabled: false
externalDatabase: 
  host: <RDS endpoint>
  port: 5432
  user: postgres
  password: <RDS Password>
  database: keycloak
auth: 
  adminUser: admin
  adminPassword: admin
service:
  type: ClusterIP

ingress:
  enabled: true
  ingressClassName: "alb"
  pathType: "Prefix"
  hostname: "kcauth.example.com"
  annotations:
    #kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/target-type: 'ip'
    alb.ingress.kubernetes.io/certificate-arn: "<ARN of ACM>"
    alb.ingress.kubernetes.io/subnets: <SUBNETS IDs>
    alb.ingress.kubernetes.io/conditions.keycloak: |
      [{"Field":"host-header","HostHeaderConfig":{"Values":["*.example.com"]}}]
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-TLS-1-1-2017-01


Solution

  • Found fix for this. Ref: https://github.com/keycloak/keycloak/issues/20031

    Now Keycloak version 21 is working with Infinispan cache.

    Now my cache-ispn-remote.xml looks like:

    <?xml version="1.0" encoding="UTF-8"?>
    <infinispan
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="urn:infinispan:config:14.0 http://www.infinispan.org/schemas/infinispan-config-14.0.xsd"
            xmlns="urn:infinispan:config:14.0">
    
        <cache-container name="keycloak">
            <transport lock-timeout="60000" site="site1"/>
    
            <local-cache name="realms">
                <encoding>
                    <key media-type="application/x-java-object"/>
                    <value media-type="application/x-java-object"/>
                </encoding>
                <memory max-count="10000"/>
            </local-cache>
            <local-cache name="users">
                <encoding>
                    <key media-type="application/x-java-object"/>
                    <value media-type="application/x-java-object"/>
                </encoding>
                <memory max-count="10000"/>
            </local-cache>
            <local-cache name="keys">
                <encoding>
                    <key media-type="application/x-java-object"/>
                    <value media-type="application/x-java-object"/>
                </encoding>
                <expiration max-idle="3600000"/>
                <memory max-count="1000"/>
            </local-cache>
            <local-cache name="authorization">
                <encoding>
                    <key media-type="application/x-java-object"/>
                    <value media-type="application/x-java-object"/>
                </encoding>
                <memory max-count="10000"/>
            </local-cache>
           <distributed-cache name="sessions" owners="2">
                <remote-store xmlns="urn:infinispan:config:store:remote:14.0"
                              cache="sessions"
                              purge="false"
                              preload="false"
                              segmented="false"
                              shared="true"
                              raw-values="true"
                              marshaller="org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory"
                              connect-timeout="${env.KEYCLOAK_REMOTE_ISPN_CONN_TIMEOUT:2000}">
                    <remote-server host="${env.INFINISPAN_SERVER}" port="${infinispan.bind.port:11222}"/>
                    <security>
                        <authentication>
                            <digest username="${env.KEYCLOAK_REMOTE_ISPN_USERNAME:keycloak}"
                                    password="${env.KEYCLOAK_REMOTE_ISPN_PASSWORD:password}"
                                    realm="default"/>
                        </authentication>
                    </security>
                </remote-store>
           </distributed-cache>
           <distributed-cache name="authenticationSessions" owners="2">
                <remote-store xmlns="urn:infinispan:config:store:remote:14.0"
                              cache="authenticationSessions"
                              purge="false"
                              preload="false"
                              segmented="false"
                              shared="true"
                              raw-values="true"
                              marshaller="org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory"
                              connect-timeout="${env.KEYCLOAK_REMOTE_ISPN_CONN_TIMEOUT:2000}">
                    <remote-server host="${env.INFINISPAN_SERVER}" port="${infinispan.bind.port:11222}"/>
                    <security>
                        <authentication>
                            <digest username="${env.KEYCLOAK_REMOTE_ISPN_USERNAME:keycloak}"
                                    password="${env.KEYCLOAK_REMOTE_ISPN_PASSWORD:password}"
                                    realm="default"/>
                        </authentication>
                    </security>
                </remote-store>
            </distributed-cache>
           <distributed-cache name="offlineSessions" owners="2">
                <remote-store xmlns="urn:infinispan:config:store:remote:14.0"
                              cache="offlineSessions"
                              purge="false"
                              preload="false"
                              segmented="false"
                              shared="true"
                              raw-values="true"
                              marshaller="org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory"
                              connect-timeout="${env.KEYCLOAK_REMOTE_ISPN_CONN_TIMEOUT:2000}">
                    <remote-server host="${env.INFINISPAN_SERVER}" port="${infinispan.bind.port:11222}"/>
                    <security>
                        <authentication>
                            <digest username="${env.KEYCLOAK_REMOTE_ISPN_USERNAME:keycloak}"
                                    password="${env.KEYCLOAK_REMOTE_ISPN_PASSWORD:password}"
                                    realm="default"/>
                        </authentication>
                    </security>
                </remote-store>
            </distributed-cache>
           <distributed-cache name="clientSessions" owners="2">
                <remote-store xmlns="urn:infinispan:config:store:remote:14.0"
                              cache="clientSessions"
                              purge="false"
                              preload="false"
                              segmented="false"
                              shared="true"
                              raw-values="true"
                              marshaller="org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory"
                              connect-timeout="${env.KEYCLOAK_REMOTE_ISPN_CONN_TIMEOUT:2000}">
                    <remote-server host="${env.INFINISPAN_SERVER}" port="${infinispan.bind.port:11222}"/>
                    <security>
                        <authentication>
                            <digest username="${env.KEYCLOAK_REMOTE_ISPN_USERNAME:keycloak}"
                                    password="${env.KEYCLOAK_REMOTE_ISPN_PASSWORD:password}"
                                    realm="default"/>
                        </authentication>
                    </security>
                </remote-store>
            </distributed-cache>
           <distributed-cache name="offlineClientSessions" owners="2">
                <remote-store xmlns="urn:infinispan:config:store:remote:14.0"
                              cache="offlineClientSessions"
                              purge="false"
                              preload="false"
                              segmented="false"
                              shared="true"
                              raw-values="true"
                              marshaller="org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory"
                              connect-timeout="${env.KEYCLOAK_REMOTE_ISPN_CONN_TIMEOUT:2000}">
                    <remote-server host="${env.INFINISPAN_SERVER}" port="${infinispan.bind.port:11222}"/>
                    <security>
                        <authentication>
                            <digest username="${env.KEYCLOAK_REMOTE_ISPN_USERNAME:keycloak}"
                                    password="${env.KEYCLOAK_REMOTE_ISPN_PASSWORD:password}"
                                    realm="default"/>
                        </authentication>
                    </security>
                </remote-store>
            </distributed-cache>
            <distributed-cache name="loginFailures" owners="2">
                <remote-store xmlns="urn:infinispan:config:store:remote:14.0"
                              cache="loginFailures"
                              purge="false"
                              preload="false"
                              segmented="false"
                              shared="true"
                              raw-values="true"
                              marshaller="org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory"
                              connect-timeout="${env.KEYCLOAK_REMOTE_ISPN_CONN_TIMEOUT:2000}">
                    <remote-server host="${env.INFINISPAN_SERVER}" port="${infinispan.bind.port:11222}"/>
                    <security>
                        <authentication>
                            <digest username="${env.KEYCLOAK_REMOTE_ISPN_USERNAME:keycloak}"
                                    password="${env.KEYCLOAK_REMOTE_ISPN_PASSWORD:password}"
                                    realm="default"/>
                        </authentication>
                    </security>
                </remote-store>
            </distributed-cache>
            <distributed-cache name="actionTokens" owners="2">
                <remote-store xmlns="urn:infinispan:config:store:remote:14.0"
                              cache="actionTokens"
                              purge="false"
                              preload="false"
                              segmented="false"
                              shared="true"
                              raw-values="true"
                              marshaller="org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory"
                              connect-timeout="${env.KEYCLOAK_REMOTE_ISPN_CONN_TIMEOUT:2000}">
                    <remote-server host="${env.INFINISPAN_SERVER}" port="${infinispan.bind.port:11222}"/>
                    <security>
                        <authentication>
                            <digest username="${env.KEYCLOAK_REMOTE_ISPN_USERNAME:keycloak}"
                                    password="${env.KEYCLOAK_REMOTE_ISPN_PASSWORD:password}"
                                    realm="default"/>
                        </authentication>
                    </security>
                </remote-store>
            </distributed-cache>
            <replicated-cache name="work">
                <remote-store xmlns="urn:infinispan:config:store:remote:14.0"
                              cache="actionTokens"
                              purge="false"
                              preload="false"
                              segmented="false"
                              shared="true"
                              raw-values="true"
                              marshaller="org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory"
                              connect-timeout="${env.KEYCLOAK_REMOTE_ISPN_CONN_TIMEOUT:2000}">
                    <remote-server host="${env.INFINISPAN_SERVER}" port="${infinispan.bind.port:11222}"/>
                    <security>
                        <authentication>
                            <digest username="${env.KEYCLOAK_REMOTE_ISPN_USERNAME:keycloak}"
                                    password="${env.KEYCLOAK_REMOTE_ISPN_PASSWORD:password}"
                                    realm="default"/>
                        </authentication>
                    </security>
                </remote-store>
            </replicated-cache>
        </cache-container>
    </infinispan>