fix: limit the scope of when a single transaction is used for import (#37990)

closes: #34364

Signed-off-by: Steve Hawkins <shawkins@redhat.com>
This commit is contained in:
Steven Hawkins 2025-03-24 14:39:07 -04:00 committed by GitHub
parent 1c57035d41
commit c0da146873
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 34 additions and 14 deletions

View File

@ -17,6 +17,7 @@
package org.keycloak.exportimport.util;
import org.keycloak.exportimport.ExportImportConfig;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionTask;
@ -40,7 +41,7 @@ public abstract class ExportImportSessionTask implements KeycloakSessionTask {
@Override
public boolean useExistingSession() {
return true;
return ExportImportConfig.isSingleTransaction();
}
protected abstract void runExportImportTask(KeycloakSession session) throws IOException;

View File

@ -31,6 +31,8 @@ public class ExportImportConfig {
public static final String ACTION_EXPORT = "export";
public static final String ACTION_IMPORT = "import";
public static final String SINGLE_TRANSACTION = PREFIX + "single-transaction";
public static final String PROVIDER = PREFIX + "provider";
public static final String PROVIDER_DEFAULT = "dir";
@ -61,15 +63,15 @@ public class ExportImportConfig {
public static String getAction() {
return System.getProperty(ACTION);
}
public static String getStrategy() {
return System.getProperty(STRATEGY);
}
public static String setStrategy(Strategy strategy) {
return System.setProperty(STRATEGY, strategy.toString());
}
public static Optional<String> getDir() {
return Optional.ofNullable(System.getProperty(DIR));
}
@ -106,9 +108,19 @@ public class ExportImportConfig {
public static void setReplacePlaceholders(boolean replacePlaceholders) {
System.setProperty(REPLACE_PLACEHOLDERS, String.valueOf(replacePlaceholders));
}
public static void reset() {
Stream.of(FILE, DIR, ACTION, STRATEGY, REPLACE_PLACEHOLDERS)
.forEach(prop -> System.getProperties().remove(prop));
}
public static void setSingleTransaction(boolean b) {
System.setProperty(SINGLE_TRANSACTION, String.valueOf(b));
}
public static boolean isSingleTransaction() {
return Boolean.getBoolean(SINGLE_TRANSACTION);
}
}

View File

@ -20,6 +20,7 @@ import org.jboss.logging.Logger;
import org.keycloak.Config;
import org.keycloak.common.crypto.CryptoIntegration;
import org.keycloak.config.ConfigProviderFactory;
import org.keycloak.exportimport.ExportImportConfig;
import org.keycloak.exportimport.ExportImportManager;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
@ -113,10 +114,11 @@ public abstract class KeycloakApplication extends Application {
}
protected void shutdown() {
if (sessionFactory != null)
if (sessionFactory != null) {
sessionFactory.close();
}
}
private static class BootstrapState {
ExportImportManager exportImportManager;
boolean newInstall;
@ -151,20 +153,25 @@ public abstract class KeycloakApplication extends Application {
var exportImportManager = bootstrapState.exportImportManager = new ExportImportManager(session);
bootstrapState.newInstall = applianceBootstrap.isNewInstall();
if (bootstrapState.newInstall) {
if (!exportImportManager.isImportMasterIncluded()) {
applianceBootstrap.createMasterRealm();
ExportImportConfig.setSingleTransaction(true);
try {
if (!exportImportManager.isImportMasterIncluded()) {
applianceBootstrap.createMasterRealm();
}
// these are also running in the initial bootstrap transaction - if there is a problem, the server won't be initialized at all
exportImportManager.runImport();
createTemporaryAdmin(session);
} finally {
ExportImportConfig.setSingleTransaction(false);
}
// these are also running in the initial bootstrap transaction - if there is a problem, the server won't be initialized at all
exportImportManager.runImport();
createTemporaryAdmin(session);
}
}
}
});
if (!bootstrapState.newInstall) {
bootstrapState.exportImportManager.runImport();
}
importAddUser();
return bootstrapState.exportImportManager;