Imposing certain constraints to files when importing at start-up
Closes #11861
This commit is contained in:
parent
3feed3827c
commit
b5a5d68dbc
3 changed files with 55 additions and 9 deletions
|
@ -80,7 +80,7 @@ You are also able to import realms when the server is starting by using the `--i
|
||||||
<@kc.start parameters="--import-realm"/>
|
<@kc.start parameters="--import-realm"/>
|
||||||
|
|
||||||
When you set the `--import-realm` option, the server is going to try to import any realm configuration file from the `data/import` directory. Each file in this directory should
|
When you set the `--import-realm` option, the server is going to try to import any realm configuration file from the `data/import` directory. Each file in this directory should
|
||||||
contain a single realm configuration.
|
contain a single realm configuration. Only regular files using the `.json` extension are read from this directory, sub-directories are ignored.
|
||||||
|
|
||||||
If a realm already exists in the server, the import operation is skipped.
|
If a realm already exists in the server, the import operation is skipped.
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.DatabaseMetaData;
|
import java.sql.DatabaseMetaData;
|
||||||
|
@ -58,10 +59,14 @@ import org.keycloak.connections.jpa.JpaConnectionProvider;
|
||||||
import org.keycloak.connections.jpa.updater.JpaUpdaterProvider;
|
import org.keycloak.connections.jpa.updater.JpaUpdaterProvider;
|
||||||
import org.keycloak.connections.jpa.util.JpaUtils;
|
import org.keycloak.connections.jpa.util.JpaUtils;
|
||||||
import org.keycloak.exportimport.ExportImportManager;
|
import org.keycloak.exportimport.ExportImportManager;
|
||||||
import org.keycloak.migration.MigrationModel;
|
|
||||||
import org.keycloak.migration.MigrationModelManager;
|
import org.keycloak.migration.MigrationModelManager;
|
||||||
import org.keycloak.migration.ModelVersion;
|
import org.keycloak.migration.ModelVersion;
|
||||||
import org.keycloak.models.*;
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
|
import org.keycloak.models.ModelDuplicateException;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.UserModel;
|
||||||
|
import org.keycloak.models.UserProvider;
|
||||||
import org.keycloak.models.dblock.DBLockManager;
|
import org.keycloak.models.dblock.DBLockManager;
|
||||||
import org.keycloak.models.dblock.DBLockProvider;
|
import org.keycloak.models.dblock.DBLockProvider;
|
||||||
import org.keycloak.models.utils.RepresentationToModel;
|
import org.keycloak.models.utils.RepresentationToModel;
|
||||||
|
@ -322,8 +327,15 @@ public class QuarkusJpaConnectionProviderFactory extends AbstractJpaConnectionPr
|
||||||
String file = tokenizer.nextToken().trim();
|
String file = tokenizer.nextToken().trim();
|
||||||
RealmRepresentation rep;
|
RealmRepresentation rep;
|
||||||
try {
|
try {
|
||||||
|
Path filePath = Paths.get(file);
|
||||||
|
|
||||||
|
if (!(Files.exists(filePath) && Files.isRegularFile(filePath) && filePath.toString().endsWith(".json"))) {
|
||||||
|
logger.debugf("Ignoring import file because it is not a valid file: %s", file);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
rep = JsonSerialization.readValue(StringPropertyReplacer.replaceProperties(
|
rep = JsonSerialization.readValue(StringPropertyReplacer.replaceProperties(
|
||||||
Files.readString(Paths.get(file)), new StringPropertyReplacer.PropertyResolver() {
|
Files.readString(filePath), new StringPropertyReplacer.PropertyResolver() {
|
||||||
@Override
|
@Override
|
||||||
public String resolve(String property) {
|
public String resolve(String property) {
|
||||||
return Optional.ofNullable(System.getenv(property)).orElse(null);
|
return Optional.ofNullable(System.getenv(property)).orElse(null);
|
||||||
|
|
|
@ -18,22 +18,19 @@
|
||||||
package org.keycloak.it.cli.dist;
|
package org.keycloak.it.cli.dist;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import org.junit.jupiter.api.MethodOrderer;
|
|
||||||
import org.junit.jupiter.api.Order;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.TestMethodOrder;
|
|
||||||
import org.keycloak.it.junit5.extension.BeforeStartDistribution;
|
import org.keycloak.it.junit5.extension.BeforeStartDistribution;
|
||||||
import org.keycloak.it.junit5.extension.CLIResult;
|
import org.keycloak.it.junit5.extension.CLIResult;
|
||||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||||
import org.keycloak.it.utils.KeycloakDistribution;
|
import org.keycloak.it.utils.KeycloakDistribution;
|
||||||
|
import org.keycloak.it.utils.RawKeycloakDistribution;
|
||||||
|
|
||||||
import io.quarkus.test.junit.main.Launch;
|
import io.quarkus.test.junit.main.Launch;
|
||||||
import io.quarkus.test.junit.main.LaunchResult;
|
import io.quarkus.test.junit.main.LaunchResult;
|
||||||
|
|
||||||
@DistributionTest
|
@DistributionTest(reInstall = DistributionTest.ReInstall.BEFORE_TEST)
|
||||||
@RawDistOnly(reason = "Containers are immutable")
|
@RawDistOnly(reason = "Containers are immutable")
|
||||||
public class ImportAtStartupDistTest {
|
public class ImportAtStartupDistTest {
|
||||||
|
|
||||||
|
@ -45,6 +42,23 @@ public class ImportAtStartupDistTest {
|
||||||
cliResult.assertMessage("Imported realm quickstart-realm from file");
|
cliResult.assertMessage("Imported realm quickstart-realm from file");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@BeforeStartDistribution(CreateRealmConfigurationFileAndDir.class)
|
||||||
|
@Launch({"start-dev", "--import-realm", "--log-level=org.keycloak.quarkus.runtime.storage.database.jpa:debug"})
|
||||||
|
void testImportAndIgnoreDirectory(LaunchResult result) {
|
||||||
|
CLIResult cliResult = (CLIResult) result;
|
||||||
|
cliResult.assertMessage("Imported realm quickstart-realm from file");
|
||||||
|
cliResult.assertMessage("Ignoring import file because it is not a valid file");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@BeforeStartDistribution(CreateRealmConfigurationFileWithUnsupportedExtension.class)
|
||||||
|
@Launch({"start-dev", "--import-realm", "--log-level=org.keycloak.quarkus.runtime.storage.database.jpa:debug"})
|
||||||
|
void testIgnoreFileWithUnsupportedExtension(LaunchResult result) {
|
||||||
|
CLIResult cliResult = (CLIResult) result;
|
||||||
|
cliResult.assertMessage("Ignoring import file because it is not a valid file");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@BeforeStartDistribution(CreateRealmConfigurationFile.class)
|
@BeforeStartDistribution(CreateRealmConfigurationFile.class)
|
||||||
@Launch({"start-dev", "--import-realm", "some-file"})
|
@Launch({"start-dev", "--import-realm", "some-file"})
|
||||||
|
@ -60,4 +74,24 @@ public class ImportAtStartupDistTest {
|
||||||
distribution.copyOrReplaceFileFromClasspath("/quickstart-realm.json", Path.of("data", "import", "realm.json"));
|
distribution.copyOrReplaceFileFromClasspath("/quickstart-realm.json", Path.of("data", "import", "realm.json"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class CreateRealmConfigurationFileAndDir implements Consumer<KeycloakDistribution> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(KeycloakDistribution distribution) {
|
||||||
|
distribution.copyOrReplaceFileFromClasspath("/quickstart-realm.json", Path.of("data", "import", "realm.json"));
|
||||||
|
|
||||||
|
RawKeycloakDistribution rawDist = (RawKeycloakDistribution) distribution;
|
||||||
|
|
||||||
|
rawDist.getDistPath().resolve("data").resolve("import").resolve("sub-dir").toFile().mkdirs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CreateRealmConfigurationFileWithUnsupportedExtension implements Consumer<KeycloakDistribution> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(KeycloakDistribution distribution) {
|
||||||
|
distribution.copyOrReplaceFileFromClasspath("/quickstart-realm.json", Path.of("data", "import", "realm"));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue