Ignore unknown clients in LDAP role mapper

Fixes: #10958
This commit is contained in:
Hynek Mlnařík 2022-11-30 12:40:26 +01:00
parent 26901dce19
commit 60ce949304
2 changed files with 92 additions and 22 deletions

View file

@ -92,10 +92,15 @@ public class RoleLDAPStorageMapper extends AbstractLDAPStorageMapper implements
// Import role mappings from LDAP into Keycloak DB
String roleNameAttr = config.getRoleNameLdapAttribute();
RoleContainerModel roleContainer = getTargetRoleContainer(realm);
if (roleContainer == null) {
logger.warnf("Ignored client role grant for federation mapper '%s' as client not found: '%s'", mapperModel.getName(), config.getClientId());
return;
}
for (LDAPObject ldapRole : ldapRoles) {
String roleName = ldapRole.getAttributeAsString(roleNameAttr);
RoleContainerModel roleContainer = getTargetRoleContainer(realm);
RoleModel role = roleContainer.getRole(roleName);
if (role == null) {
@ -127,11 +132,16 @@ public class RoleLDAPStorageMapper extends AbstractLDAPStorageMapper implements
logger.debugf("Syncing roles from LDAP into Keycloak DB. Mapper is [%s], LDAP provider is [%s]", mapperModel.getName(), ldapProvider.getModel().getName());
RoleContainerModel roleContainer = getTargetRoleContainer(realm);
if (roleContainer == null) {
logger.warnf("Ignored sync for federation mapper '%s' as client not found: '%s'", mapperModel.getName(), config.getClientId());
return syncResult;
}
// Send LDAP query to load all roles
try (LDAPQuery ldapRoleQuery = createRoleQuery(false)) {
List<LDAPObject> ldapRoles = LDAPUtils.loadAllLDAPObjects(ldapRoleQuery, ldapProvider);
RoleContainerModel roleContainer = getTargetRoleContainer(realm);
String rolesRdnAttr = config.getRoleNameLdapAttribute();
for (LDAPObject ldapRole : ldapRoles) {
String roleName = ldapRole.getAttributeAsString(rolesRdnAttr);
@ -169,6 +179,12 @@ public class RoleLDAPStorageMapper extends AbstractLDAPStorageMapper implements
logger.debugf("Syncing roles from Keycloak into LDAP. Mapper is [%s], LDAP provider is [%s]", mapperModel.getName(), ldapProvider.getModel().getName());
RoleContainerModel roleContainer = getTargetRoleContainer(realm);
if (roleContainer == null) {
logger.warnf("Ignored sync for federation mapper '%s' as client not found: '%s'", mapperModel.getName(), config.getClientId());
return syncResult;
}
// Send LDAP query to see which roles exists there
try (LDAPQuery ldapQuery = createRoleQuery(false)) {
List<LDAPObject> ldapRoles = LDAPUtils.loadAllLDAPObjects(ldapQuery, ldapProvider);
@ -181,7 +197,6 @@ public class RoleLDAPStorageMapper extends AbstractLDAPStorageMapper implements
}
RoleContainerModel roleContainer = getTargetRoleContainer(realm);
Stream<RoleModel> keycloakRoles = roleContainer.getRolesStream();
Consumer<String> syncRoleFromKCToLDAP = roleName -> {
@ -242,7 +257,7 @@ public class RoleLDAPStorageMapper extends AbstractLDAPStorageMapper implements
}
ClientModel client = realm.getClientByClientId(clientId);
if (client == null) {
throw new ModelException("Can't found requested client with clientId: " + clientId);
logger.warnf("Cannot find requested client with clientId '%s' in federation mapper '%s'", clientId, mapperModel.getName());
}
return client;
}
@ -296,8 +311,12 @@ public class RoleLDAPStorageMapper extends AbstractLDAPStorageMapper implements
// For IMPORT mode, all operations are performed against local DB
if (mode == LDAPGroupMapperMode.IMPORT) {
return delegate;
}
final RoleContainerModel targetRoleContainer = getTargetRoleContainer(realm);
if (targetRoleContainer == null) {
return delegate;
} else {
return new LDAPRoleMappingsUserDelegate(realm, delegate, ldapUser);
return new LDAPRoleMappingsUserDelegate(realm, delegate, ldapUser, targetRoleContainer);
}
}
@ -324,11 +343,11 @@ public class RoleLDAPStorageMapper extends AbstractLDAPStorageMapper implements
// Avoid loading role mappings from LDAP more times per-request
private Set<RoleModel> cachedLDAPRoleMappings;
public LDAPRoleMappingsUserDelegate(RealmModel realm, UserModel user, LDAPObject ldapUser) {
public LDAPRoleMappingsUserDelegate(RealmModel realm, UserModel user, LDAPObject ldapUser, RoleContainerModel targetRoleContainer) {
super(user);
this.realm = realm;
this.ldapUser = ldapUser;
this.roleContainer = getTargetRoleContainer(realm);
this.roleContainer = targetRoleContainer;
}
@Override

View file

@ -33,6 +33,9 @@ import org.keycloak.storage.ldap.mappers.membership.role.RoleMapperConfig;
import org.keycloak.testsuite.util.LDAPRule;
import org.keycloak.testsuite.util.LDAPTestUtils;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.nullValue;
/**
*
* @author rmartinc
@ -62,29 +65,29 @@ public class LDAPRoleMapperTest extends AbstractLDAPTest {
// check users
UserModel john = session.users().getUserByUsername(appRealm, "johnkeycloak");
Assert.assertNotNull(john);
Assert.assertThat(john.getRealmRoleMappingsStream().map(RoleModel::getName).collect(Collectors.toSet()), Matchers.containsInAnyOrder("group1", "group2"));
assertThat(john.getRealmRoleMappingsStream().map(RoleModel::getName).collect(Collectors.toSet()), Matchers.containsInAnyOrder("group1", "group2"));
UserModel mary = session.users().getUserByUsername(appRealm, "marykeycloak");
Assert.assertNotNull(mary);
Assert.assertThat(mary.getRealmRoleMappingsStream().map(RoleModel::getName).collect(Collectors.toSet()), Matchers.containsInAnyOrder("group1", "group2"));
assertThat(mary.getRealmRoleMappingsStream().map(RoleModel::getName).collect(Collectors.toSet()), Matchers.containsInAnyOrder("group1", "group2"));
UserModel rob = session.users().getUserByUsername(appRealm, "robkeycloak");
Assert.assertNotNull(rob);
Assert.assertThat(rob.getRealmRoleMappingsStream().map(RoleModel::getName).collect(Collectors.toSet()), Matchers.containsInAnyOrder("group1"));
assertThat(rob.getRealmRoleMappingsStream().map(RoleModel::getName).collect(Collectors.toSet()), Matchers.containsInAnyOrder("group1"));
UserModel james = session.users().getUserByUsername(appRealm, "jameskeycloak");
Assert.assertNotNull(james);
Assert.assertThat(james.getRealmRoleMappingsStream().collect(Collectors.toSet()), Matchers.empty());
assertThat(james.getRealmRoleMappingsStream().collect(Collectors.toSet()), Matchers.empty());
// check groups
RoleModel group1 = appRealm.getRole("group1");
Assert.assertNotNull(group1);
Assert.assertThat(session.users().getRoleMembersStream(appRealm, group1).map(UserModel::getUsername).collect(Collectors.toSet()),
assertThat(session.users().getRoleMembersStream(appRealm, group1).map(UserModel::getUsername).collect(Collectors.toSet()),
Matchers.containsInAnyOrder("johnkeycloak", "marykeycloak", "robkeycloak"));
RoleModel group2 = appRealm.getRole("group2");
Assert.assertNotNull(group2);
Assert.assertThat(session.users().getRoleMembersStream(appRealm, group2).map(UserModel::getUsername).collect(Collectors.toSet()),
assertThat(session.users().getRoleMembersStream(appRealm, group2).map(UserModel::getUsername).collect(Collectors.toSet()),
Matchers.containsInAnyOrder("johnkeycloak", "marykeycloak"));
RoleModel group3 = appRealm.getRole("group3");
Assert.assertNotNull(group3);
Assert.assertThat(session.users().getRoleMembersStream(appRealm, group3).collect(Collectors.toSet()), Matchers.empty());
assertThat(session.users().getRoleMembersStream(appRealm, group3).collect(Collectors.toSet()), Matchers.empty());
});
}
@ -110,29 +113,77 @@ public class LDAPRoleMapperTest extends AbstractLDAPTest {
// check users
UserModel john = session.users().getUserByUsername(appRealm, "johnkeycloak");
Assert.assertNotNull(john);
Assert.assertThat(john.getClientRoleMappingsStream(rolesClient).map(RoleModel::getName).collect(Collectors.toSet()), Matchers.containsInAnyOrder("group1", "group2"));
assertThat(john.getClientRoleMappingsStream(rolesClient).map(RoleModel::getName).collect(Collectors.toSet()), Matchers.containsInAnyOrder("group1", "group2"));
UserModel mary = session.users().getUserByUsername(appRealm, "marykeycloak");
Assert.assertNotNull(mary);
Assert.assertThat(mary.getClientRoleMappingsStream(rolesClient).map(RoleModel::getName).collect(Collectors.toSet()), Matchers.containsInAnyOrder("group1", "group2"));
assertThat(mary.getClientRoleMappingsStream(rolesClient).map(RoleModel::getName).collect(Collectors.toSet()), Matchers.containsInAnyOrder("group1", "group2"));
UserModel rob = session.users().getUserByUsername(appRealm, "robkeycloak");
Assert.assertNotNull(rob);
Assert.assertThat(rob.getClientRoleMappingsStream(rolesClient).map(RoleModel::getName).collect(Collectors.toSet()), Matchers.containsInAnyOrder("group1"));
assertThat(rob.getClientRoleMappingsStream(rolesClient).map(RoleModel::getName).collect(Collectors.toSet()), Matchers.containsInAnyOrder("group1"));
UserModel james = session.users().getUserByUsername(appRealm, "jameskeycloak");
Assert.assertNotNull(james);
Assert.assertThat(james.getClientRoleMappingsStream(rolesClient).map(RoleModel::getName).collect(Collectors.toSet()), Matchers.empty());
assertThat(james.getClientRoleMappingsStream(rolesClient).map(RoleModel::getName).collect(Collectors.toSet()), Matchers.empty());
// check groups
RoleModel group1 = rolesClient.getRole("group1");
Assert.assertNotNull(group1);
Assert.assertThat(session.users().getRoleMembersStream(appRealm, group1).map(UserModel::getUsername).collect(Collectors.toSet()),
assertThat(session.users().getRoleMembersStream(appRealm, group1).map(UserModel::getUsername).collect(Collectors.toSet()),
Matchers.containsInAnyOrder("johnkeycloak", "marykeycloak", "robkeycloak"));
RoleModel group2 = rolesClient.getRole("group2");
Assert.assertNotNull(group2);
Assert.assertThat(session.users().getRoleMembersStream(appRealm, group2).map(UserModel::getUsername).collect(Collectors.toSet()),
assertThat(session.users().getRoleMembersStream(appRealm, group2).map(UserModel::getUsername).collect(Collectors.toSet()),
Matchers.containsInAnyOrder("johnkeycloak", "marykeycloak"));
RoleModel group3 = rolesClient.getRole("group3");
Assert.assertNotNull(group3);
Assert.assertThat(session.users().getRoleMembersStream(appRealm, group3).collect(Collectors.toSet()), Matchers.empty());
assertThat(session.users().getRoleMembersStream(appRealm, group3).collect(Collectors.toSet()), Matchers.empty());
} finally {
appRealm.removeClient(rolesClient.getId());
}
});
}
@Test
public void test03RoleMapperClientRoles() {
testingClient.server().run(session -> {
LDAPTestContext ctx = LDAPTestContext.init(session);
RealmModel appRealm = ctx.getRealm();
// create a client to set the roles in it
ClientModel rolesClient = session.clients().addClient(appRealm, "role-mapper-client");
final String clientId = rolesClient.getClientId();
try {
ComponentModel mapperModel = LDAPTestUtils.getSubcomponentByName(appRealm, ctx.getLdapModel(), "rolesMapper");
LDAPTestUtils.updateGroupMapperConfigOptions(mapperModel,
RoleMapperConfig.USE_REALM_ROLES_MAPPING, "false",
RoleMapperConfig.CLIENT_ID, clientId);
appRealm.updateComponent(mapperModel);
rolesClient.setClientId(clientId + "-suffix");
rolesClient.updateClient();
// synch to the client to create the roles at the client
new RoleLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(appRealm);
// check users
UserModel john = session.users().getUserByUsername(appRealm, "johnkeycloak");
Assert.assertNotNull(john);
assertThat(john.getClientRoleMappingsStream(rolesClient).map(RoleModel::getName).collect(Collectors.toSet()), Matchers.empty());
UserModel mary = session.users().getUserByUsername(appRealm, "marykeycloak");
Assert.assertNotNull(mary);
assertThat(mary.getClientRoleMappingsStream(rolesClient).map(RoleModel::getName).collect(Collectors.toSet()), Matchers.empty());
UserModel rob = session.users().getUserByUsername(appRealm, "robkeycloak");
Assert.assertNotNull(rob);
assertThat(rob.getClientRoleMappingsStream(rolesClient).map(RoleModel::getName).collect(Collectors.toSet()), Matchers.empty());
UserModel james = session.users().getUserByUsername(appRealm, "jameskeycloak");
Assert.assertNotNull(james);
assertThat(james.getClientRoleMappingsStream(rolesClient).map(RoleModel::getName).collect(Collectors.toSet()), Matchers.empty());
// check groups
assertThat(rolesClient.getRole("group1"), nullValue());
assertThat(rolesClient.getRole("group2"), nullValue());
assertThat(rolesClient.getRole("group3"), nullValue());
} finally {
appRealm.removeClient(rolesClient.getId());