Resolved errors during component import referencing groups

Whenever a component being imported contained a reference to a group also being imported, the group was not found because groups were being imported after components by DefaultImportExportManager

Closes #10730

Signed-off-by: Kyale <github@chalkyweb.com>
This commit is contained in:
Kyale 2024-09-27 19:43:11 +02:00 committed by Pedro Igor
parent 8d314a69a0
commit a35edeb488
3 changed files with 222 additions and 7 deletions

View file

@ -419,6 +419,13 @@ public class DefaultExportImportManager implements ExportImportManager {
newRealm.setBrowserSecurityHeaders(BrowserSecurityHeaders.realmDefaultHeaders); newRealm.setBrowserSecurityHeaders(BrowserSecurityHeaders.realmDefaultHeaders);
} }
if (rep.getGroups() != null) {
importGroups(newRealm, rep);
if (rep.getDefaultGroups() != null) {
KeycloakModelUtils.setDefaultGroups(session, newRealm, rep.getDefaultGroups().stream());
}
}
if (rep.getComponents() != null) { if (rep.getComponents() != null) {
MultivaluedHashMap<String, ComponentExportRepresentation> components = rep.getComponents(); MultivaluedHashMap<String, ComponentExportRepresentation> components = rep.getComponents();
String parentId = newRealm.getId(); String parentId = newRealm.getId();
@ -427,12 +434,6 @@ public class DefaultExportImportManager implements ExportImportManager {
importUserFederationProvidersAndMappers(session, rep, newRealm); importUserFederationProvidersAndMappers(session, rep, newRealm);
if (rep.getGroups() != null) {
importGroups(newRealm, rep);
if (rep.getDefaultGroups() != null) {
KeycloakModelUtils.setDefaultGroups(session, newRealm, rep.getDefaultGroups().stream());
}
}
// create users and their role mappings and social mappings // create users and their role mappings and social mappings
@ -663,7 +664,6 @@ public class DefaultExportImportManager implements ExportImportManager {
} }
} }
public static void renameRealm(RealmModel realm, String name) { public static void renameRealm(RealmModel realm, String name) {
if (name.equals(realm.getName())) { if (name.equals(realm.getName())) {
return; return;

View file

@ -25,6 +25,7 @@ import org.junit.runners.MethodSorters;
import org.keycloak.authorization.AuthorizationProvider; import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.model.ResourceServer; import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.common.Profile; import org.keycloak.common.Profile;
import org.keycloak.component.ComponentModel;
import org.keycloak.exportimport.Strategy; import org.keycloak.exportimport.Strategy;
import org.keycloak.exportimport.util.ImportUtils; import org.keycloak.exportimport.util.ImportUtils;
import org.keycloak.models.ClientModel; import org.keycloak.models.ClientModel;
@ -49,6 +50,7 @@ import java.nio.charset.StandardCharsets;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -155,6 +157,23 @@ public class ImportTest extends AbstractTestRealmKeycloakTest {
}); });
} }
// https://github.com/keycloak/keycloak/issues/10730
@Test
public void importLdapWithReferenceToGroupBeingImported() {
RealmRepresentation testRealm = loadJson(getClass().getResourceAsStream("/model/testrealm-ldap-group.json"), RealmRepresentation.class);
adminClient.realms().create(testRealm);
testingClient.server().run(session -> {
RealmModel realm = session.realms().getRealmByName("ldap-group-import-bug");
Optional<ComponentModel> hardCodedGroup = realm.getComponentsStream()
.filter((component) -> component.getName().equals("hard-coded-group"))
.findFirst();
Assert.assertTrue(hardCodedGroup.isPresent());
});
}
@Test @Test
public void importUserProfile() throws Exception { public void importUserProfile() throws Exception {
final String realmString = IOUtils.toString(getClass().getResourceAsStream("/model/import-userprofile.json"), StandardCharsets.UTF_8); final String realmString = IOUtils.toString(getClass().getResourceAsStream("/model/import-userprofile.json"), StandardCharsets.UTF_8);

View file

@ -0,0 +1,196 @@
{
"realm": "ldap-group-import-bug",
"enabled": true,
"accessTokenLifespan": 300,
"accessCodeLifespan": 10,
"accessCodeLifespanUserAction": 600,
"sslRequired": "external",
"requiredCredentials": [
"password"
],
"users": [
{
"username": "kyale",
"enabled": true,
"email": "kyale@foo.bar",
"credentials": [
{
"type": "Password",
"value": "password"
}
],
"realmRoles": [
"user"
]
}
],
"oauthClients": [
{
"name": "third-party",
"enabled": true,
"secret": "password"
}
],
"roles": {
"realm": [
{
"name": "user",
"description": "Have User privileges"
},
{
"name": "admin",
"description": "Have Administrator privileges"
}
]
},
"groups": [
{
"name": "hardcoded",
"path": "/hardcoded",
"subGroups": [],
"attributes": {},
"realmRoles": [],
"clientRoles": {}
}
],
"scopeMappings": [
{
"client": "third-party",
"roles": [
"user"
]
}
],
"applications": [
{
"name": "customer-portal",
"enabled": true,
"adminUrl": "http://localhost:8080/customer-portal/j_admin_request",
"secret": "password"
},
{
"name": "product-portal",
"enabled": true,
"adminUrl": "http://localhost:8080/product-portal/j_admin_request",
"secret": "password"
}
],
"components": {
"org.keycloak.storage.UserStorageProvider": [
{
"id": "34192d41-8e0d-4a2f-916e-7061de988801",
"name": "LDAP Login",
"providerId": "ldap",
"subComponents": {
"org.keycloak.storage.ldap.mappers.LDAPStorageMapper": [
{
"name": "hard-coded-group",
"providerId": "hardcoded-ldap-group-mapper",
"subComponents": {},
"config": {
"group": [
"hardcoded"
]
}
}
]
},
"config": {
"fullSyncPeriod": [
"-1"
],
"pagination": [
"false"
],
"startTls": [
"false"
],
"connectionPooling": [
"true"
],
"usersDn": [
"OU=users,DC=apmoller,DC=local"
],
"cachePolicy": [
"DEFAULT"
],
"useKerberosForPasswordAuthentication": [
"false"
],
"importEnabled": [
"false"
],
"enabled": [
"true"
],
"bindDn": [
"CN=admin,DC=apmoller,DC=local"
],
"changedSyncPeriod": [
"-1"
],
"bindCredential": [
"**********"
],
"usernameLDAPAttribute": [
"uid"
],
"vendor": [
"other"
],
"uuidLDAPAttribute": [
"entryUUID"
],
"allowKerberosAuthentication": [
"false"
],
"connectionUrl": [
"ldap://mock-ldap.apmt-dpos.svc.cluster.local:389"
],
"syncRegistrations": [
"false"
],
"authType": [
"simple"
],
"krbPrincipalAttribute": [
"userPrincipalName"
],
"customUserSearchFilter": [
"(objectClass=*)"
],
"searchScope": [
"2"
],
"useTruststoreSpi": [
"always"
],
"usePasswordModifyExtendedOp": [
"false"
],
"trustEmail": [
"false"
],
"userObjectClasses": [
"inetOrgPerson"
],
"rdnLDAPAttribute": [
"uid"
],
"referral": [
"ignore"
],
"readTimeout": [
"5000"
],
"editMode": [
"READ_ONLY"
],
"validatePasswordPolicy": [
"false"
]
}
}
]
}
}