fix: adding a check and documenting import naming conventions (#36340)

closes: #36284 #34793

Signed-off-by: Steve Hawkins <shawkins@redhat.com>
This commit is contained in:
Steven Hawkins 2025-01-28 12:44:47 -05:00 committed by GitHub
parent 8671f86046
commit 827e82ad25
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 50 additions and 1 deletions

View File

@ -76,6 +76,12 @@ If you do not specify a specific realm to export, all realms are exported. To ex
<@kc.export parameters="[--dir|--file] <path> --realm my-realm"/>
== Import File Naming Conventions
When you export a realm specific file name conventions are used, which must also be used for importing from a directory or import at startup. The realm file to be imported must be named <realm name>-realm.json.
Regular and federated user files associated with a realm must be named <realm-name>-users-<file number>.json and <realm-name>-federated-users-<file number>.json. Failure to use this convention will result in errors or
user files not being imported.
== Importing a Realm from a Directory
To import a realm, you can use the `import` command. Your {project_name} server instance must not be started when invoking this command.

View File

@ -138,6 +138,9 @@ public class DirImportProvider extends AbstractFileBasedImportProvider {
// Import realm first
InputStream is = parseFile(realmFile);
final RealmRepresentation realmRep = JsonSerialization.readValue(is, RealmRepresentation.class);
if (!realmRep.getRealm().equals(realmName)) {
throw new IllegalStateException(String.format("File name / realm name mismatch. %s, contains realm %s. File name should be %s", realmFile.getName(), realmRep.getRealm(), realmRep.getRealm() + "-realm.json"));
}
final AtomicBoolean realmImported = new AtomicBoolean();
KeycloakModelUtils.runJobInTransaction(factory, new ExportImportSessionTask() {

View File

@ -43,6 +43,7 @@ import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.representations.userprofile.config.UPConfig;
import org.keycloak.testsuite.AbstractKeycloakTest;
import org.keycloak.testsuite.Assert;
import org.keycloak.testsuite.arquillian.annotation.UncaughtServerErrorExpected;
import org.keycloak.testsuite.client.resources.TestingExportImportResource;
import org.keycloak.testsuite.forms.VerifyProfileTest;
import org.keycloak.testsuite.runonserver.RunHelpers;
@ -336,7 +337,7 @@ public class ExportImportTest extends AbstractKeycloakTest {
File testRealm = new File(url.getFile());
assertThat(testRealm, Matchers.notNullValue());
File newFile = new File("target", "test-new-realm.json");
File newFile = new File("target", "test-realm-realm.json");
try {
FileUtils.copyFile(testRealm, newFile);
@ -362,6 +363,45 @@ public class ExportImportTest extends AbstractKeycloakTest {
}
}
@UncaughtServerErrorExpected
public void testImportNameMismatch() {
TestingExportImportResource resource = testingClient.testing().exportImport();
resource.setStrategy(Strategy.IGNORE_EXISTING);
resource.setProvider(DirExportProviderFactory.PROVIDER_ID);
String targetDirPath = resource.getExportImportTestDirectory() + File.separator + "dirRealmExport";
File dest = new File(targetDirPath);
try {
DirExportProvider.recursiveDeleteDir(dest);
resource.setDir(targetDirPath);
resource.setAction(ExportImportConfig.ACTION_EXPORT);
URL url = ExportImportTest.class.getResource("/model/testrealm.json");
File testRealm = new File(url.getFile());
assertThat(testRealm, Matchers.notNullValue());
File newFile = new File("target", "test-new-realm.json");
try {
FileUtils.copyFile(testRealm, newFile);
FileUtils.copyFileToDirectory(newFile, dest);
} catch (IOException e) {
Assert.fail("Cannot copy file. Details: " + e.getMessage());
}
File existingFile = FileUtils.getFile(dest, newFile.getName());
assertThat(existingFile, Matchers.notNullValue());
resource.setAction(ExportImportConfig.ACTION_IMPORT);
resource.runImport();
} finally {
DirExportProvider.recursiveDeleteDir(dest);
}
}
private boolean isRealmPresent(String realmName) {
return adminClient.realms().findAll().stream().anyMatch(realm -> realmName.equals(realm.getRealm()));
}