Fail to start if work cache is not replicated
Keycloak will now fail to start if the work cache is replicated. Listeners require the data to be local. Closes #33702 Signed-off-by: Pedro Ruivo <pruivo@redhat.com> Signed-off-by: Alexander Schwartz <aschwart@redhat.com> Co-authored-by: Alexander Schwartz <aschwart@redhat.com>
This commit is contained in:
parent
0e3554934e
commit
464fc90519
3 changed files with 24 additions and 1 deletions
|
@ -3,3 +3,9 @@
|
||||||
Previous releases ignored any change to `conf/cache-ispn.xml` if the `--cache-config-file` option was not provided.
|
Previous releases ignored any change to `conf/cache-ispn.xml` if the `--cache-config-file` option was not provided.
|
||||||
|
|
||||||
Starting from this release, when `--cache-config-file` is not set, the default Infinispan XML configuration file is `conf/cache-ispn.xml` as this is both the expected behavior and the implied behavior given the docs of the current and previous releases.
|
Starting from this release, when `--cache-config-file` is not set, the default Infinispan XML configuration file is `conf/cache-ispn.xml` as this is both the expected behavior and the implied behavior given the docs of the current and previous releases.
|
||||||
|
|
||||||
|
= Embedded Infinispan: `work` cache must be replicated
|
||||||
|
|
||||||
|
The embedded `work` cache needs to be configured as a `replicated-cache` for cache invalidation to work as expected.
|
||||||
|
|
||||||
|
Starting from this release, {project_name} check this at startup and will fail to start if it is not configured as such.
|
||||||
|
|
|
@ -371,7 +371,7 @@ public class DefaultInfinispanConnectionProviderFactory implements InfinispanCon
|
||||||
workBuilder.simpleCache(false);
|
workBuilder.simpleCache(false);
|
||||||
workBuilder.clustering().cacheMode(async ? CacheMode.REPL_ASYNC : CacheMode.REPL_SYNC);
|
workBuilder.clustering().cacheMode(async ? CacheMode.REPL_ASYNC : CacheMode.REPL_SYNC);
|
||||||
}
|
}
|
||||||
defineClusteredCache(cacheManager, WORK_CACHE_NAME, builder.build());
|
defineClusteredCache(cacheManager, WORK_CACHE_NAME, workBuilder.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
return cacheManager;
|
return cacheManager;
|
||||||
|
|
|
@ -87,6 +87,7 @@ import static org.keycloak.connections.infinispan.InfinispanConnectionProvider.L
|
||||||
import static org.keycloak.connections.infinispan.InfinispanConnectionProvider.OFFLINE_CLIENT_SESSION_CACHE_NAME;
|
import static org.keycloak.connections.infinispan.InfinispanConnectionProvider.OFFLINE_CLIENT_SESSION_CACHE_NAME;
|
||||||
import static org.keycloak.connections.infinispan.InfinispanConnectionProvider.OFFLINE_USER_SESSION_CACHE_NAME;
|
import static org.keycloak.connections.infinispan.InfinispanConnectionProvider.OFFLINE_USER_SESSION_CACHE_NAME;
|
||||||
import static org.keycloak.connections.infinispan.InfinispanConnectionProvider.USER_SESSION_CACHE_NAME;
|
import static org.keycloak.connections.infinispan.InfinispanConnectionProvider.USER_SESSION_CACHE_NAME;
|
||||||
|
import static org.keycloak.connections.infinispan.InfinispanConnectionProvider.WORK_CACHE_NAME;
|
||||||
import static org.keycloak.connections.infinispan.InfinispanConnectionProvider.skipSessionsCacheIfRequired;
|
import static org.keycloak.connections.infinispan.InfinispanConnectionProvider.skipSessionsCacheIfRequired;
|
||||||
import static org.wildfly.security.sasl.util.SaslMechanismInformation.Names.SCRAM_SHA_512;
|
import static org.wildfly.security.sasl.util.SaslMechanismInformation.Names.SCRAM_SHA_512;
|
||||||
|
|
||||||
|
@ -314,6 +315,7 @@ public class CacheManagerFactory {
|
||||||
}
|
}
|
||||||
configureCacheMaxCount(builder, CachingOptions.CLUSTERED_MAX_COUNT_CACHES);
|
configureCacheMaxCount(builder, CachingOptions.CLUSTERED_MAX_COUNT_CACHES);
|
||||||
configureSessionsCaches(builder);
|
configureSessionsCaches(builder);
|
||||||
|
validateWorkCacheConfiguration(builder);
|
||||||
}
|
}
|
||||||
configureCacheMaxCount(builder, CachingOptions.LOCAL_MAX_COUNT_CACHES);
|
configureCacheMaxCount(builder, CachingOptions.LOCAL_MAX_COUNT_CACHES);
|
||||||
checkForRemoteStores(builder);
|
checkForRemoteStores(builder);
|
||||||
|
@ -514,6 +516,21 @@ public class CacheManagerFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void validateWorkCacheConfiguration(ConfigurationBuilderHolder builder) {
|
||||||
|
var cacheBuilder = builder.getNamedConfigurationBuilders().get(WORK_CACHE_NAME);
|
||||||
|
if (cacheBuilder == null) {
|
||||||
|
throw new RuntimeException("Unable to start Keycloak. '%s' cache is missing".formatted(WORK_CACHE_NAME));
|
||||||
|
}
|
||||||
|
if (builder.getGlobalConfigurationBuilder().cacheContainer().transport().getTransport() == null) {
|
||||||
|
// non-clustered, Keycloak started in dev mode?
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var cacheMode = cacheBuilder.clustering().cacheMode();
|
||||||
|
if (!cacheMode.isReplicated()) {
|
||||||
|
throw new RuntimeException("Unable to start Keycloak. '%s' cache must be replicated but is %s".formatted(WORK_CACHE_NAME, cacheMode.friendlyCacheModeString().toLowerCase()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static String requiredStringProperty(String propertyName) {
|
private static String requiredStringProperty(String propertyName) {
|
||||||
return Configuration.getOptionalKcValue(propertyName).orElseThrow(() -> new RuntimeException("Property " + propertyName + " required but not specified"));
|
return Configuration.getOptionalKcValue(propertyName).orElseThrow(() -> new RuntimeException("Property " + propertyName + " required but not specified"));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue