Remove unnecessary code paths during startup (#13848)

Closes #13847
This commit is contained in:
Pedro Igor 2022-08-19 09:54:11 -03:00 committed by GitHub
parent 68d14783f5
commit 5f2191813a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 119 additions and 57 deletions

View file

@ -1,24 +0,0 @@
package org.keycloak.config;
import java.util.ArrayList;
import java.util.List;
public class AllOptions {
public static final List<Option<?>> ALL_OPTIONS = new ArrayList<>();
static {
ALL_OPTIONS.addAll(CachingOptions.ALL_OPTIONS);
ALL_OPTIONS.addAll(DatabaseOptions.ALL_OPTIONS);
ALL_OPTIONS.addAll(FeatureOptions.ALL_OPTIONS);
ALL_OPTIONS.addAll(HealthOptions.ALL_OPTIONS);
ALL_OPTIONS.addAll(HostnameOptions.ALL_OPTIONS);
ALL_OPTIONS.addAll(HttpOptions.ALL_OPTIONS);
ALL_OPTIONS.addAll(LoggingOptions.ALL_OPTIONS);
ALL_OPTIONS.addAll(MetricsOptions.ALL_OPTIONS);
ALL_OPTIONS.addAll(ProxyOptions.ALL_OPTIONS);
ALL_OPTIONS.addAll(TransactionOptions.ALL_OPTIONS);
ALL_OPTIONS.addAll(VaultOptions.ALL_OPTIONS);
ALL_OPTIONS.addAll(StorageOptions.ALL_OPTIONS);
}
}

View file

@ -29,6 +29,7 @@ import static org.keycloak.representations.provider.ScriptProviderDescriptor.AUT
import static org.keycloak.representations.provider.ScriptProviderDescriptor.MAPPERS; import static org.keycloak.representations.provider.ScriptProviderDescriptor.MAPPERS;
import static org.keycloak.representations.provider.ScriptProviderDescriptor.POLICIES; import static org.keycloak.representations.provider.ScriptProviderDescriptor.POLICIES;
import static org.keycloak.quarkus.runtime.Environment.getProviderFiles; import static org.keycloak.quarkus.runtime.Environment.getProviderFiles;
import static org.keycloak.theme.ClasspathThemeProviderFactory.KEYCLOAK_THEMES_JSON;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.spi.PersistenceUnitTransactionType; import javax.persistence.spi.PersistenceUnitTransactionType;
@ -132,8 +133,10 @@ import org.keycloak.representations.provider.ScriptProviderDescriptor;
import org.keycloak.representations.provider.ScriptProviderMetadata; import org.keycloak.representations.provider.ScriptProviderMetadata;
import org.keycloak.quarkus.runtime.integration.web.NotFoundHandler; import org.keycloak.quarkus.runtime.integration.web.NotFoundHandler;
import org.keycloak.services.ServicesLogger; import org.keycloak.services.ServicesLogger;
import org.keycloak.theme.ClasspathThemeProviderFactory;
import org.keycloak.theme.ClasspathThemeResourceProviderFactory; import org.keycloak.theme.ClasspathThemeResourceProviderFactory;
import org.keycloak.theme.FolderThemeProviderFactory; import org.keycloak.theme.FolderThemeProviderFactory;
import org.keycloak.theme.JarThemeProviderFactory;
import org.keycloak.theme.ThemeResourceSpi; import org.keycloak.theme.ThemeResourceSpi;
import org.keycloak.transaction.JBossJtaTransactionManagerLookup; import org.keycloak.transaction.JBossJtaTransactionManagerLookup;
import org.keycloak.quarkus.runtime.Environment; import org.keycloak.quarkus.runtime.Environment;
@ -163,6 +166,7 @@ class KeycloakProcessor {
FilesPlainTextVaultProviderFactory.class, FilesPlainTextVaultProviderFactory.class,
BlacklistPasswordPolicyProviderFactory.class, BlacklistPasswordPolicyProviderFactory.class,
ClasspathThemeResourceProviderFactory.class, ClasspathThemeResourceProviderFactory.class,
JarThemeProviderFactory.class,
JpaMapStorageProviderFactory.class); JpaMapStorageProviderFactory.class);
static { static {
@ -316,11 +320,26 @@ class KeycloakProcessor {
} }
} }
recorder.configSessionFactory(factories, defaultProviders, preConfiguredProviders, Environment.isRebuild()); recorder.configSessionFactory(factories, defaultProviders, preConfiguredProviders, loadThemesFromClassPath(), Environment.isRebuild());
return new KeycloakSessionFactoryPreInitBuildItem(); return new KeycloakSessionFactoryPreInitBuildItem();
} }
private List<ClasspathThemeProviderFactory.ThemesRepresentation> loadThemesFromClassPath() {
try {
List<ClasspathThemeProviderFactory.ThemesRepresentation> themes = new ArrayList<>();
Enumeration<URL> resources = Thread.currentThread().getContextClassLoader().getResources(KEYCLOAK_THEMES_JSON);
while (resources.hasMoreElements()) {
themes.add(JsonSerialization.readValue(resources.nextElement().openStream(), ClasspathThemeProviderFactory.ThemesRepresentation.class));
}
return themes;
} catch (IOException e) {
throw new RuntimeException("Failed to load themes", e);
}
}
private void configureThemeResourceProviders(Map<Spi, Map<Class<? extends Provider>, Map<String, Class<? extends ProviderFactory>>>> factories, Spi spi) { private void configureThemeResourceProviders(Map<Spi, Map<Class<? extends Provider>, Map<String, Class<? extends ProviderFactory>>>> factories, Spi spi) {
try { try {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

View file

@ -47,6 +47,7 @@ import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory; import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi; import org.keycloak.provider.Spi;
import org.keycloak.quarkus.runtime.storage.legacy.infinispan.CacheManagerFactory; import org.keycloak.quarkus.runtime.storage.legacy.infinispan.CacheManagerFactory;
import org.keycloak.theme.ClasspathThemeProviderFactory;
import io.quarkus.runtime.RuntimeValue; import io.quarkus.runtime.RuntimeValue;
import io.quarkus.runtime.ShutdownContext; import io.quarkus.runtime.ShutdownContext;
@ -69,10 +70,10 @@ public class KeycloakRecorder {
Map<Spi, Map<Class<? extends Provider>, Map<String, Class<? extends ProviderFactory>>>> factories, Map<Spi, Map<Class<? extends Provider>, Map<String, Class<? extends ProviderFactory>>>> factories,
Map<Class<? extends Provider>, String> defaultProviders, Map<Class<? extends Provider>, String> defaultProviders,
Map<String, ProviderFactory> preConfiguredProviders, Map<String, ProviderFactory> preConfiguredProviders,
Boolean reaugmented) { List<ClasspathThemeProviderFactory.ThemesRepresentation> themes, Boolean reaugmented) {
Config.init(new MicroProfileConfigProvider()); Config.init(new MicroProfileConfigProvider());
Profile.setInstance(new QuarkusProfile()); Profile.setInstance(new QuarkusProfile());
QuarkusKeycloakSessionFactory.setInstance(new QuarkusKeycloakSessionFactory(factories, defaultProviders, preConfiguredProviders, reaugmented)); QuarkusKeycloakSessionFactory.setInstance(new QuarkusKeycloakSessionFactory(factories, defaultProviders, preConfiguredProviders, themes, reaugmented));
} }
public RuntimeValue<CacheManagerFactory> createCacheInitializer(String config, ShutdownContext shutdownContext) { public RuntimeValue<CacheManagerFactory> createCacheInitializer(String config, ShutdownContext shutdownContext) {

View file

@ -63,9 +63,13 @@ public class MicroProfileConfigProvider implements Config.ConfigProvider {
private final String[] scope; private final String[] scope;
private final String prefix; private final String prefix;
public MicroProfileScope(String... scope) { public MicroProfileScope(String... scopes) {
this.scope = scope; this.scope = scopes;
this.prefix = NS_KEYCLOAK_PREFIX + String.join(OPTION_PART_SEPARATOR, ArrayUtils.insert(0, scope, "spi")); StringBuilder prefix = new StringBuilder(NS_KEYCLOAK_PREFIX).append("spi");
for (String scope : scopes) {
prefix.append(OPTION_PART_SEPARATOR).append(scope);
}
this.prefix = prefix.toString();
} }
@Override @Override

View file

@ -21,7 +21,7 @@ import java.util.function.Predicate;
public final class PropertyMappers { public final class PropertyMappers {
public static String VALUE_MASK = "*******"; public static String VALUE_MASK = "*******";
static final MappersConfig MAPPERS = new MappersConfig(); private static final MappersConfig MAPPERS = new MappersConfig();
private PropertyMappers(){} private PropertyMappers(){}

View file

@ -19,6 +19,7 @@ package org.keycloak.quarkus.runtime.integration;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import org.keycloak.Config; import org.keycloak.Config;
@ -26,8 +27,10 @@ import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory; import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.ProviderManagerRegistry; import org.keycloak.provider.ProviderManagerRegistry;
import org.keycloak.provider.Spi; import org.keycloak.provider.Spi;
import org.keycloak.quarkus.runtime.themes.QuarkusJarThemeProviderFactory;
import org.keycloak.services.DefaultKeycloakSessionFactory; import org.keycloak.services.DefaultKeycloakSessionFactory;
import org.keycloak.services.resources.admin.permissions.AdminPermissions; import org.keycloak.services.resources.admin.permissions.AdminPermissions;
import org.keycloak.theme.ClasspathThemeProviderFactory;
public final class QuarkusKeycloakSessionFactory extends DefaultKeycloakSessionFactory { public final class QuarkusKeycloakSessionFactory extends DefaultKeycloakSessionFactory {
@ -52,6 +55,7 @@ public final class QuarkusKeycloakSessionFactory extends DefaultKeycloakSessionF
Map<Spi, Map<Class<? extends Provider>, Map<String, Class<? extends ProviderFactory>>>> factories, Map<Spi, Map<Class<? extends Provider>, Map<String, Class<? extends ProviderFactory>>>> factories,
Map<Class<? extends Provider>, String> defaultProviders, Map<Class<? extends Provider>, String> defaultProviders,
Map<String, ProviderFactory> preConfiguredProviders, Map<String, ProviderFactory> preConfiguredProviders,
List<ClasspathThemeProviderFactory.ThemesRepresentation> themes,
Boolean reaugmented) { Boolean reaugmented) {
this.provider = defaultProviders; this.provider = defaultProviders;
this.factories = factories; this.factories = factories;
@ -69,6 +73,10 @@ public final class QuarkusKeycloakSessionFactory extends DefaultKeycloakSessionF
factory = lookupProviderFactory(entry.getValue()); factory = lookupProviderFactory(entry.getValue());
} }
if (factory instanceof QuarkusJarThemeProviderFactory) {
((QuarkusJarThemeProviderFactory) factory).setThemes(themes);
}
Config.Scope scope = Config.scope(spi.getName(), factory.getId()); Config.Scope scope = Config.scope(spi.getName(), factory.getId());
factory.init(scope); factory.init(scope);

View file

@ -0,0 +1,36 @@
/*
* Copyright ${YEAR} Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.quarkus.runtime.themes;
import java.util.List;
import org.keycloak.Config;
import org.keycloak.theme.JarThemeProviderFactory;
public class QuarkusJarThemeProviderFactory extends JarThemeProviderFactory {
public void setThemes(List<ThemesRepresentation> themes) {
for (ThemesRepresentation theme : themes) {
loadThemes(Thread.currentThread().getContextClassLoader(), theme);
}
}
@Override
public void init(Config.Scope config) {
// no-op
}
}

View file

@ -1,3 +1,4 @@
org.keycloak.quarkus.runtime.themes.QuarkusFolderThemeProviderFactory org.keycloak.quarkus.runtime.themes.QuarkusFolderThemeProviderFactory
org.keycloak.quarkus.runtime.themes.QuarkusJarThemeProviderFactory

View file

@ -32,13 +32,19 @@ public class WebAuthnCredentialProviderFactory implements CredentialProviderFact
@Override @Override
public CredentialProvider create(KeycloakSession session) { public CredentialProvider create(KeycloakSession session) {
return new WebAuthnCredentialProvider(session, converter); return new WebAuthnCredentialProvider(session, createOrGetObjectConverter());
} }
@Override private ObjectConverter createOrGetObjectConverter() {
public void init(Config.Scope config) { if (converter == null) {
synchronized (this) {
if (converter == null) {
converter = new ObjectConverter(); converter = new ObjectConverter();
} }
}
}
return converter;
}
@Override @Override
public String getId() { public String getId() {

View file

@ -30,11 +30,22 @@ public class WebAuthnPasswordlessCredentialProviderFactory implements Credential
public static final String PROVIDER_ID = "keycloak-webauthn-passwordless"; public static final String PROVIDER_ID = "keycloak-webauthn-passwordless";
private static ObjectConverter objectConverter = new ObjectConverter(); private ObjectConverter converter;
@Override @Override
public CredentialProvider create(KeycloakSession session) { public CredentialProvider create(KeycloakSession session) {
return new WebAuthnPasswordlessCredentialProvider(session, objectConverter); return new WebAuthnPasswordlessCredentialProvider(session, createOrGetObjectConverter());
}
private ObjectConverter createOrGetObjectConverter() {
if (converter == null) {
synchronized (this) {
if (converter == null) {
converter = new ObjectConverter();
}
}
}
return converter;
} }
@Override @Override

View file

@ -68,24 +68,6 @@ public class SamlProtocolFactory extends AbstractLoginProtocolFactory {
public void init(Config.Scope config) { public void init(Config.Scope config) {
//PicketLinkCoreSTS sts = PicketLinkCoreSTS.instance(); //PicketLinkCoreSTS sts = PicketLinkCoreSTS.instance();
//sts.installDefaultConfiguration(); //sts.installDefaultConfiguration();
this.destinationValidator = DestinationValidator.forProtocolMap(config.getArray("knownProtocols"));
}
@Override
public String getId() {
return SamlProtocol.LOGIN_PROTOCOL;
}
@Override
public Map<String, ProtocolMapperModel> getBuiltinMappers() {
return builtins;
}
static Map<String, ProtocolMapperModel> builtins = new HashMap<>();
static List<ProtocolMapperModel> defaultBuiltins = new ArrayList<>();
static {
ProtocolMapperModel model; ProtocolMapperModel model;
model = UserPropertyAttributeStatementMapper.createAttributeMapper("X500 email", model = UserPropertyAttributeStatementMapper.createAttributeMapper("X500 email",
"email", "email",
@ -111,9 +93,21 @@ public class SamlProtocolFactory extends AbstractLoginProtocolFactory {
model = RoleListMapper.create("role list", "Role", AttributeStatementHelper.BASIC, null, false); model = RoleListMapper.create("role list", "Role", AttributeStatementHelper.BASIC, null, false);
builtins.put("role list", model); builtins.put("role list", model);
defaultBuiltins.add(model); defaultBuiltins.add(model);
this.destinationValidator = DestinationValidator.forProtocolMap(config.getArray("knownProtocols"));
} }
@Override
public String getId() {
return SamlProtocol.LOGIN_PROTOCOL;
}
@Override
public Map<String, ProtocolMapperModel> getBuiltinMappers() {
return builtins;
}
private Map<String, ProtocolMapperModel> builtins = new HashMap<>();
private List<ProtocolMapperModel> defaultBuiltins = new ArrayList<>();
@Override @Override
protected void createDefaultClientScopesImpl(RealmModel newRealm) { protected void createDefaultClientScopesImpl(RealmModel newRealm) {

View file

@ -102,8 +102,14 @@ public class ClasspathThemeProviderFactory implements ThemeProviderFactory {
protected void loadThemes(ClassLoader classLoader, InputStream themesInputStream) { protected void loadThemes(ClassLoader classLoader, InputStream themesInputStream) {
try { try {
ThemesRepresentation themesRep = JsonSerialization.readValue(themesInputStream, ThemesRepresentation.class); loadThemes(classLoader, JsonSerialization.readValue(themesInputStream, ThemesRepresentation.class));
} catch (Exception e) {
throw new RuntimeException("Failed to load themes", e);
}
}
protected void loadThemes(ClassLoader classLoader, ThemesRepresentation themesRep) {
try {
for (ThemeRepresentation themeRep : themesRep.getThemes()) { for (ThemeRepresentation themeRep : themesRep.getThemes()) {
for (String t : themeRep.getTypes()) { for (String t : themeRep.getTypes()) {
Theme.Type type = Theme.Type.valueOf(t.toUpperCase()); Theme.Type type = Theme.Type.valueOf(t.toUpperCase());