KEYCLOAK-886 Added builtin federation mappers when creating new LDAP Federation model. Testsuite passing
This commit is contained in:
parent
7476ee51e4
commit
490b3e3603
22 changed files with 348 additions and 200 deletions
|
@ -11,6 +11,7 @@ import java.util.Set;
|
|||
import javax.naming.directory.SearchControls;
|
||||
|
||||
import org.keycloak.models.LDAPConstants;
|
||||
import org.keycloak.models.UserFederationProvider;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
|
||||
/**
|
||||
|
@ -62,7 +63,7 @@ public class LDAPConfig {
|
|||
return dns.iterator().next();
|
||||
}
|
||||
|
||||
public Collection<String> getObjectClasses() {
|
||||
public Collection<String> getUserObjectClasses() {
|
||||
String objClassesCfg = config.get(LDAPConstants.USER_OBJECT_CLASSES);
|
||||
String objClassesStr = (objClassesCfg != null && objClassesCfg.length() > 0) ? objClassesCfg.trim() : "inetOrgPerson,organizationalPerson";
|
||||
|
||||
|
@ -162,4 +163,13 @@ public class LDAPConfig {
|
|||
}
|
||||
return rdn;
|
||||
}
|
||||
|
||||
public UserFederationProvider.EditMode getEditMode() {
|
||||
String editModeString = config.get(LDAPConstants.EDIT_MODE);
|
||||
if (editModeString == null) {
|
||||
return UserFederationProvider.EditMode.READ_ONLY;
|
||||
} else {
|
||||
return UserFederationProvider.EditMode.valueOf(editModeString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,12 +59,7 @@ public class LDAPFederationProvider implements UserFederationProvider {
|
|||
this.model = model;
|
||||
this.ldapIdentityStore = ldapIdentityStore;
|
||||
this.kerberosConfig = new LDAPProviderKerberosConfig(model);
|
||||
String editModeString = model.getConfig().get(LDAPConstants.EDIT_MODE);
|
||||
if (editModeString == null) {
|
||||
editMode = EditMode.READ_ONLY;
|
||||
} else {
|
||||
editMode = EditMode.valueOf(editModeString);
|
||||
}
|
||||
this.editMode = ldapIdentityStore.getConfig().getEditMode();
|
||||
|
||||
supportedCredentialTypes.add(UserCredentialModel.PASSWORD);
|
||||
if (kerberosConfig.isAllowKerberosAuthentication()) {
|
||||
|
|
|
@ -12,15 +12,22 @@ import org.keycloak.federation.ldap.idm.query.QueryParameter;
|
|||
import org.keycloak.federation.ldap.idm.query.internal.LDAPIdentityQuery;
|
||||
import org.keycloak.federation.ldap.idm.query.internal.LDAPQueryConditionsBuilder;
|
||||
import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore;
|
||||
import org.keycloak.federation.ldap.mappers.FullNameLDAPFederationMapper;
|
||||
import org.keycloak.federation.ldap.mappers.FullNameLDAPFederationMapperFactory;
|
||||
import org.keycloak.federation.ldap.mappers.UserAttributeLDAPFederationMapper;
|
||||
import org.keycloak.federation.ldap.mappers.UserAttributeLDAPFederationMapperFactory;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.models.KeycloakSessionTask;
|
||||
import org.keycloak.models.LDAPConstants;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserFederationEventAwareProviderFactory;
|
||||
import org.keycloak.models.UserFederationMapperModel;
|
||||
import org.keycloak.models.UserFederationProvider;
|
||||
import org.keycloak.models.UserFederationProviderFactory;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
import org.keycloak.models.UserFederationSyncResult;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
|
@ -33,7 +40,7 @@ import java.util.Set;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class LDAPFederationProviderFactory implements UserFederationProviderFactory {
|
||||
public class LDAPFederationProviderFactory extends UserFederationEventAwareProviderFactory {
|
||||
private static final Logger logger = Logger.getLogger(LDAPFederationProviderFactory.class);
|
||||
public static final String PROVIDER_NAME = "ldap";
|
||||
|
||||
|
@ -55,11 +62,6 @@ public class LDAPFederationProviderFactory implements UserFederationProviderFact
|
|||
this.ldapStoreRegistry = new LDAPIdentityStoreRegistry();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
this.ldapStoreRegistry = null;
|
||||
|
@ -75,6 +77,69 @@ public class LDAPFederationProviderFactory implements UserFederationProviderFact
|
|||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
|
||||
// Best effort to create appropriate mappers according to our LDAP config
|
||||
@Override
|
||||
protected void onProviderModelCreated(RealmModel realm, UserFederationProviderModel newProviderModel) {
|
||||
LDAPConfig ldapConfig = new LDAPConfig(newProviderModel.getConfig());
|
||||
|
||||
boolean activeDirectory = ldapConfig.isActiveDirectory();
|
||||
UserFederationProvider.EditMode editMode = ldapConfig.getEditMode();
|
||||
String readOnly = String.valueOf(editMode==UserFederationProvider.EditMode.READ_ONLY || editMode== UserFederationProvider.EditMode.UNSYNCED);
|
||||
String usernameLdapAttribute = ldapConfig.getUsernameLdapAttribute();
|
||||
|
||||
UserFederationMapperModel mapperModel;
|
||||
mapperModel = KeycloakModelUtils.createUserFederationMapperModel("usernameMapper", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.ID,
|
||||
UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, UserModel.USERNAME,
|
||||
UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, usernameLdapAttribute,
|
||||
UserAttributeLDAPFederationMapper.READ_ONLY, readOnly);
|
||||
realm.addUserFederationMapper(mapperModel);
|
||||
|
||||
// For AD deployments with sAMAccountName is probably more common to map "cn" to full name of user
|
||||
if (activeDirectory && usernameLdapAttribute.equalsIgnoreCase(LDAPConstants.SAM_ACCOUNT_NAME)) {
|
||||
mapperModel = KeycloakModelUtils.createUserFederationMapperModel("fullNameMapper", newProviderModel.getId(), FullNameLDAPFederationMapperFactory.ID,
|
||||
FullNameLDAPFederationMapper.LDAP_FULL_NAME_ATTRIBUTE, LDAPConstants.CN,
|
||||
UserAttributeLDAPFederationMapper.READ_ONLY, readOnly);
|
||||
realm.addUserFederationMapper(mapperModel);
|
||||
} else {
|
||||
mapperModel = KeycloakModelUtils.createUserFederationMapperModel("firstNameMapper", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.ID,
|
||||
UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, UserModel.FIRST_NAME,
|
||||
UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, LDAPConstants.CN,
|
||||
UserAttributeLDAPFederationMapper.READ_ONLY, readOnly);
|
||||
realm.addUserFederationMapper(mapperModel);
|
||||
}
|
||||
|
||||
mapperModel = KeycloakModelUtils.createUserFederationMapperModel("lastNameMapper", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.ID,
|
||||
UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, UserModel.LAST_NAME,
|
||||
UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, LDAPConstants.SN,
|
||||
UserAttributeLDAPFederationMapper.READ_ONLY, readOnly);
|
||||
realm.addUserFederationMapper(mapperModel);
|
||||
|
||||
mapperModel = KeycloakModelUtils.createUserFederationMapperModel("emailMapper", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.ID,
|
||||
UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, UserModel.EMAIL,
|
||||
UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, LDAPConstants.EMAIL,
|
||||
UserAttributeLDAPFederationMapper.READ_ONLY, readOnly);
|
||||
realm.addUserFederationMapper(mapperModel);
|
||||
|
||||
String createTimestampLdapAttrName = activeDirectory ? "whenCreated" : LDAPConstants.CREATE_TIMESTAMP;
|
||||
String modifyTimestampLdapAttrName = activeDirectory ? "whenChanged" : LDAPConstants.MODIFY_TIMESTAMP;
|
||||
|
||||
// map createTimeStamp as read-only
|
||||
mapperModel = KeycloakModelUtils.createUserFederationMapperModel("creationDateMapper", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.ID,
|
||||
UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, LDAPConstants.CREATE_TIMESTAMP,
|
||||
UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, createTimestampLdapAttrName,
|
||||
UserAttributeLDAPFederationMapper.READ_ONLY, "true");
|
||||
realm.addUserFederationMapper(mapperModel);
|
||||
|
||||
// map modifyTimeStamp as read-only
|
||||
mapperModel = KeycloakModelUtils.createUserFederationMapperModel("modifyDateMapper", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.ID,
|
||||
UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, LDAPConstants.MODIFY_TIMESTAMP,
|
||||
UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, modifyTimestampLdapAttrName,
|
||||
UserAttributeLDAPFederationMapper.READ_ONLY, "true");
|
||||
realm.addUserFederationMapper(mapperModel);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public UserFederationSyncResult syncAllUsers(KeycloakSessionFactory sessionFactory, final String realmId, final UserFederationProviderModel model) {
|
||||
logger.infof("Sync all users from LDAP to local store: realm: %s, federation provider: %s", realmId, model.getDisplayName());
|
||||
|
|
|
@ -81,20 +81,6 @@ public class LDAPIdentityStoreRegistry {
|
|||
}
|
||||
}
|
||||
|
||||
// Parse array of strings like [ "inetOrgPerson", "organizationalPerson" ] from the string like: "inetOrgPerson, organizationalPerson"
|
||||
/*private static String[] getUserObjectClasses(Map<String,String> ldapConfig) {
|
||||
String objClassesCfg = ldapConfig.get(LDAPConstants.USER_OBJECT_CLASSES);
|
||||
String objClassesStr = (objClassesCfg != null && objClassesCfg.length() > 0) ? objClassesCfg.trim() : "inetOrgPerson, organizationalPerson";
|
||||
|
||||
String[] addObjectClasses = objClassesStr.split(",");
|
||||
|
||||
// Trim them
|
||||
String[] userObjectClasses = new String[addObjectClasses.length];
|
||||
for (int i=0 ; i<addObjectClasses.length ; i++) {
|
||||
userObjectClasses[i] = addObjectClasses[i].trim();
|
||||
}
|
||||
return userObjectClasses;
|
||||
} */
|
||||
|
||||
private class LDAPIdentityStoreContext {
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@ import org.keycloak.models.UserModel;
|
|||
|
||||
/**
|
||||
* Allow to directly call some operations against LDAPIdentityStore.
|
||||
* TODO: Is this class still needed?
|
||||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
|
@ -28,92 +27,24 @@ public class LDAPUtils {
|
|||
* @return newly created LDAPObject with all the attributes, uuid and DN properly set
|
||||
*/
|
||||
public static LDAPObject addUserToLDAP(LDAPFederationProvider ldapProvider, RealmModel realm, UserModel user) {
|
||||
LDAPObject ldapObject = new LDAPObject();
|
||||
LDAPObject ldapUser = new LDAPObject();
|
||||
|
||||
LDAPIdentityStore ldapStore = ldapProvider.getLdapIdentityStore();
|
||||
LDAPConfig ldapConfig = ldapStore.getConfig();
|
||||
ldapObject.setRdnAttributeName(ldapConfig.getRdnLdapAttribute());
|
||||
ldapObject.setObjectClasses(ldapConfig.getObjectClasses());
|
||||
ldapUser.setRdnAttributeName(ldapConfig.getRdnLdapAttribute());
|
||||
ldapUser.setObjectClasses(ldapConfig.getUserObjectClasses());
|
||||
|
||||
Set<UserFederationMapperModel> federationMappers = realm.getUserFederationMappers();
|
||||
for (UserFederationMapperModel mapperModel : federationMappers) {
|
||||
LDAPFederationMapper ldapMapper = ldapProvider.getMapper(mapperModel);
|
||||
ldapMapper.onRegisterUserToLDAP(mapperModel, ldapProvider, ldapObject, user, realm);
|
||||
ldapMapper.onRegisterUserToLDAP(mapperModel, ldapProvider, ldapUser, user, realm);
|
||||
}
|
||||
|
||||
LDAPUtils.computeAndSetDn(ldapConfig, ldapObject);
|
||||
ldapStore.add(ldapObject);
|
||||
return ldapObject;
|
||||
}
|
||||
|
||||
/*public static LDAPUser updateUser(LDAPIdentityStore ldapIdentityStore, String username, String firstName, String lastName, String email) {
|
||||
LDAPUser ldapUser = getUser(ldapIdentityStore, username);
|
||||
ldapUser.setFirstName(firstName);
|
||||
ldapUser.setLastName(lastName);
|
||||
ldapUser.setEmail(email);
|
||||
ldapIdentityStore.update(ldapUser);
|
||||
LDAPUtils.computeAndSetDn(ldapConfig, ldapUser);
|
||||
ldapStore.add(ldapUser);
|
||||
return ldapUser;
|
||||
}
|
||||
|
||||
public static void updatePassword(LDAPIdentityStore ldapIdentityStore, UserModel user, String password) {
|
||||
LDAPUser ldapUser = convertUserForPasswordUpdate(user);
|
||||
|
||||
ldapIdentityStore.updatePassword(ldapUser, password);
|
||||
}
|
||||
|
||||
public static void updatePassword(LDAPIdentityStore ldapIdentityStore, LDAPUser user, String password) {
|
||||
ldapIdentityStore.updatePassword(user, password);
|
||||
}
|
||||
|
||||
public static boolean validatePassword(LDAPIdentityStore ldapIdentityStore, UserModel user, String password) {
|
||||
LDAPUser ldapUser = convertUserForPasswordUpdate(user);
|
||||
|
||||
return ldapIdentityStore.validatePassword(ldapUser, password);
|
||||
}
|
||||
|
||||
public static boolean validatePassword(LDAPIdentityStore ldapIdentityStore, LDAPUser user, String password) {
|
||||
return ldapIdentityStore.validatePassword(user, password);
|
||||
}
|
||||
|
||||
public static LDAPUser getUser(LDAPIdentityStore ldapIdentityStore, String username) {
|
||||
return ldapIdentityStore.getUser(username);
|
||||
}
|
||||
|
||||
// Put just username and entryDN as these are needed by LDAPIdentityStore for passwordUpdate
|
||||
private static LDAPUser convertUserForPasswordUpdate(UserModel kcUser) {
|
||||
LDAPUser ldapUser = new LDAPUser(kcUser.getUsername());
|
||||
String ldapEntryDN = kcUser.getAttribute(LDAPConstants.LDAP_ENTRY_DN);
|
||||
if (ldapEntryDN != null) {
|
||||
ldapUser.setEntryDN(ldapEntryDN);
|
||||
}
|
||||
return ldapUser;
|
||||
}
|
||||
|
||||
|
||||
public static LDAPUser getUserByEmail(LDAPIdentityStore ldapIdentityStore, String email) {
|
||||
IdentityQueryBuilder queryBuilder = ldapIdentityStore.createQueryBuilder();
|
||||
LDAPIdentityQuery<LDAPUser> query = queryBuilder.createIdentityQuery(LDAPUser.class)
|
||||
.where(queryBuilder.equal(LDAPUser.EMAIL, email));
|
||||
List<LDAPUser> users = query.getResultList();
|
||||
|
||||
if (users.isEmpty()) {
|
||||
return null;
|
||||
} else if (users.size() == 1) {
|
||||
return users.get(0);
|
||||
} else {
|
||||
throw new ModelDuplicateException("Error - multiple users found with same email " + email);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean removeUser(LDAPIdentityStore ldapIdentityStore, String username) {
|
||||
LDAPUser ldapUser = getUser(ldapIdentityStore, username);
|
||||
if (ldapUser == null) {
|
||||
return false;
|
||||
}
|
||||
ldapIdentityStore.remove(ldapUser);
|
||||
return true;
|
||||
} */
|
||||
|
||||
public static void removeAllUsers(LDAPFederationProvider ldapProvider, RealmModel realm) {
|
||||
LDAPIdentityStore ldapStore = ldapProvider.getLdapIdentityStore();
|
||||
LDAPIdentityQuery ldapQuery = LDAPUtils.createQueryForUserSearch(ldapProvider, realm);
|
||||
|
@ -129,7 +60,7 @@ public class LDAPUtils {
|
|||
LDAPConfig config = ldapProvider.getLdapIdentityStore().getConfig();
|
||||
ldapQuery.setSearchScope(config.getSearchScope());
|
||||
ldapQuery.addSearchDns(config.getUserDns());
|
||||
ldapQuery.addObjectClasses(config.getObjectClasses());
|
||||
ldapQuery.addObjectClasses(config.getUserObjectClasses());
|
||||
|
||||
Set<UserFederationMapperModel> mapperModels = realm.getUserFederationMappers();
|
||||
ldapQuery.addMappers(mapperModels);
|
||||
|
@ -137,31 +68,6 @@ public class LDAPUtils {
|
|||
return ldapQuery;
|
||||
}
|
||||
|
||||
/*
|
||||
public static List<LDAPUser> getAllUsers(LDAPIdentityStore ldapIdentityStore) {
|
||||
LDAPIdentityQuery<LDAPUser> userQuery = ldapIdentityStore.createQueryBuilder().createIdentityQuery(LDAPUser.class);
|
||||
return userQuery.getResultList();
|
||||
}
|
||||
|
||||
// Needed for ActiveDirectory updates
|
||||
private static String getFullName(String username, String firstName, String lastName) {
|
||||
String fullName;
|
||||
if (firstName != null && lastName != null) {
|
||||
fullName = firstName + " " + lastName;
|
||||
} else if (firstName != null && firstName.trim().length() > 0) {
|
||||
fullName = firstName;
|
||||
} else {
|
||||
fullName = lastName;
|
||||
}
|
||||
|
||||
// Fallback to loginName
|
||||
if (fullName == null || fullName.trim().length() == 0) {
|
||||
fullName = username;
|
||||
}
|
||||
|
||||
return fullName;
|
||||
} */
|
||||
|
||||
// ldapUser has filled attributes, but doesn't have filled dn
|
||||
public static void computeAndSetDn(LDAPConfig config, LDAPObject ldapObject) {
|
||||
String rdnLdapAttrName = config.getRdnLdapAttribute();
|
||||
|
|
|
@ -50,6 +50,7 @@ public class LDAPConstants {
|
|||
public static final String GIVENNAME = "givenname";
|
||||
public static final String CN = "cn";
|
||||
public static final String SN = "sn";
|
||||
public static final String SAM_ACCOUNT_NAME = "sAMAccountName";
|
||||
public static final String EMAIL = "mail";
|
||||
public static final String POSTAL_CODE = "postalCode";
|
||||
public static final String MEMBER = "member";
|
||||
|
|
|
@ -24,6 +24,11 @@ public interface RealmModel extends RoleContainerModel {
|
|||
ClientModel getCreatedClient();
|
||||
}
|
||||
|
||||
interface UserFederationProviderCreationEvent extends ProviderEvent {
|
||||
UserFederationProviderModel getCreatedFederationProvider();
|
||||
RealmModel getRealm();
|
||||
}
|
||||
|
||||
String getId();
|
||||
|
||||
String getName();
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package org.keycloak.models;
|
||||
|
||||
import org.keycloak.provider.ProviderEvent;
|
||||
import org.keycloak.provider.ProviderEventListener;
|
||||
|
||||
/**
|
||||
* Provides "onProviderModelCreated" callback invoked when UserFederationProviderModel for this factory implementation is created in realm
|
||||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public abstract class UserFederationEventAwareProviderFactory implements UserFederationProviderFactory {
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
factory.register(new ProviderEventListener() {
|
||||
|
||||
@Override
|
||||
public void onEvent(ProviderEvent event) {
|
||||
if (event instanceof RealmModel.UserFederationProviderCreationEvent) {
|
||||
RealmModel.UserFederationProviderCreationEvent fedCreationEvent = (RealmModel.UserFederationProviderCreationEvent)event;
|
||||
UserFederationProviderModel providerModel = fedCreationEvent.getCreatedFederationProvider();
|
||||
|
||||
if (providerModel.getProviderName().equals(getId())) {
|
||||
onProviderModelCreated(fedCreationEvent.getRealm(), providerModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
protected abstract void onProviderModelCreated(RealmModel realm, UserFederationProviderModel createdProviderModel);
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package org.keycloak.models;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class UserFederationProviderCreationEventImpl implements RealmModel.UserFederationProviderCreationEvent {
|
||||
|
||||
private final UserFederationProviderModel createdFederationProvider;
|
||||
private final RealmModel realm;
|
||||
|
||||
public UserFederationProviderCreationEventImpl(RealmModel realm, UserFederationProviderModel createdFederationProvider) {
|
||||
this.realm = realm;
|
||||
this.createdFederationProvider = createdFederationProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserFederationProviderModel getCreatedFederationProvider() {
|
||||
return createdFederationProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RealmModel getRealm() {
|
||||
return realm;
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@ public class UserFederationProviderModel {
|
|||
private int changedSyncPeriod = -1; // In seconds. -1 means that periodic changed sync is disabled
|
||||
private int lastSync; // Date when last sync was done for this provider
|
||||
|
||||
public UserFederationProviderModel() {};
|
||||
public UserFederationProviderModel() {}
|
||||
|
||||
public UserFederationProviderModel(String id, String providerName, Map<String, String> config, int priority, String displayName, int fullSyncPeriod, int changedSyncPeriod, int lastSync) {
|
||||
this.id = id;
|
||||
|
@ -39,6 +39,10 @@ public class UserFederationProviderModel {
|
|||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getProviderName() {
|
||||
return providerName;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.keycloak.models.ModelDuplicateException;
|
|||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserFederationMapperModel;
|
||||
import org.keycloak.models.UserFederationProvider;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
|
@ -26,8 +27,10 @@ import java.security.NoSuchAlgorithmException;
|
|||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -273,6 +276,8 @@ public final class KeycloakModelUtils {
|
|||
return false;
|
||||
}
|
||||
|
||||
// USER FEDERATION RELATED STUFF
|
||||
|
||||
/**
|
||||
* Ensure that displayName of myProvider (if not null) is unique and there is no other provider with same displayName in the list.
|
||||
*
|
||||
|
@ -296,6 +301,7 @@ public final class KeycloakModelUtils {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public static UserFederationProviderModel findUserFederationProviderByDisplayName(String displayName, RealmModel realm) {
|
||||
if (displayName == null) {
|
||||
return null;
|
||||
|
@ -309,6 +315,7 @@ public final class KeycloakModelUtils {
|
|||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static UserFederationProviderModel findUserFederationProviderById(String fedProviderId, RealmModel realm) {
|
||||
for (UserFederationProviderModel fedProvider : realm.getUserFederationProviders()) {
|
||||
if (fedProviderId.equals(fedProvider.getId())) {
|
||||
|
@ -317,4 +324,29 @@ public final class KeycloakModelUtils {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static UserFederationMapperModel createUserFederationMapperModel(String name, String federationProviderId, String mapperType, String... config) {
|
||||
UserFederationMapperModel mapperModel = new UserFederationMapperModel();
|
||||
mapperModel.setName(name);
|
||||
mapperModel.setFederationProviderId(federationProviderId);
|
||||
mapperModel.setFederationMapperType(mapperType);
|
||||
|
||||
Map<String, String> configMap = new HashMap<String, String>();
|
||||
String key = null;
|
||||
for (String configEntry : config) {
|
||||
if (key == null) {
|
||||
key = configEntry;
|
||||
} else {
|
||||
configMap.put(key, configEntry);
|
||||
key = null;
|
||||
}
|
||||
}
|
||||
if (key != null) {
|
||||
throw new IllegalStateException("Invalid count of arguments for config. Maybe mistake?");
|
||||
}
|
||||
mapperModel.setConfig(configMap);
|
||||
|
||||
return mapperModel;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import org.keycloak.models.UserFederationMapperModel;
|
|||
import org.keycloak.models.UserFederationProviderModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UserSessionModel;
|
||||
|
||||
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.representations.idm.FederatedIdentityRepresentation;
|
||||
|
@ -307,7 +307,7 @@ public class ModelToRepresentation {
|
|||
config.putAll(model.getConfig());
|
||||
rep.setConfig(config);
|
||||
|
||||
UserFederationProviderModel fedProvider = KeycloakModelUtils.findUserFederationProviderById(model.getId(), realm);
|
||||
UserFederationProviderModel fedProvider = KeycloakModelUtils.findUserFederationProviderById(model.getFederationProviderId(), realm);
|
||||
if (fedProvider == null) {
|
||||
throw new ModelException("Couldn't find federation provider with ID " + model.getId());
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ import java.util.LinkedList;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
public class RepresentationToModel {
|
||||
|
||||
|
@ -239,11 +240,31 @@ public class RepresentationToModel {
|
|||
newRealm.setBrowserSecurityHeaders(BrowserSecurityHeaders.defaultHeaders);
|
||||
}
|
||||
|
||||
List<UserFederationProviderModel> providerModels = null;
|
||||
if (rep.getUserFederationProviders() != null) {
|
||||
List<UserFederationProviderModel> providerModels = convertFederationProviders(rep.getUserFederationProviders());
|
||||
providerModels = convertFederationProviders(rep.getUserFederationProviders());
|
||||
newRealm.setUserFederationProviders(providerModels);
|
||||
}
|
||||
if (rep.getUserFederationMappers() != null) {
|
||||
|
||||
// Remove builtin mappers for federation providers, which have some mappers already provided in JSON (likely due to previous export)
|
||||
if (rep.getUserFederationProviders() != null) {
|
||||
Set<String> providerNames = new TreeSet<String>();
|
||||
for (UserFederationMapperRepresentation representation : rep.getUserFederationMappers()) {
|
||||
providerNames.add(representation.getFederationProviderDisplayName());
|
||||
}
|
||||
for (String providerName : providerNames) {
|
||||
for (UserFederationProviderModel providerModel : providerModels) {
|
||||
if (providerName.equals(providerModel.getDisplayName())) {
|
||||
Set<UserFederationMapperModel> toDelete = newRealm.getUserFederationMappersByFederationProvider(providerModel.getId());
|
||||
for (UserFederationMapperModel mapperModel : toDelete) {
|
||||
newRealm.removeUserFederationMapper(mapperModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (UserFederationMapperRepresentation representation : rep.getUserFederationMappers()) {
|
||||
newRealm.addUserFederationMapper(toModel(newRealm, representation));
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.keycloak.models.RealmModel;
|
|||
import org.keycloak.models.RequiredCredentialModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserFederationMapperModel;
|
||||
import org.keycloak.models.UserFederationProviderCreationEventImpl;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.entities.ClientEntity;
|
||||
|
@ -829,7 +830,9 @@ public class RealmAdapter implements RealmModel {
|
|||
entity.setLastSync(lastSync);
|
||||
realm.getUserFederationProviders().add(entity);
|
||||
|
||||
return new UserFederationProviderModel(entity.getId(), providerName, config, priority, displayName, fullSyncPeriod, changedSyncPeriod, lastSync);
|
||||
UserFederationProviderModel providerModel = new UserFederationProviderModel(entity.getId(), providerName, config, priority, displayName, fullSyncPeriod, changedSyncPeriod, lastSync);
|
||||
session.getKeycloakSessionFactory().publish(new UserFederationProviderCreationEventImpl(this, providerModel));
|
||||
return providerModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -907,8 +910,13 @@ public class RealmAdapter implements RealmModel {
|
|||
List<UserFederationProviderEntity> entities = new LinkedList<UserFederationProviderEntity>();
|
||||
for (UserFederationProviderModel model : providers) {
|
||||
UserFederationProviderEntity entity = new UserFederationProviderEntity();
|
||||
if (model.getId() != null) entity.setId(model.getId());
|
||||
else entity.setId(KeycloakModelUtils.generateId());
|
||||
if (model.getId() != null) {
|
||||
entity.setId(model.getId());
|
||||
} else {
|
||||
String id = KeycloakModelUtils.generateId();
|
||||
entity.setId(id);
|
||||
model.setId(id);
|
||||
}
|
||||
entity.setProviderName(model.getProviderName());
|
||||
entity.setConfig(model.getConfig());
|
||||
entity.setPriority(model.getPriority());
|
||||
|
@ -921,6 +929,7 @@ public class RealmAdapter implements RealmModel {
|
|||
entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
|
||||
entity.setLastSync(model.getLastSync());
|
||||
entities.add(entity);
|
||||
session.getKeycloakSessionFactory().publish(new UserFederationProviderCreationEventImpl(this, model));
|
||||
}
|
||||
|
||||
realm.setUserFederationProviders(entities);
|
||||
|
@ -1205,7 +1214,7 @@ public class RealmAdapter implements RealmModel {
|
|||
@Override
|
||||
public UserFederationMapperModel addUserFederationMapper(UserFederationMapperModel model) {
|
||||
if (getUserFederationMapperByName(model.getFederationProviderId(), model.getName()) != null) {
|
||||
throw new ModelDuplicateException("User federation mapper must be unique per federation provider");
|
||||
throw new ModelDuplicateException("User federation mapper must be unique per federation provider. There is already: " + model.getName());
|
||||
}
|
||||
String id = KeycloakModelUtils.generateId();
|
||||
UserFederationMapperEntity entity = new UserFederationMapperEntity();
|
||||
|
|
|
@ -6,13 +6,12 @@ import org.keycloak.models.IdentityProviderMapperModel;
|
|||
import org.keycloak.models.IdentityProviderModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.ModelDuplicateException;
|
||||
import org.keycloak.models.ModelException;
|
||||
import org.keycloak.models.PasswordPolicy;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RequiredCredentialModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserFederationMapperModel;
|
||||
import org.keycloak.models.UserFederationProvider;
|
||||
import org.keycloak.models.UserFederationProviderCreationEventImpl;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
import org.keycloak.models.jpa.entities.ClientEntity;
|
||||
import org.keycloak.models.jpa.entities.IdentityProviderEntity;
|
||||
|
@ -783,7 +782,9 @@ public class RealmAdapter implements RealmModel {
|
|||
em.persist(entity);
|
||||
realm.getUserFederationProviders().add(entity);
|
||||
em.flush();
|
||||
return new UserFederationProviderModel(entity.getId(), providerName, config, priority, displayName, fullSyncPeriod, changedSyncPeriod, lastSync);
|
||||
UserFederationProviderModel providerModel = new UserFederationProviderModel(entity.getId(), providerName, config, priority, displayName, fullSyncPeriod, changedSyncPeriod, lastSync);
|
||||
session.getKeycloakSessionFactory().publish(new UserFederationProviderCreationEventImpl(this, providerModel));
|
||||
return providerModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -879,8 +880,13 @@ public class RealmAdapter implements RealmModel {
|
|||
|
||||
for (UserFederationProviderModel model : add) {
|
||||
UserFederationProviderEntity entity = new UserFederationProviderEntity();
|
||||
if (model.getId() != null) entity.setId(model.getId());
|
||||
else entity.setId(KeycloakModelUtils.generateId());
|
||||
if (model.getId() != null) {
|
||||
entity.setId(model.getId());
|
||||
} else {
|
||||
String id = KeycloakModelUtils.generateId();
|
||||
entity.setId(id);
|
||||
model.setId(id);
|
||||
}
|
||||
entity.setConfig(model.getConfig());
|
||||
entity.setPriority(model.getPriority());
|
||||
entity.setProviderName(model.getProviderName());
|
||||
|
@ -895,7 +901,7 @@ public class RealmAdapter implements RealmModel {
|
|||
entity.setLastSync(model.getLastSync());
|
||||
em.persist(entity);
|
||||
realm.getUserFederationProviders().add(entity);
|
||||
|
||||
session.getKeycloakSessionFactory().publish(new UserFederationProviderCreationEventImpl(this, model));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1385,7 +1391,7 @@ public class RealmAdapter implements RealmModel {
|
|||
@Override
|
||||
public UserFederationMapperModel addUserFederationMapper(UserFederationMapperModel model) {
|
||||
if (getUserFederationMapperByName(model.getFederationProviderId(), model.getName()) != null) {
|
||||
throw new ModelDuplicateException("User federation mapper must be unique per federation provider");
|
||||
throw new ModelDuplicateException("User federation mapper must be unique per federation provider. There is already: " + model.getName());
|
||||
}
|
||||
String id = KeycloakModelUtils.generateId();
|
||||
UserFederationMapperEntity entity = new UserFederationMapperEntity();
|
||||
|
|
|
@ -16,6 +16,7 @@ import org.keycloak.models.RealmProvider;
|
|||
import org.keycloak.models.RequiredCredentialModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserFederationMapperModel;
|
||||
import org.keycloak.models.UserFederationProviderCreationEventImpl;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
import org.keycloak.models.entities.IdentityProviderEntity;
|
||||
import org.keycloak.models.entities.IdentityProviderMapperEntity;
|
||||
|
@ -852,7 +853,9 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
|
|||
realm.getUserFederationProviders().add(entity);
|
||||
updateRealm();
|
||||
|
||||
return new UserFederationProviderModel(entity.getId(), providerName, config, priority, displayName, fullSyncPeriod, changedSyncPeriod, lastSync);
|
||||
UserFederationProviderModel providerModel = new UserFederationProviderModel(entity.getId(), providerName, config, priority, displayName, fullSyncPeriod, changedSyncPeriod, lastSync);
|
||||
session.getKeycloakSessionFactory().publish(new UserFederationProviderCreationEventImpl(this, providerModel));
|
||||
return providerModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -932,8 +935,13 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
|
|||
List<UserFederationProviderEntity> entities = new LinkedList<UserFederationProviderEntity>();
|
||||
for (UserFederationProviderModel model : providers) {
|
||||
UserFederationProviderEntity entity = new UserFederationProviderEntity();
|
||||
if (model.getId() != null) entity.setId(model.getId());
|
||||
else entity.setId(KeycloakModelUtils.generateId());
|
||||
if (model.getId() != null) {
|
||||
entity.setId(model.getId());
|
||||
} else {
|
||||
String id = KeycloakModelUtils.generateId();
|
||||
entity.setId(id);
|
||||
model.setId(id);
|
||||
}
|
||||
entity.setProviderName(model.getProviderName());
|
||||
entity.setConfig(model.getConfig());
|
||||
entity.setPriority(model.getPriority());
|
||||
|
@ -946,6 +954,7 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
|
|||
entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
|
||||
entity.setLastSync(model.getLastSync());
|
||||
entities.add(entity);
|
||||
session.getKeycloakSessionFactory().publish(new UserFederationProviderCreationEventImpl(this, model));
|
||||
}
|
||||
|
||||
realm.setUserFederationProviders(entities);
|
||||
|
@ -1236,7 +1245,7 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
|
|||
@Override
|
||||
public UserFederationMapperModel addUserFederationMapper(UserFederationMapperModel model) {
|
||||
if (getUserFederationMapperByName(model.getFederationProviderId(), model.getName()) != null) {
|
||||
throw new ModelDuplicateException("User federation mapper must be unique per federation provider");
|
||||
throw new ModelDuplicateException("User federation mapper must be unique per federation provider. There is already: " + model.getName());
|
||||
}
|
||||
String id = KeycloakModelUtils.generateId();
|
||||
UserFederationMapperEntity entity = new UserFederationMapperEntity();
|
||||
|
|
|
@ -23,8 +23,6 @@ import org.keycloak.models.UserCredentialValueModel;
|
|||
import org.keycloak.models.UserFederationProvider;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.utils.UserModelDelegate;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.testsuite.OAuthClient;
|
||||
import org.keycloak.testsuite.pages.AccountPasswordPage;
|
||||
|
@ -61,6 +59,7 @@ public class FederationProvidersIntegrationTest {
|
|||
ldapConfig.put(LDAPConstants.EDIT_MODE, UserFederationProvider.EditMode.WRITABLE.toString());
|
||||
|
||||
ldapModel = appRealm.addUserFederationProvider(LDAPFederationProviderFactory.PROVIDER_NAME, ldapConfig, 0, "test-ldap", -1, -1, 0);
|
||||
FederationTestUtils.addZipCodeLDAPMapper(appRealm, ldapModel);
|
||||
|
||||
// Delete all LDAP users and add some new for testing
|
||||
LDAPFederationProvider ldapFedProvider = FederationTestUtils.getLdapProvider(session, ldapModel);
|
||||
|
@ -150,6 +149,7 @@ public class FederationProvidersIntegrationTest {
|
|||
|
||||
RealmModel appRealm = manager.getRealm("test");
|
||||
ldapModel = appRealm.addUserFederationProvider(ldapModel.getProviderName(), ldapModel.getConfig(), ldapModel.getPriority(), ldapModel.getDisplayName(), -1, -1, 0);
|
||||
FederationTestUtils.addZipCodeLDAPMapper(appRealm, ldapModel);
|
||||
} finally {
|
||||
keycloakRule.stopSession(session, true);
|
||||
}
|
||||
|
|
|
@ -5,13 +5,20 @@ import org.keycloak.federation.ldap.LDAPFederationProvider;
|
|||
import org.keycloak.federation.ldap.LDAPFederationProviderFactory;
|
||||
import org.keycloak.federation.ldap.LDAPUtils;
|
||||
import org.keycloak.federation.ldap.idm.model.LDAPObject;
|
||||
import org.keycloak.federation.ldap.mappers.RoleLDAPFederationMapper;
|
||||
import org.keycloak.federation.ldap.mappers.RoleLDAPFederationMapperFactory;
|
||||
import org.keycloak.federation.ldap.mappers.UserAttributeLDAPFederationMapper;
|
||||
import org.keycloak.federation.ldap.mappers.UserAttributeLDAPFederationMapperFactory;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.LDAPConstants;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserFederationMapperModel;
|
||||
import org.keycloak.models.UserFederationProvider;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UserProvider;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.models.utils.UserModelDelegate;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
|
||||
|
@ -59,7 +66,7 @@ class FederationTestUtils {
|
|||
|
||||
@Override
|
||||
public String getAttribute(String name) {
|
||||
if (name == "postal_code") {
|
||||
if ("postal_code".equals(name)) {
|
||||
return postalCode;
|
||||
} else {
|
||||
return null;
|
||||
|
@ -82,4 +89,39 @@ class FederationTestUtils {
|
|||
Assert.assertEquals(expectedEmail, user.getEmail());
|
||||
Assert.assertEquals(expectedPostalCode, user.getAttribute("postal_code"));
|
||||
}
|
||||
|
||||
public static void addZipCodeLDAPMapper(RealmModel realm, UserFederationProviderModel providerModel) {
|
||||
UserFederationMapperModel mapperModel = KeycloakModelUtils.createUserFederationMapperModel("zipCodeMapper", providerModel.getId(), UserAttributeLDAPFederationMapperFactory.ID,
|
||||
UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, "postal_code",
|
||||
UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, LDAPConstants.POSTAL_CODE,
|
||||
UserAttributeLDAPFederationMapper.READ_ONLY, "false");
|
||||
realm.addUserFederationMapper(mapperModel);
|
||||
}
|
||||
|
||||
public static void addOrUpdateRoleLDAPMappers(RealmModel realm, UserFederationProviderModel providerModel, RoleLDAPFederationMapper.Mode mode) {
|
||||
UserFederationMapperModel mapperModel = realm.getUserFederationMapperByName(providerModel.getId(), "realmRolesMapper");
|
||||
if (mapperModel != null) {
|
||||
mapperModel.getConfig().put(RoleLDAPFederationMapper.MODE, mode.toString());
|
||||
realm.updateUserFederationMapper(mapperModel);
|
||||
} else {
|
||||
mapperModel = KeycloakModelUtils.createUserFederationMapperModel("realmRolesMapper", providerModel.getId(), RoleLDAPFederationMapperFactory.ID,
|
||||
RoleLDAPFederationMapper.ROLES_DN, "ou=RealmRoles,dc=keycloak,dc=org",
|
||||
RoleLDAPFederationMapper.USE_REALM_ROLES_MAPPING, "true",
|
||||
RoleLDAPFederationMapper.MODE, mode.toString());
|
||||
realm.addUserFederationMapper(mapperModel);
|
||||
}
|
||||
|
||||
mapperModel = realm.getUserFederationMapperByName(providerModel.getId(), "financeRolesMapper");
|
||||
if (mapperModel != null) {
|
||||
mapperModel.getConfig().put(RoleLDAPFederationMapper.MODE, mode.toString());
|
||||
realm.updateUserFederationMapper(mapperModel);
|
||||
} else {
|
||||
mapperModel = KeycloakModelUtils.createUserFederationMapperModel("financeRolesMapper", providerModel.getId(), RoleLDAPFederationMapperFactory.ID,
|
||||
RoleLDAPFederationMapper.ROLES_DN, "ou=FinanceRoles,dc=keycloak,dc=org",
|
||||
RoleLDAPFederationMapper.USE_REALM_ROLES_MAPPING, "false",
|
||||
RoleLDAPFederationMapper.CLIENT_ID, "finance",
|
||||
RoleLDAPFederationMapper.MODE, mode.toString());
|
||||
realm.addUserFederationMapper(mapperModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package org.keycloak.testsuite.federation;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -33,7 +32,6 @@ import org.keycloak.models.UserFederationMapperModel;
|
|||
import org.keycloak.models.UserFederationProvider;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.cache.RealmAdapter;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.testsuite.OAuthClient;
|
||||
import org.keycloak.testsuite.pages.AccountPasswordPage;
|
||||
|
@ -96,7 +94,9 @@ public class LDAPRoleMappingsTest {
|
|||
@Override
|
||||
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
|
||||
RoleLDAPFederationMapper roleMapper = new RoleLDAPFederationMapper();
|
||||
UserFederationMapperModel roleMapperModel = findRoleMapperModel(appRealm);
|
||||
|
||||
FederationTestUtils.addOrUpdateRoleLDAPMappers(appRealm, ldapModel, RoleLDAPFederationMapper.Mode.LDAP_ONLY);
|
||||
UserFederationMapperModel roleMapperModel = appRealm.getUserFederationMapperByName(ldapModel.getId(), "realmRolesMapper");
|
||||
LDAPFederationProvider ldapProvider = FederationTestUtils.getLdapProvider(session, ldapModel);
|
||||
|
||||
LDAPObject ldapRole = roleMapper.loadLDAPRoleByName(roleMapperModel, ldapProvider, "realmRole3");
|
||||
|
@ -129,26 +129,17 @@ public class LDAPRoleMappingsTest {
|
|||
@WebResource
|
||||
protected AppPage appPage;
|
||||
|
||||
@WebResource
|
||||
protected RegisterPage registerPage;
|
||||
|
||||
@WebResource
|
||||
protected LoginPage loginPage;
|
||||
|
||||
@WebResource
|
||||
protected AccountUpdateProfilePage profilePage;
|
||||
|
||||
@WebResource
|
||||
protected AccountPasswordPage changePasswordPage;
|
||||
|
||||
@Test
|
||||
public void test01_ldapOnlyRoleMappings() {
|
||||
// TODO: Remove me!!!
|
||||
//RealmAdapter.LDAP_MODE = "LDAP_ONLY";
|
||||
|
||||
KeycloakSession session = keycloakRule.startSession();
|
||||
try {
|
||||
RealmModel appRealm = session.realms().getRealmByName("test");
|
||||
|
||||
FederationTestUtils.addOrUpdateRoleLDAPMappers(appRealm, ldapModel, RoleLDAPFederationMapper.Mode.LDAP_ONLY);
|
||||
|
||||
UserModel john = session.users().getUserByUsername("johnkeycloak", appRealm);
|
||||
UserModel mary = session.users().getUserByUsername("marykeycloak", appRealm);
|
||||
|
||||
|
@ -230,12 +221,12 @@ public class LDAPRoleMappingsTest {
|
|||
|
||||
@Test
|
||||
public void test02_readOnlyRoleMappings() {
|
||||
// TODO: Remove me!!!
|
||||
//RealmAdapter.LDAP_MODE = "READ_ONLY";
|
||||
|
||||
KeycloakSession session = keycloakRule.startSession();
|
||||
try {
|
||||
RealmModel appRealm = session.realms().getRealmByName("test");
|
||||
|
||||
FederationTestUtils.addOrUpdateRoleLDAPMappers(appRealm, ldapModel, RoleLDAPFederationMapper.Mode.READ_ONLY);
|
||||
|
||||
UserModel mary = session.users().getUserByUsername("marykeycloak", appRealm);
|
||||
|
||||
RoleModel realmRole1 = appRealm.getRole("realmRole1");
|
||||
|
@ -247,7 +238,7 @@ public class LDAPRoleMappingsTest {
|
|||
|
||||
// Add some role mappings directly into LDAP
|
||||
RoleLDAPFederationMapper roleMapper = new RoleLDAPFederationMapper();
|
||||
UserFederationMapperModel roleMapperModel = findRoleMapperModel(appRealm);
|
||||
UserFederationMapperModel roleMapperModel = appRealm.getUserFederationMapperByName(ldapModel.getId(), "realmRolesMapper");
|
||||
LDAPFederationProvider ldapProvider = FederationTestUtils.getLdapProvider(session, ldapModel);
|
||||
LDAPObject maryLdap = ldapProvider.loadLDAPUserByUsername(appRealm, "marykeycloak");
|
||||
roleMapper.addRoleMappingInLDAP(roleMapperModel, "realmRole1", ldapProvider, maryLdap);
|
||||
|
@ -292,16 +283,15 @@ public class LDAPRoleMappingsTest {
|
|||
|
||||
@Test
|
||||
public void test03_importRoleMappings() {
|
||||
// TODO: Remove me!!!
|
||||
//RealmAdapter.LDAP_MODE = "IMPORT";
|
||||
|
||||
KeycloakSession session = keycloakRule.startSession();
|
||||
try {
|
||||
RealmModel appRealm = session.realms().getRealmByName("test");
|
||||
|
||||
FederationTestUtils.addOrUpdateRoleLDAPMappers(appRealm, ldapModel, RoleLDAPFederationMapper.Mode.IMPORT);
|
||||
|
||||
// Add some role mappings directly in LDAP
|
||||
RoleLDAPFederationMapper roleMapper = new RoleLDAPFederationMapper();
|
||||
UserFederationMapperModel roleMapperModel = findRoleMapperModel(appRealm);
|
||||
UserFederationMapperModel roleMapperModel = appRealm.getUserFederationMapperByName(ldapModel.getId(), "realmRolesMapper");
|
||||
LDAPFederationProvider ldapProvider = FederationTestUtils.getLdapProvider(session, ldapModel);
|
||||
LDAPObject robLdap = ldapProvider.loadLDAPUserByUsername(appRealm, "robkeycloak");
|
||||
roleMapper.addRoleMappingInLDAP(roleMapperModel, "realmRole1", ldapProvider, robLdap);
|
||||
|
@ -345,17 +335,6 @@ public class LDAPRoleMappingsTest {
|
|||
}
|
||||
}
|
||||
|
||||
private static UserFederationMapperModel findRoleMapperModel(RealmModel appRealm) {
|
||||
Set<UserFederationMapperModel> fedMappers = appRealm.getUserFederationMappers();
|
||||
for (UserFederationMapperModel mapper : fedMappers) {
|
||||
if ("realmRoleMapper".equals(mapper.getName())) {
|
||||
return mapper;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Mapper 'realmRoleMapper' not found");
|
||||
}
|
||||
|
||||
private void deleteRoleMappingsInLDAP(UserFederationMapperModel roleMapperModel, RoleLDAPFederationMapper roleMapper, LDAPFederationProvider ldapProvider, LDAPObject ldapUser, String roleName) {
|
||||
LDAPIdentityQuery ldapQuery = roleMapper.createRoleQuery(roleMapperModel, ldapProvider);
|
||||
LDAPQueryConditionsBuilder conditionsBuilder = new LDAPQueryConditionsBuilder();
|
||||
|
|
|
@ -19,7 +19,6 @@ import org.keycloak.models.RealmModel;
|
|||
import org.keycloak.models.UserFederationProvider;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
import org.keycloak.models.UserFederationSyncResult;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UserProvider;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.services.managers.UsersSyncManager;
|
||||
|
@ -52,11 +51,13 @@ public class SyncProvidersTest {
|
|||
|
||||
Map<String,String> ldapConfig = ldapRule.getConfig();
|
||||
ldapConfig.put(LDAPConstants.SYNC_REGISTRATIONS, "false");
|
||||
ldapConfig.put(LDAPConstants.EDIT_MODE, UserFederationProvider.EditMode.UNSYNCED.toString());
|
||||
ldapConfig.put(LDAPConstants.EDIT_MODE, UserFederationProvider.EditMode.WRITABLE.toString());
|
||||
|
||||
ldapModel = appRealm.addUserFederationProvider(LDAPFederationProviderFactory.PROVIDER_NAME, ldapConfig, 0, "test-ldap",
|
||||
-1, -1, 0);
|
||||
|
||||
FederationTestUtils.addZipCodeLDAPMapper(appRealm, ldapModel);
|
||||
|
||||
// Delete all LDAP users and add 5 new users for testing
|
||||
LDAPFederationProvider ldapFedProvider = FederationTestUtils.getLdapProvider(session, ldapModel);
|
||||
LDAPUtils.removeAllUsers(ldapFedProvider, appRealm);
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.keycloak.models.Constants;
|
|||
import org.keycloak.models.FederatedIdentityModel;
|
||||
import org.keycloak.models.IdentityProviderModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.LDAPConstants;
|
||||
import org.keycloak.models.ProtocolMapperModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RequiredCredentialModel;
|
||||
|
@ -216,22 +217,32 @@ public class ImportTest extends AbstractModelTest {
|
|||
|
||||
// Test federation providers
|
||||
List<UserFederationProviderModel> fedProviders = realm.getUserFederationProviders();
|
||||
Assert.assertTrue(fedProviders.size() == 1);
|
||||
UserFederationProviderModel ldap = fedProviders.get(0);
|
||||
Assert.assertEquals("MyLDAPProvider", ldap.getDisplayName());
|
||||
Assert.assertEquals("dummy", ldap.getProviderName());
|
||||
Assert.assertEquals(1, ldap.getPriority());
|
||||
Assert.assertEquals("ldap://foo", ldap.getConfig().get("important.config"));
|
||||
Assert.assertTrue(fedProviders.size() == 2);
|
||||
UserFederationProviderModel ldap1 = fedProviders.get(0);
|
||||
Assert.assertEquals("MyLDAPProvider1", ldap1.getDisplayName());
|
||||
Assert.assertEquals("ldap", ldap1.getProviderName());
|
||||
Assert.assertEquals(1, ldap1.getPriority());
|
||||
Assert.assertEquals("ldap://foo", ldap1.getConfig().get(LDAPConstants.CONNECTION_URL));
|
||||
|
||||
UserFederationProviderModel ldap2 = fedProviders.get(1);
|
||||
Assert.assertEquals("MyLDAPProvider2", ldap2.getDisplayName());
|
||||
Assert.assertEquals("ldap://bar", ldap2.getConfig().get(LDAPConstants.CONNECTION_URL));
|
||||
|
||||
// Test federation mappers
|
||||
Set<UserFederationMapperModel> fedMappers = realm.getUserFederationMappers();
|
||||
Assert.assertTrue(fedMappers.size() == 1);
|
||||
UserFederationMapperModel fullNameMapper = fedMappers.iterator().next();
|
||||
Set<UserFederationMapperModel> fedMappers1 = realm.getUserFederationMappersByFederationProvider(ldap1.getId());
|
||||
Assert.assertTrue(fedMappers1.size() == 1);
|
||||
UserFederationMapperModel fullNameMapper = fedMappers1.iterator().next();
|
||||
Assert.assertEquals("FullNameMapper", fullNameMapper.getName());
|
||||
Assert.assertEquals(FullNameLDAPFederationMapperFactory.ID, fullNameMapper.getFederationMapperType());
|
||||
Assert.assertEquals(ldap.getId(), fullNameMapper.getFederationProviderId());
|
||||
Assert.assertEquals(ldap1.getId(), fullNameMapper.getFederationProviderId());
|
||||
Assert.assertEquals("cn", fullNameMapper.getConfig().get(FullNameLDAPFederationMapper.LDAP_FULL_NAME_ATTRIBUTE));
|
||||
|
||||
// All builtin LDAP mappers should be here
|
||||
Set<UserFederationMapperModel> fedMappers2 = realm.getUserFederationMappersByFederationProvider(ldap2.getId());
|
||||
Assert.assertTrue(fedMappers2.size() > 3);
|
||||
Set<UserFederationMapperModel> allMappers = realm.getUserFederationMappers();
|
||||
Assert.assertEquals(allMappers.size(), fedMappers1.size() + fedMappers2.size());
|
||||
|
||||
// Assert that federation link wasn't created during import
|
||||
UserFederationProviderFactory factory = (UserFederationProviderFactory)session.getKeycloakSessionFactory().getProviderFactory(UserFederationProvider.class, "dummy");
|
||||
Assert.assertNull(factory.getInstance(session, null).getUserByUsername(realm, "wburke"));
|
||||
|
|
|
@ -25,18 +25,26 @@
|
|||
],
|
||||
"userFederationProviders": [
|
||||
{
|
||||
"displayName": "MyLDAPProvider",
|
||||
"providerName": "dummy",
|
||||
"displayName": "MyLDAPProvider1",
|
||||
"providerName": "ldap",
|
||||
"priority": 1,
|
||||
"config": {
|
||||
"important.config": "ldap://foo"
|
||||
"connectionUrl": "ldap://foo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"displayName": "MyLDAPProvider2",
|
||||
"providerName": "ldap",
|
||||
"priority": 2,
|
||||
"config": {
|
||||
"connectionUrl": "ldap://bar"
|
||||
}
|
||||
}
|
||||
],
|
||||
"userFederationMappers": [
|
||||
{
|
||||
"name": "FullNameMapper",
|
||||
"federationProviderDisplayName": "MyLDAPProvider",
|
||||
"federationProviderDisplayName": "MyLDAPProvider1",
|
||||
"federationMapperType": "full-name-ldap-mapper",
|
||||
"config": {
|
||||
"ldap.full.name.attribute": "cn"
|
||||
|
|
Loading…
Reference in a new issue