Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Bill Burke 2016-12-08 17:05:46 -05:00
commit 4a80f1e913
34 changed files with 213 additions and 309 deletions

View file

@ -63,7 +63,7 @@ public class JWKPublicKeyLocator implements PublicKeyLocator {
sendRequest(deployment); sendRequest(deployment);
lastRequestTime = currentTime; lastRequestTime = currentTime;
} else { } else {
log.debugf("Won't send request to realm jwks url. Last request time was %d", lastRequestTime); log.debug("Won't send request to realm jwks url. Last request time was " + lastRequestTime);
} }
return lookupCachedKey(publicKeyCacheTtl, currentTime, kid); return lookupCachedKey(publicKeyCacheTtl, currentTime, kid);
@ -89,7 +89,7 @@ public class JWKPublicKeyLocator implements PublicKeyLocator {
private void sendRequest(KeycloakDeployment deployment) { private void sendRequest(KeycloakDeployment deployment) {
if (log.isTraceEnabled()) { if (log.isTraceEnabled()) {
log.tracef("Going to send request to retrieve new set of realm public keys for client %s", deployment.getResourceName()); log.trace("Going to send request to retrieve new set of realm public keys for client " + deployment.getResourceName());
} }
HttpGet getMethod = new HttpGet(deployment.getJwksUrl()); HttpGet getMethod = new HttpGet(deployment.getJwksUrl());
@ -99,7 +99,7 @@ public class JWKPublicKeyLocator implements PublicKeyLocator {
Map<String, PublicKey> publicKeys = JWKSUtils.getKeysForUse(jwks, JWK.Use.SIG); Map<String, PublicKey> publicKeys = JWKSUtils.getKeysForUse(jwks, JWK.Use.SIG);
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debugf("Realm public keys successfully retrieved for client %s. New kids: %s", deployment.getResourceName(), publicKeys.keySet().toString()); log.debug("Realm public keys successfully retrieved for client " + deployment.getResourceName() + ". New kids: " + publicKeys.keySet().toString());
} }
// Update current keys // Update current keys

View file

@ -152,7 +152,7 @@ public class LDAPStorageProvider implements UserStorageProvider,
List<ComponentModel> sortedMappers = sortMappersAsc(mappers); List<ComponentModel> sortedMappers = sortMappersAsc(mappers);
for (ComponentModel mapperModel : sortedMappers) { for (ComponentModel mapperModel : sortedMappers) {
LDAPStorageMapper ldapMapper = getMapper(mapperModel); LDAPStorageMapper ldapMapper = getMapper(mapperModel);
proxied = ldapMapper.proxy(mapperModel, this, ldapObject, proxied, realm); proxied = ldapMapper.proxy(ldapObject, proxied, realm);
} }
return proxied; return proxied;
@ -283,7 +283,7 @@ public class LDAPStorageProvider implements UserStorageProvider,
List<ComponentModel> sortedMappers = sortMappersAsc(mappers); List<ComponentModel> sortedMappers = sortMappersAsc(mappers);
for (ComponentModel mapperModel : sortedMappers) { for (ComponentModel mapperModel : sortedMappers) {
LDAPStorageMapper ldapMapper = getMapper(mapperModel); LDAPStorageMapper ldapMapper = getMapper(mapperModel);
List<UserModel> users = ldapMapper.getGroupMembers(mapperModel, this, realm, group, firstResult, maxResults); List<UserModel> users = ldapMapper.getGroupMembers(realm, group, firstResult, maxResults);
// Sufficient for now // Sufficient for now
if (users.size() > 0) { if (users.size() > 0) {
@ -387,7 +387,7 @@ public class LDAPStorageProvider implements UserStorageProvider,
logger.tracef("Using mapper %s during import user from LDAP", mapperModel); logger.tracef("Using mapper %s during import user from LDAP", mapperModel);
} }
LDAPStorageMapper ldapMapper = getMapper(mapperModel); LDAPStorageMapper ldapMapper = getMapper(mapperModel);
ldapMapper.onImportUserFromLDAP(mapperModel, this, ldapUser, imported, realm, true); ldapMapper.onImportUserFromLDAP(ldapUser, imported, realm, true);
} }
String userDN = ldapUser.getDn().toString(); String userDN = ldapUser.getDn().toString();
@ -469,7 +469,7 @@ public class LDAPStorageProvider implements UserStorageProvider,
logger.tracef("Using mapper %s during import user from LDAP", mapperModel); logger.tracef("Using mapper %s during import user from LDAP", mapperModel);
} }
LDAPStorageMapper ldapMapper = getMapper(mapperModel); LDAPStorageMapper ldapMapper = getMapper(mapperModel);
processed = processed || ldapMapper.onAuthenticationFailure(mapperModel, this, ldapUser, user, ae, realm); processed = processed || ldapMapper.onAuthenticationFailure(ldapUser, user, ae, realm);
} }
return processed; return processed;
} }

View file

@ -360,12 +360,12 @@ public class LDAPStorageProviderFactory implements UserStorageProviderFactory<LD
@Override @Override
public void run(KeycloakSession session) { public void run(KeycloakSession session) {
LDAPStorageProvider ldapProvider = (LDAPStorageProvider)session.getProvider(UserStorageProvider.class, model);
RealmModel realm = session.realms().getRealm(realmId); RealmModel realm = session.realms().getRealm(realmId);
session.getProvider(UserStorageProvider.class, model);
List<ComponentModel> mappers = realm.getComponents(model.getId(), LDAPStorageMapper.class.getName()); List<ComponentModel> mappers = realm.getComponents(model.getId(), LDAPStorageMapper.class.getName());
for (ComponentModel mapperModel : mappers) { for (ComponentModel mapperModel : mappers) {
LDAPStorageMapper ldapMapper = session.getProvider(LDAPStorageMapper.class, mapperModel); LDAPStorageMapper ldapMapper = session.getProvider(LDAPStorageMapper.class, mapperModel);
SynchronizationResult syncResult = ldapMapper.syncDataFromFederationProviderToKeycloak(mapperModel, ldapProvider, session, realm); SynchronizationResult syncResult = ldapMapper.syncDataFromFederationProviderToKeycloak(realm);
if (syncResult.getAdded() > 0 || syncResult.getUpdated() > 0 || syncResult.getRemoved() > 0 || syncResult.getFailed() > 0) { if (syncResult.getAdded() > 0 || syncResult.getUpdated() > 0 || syncResult.getRemoved() > 0 || syncResult.getFailed() > 0) {
logger.infof("Sync of federation mapper '%s' finished. Status: %s", mapperModel.getName(), syncResult.toString()); logger.infof("Sync of federation mapper '%s' finished. Status: %s", mapperModel.getName(), syncResult.toString());
} }
@ -461,7 +461,7 @@ public class LDAPStorageProviderFactory implements UserStorageProviderFactory<LD
List<ComponentModel> sortedMappers = ldapFedProvider.sortMappersDesc(federationMappers); List<ComponentModel> sortedMappers = ldapFedProvider.sortMappersDesc(federationMappers);
for (ComponentModel mapperModel : sortedMappers) { for (ComponentModel mapperModel : sortedMappers) {
LDAPStorageMapper ldapMapper = ldapFedProvider.getMapper(mapperModel); LDAPStorageMapper ldapMapper = ldapFedProvider.getMapper(mapperModel);
ldapMapper.onImportUserFromLDAP(mapperModel, ldapFedProvider, ldapUser, currentUser, currentRealm, false); ldapMapper.onImportUserFromLDAP(ldapUser, currentUser, currentRealm, false);
} }
logger.debugf("Updated user from LDAP: %s", currentUser.getUsername()); logger.debugf("Updated user from LDAP: %s", currentUser.getUsername());

View file

@ -64,7 +64,7 @@ public class LDAPUtils {
List<ComponentModel> sortedMappers = ldapProvider.sortMappersAsc(federationMappers); List<ComponentModel> sortedMappers = ldapProvider.sortMappersAsc(federationMappers);
for (ComponentModel mapperModel : sortedMappers) { for (ComponentModel mapperModel : sortedMappers) {
LDAPStorageMapper ldapMapper = ldapProvider.getMapper(mapperModel); LDAPStorageMapper ldapMapper = ldapProvider.getMapper(mapperModel);
ldapMapper.onRegisterUserToLDAP(mapperModel, ldapProvider, ldapUser, user, realm); ldapMapper.onRegisterUserToLDAP(ldapUser, user, realm);
} }
LDAPUtils.computeAndSetDn(ldapConfig, ldapUser); LDAPUtils.computeAndSetDn(ldapConfig, ldapUser);

View file

@ -155,7 +155,7 @@ public class LDAPQuery {
List<ComponentModel> sortedMappers = ldapFedProvider.sortMappersAsc(mappers); List<ComponentModel> sortedMappers = ldapFedProvider.sortMappersAsc(mappers);
for (ComponentModel mapperModel : sortedMappers) { for (ComponentModel mapperModel : sortedMappers) {
LDAPStorageMapper fedMapper = ldapFedProvider.getMapper(mapperModel); LDAPStorageMapper fedMapper = ldapFedProvider.getMapper(mapperModel);
fedMapper.beforeLDAPQuery(mapperModel, this); fedMapper.beforeLDAPQuery(this);
} }
List<LDAPObject> result = new ArrayList<LDAPObject>(); List<LDAPObject> result = new ArrayList<LDAPObject>();

View file

@ -36,57 +36,35 @@ import java.util.List;
* *
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a> * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/ */
public abstract class AbstractLDAPStorageMapper { public abstract class AbstractLDAPStorageMapper implements LDAPStorageMapper {
protected final KeycloakSession session;
protected final ComponentModel mapperModel; protected final ComponentModel mapperModel;
protected final LDAPStorageProvider ldapProvider; protected final LDAPStorageProvider ldapProvider;
protected final RealmModel realm;
public AbstractLDAPStorageMapper(ComponentModel mapperModel, LDAPStorageProvider ldapProvider, RealmModel realm) { public AbstractLDAPStorageMapper(ComponentModel mapperModel, LDAPStorageProvider ldapProvider) {
this.mapperModel = mapperModel; this.mapperModel = mapperModel;
this.ldapProvider = ldapProvider; this.ldapProvider = ldapProvider;
this.realm = realm; this.session = ldapProvider.getSession();
} }
/**
* @see LDAPStorageMapper#syncDataFromFederationProviderToKeycloak(ComponentModel, LDAPStorageProvider, KeycloakSession, RealmModel) public SynchronizationResult syncDataFromFederationProviderToKeycloak(RealmModel realm) {
*/
public SynchronizationResult syncDataFromFederationProviderToKeycloak() {
return new SynchronizationResult(); return new SynchronizationResult();
} }
/**
* @see LDAPStorageMapper#syncDataFromKeycloakToFederationProvider(ComponentModel, LDAPStorageProvider, KeycloakSession, RealmModel) public SynchronizationResult syncDataFromKeycloakToFederationProvider(RealmModel realm) {
*/
public SynchronizationResult syncDataFromKeycloakToFederationProvider() {
return new SynchronizationResult(); return new SynchronizationResult();
} }
/**
* @see LDAPStorageMapper#beforeLDAPQuery(ComponentModel, LDAPQuery)
*/
public abstract void beforeLDAPQuery(LDAPQuery query);
/** public List<UserModel> getGroupMembers(RealmModel realm, GroupModel group, int firstResult, int maxResults) {
* @see LDAPStorageMapper#proxy(ComponentModel, LDAPStorageProvider, LDAPObject, UserModel, RealmModel)
*/
public abstract UserModel proxy(LDAPObject ldapUser, UserModel delegate);
/**
* @see LDAPStorageMapper#onRegisterUserToLDAP(ComponentModel, LDAPStorageProvider, LDAPObject, UserModel, RealmModel)
*/
public abstract void onRegisterUserToLDAP(LDAPObject ldapUser, UserModel localUser);
/**
* @see LDAPStorageMapper#onImportUserFromLDAP(ComponentModel, LDAPStorageProvider, LDAPObject, UserModel, RealmModel, boolean)
*/
public abstract void onImportUserFromLDAP(LDAPObject ldapUser, UserModel user, boolean isCreate);
public List<UserModel> getGroupMembers(GroupModel group, int firstResult, int maxResults) {
return Collections.emptyList(); return Collections.emptyList();
} }
public boolean onAuthenticationFailure(LDAPObject ldapUser, UserModel user, AuthenticationException ldapException) {
public boolean onAuthenticationFailure(LDAPObject ldapUser, UserModel user, AuthenticationException ldapException, RealmModel realm) {
return false; return false;
} }
@ -96,11 +74,15 @@ public abstract class AbstractLDAPStorageMapper {
return Boolean.parseBoolean(paramm); return Boolean.parseBoolean(paramm);
} }
public LDAPStorageProvider getLdapProvider() { public LDAPStorageProvider getLdapProvider() {
return ldapProvider; return ldapProvider;
} }
public RealmModel getRealm() {
return realm; @Override
public void close() {
} }
} }

View file

@ -22,9 +22,7 @@ import org.keycloak.component.ComponentModel;
import org.keycloak.component.ComponentValidationException; import org.keycloak.component.ComponentValidationException;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
import org.keycloak.provider.ProviderConfigProperty; import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.idm.UserFederationMapperSyncConfigRepresentation;
import org.keycloak.storage.ldap.LDAPStorageProvider; import org.keycloak.storage.ldap.LDAPStorageProvider;
import java.util.HashMap; import java.util.HashMap;
@ -52,10 +50,15 @@ public abstract class AbstractLDAPStorageMapperFactory implements LDAPStorageMap
@Override @Override
public LDAPStorageMapper create(KeycloakSession session, ComponentModel model) { public LDAPStorageMapper create(KeycloakSession session, ComponentModel model) {
return new LDAPStorageMapperBridge(this); } // LDAPStorageProvider is in the session already as mappers are always called from it
String ldapProviderModelId = model.getParentId();
LDAPStorageProvider ldapProvider = (LDAPStorageProvider) session.getAttribute(ldapProviderModelId);
return createMapper(model, ldapProvider);
}
// Used just by LDAPFederationMapperBridge. // Used just by LDAPFederationMapperBridge.
protected abstract AbstractLDAPStorageMapper createMapper(ComponentModel mapperModel, LDAPStorageProvider federationProvider, RealmModel realm); protected abstract AbstractLDAPStorageMapper createMapper(ComponentModel mapperModel, LDAPStorageProvider federationProvider);
@Override @Override
public void postInit(KeycloakSessionFactory factory) { public void postInit(KeycloakSessionFactory factory) {

View file

@ -43,12 +43,12 @@ public class FullNameLDAPStorageMapper extends AbstractLDAPStorageMapper {
public static final String WRITE_ONLY = "write.only"; public static final String WRITE_ONLY = "write.only";
public FullNameLDAPStorageMapper(ComponentModel mapperModel, LDAPStorageProvider ldapProvider, RealmModel realm) { public FullNameLDAPStorageMapper(ComponentModel mapperModel, LDAPStorageProvider ldapProvider) {
super(mapperModel, ldapProvider, realm); super(mapperModel, ldapProvider);
} }
@Override @Override
public void onImportUserFromLDAP(LDAPObject ldapUser, UserModel user, boolean isCreate) { public void onImportUserFromLDAP(LDAPObject ldapUser, UserModel user, RealmModel realm, boolean isCreate) {
if (isWriteOnly()) { if (isWriteOnly()) {
return; return;
} }
@ -72,7 +72,7 @@ public class FullNameLDAPStorageMapper extends AbstractLDAPStorageMapper {
} }
@Override @Override
public void onRegisterUserToLDAP(LDAPObject ldapUser, UserModel localUser) { public void onRegisterUserToLDAP(LDAPObject ldapUser, UserModel localUser, RealmModel realm) {
String ldapFullNameAttrName = getLdapFullNameAttrName(); String ldapFullNameAttrName = getLdapFullNameAttrName();
String fullName = getFullName(localUser.getFirstName(), localUser.getLastName()); String fullName = getFullName(localUser.getFirstName(), localUser.getLastName());
ldapUser.setSingleAttribute(ldapFullNameAttrName, fullName); ldapUser.setSingleAttribute(ldapFullNameAttrName, fullName);
@ -83,7 +83,7 @@ public class FullNameLDAPStorageMapper extends AbstractLDAPStorageMapper {
} }
@Override @Override
public UserModel proxy(LDAPObject ldapUser, UserModel delegate) { public UserModel proxy(LDAPObject ldapUser, UserModel delegate, RealmModel realm) {
if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE && !isReadOnly()) { if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE && !isReadOnly()) {

View file

@ -114,7 +114,7 @@ public class FullNameLDAPStorageMapperFactory extends AbstractLDAPStorageMapperF
} }
@Override @Override
protected AbstractLDAPStorageMapper createMapper(ComponentModel mapperModel, LDAPStorageProvider federationProvider, RealmModel realm) { protected AbstractLDAPStorageMapper createMapper(ComponentModel mapperModel, LDAPStorageProvider federationProvider) {
return new FullNameLDAPStorageMapper(mapperModel, federationProvider, realm); return new FullNameLDAPStorageMapper(mapperModel, federationProvider);
} }
} }

View file

@ -41,8 +41,8 @@ public class HardcodedLDAPRoleStorageMapper extends AbstractLDAPStorageMapper {
public static final String ROLE = "role"; public static final String ROLE = "role";
public HardcodedLDAPRoleStorageMapper(ComponentModel mapperModel, LDAPStorageProvider ldapProvider, RealmModel realm) { public HardcodedLDAPRoleStorageMapper(ComponentModel mapperModel, LDAPStorageProvider ldapProvider) {
super(mapperModel, ldapProvider, realm); super(mapperModel, ldapProvider);
} }
@Override @Override
@ -50,14 +50,14 @@ public class HardcodedLDAPRoleStorageMapper extends AbstractLDAPStorageMapper {
} }
@Override @Override
public UserModel proxy(LDAPObject ldapUser, UserModel delegate) { public UserModel proxy(LDAPObject ldapUser, UserModel delegate, RealmModel realm) {
return new UserModelDelegate(delegate) { return new UserModelDelegate(delegate) {
@Override @Override
public Set<RoleModel> getRealmRoleMappings() { public Set<RoleModel> getRealmRoleMappings() {
Set<RoleModel> roles = super.getRealmRoleMappings(); Set<RoleModel> roles = super.getRealmRoleMappings();
RoleModel role = getRole(); RoleModel role = getRole(realm);
if (role != null && role.getContainer().equals(realm)) { if (role != null && role.getContainer().equals(realm)) {
roles.add(role); roles.add(role);
} }
@ -69,7 +69,7 @@ public class HardcodedLDAPRoleStorageMapper extends AbstractLDAPStorageMapper {
public Set<RoleModel> getClientRoleMappings(ClientModel app) { public Set<RoleModel> getClientRoleMappings(ClientModel app) {
Set<RoleModel> roles = super.getClientRoleMappings(app); Set<RoleModel> roles = super.getClientRoleMappings(app);
RoleModel role = getRole(); RoleModel role = getRole(realm);
if (role != null && role.getContainer().equals(app)) { if (role != null && role.getContainer().equals(app)) {
roles.add(role); roles.add(role);
} }
@ -79,14 +79,14 @@ public class HardcodedLDAPRoleStorageMapper extends AbstractLDAPStorageMapper {
@Override @Override
public boolean hasRole(RoleModel role) { public boolean hasRole(RoleModel role) {
return super.hasRole(role) || role.equals(getRole()); return super.hasRole(role) || role.equals(getRole(realm));
} }
@Override @Override
public Set<RoleModel> getRoleMappings() { public Set<RoleModel> getRoleMappings() {
Set<RoleModel> roles = super.getRoleMappings(); Set<RoleModel> roles = super.getRoleMappings();
RoleModel role = getRole(); RoleModel role = getRole(realm);
if (role != null) { if (role != null) {
roles.add(role); roles.add(role);
} }
@ -96,7 +96,7 @@ public class HardcodedLDAPRoleStorageMapper extends AbstractLDAPStorageMapper {
@Override @Override
public void deleteRoleMapping(RoleModel role) { public void deleteRoleMapping(RoleModel role) {
if (role.equals(getRole())) { if (role.equals(getRole(realm))) {
throw new ModelException("Not possible to delete role. It's hardcoded by LDAP mapper"); throw new ModelException("Not possible to delete role. It's hardcoded by LDAP mapper");
} else { } else {
super.deleteRoleMapping(role); super.deleteRoleMapping(role);
@ -106,16 +106,16 @@ public class HardcodedLDAPRoleStorageMapper extends AbstractLDAPStorageMapper {
} }
@Override @Override
public void onRegisterUserToLDAP(LDAPObject ldapUser, UserModel localUser) { public void onRegisterUserToLDAP(LDAPObject ldapUser, UserModel localUser, RealmModel realm) {
} }
@Override @Override
public void onImportUserFromLDAP(LDAPObject ldapUser, UserModel user, boolean isCreate) { public void onImportUserFromLDAP(LDAPObject ldapUser, UserModel user, RealmModel realm, boolean isCreate) {
} }
private RoleModel getRole() { private RoleModel getRole(RealmModel realm) {
String roleName = mapperModel.getConfig().getFirst(HardcodedLDAPRoleStorageMapper.ROLE); String roleName = mapperModel.getConfig().getFirst(HardcodedLDAPRoleStorageMapper.ROLE);
RoleModel role = KeycloakModelUtils.getRoleFromString(realm, roleName); RoleModel role = KeycloakModelUtils.getRoleFromString(realm, roleName);
if (role == null) { if (role == null) {

View file

@ -72,7 +72,7 @@ public class HardcodedLDAPRoleStorageMapperFactory extends AbstractLDAPStorageMa
} }
@Override @Override
protected AbstractLDAPStorageMapper createMapper(ComponentModel mapperModel, LDAPStorageProvider federationProvider, RealmModel realm) { protected AbstractLDAPStorageMapper createMapper(ComponentModel mapperModel, LDAPStorageProvider federationProvider) {
return new HardcodedLDAPRoleStorageMapper(mapperModel, federationProvider, realm); return new HardcodedLDAPRoleStorageMapper(mapperModel, federationProvider);
} }
} }

View file

@ -17,13 +17,10 @@
package org.keycloak.storage.ldap.mappers; package org.keycloak.storage.ldap.mappers;
import org.keycloak.component.ComponentModel;
import org.keycloak.models.GroupModel; import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel; import org.keycloak.models.UserModel;
import org.keycloak.provider.Provider; import org.keycloak.provider.Provider;
import org.keycloak.storage.ldap.LDAPStorageProvider;
import org.keycloak.storage.ldap.idm.model.LDAPObject; import org.keycloak.storage.ldap.idm.model.LDAPObject;
import org.keycloak.storage.ldap.idm.query.internal.LDAPQuery; import org.keycloak.storage.ldap.idm.query.internal.LDAPQuery;
import org.keycloak.storage.user.SynchronizationResult; import org.keycloak.storage.user.SynchronizationResult;
@ -42,84 +39,66 @@ public interface LDAPStorageMapper extends Provider {
* *
* Applicable just if sync is supported * Applicable just if sync is supported
* *
* @param mapperModel
* @param provider
* @param session
* @param realm
*/ */
SynchronizationResult syncDataFromFederationProviderToKeycloak(ComponentModel mapperModel, LDAPStorageProvider provider, KeycloakSession session, RealmModel realm); SynchronizationResult syncDataFromFederationProviderToKeycloak(RealmModel realm);
/** /**
* Sync data from Keycloak back to federated storage * Sync data from Keycloak back to federated storage
* *
* @param mapperModel **/
* @param provider SynchronizationResult syncDataFromKeycloakToFederationProvider(RealmModel realm);
* @param session
* @param realm
*/
SynchronizationResult syncDataFromKeycloakToFederationProvider(ComponentModel mapperModel, LDAPStorageProvider provider, KeycloakSession session, RealmModel realm);
/** /**
* Return empty list if doesn't support storing of groups * Return empty list if doesn't support storing of groups
*/ */
List<UserModel> getGroupMembers(ComponentModel mapperModel, LDAPStorageProvider provider, RealmModel realm, GroupModel group, int firstResult, int maxResults); List<UserModel> getGroupMembers(RealmModel realm, GroupModel group, int firstResult, int maxResults);
/** /**
* Called when importing user from LDAP to local keycloak DB. * Called when importing user from LDAP to local keycloak DB.
* *
* @param mapperModel
* @param ldapProvider
* @param ldapUser * @param ldapUser
* @param user * @param user
* @param realm * @param realm
* @param isCreate true if we importing new user from LDAP. False if user already exists in Keycloak, but we are upgrading (syncing) it from LDAP * @param isCreate true if we importing new user from LDAP. False if user already exists in Keycloak, but we are upgrading (syncing) it from LDAP
*/ */
void onImportUserFromLDAP(ComponentModel mapperModel, LDAPStorageProvider ldapProvider, LDAPObject ldapUser, UserModel user, RealmModel realm, boolean isCreate); void onImportUserFromLDAP(LDAPObject ldapUser, UserModel user, RealmModel realm, boolean isCreate);
/** /**
* Called when register new user to LDAP - just after user was created in Keycloak DB * Called when register new user to LDAP - just after user was created in Keycloak DB
* *
* @param mapperModel
* @param ldapProvider
* @param ldapUser * @param ldapUser
* @param localUser * @param localUser
* @param realm * @param realm
*/ */
void onRegisterUserToLDAP(ComponentModel mapperModel, LDAPStorageProvider ldapProvider, LDAPObject ldapUser, UserModel localUser, RealmModel realm); void onRegisterUserToLDAP(LDAPObject ldapUser, UserModel localUser, RealmModel realm);
/** /**
* Called when invoke proxy on LDAP federation provider * Called when invoke proxy on LDAP federation provider
* *
* @param mapperModel
* @param ldapProvider
* @param ldapUser * @param ldapUser
* @param delegate * @param delegate
* @param realm * @param realm
* @return * @return
*/ */
UserModel proxy(ComponentModel mapperModel, LDAPStorageProvider ldapProvider, LDAPObject ldapUser, UserModel delegate, RealmModel realm); UserModel proxy(LDAPObject ldapUser, UserModel delegate, RealmModel realm);
/** /**
* Called before LDAP Identity query for retrieve LDAP users was executed. It allows to change query somehow (add returning attributes from LDAP, change conditions etc) * Called before LDAP Identity query for retrieve LDAP users was executed. It allows to change query somehow (add returning attributes from LDAP, change conditions etc)
* *
* @param mapperModel
* @param query * @param query
*/ */
void beforeLDAPQuery(ComponentModel mapperModel, LDAPQuery query); void beforeLDAPQuery(LDAPQuery query);
/** /**
* Called when LDAP authentication of specified user fails. If any mapper returns true from this method, AuthenticationException won't be rethrown! * Called when LDAP authentication of specified user fails. If any mapper returns true from this method, AuthenticationException won't be rethrown!
* *
* @param mapperModel
* @param ldapProvider
* @param realm
* @param user * @param user
* @param ldapUser * @param ldapUser
* @param ldapException * @param ldapException
* @return true if mapper processed the AuthenticationException and did some actions based on that. In that case, AuthenticationException won't be rethrown! * @return true if mapper processed the AuthenticationException and did some actions based on that. In that case, AuthenticationException won't be rethrown!
*/ */
boolean onAuthenticationFailure(ComponentModel mapperModel, LDAPStorageProvider ldapProvider, LDAPObject ldapUser, UserModel user, AuthenticationException ldapException, RealmModel realm); boolean onAuthenticationFailure(LDAPObject ldapUser, UserModel user, AuthenticationException ldapException, RealmModel realm);
} }

View file

@ -1,98 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.storage.ldap.mappers;
import org.keycloak.component.ComponentModel;
import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.storage.ldap.LDAPStorageProvider;
import org.keycloak.storage.ldap.idm.model.LDAPObject;
import org.keycloak.storage.ldap.idm.query.internal.LDAPQuery;
import org.keycloak.storage.user.SynchronizationResult;
import javax.naming.AuthenticationException;
import java.util.List;
/**
* Sufficient if mapper implementation is stateless and doesn't need to "close" any state
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class LDAPStorageMapperBridge implements LDAPStorageMapper {
private final AbstractLDAPStorageMapperFactory factory;
public LDAPStorageMapperBridge(AbstractLDAPStorageMapperFactory factory) {
this.factory = factory;
}
// Sync groups from LDAP to Keycloak DB
@Override
public SynchronizationResult syncDataFromFederationProviderToKeycloak(ComponentModel mapperModel, LDAPStorageProvider federationProvider, KeycloakSession session, RealmModel realm) {
return getDelegate(mapperModel, federationProvider, realm).syncDataFromFederationProviderToKeycloak();
}
@Override
public SynchronizationResult syncDataFromKeycloakToFederationProvider(ComponentModel mapperModel, LDAPStorageProvider federationProvider, KeycloakSession session, RealmModel realm) {
return getDelegate(mapperModel, federationProvider, realm).syncDataFromKeycloakToFederationProvider();
}
@Override
public void onImportUserFromLDAP(ComponentModel mapperModel, LDAPStorageProvider ldapProvider, LDAPObject ldapUser, UserModel user, RealmModel realm, boolean isCreate) {
getDelegate(mapperModel, ldapProvider, realm).onImportUserFromLDAP(ldapUser, user, isCreate);
}
@Override
public void onRegisterUserToLDAP(ComponentModel mapperModel, LDAPStorageProvider ldapProvider, LDAPObject ldapUser, UserModel localUser, RealmModel realm) {
getDelegate(mapperModel, ldapProvider, realm).onRegisterUserToLDAP(ldapUser, localUser);
}
@Override
public UserModel proxy(ComponentModel mapperModel, LDAPStorageProvider ldapProvider, LDAPObject ldapUser, UserModel delegate, RealmModel realm) {
return getDelegate(mapperModel, ldapProvider, realm).proxy(ldapUser, delegate);
}
@Override
public void beforeLDAPQuery(ComponentModel mapperModel, LDAPQuery query) {
// Improve if needed
getDelegate(mapperModel, query.getLdapProvider(), null).beforeLDAPQuery(query);
}
@Override
public List<UserModel> getGroupMembers(ComponentModel mapperModel, LDAPStorageProvider ldapProvider, RealmModel realm, GroupModel group, int firstResult, int maxResults) {
return getDelegate(mapperModel, ldapProvider, realm).getGroupMembers(group, firstResult, maxResults);
}
@Override
public boolean onAuthenticationFailure(ComponentModel mapperModel, LDAPStorageProvider ldapProvider, LDAPObject ldapUser, UserModel user, AuthenticationException ldapException, RealmModel realm) {
return getDelegate(mapperModel, ldapProvider, realm).onAuthenticationFailure(ldapUser, user, ldapException);
}
private AbstractLDAPStorageMapper getDelegate(ComponentModel mapperModel, LDAPStorageProvider federationProvider, RealmModel realm) {
LDAPStorageProvider ldapProvider = (LDAPStorageProvider) federationProvider;
return factory.createMapper(mapperModel, ldapProvider, realm);
}
@Override
public void close() {
}
}

View file

@ -81,12 +81,12 @@ public class UserAttributeLDAPStorageMapper extends AbstractLDAPStorageMapper {
public static final String ALWAYS_READ_VALUE_FROM_LDAP = "always.read.value.from.ldap"; public static final String ALWAYS_READ_VALUE_FROM_LDAP = "always.read.value.from.ldap";
public static final String IS_MANDATORY_IN_LDAP = "is.mandatory.in.ldap"; public static final String IS_MANDATORY_IN_LDAP = "is.mandatory.in.ldap";
public UserAttributeLDAPStorageMapper(ComponentModel mapperModel, LDAPStorageProvider ldapProvider, RealmModel realm) { public UserAttributeLDAPStorageMapper(ComponentModel mapperModel, LDAPStorageProvider ldapProvider) {
super(mapperModel, ldapProvider, realm); super(mapperModel, ldapProvider);
} }
@Override @Override
public void onImportUserFromLDAP(LDAPObject ldapUser, UserModel user, boolean isCreate) { public void onImportUserFromLDAP(LDAPObject ldapUser, UserModel user, RealmModel realm, boolean isCreate) {
String userModelAttrName = mapperModel.getConfig().getFirst(USER_MODEL_ATTRIBUTE); String userModelAttrName = mapperModel.getConfig().getFirst(USER_MODEL_ATTRIBUTE);
String ldapAttrName = mapperModel.getConfig().getFirst(LDAP_ATTRIBUTE); String ldapAttrName = mapperModel.getConfig().getFirst(LDAP_ATTRIBUTE);
@ -113,7 +113,7 @@ public class UserAttributeLDAPStorageMapper extends AbstractLDAPStorageMapper {
} }
@Override @Override
public void onRegisterUserToLDAP(LDAPObject ldapUser, UserModel localUser) { public void onRegisterUserToLDAP(LDAPObject ldapUser, UserModel localUser, RealmModel realm) {
String userModelAttrName = mapperModel.getConfig().getFirst(USER_MODEL_ATTRIBUTE); String userModelAttrName = mapperModel.getConfig().getFirst(USER_MODEL_ATTRIBUTE);
String ldapAttrName = mapperModel.getConfig().getFirst(LDAP_ATTRIBUTE); String ldapAttrName = mapperModel.getConfig().getFirst(LDAP_ATTRIBUTE);
boolean isMandatoryInLdap = parseBooleanParameter(mapperModel, IS_MANDATORY_IN_LDAP); boolean isMandatoryInLdap = parseBooleanParameter(mapperModel, IS_MANDATORY_IN_LDAP);
@ -172,7 +172,7 @@ public class UserAttributeLDAPStorageMapper extends AbstractLDAPStorageMapper {
} }
@Override @Override
public UserModel proxy(final LDAPObject ldapUser, UserModel delegate) { public UserModel proxy(final LDAPObject ldapUser, UserModel delegate, RealmModel realm) {
final String userModelAttrName = mapperModel.getConfig().getFirst(USER_MODEL_ATTRIBUTE); final String userModelAttrName = mapperModel.getConfig().getFirst(USER_MODEL_ATTRIBUTE);
final String ldapAttrName = mapperModel.getConfig().getFirst(LDAP_ATTRIBUTE); final String ldapAttrName = mapperModel.getConfig().getFirst(LDAP_ATTRIBUTE);
boolean isAlwaysReadValueFromLDAP = parseBooleanParameter(mapperModel, ALWAYS_READ_VALUE_FROM_LDAP); boolean isAlwaysReadValueFromLDAP = parseBooleanParameter(mapperModel, ALWAYS_READ_VALUE_FROM_LDAP);

View file

@ -95,8 +95,8 @@ public class UserAttributeLDAPStorageMapperFactory extends AbstractLDAPStorageMa
} }
@Override @Override
protected AbstractLDAPStorageMapper createMapper(ComponentModel mapperModel, LDAPStorageProvider federationProvider, RealmModel realm) { protected AbstractLDAPStorageMapper createMapper(ComponentModel mapperModel, LDAPStorageProvider federationProvider) {
return new UserAttributeLDAPStorageMapper(mapperModel, federationProvider, realm); return new UserAttributeLDAPStorageMapper(mapperModel, federationProvider);
} }
@Override @Override

View file

@ -68,8 +68,7 @@ public enum MembershipType {
} }
@Override @Override
public List<UserModel> getGroupMembers(GroupLDAPStorageMapper groupMapper, LDAPObject ldapGroup, int firstResult, int maxResults) { public List<UserModel> getGroupMembers(RealmModel realm, GroupLDAPStorageMapper groupMapper, LDAPObject ldapGroup, int firstResult, int maxResults) {
RealmModel realm = groupMapper.getRealm();
LDAPStorageProvider ldapProvider = groupMapper.getLdapProvider(); LDAPStorageProvider ldapProvider = groupMapper.getLdapProvider();
CommonLDAPGroupMapperConfig config = groupMapper.getConfig(); CommonLDAPGroupMapperConfig config = groupMapper.getConfig();
@ -134,7 +133,7 @@ public enum MembershipType {
} }
@Override @Override
public List<UserModel> getGroupMembers(GroupLDAPStorageMapper groupMapper, LDAPObject ldapGroup, int firstResult, int maxResults) { public List<UserModel> getGroupMembers(RealmModel realm, GroupLDAPStorageMapper groupMapper, LDAPObject ldapGroup, int firstResult, int maxResults) {
String memberAttrName = groupMapper.getConfig().getMembershipLdapAttribute(); String memberAttrName = groupMapper.getConfig().getMembershipLdapAttribute();
Set<String> memberUids = LDAPUtils.getExistingMemberships(memberAttrName, ldapGroup); Set<String> memberUids = LDAPUtils.getExistingMemberships(memberAttrName, ldapGroup);
@ -146,12 +145,12 @@ public enum MembershipType {
int max = Math.min(memberUids.size(), firstResult + maxResults); int max = Math.min(memberUids.size(), firstResult + maxResults);
uids = uids.subList(firstResult, max); uids = uids.subList(firstResult, max);
return groupMapper.getLdapProvider().loadUsersByUsernames(uids, groupMapper.getRealm()); return groupMapper.getLdapProvider().loadUsersByUsernames(uids, realm);
} }
}; };
public abstract Set<LDAPDn> getLDAPSubgroups(GroupLDAPStorageMapper groupMapper, LDAPObject ldapGroup); public abstract Set<LDAPDn> getLDAPSubgroups(GroupLDAPStorageMapper groupMapper, LDAPObject ldapGroup);
public abstract List<UserModel> getGroupMembers(GroupLDAPStorageMapper groupMapper, LDAPObject ldapGroup, int firstResult, int maxResults); public abstract List<UserModel> getGroupMembers(RealmModel realm, GroupLDAPStorageMapper groupMapper, LDAPObject ldapGroup, int firstResult, int maxResults);
} }

View file

@ -64,8 +64,8 @@ public class GroupLDAPStorageMapper extends AbstractLDAPStorageMapper implements
// Flag to avoid syncing multiple times per transaction // Flag to avoid syncing multiple times per transaction
private boolean syncFromLDAPPerformedInThisTransaction = false; private boolean syncFromLDAPPerformedInThisTransaction = false;
public GroupLDAPStorageMapper(ComponentModel mapperModel, LDAPStorageProvider ldapProvider, RealmModel realm, GroupLDAPStorageMapperFactory factory) { public GroupLDAPStorageMapper(ComponentModel mapperModel, LDAPStorageProvider ldapProvider, GroupLDAPStorageMapperFactory factory) {
super(mapperModel, ldapProvider, realm); super(mapperModel, ldapProvider);
this.config = new GroupMapperConfig(mapperModel); this.config = new GroupMapperConfig(mapperModel);
this.factory = factory; this.factory = factory;
} }
@ -139,7 +139,7 @@ public class GroupLDAPStorageMapper extends AbstractLDAPStorageMapper implements
// Sync from Ldap to KC // Sync from Ldap to KC
@Override @Override
public SynchronizationResult syncDataFromFederationProviderToKeycloak() { public SynchronizationResult syncDataFromFederationProviderToKeycloak(RealmModel realm) {
SynchronizationResult syncResult = new SynchronizationResult() { SynchronizationResult syncResult = new SynchronizationResult() {
@Override @Override
@ -176,7 +176,7 @@ public class GroupLDAPStorageMapper extends AbstractLDAPStorageMapper implements
try { try {
List<GroupTreeResolver.GroupTreeEntry> groupTrees = new GroupTreeResolver().resolveGroupTree(ldapGroupsRep); List<GroupTreeResolver.GroupTreeEntry> groupTrees = new GroupTreeResolver().resolveGroupTree(ldapGroupsRep);
updateKeycloakGroupTree(groupTrees, ldapGroupsMap, syncResult); updateKeycloakGroupTree(realm, groupTrees, ldapGroupsMap, syncResult);
} catch (GroupTreeResolver.GroupTreeResolveException gre) { } catch (GroupTreeResolver.GroupTreeResolveException gre) {
throw new ModelException("Couldn't resolve groups from LDAP. Fix LDAP or skip preserve inheritance. Details: " + gre.getMessage(), gre); throw new ModelException("Couldn't resolve groups from LDAP. Fix LDAP or skip preserve inheritance. Details: " + gre.getMessage(), gre);
} }
@ -203,7 +203,7 @@ public class GroupLDAPStorageMapper extends AbstractLDAPStorageMapper implements
// Possibly remove keycloak groups, which doesn't exists in LDAP // Possibly remove keycloak groups, which doesn't exists in LDAP
if (config.isDropNonExistingGroupsDuringSync()) { if (config.isDropNonExistingGroupsDuringSync()) {
dropNonExistingKcGroups(syncResult, visitedGroupIds); dropNonExistingKcGroups(realm, syncResult, visitedGroupIds);
} }
} }
@ -212,20 +212,20 @@ public class GroupLDAPStorageMapper extends AbstractLDAPStorageMapper implements
return syncResult; return syncResult;
} }
private void updateKeycloakGroupTree(List<GroupTreeResolver.GroupTreeEntry> groupTrees, Map<String, LDAPObject> ldapGroups, SynchronizationResult syncResult) { private void updateKeycloakGroupTree(RealmModel realm, List<GroupTreeResolver.GroupTreeEntry> groupTrees, Map<String, LDAPObject> ldapGroups, SynchronizationResult syncResult) {
Set<String> visitedGroupIds = new HashSet<>(); Set<String> visitedGroupIds = new HashSet<>();
for (GroupTreeResolver.GroupTreeEntry groupEntry : groupTrees) { for (GroupTreeResolver.GroupTreeEntry groupEntry : groupTrees) {
updateKeycloakGroupTreeEntry(groupEntry, ldapGroups, null, syncResult, visitedGroupIds); updateKeycloakGroupTreeEntry(realm, groupEntry, ldapGroups, null, syncResult, visitedGroupIds);
} }
// Possibly remove keycloak groups, which doesn't exists in LDAP // Possibly remove keycloak groups, which doesn't exists in LDAP
if (config.isDropNonExistingGroupsDuringSync()) { if (config.isDropNonExistingGroupsDuringSync()) {
dropNonExistingKcGroups(syncResult, visitedGroupIds); dropNonExistingKcGroups(realm, syncResult, visitedGroupIds);
} }
} }
private void updateKeycloakGroupTreeEntry(GroupTreeResolver.GroupTreeEntry groupTreeEntry, Map<String, LDAPObject> ldapGroups, GroupModel kcParent, SynchronizationResult syncResult, Set<String> visitedGroupIds) { private void updateKeycloakGroupTreeEntry(RealmModel realm, GroupTreeResolver.GroupTreeEntry groupTreeEntry, Map<String, LDAPObject> ldapGroups, GroupModel kcParent, SynchronizationResult syncResult, Set<String> visitedGroupIds) {
String groupName = groupTreeEntry.getGroupName(); String groupName = groupTreeEntry.getGroupName();
// Check if group already exists // Check if group already exists
@ -259,11 +259,11 @@ public class GroupLDAPStorageMapper extends AbstractLDAPStorageMapper implements
visitedGroupIds.add(kcGroup.getId()); visitedGroupIds.add(kcGroup.getId());
for (GroupTreeResolver.GroupTreeEntry childEntry : groupTreeEntry.getChildren()) { for (GroupTreeResolver.GroupTreeEntry childEntry : groupTreeEntry.getChildren()) {
updateKeycloakGroupTreeEntry(childEntry, ldapGroups, kcGroup, syncResult, visitedGroupIds); updateKeycloakGroupTreeEntry(realm, childEntry, ldapGroups, kcGroup, syncResult, visitedGroupIds);
} }
} }
private void dropNonExistingKcGroups(SynchronizationResult syncResult, Set<String> visitedGroupIds) { private void dropNonExistingKcGroups(RealmModel realm, SynchronizationResult syncResult, Set<String> visitedGroupIds) {
// Remove keycloak groups, which doesn't exists in LDAP // Remove keycloak groups, which doesn't exists in LDAP
List<GroupModel> allGroups = realm.getGroups(); List<GroupModel> allGroups = realm.getGroups();
for (GroupModel kcGroup : allGroups) { for (GroupModel kcGroup : allGroups) {
@ -289,7 +289,7 @@ public class GroupLDAPStorageMapper extends AbstractLDAPStorageMapper implements
} }
protected GroupModel findKcGroupByLDAPGroup(LDAPObject ldapGroup) { protected GroupModel findKcGroupByLDAPGroup(RealmModel realm, LDAPObject ldapGroup) {
String groupNameAttr = config.getGroupNameLdapAttribute(); String groupNameAttr = config.getGroupNameLdapAttribute();
String groupName = ldapGroup.getAttributeAsString(groupNameAttr); String groupName = ldapGroup.getAttributeAsString(groupNameAttr);
@ -309,8 +309,8 @@ public class GroupLDAPStorageMapper extends AbstractLDAPStorageMapper implements
} }
} }
protected GroupModel findKcGroupOrSyncFromLDAP(LDAPObject ldapGroup, UserModel user) { protected GroupModel findKcGroupOrSyncFromLDAP(RealmModel realm, LDAPObject ldapGroup, UserModel user) {
GroupModel kcGroup = findKcGroupByLDAPGroup(ldapGroup); GroupModel kcGroup = findKcGroupByLDAPGroup(realm, ldapGroup);
if (kcGroup == null) { if (kcGroup == null) {
@ -318,8 +318,8 @@ public class GroupLDAPStorageMapper extends AbstractLDAPStorageMapper implements
// Better to sync all groups from LDAP with preserved inheritance // Better to sync all groups from LDAP with preserved inheritance
if (!syncFromLDAPPerformedInThisTransaction) { if (!syncFromLDAPPerformedInThisTransaction) {
syncDataFromFederationProviderToKeycloak(); syncDataFromFederationProviderToKeycloak(realm);
kcGroup = findKcGroupByLDAPGroup(ldapGroup); kcGroup = findKcGroupByLDAPGroup(realm, ldapGroup);
} }
} else { } else {
String groupNameAttr = config.getGroupNameLdapAttribute(); String groupNameAttr = config.getGroupNameLdapAttribute();
@ -348,8 +348,8 @@ public class GroupLDAPStorageMapper extends AbstractLDAPStorageMapper implements
// Sync from Keycloak to LDAP // Sync from Keycloak to LDAP
@Override
public SynchronizationResult syncDataFromKeycloakToFederationProvider() { public SynchronizationResult syncDataFromKeycloakToFederationProvider(RealmModel realm) {
SynchronizationResult syncResult = new SynchronizationResult() { SynchronizationResult syncResult = new SynchronizationResult() {
@Override @Override
@ -480,20 +480,20 @@ public class GroupLDAPStorageMapper extends AbstractLDAPStorageMapper implements
@Override @Override
public List<UserModel> getGroupMembers(GroupModel kcGroup, int firstResult, int maxResults) { public List<UserModel> getGroupMembers(RealmModel realm, GroupModel kcGroup, int firstResult, int maxResults) {
LDAPObject ldapGroup = loadLDAPGroupByName(kcGroup.getName()); LDAPObject ldapGroup = loadLDAPGroupByName(kcGroup.getName());
if (ldapGroup == null) { if (ldapGroup == null) {
return Collections.emptyList(); return Collections.emptyList();
} }
MembershipType membershipType = config.getMembershipTypeLdapAttribute(); MembershipType membershipType = config.getMembershipTypeLdapAttribute();
return membershipType.getGroupMembers(this, ldapGroup, firstResult, maxResults); return membershipType.getGroupMembers(realm, this, ldapGroup, firstResult, maxResults);
} }
public void addGroupMappingInLDAP(String groupName, LDAPObject ldapUser) { public void addGroupMappingInLDAP(RealmModel realm, String groupName, LDAPObject ldapUser) {
LDAPObject ldapGroup = loadLDAPGroupByName(groupName); LDAPObject ldapGroup = loadLDAPGroupByName(groupName);
if (ldapGroup == null) { if (ldapGroup == null) {
syncDataFromKeycloakToFederationProvider(); syncDataFromKeycloakToFederationProvider(realm);
ldapGroup = loadLDAPGroupByName(groupName); ldapGroup = loadLDAPGroupByName(groupName);
} }
@ -510,27 +510,31 @@ public class GroupLDAPStorageMapper extends AbstractLDAPStorageMapper implements
return strategy.getLDAPRoleMappings(this, ldapUser); return strategy.getLDAPRoleMappings(this, ldapUser);
} }
@Override
public void beforeLDAPQuery(LDAPQuery query) { public void beforeLDAPQuery(LDAPQuery query) {
String strategyKey = config.getUserGroupsRetrieveStrategy(); String strategyKey = config.getUserGroupsRetrieveStrategy();
UserRolesRetrieveStrategy strategy = factory.getUserGroupsRetrieveStrategy(strategyKey); UserRolesRetrieveStrategy strategy = factory.getUserGroupsRetrieveStrategy(strategyKey);
strategy.beforeUserLDAPQuery(query); strategy.beforeUserLDAPQuery(query);
} }
public UserModel proxy(LDAPObject ldapUser, UserModel delegate) { @Override
public UserModel proxy(LDAPObject ldapUser, UserModel delegate, RealmModel realm) {
final LDAPGroupMapperMode mode = config.getMode(); final LDAPGroupMapperMode mode = config.getMode();
// For IMPORT mode, all operations are performed against local DB // For IMPORT mode, all operations are performed against local DB
if (mode == LDAPGroupMapperMode.IMPORT) { if (mode == LDAPGroupMapperMode.IMPORT) {
return delegate; return delegate;
} else { } else {
return new LDAPGroupMappingsUserDelegate(delegate, ldapUser); return new LDAPGroupMappingsUserDelegate(realm, delegate, ldapUser);
} }
} }
public void onRegisterUserToLDAP(LDAPObject ldapUser, UserModel localUser) { @Override
public void onRegisterUserToLDAP(LDAPObject ldapUser, UserModel localUser, RealmModel realm) {
} }
public void onImportUserFromLDAP(LDAPObject ldapUser, UserModel user, boolean isCreate) { @Override
public void onImportUserFromLDAP(LDAPObject ldapUser, UserModel user, RealmModel realm, boolean isCreate) {
LDAPGroupMapperMode mode = config.getMode(); LDAPGroupMapperMode mode = config.getMode();
// For now, import LDAP group mappings just during create // For now, import LDAP group mappings just during create
@ -541,7 +545,7 @@ public class GroupLDAPStorageMapper extends AbstractLDAPStorageMapper implements
// Import role mappings from LDAP into Keycloak DB // Import role mappings from LDAP into Keycloak DB
for (LDAPObject ldapGroup : ldapGroups) { for (LDAPObject ldapGroup : ldapGroups) {
GroupModel kcGroup = findKcGroupOrSyncFromLDAP(ldapGroup, user); GroupModel kcGroup = findKcGroupOrSyncFromLDAP(realm, ldapGroup, user);
if (kcGroup != null) { if (kcGroup != null) {
logger.debugf("User '%s' joins group '%s' during import from LDAP", user.getUsername(), kcGroup.getName()); logger.debugf("User '%s' joins group '%s' during import from LDAP", user.getUsername(), kcGroup.getName());
user.joinGroup(kcGroup); user.joinGroup(kcGroup);
@ -553,13 +557,15 @@ public class GroupLDAPStorageMapper extends AbstractLDAPStorageMapper implements
public class LDAPGroupMappingsUserDelegate extends UserModelDelegate { public class LDAPGroupMappingsUserDelegate extends UserModelDelegate {
private final RealmModel realm;
private final LDAPObject ldapUser; private final LDAPObject ldapUser;
// Avoid loading group mappings from LDAP more times per-request // Avoid loading group mappings from LDAP more times per-request
private Set<GroupModel> cachedLDAPGroupMappings; private Set<GroupModel> cachedLDAPGroupMappings;
public LDAPGroupMappingsUserDelegate(UserModel user, LDAPObject ldapUser) { public LDAPGroupMappingsUserDelegate(RealmModel realm, UserModel user, LDAPObject ldapUser) {
super(user); super(user);
this.realm = realm;
this.ldapUser = ldapUser; this.ldapUser = ldapUser;
} }
@ -587,7 +593,7 @@ public class GroupLDAPStorageMapper extends AbstractLDAPStorageMapper implements
if (config.getMode() == LDAPGroupMapperMode.LDAP_ONLY) { if (config.getMode() == LDAPGroupMapperMode.LDAP_ONLY) {
// We need to create new role mappings in LDAP // We need to create new role mappings in LDAP
cachedLDAPGroupMappings = null; cachedLDAPGroupMappings = null;
addGroupMappingInLDAP(group.getName(), ldapUser); addGroupMappingInLDAP(realm, group.getName(), ldapUser);
} else { } else {
super.joinGroup(group); super.joinGroup(group);
} }
@ -635,7 +641,7 @@ public class GroupLDAPStorageMapper extends AbstractLDAPStorageMapper implements
Set<GroupModel> result = new HashSet<>(); Set<GroupModel> result = new HashSet<>();
for (LDAPObject ldapGroup : ldapGroups) { for (LDAPObject ldapGroup : ldapGroups) {
GroupModel kcGroup = findKcGroupOrSyncFromLDAP(ldapGroup, this); GroupModel kcGroup = findKcGroupOrSyncFromLDAP(realm, ldapGroup, this);
if (kcGroup != null) { if (kcGroup != null) {
result.add(kcGroup); result.add(kcGroup);
} }

View file

@ -200,8 +200,8 @@ public class GroupLDAPStorageMapperFactory extends AbstractLDAPStorageMapperFact
} }
@Override @Override
protected AbstractLDAPStorageMapper createMapper(ComponentModel mapperModel, LDAPStorageProvider federationProvider, RealmModel realm) { protected AbstractLDAPStorageMapper createMapper(ComponentModel mapperModel, LDAPStorageProvider federationProvider) {
return new GroupLDAPStorageMapper(mapperModel, federationProvider, realm, this); return new GroupLDAPStorageMapper(mapperModel, federationProvider, this);
} }
protected UserRolesRetrieveStrategy getUserGroupsRetrieveStrategy(String strategyKey) { protected UserRolesRetrieveStrategy getUserGroupsRetrieveStrategy(String strategyKey) {

View file

@ -58,8 +58,8 @@ public class RoleLDAPStorageMapper extends AbstractLDAPStorageMapper implements
private final RoleMapperConfig config; private final RoleMapperConfig config;
private final RoleLDAPStorageMapperFactory factory; private final RoleLDAPStorageMapperFactory factory;
public RoleLDAPStorageMapper(ComponentModel mapperModel, LDAPStorageProvider ldapProvider, RealmModel realm, RoleLDAPStorageMapperFactory factory) { public RoleLDAPStorageMapper(ComponentModel mapperModel, LDAPStorageProvider ldapProvider, RoleLDAPStorageMapperFactory factory) {
super(mapperModel, ldapProvider, realm); super(mapperModel, ldapProvider);
this.config = new RoleMapperConfig(mapperModel); this.config = new RoleMapperConfig(mapperModel);
this.factory = factory; this.factory = factory;
} }
@ -77,7 +77,7 @@ public class RoleLDAPStorageMapper extends AbstractLDAPStorageMapper implements
@Override @Override
public void onImportUserFromLDAP(LDAPObject ldapUser, UserModel user, boolean isCreate) { public void onImportUserFromLDAP(LDAPObject ldapUser, UserModel user, RealmModel realm, boolean isCreate) {
LDAPGroupMapperMode mode = config.getMode(); LDAPGroupMapperMode mode = config.getMode();
// For now, import LDAP role mappings just during create // For now, import LDAP role mappings just during create
@ -90,7 +90,7 @@ public class RoleLDAPStorageMapper extends AbstractLDAPStorageMapper implements
for (LDAPObject ldapRole : ldapRoles) { for (LDAPObject ldapRole : ldapRoles) {
String roleName = ldapRole.getAttributeAsString(roleNameAttr); String roleName = ldapRole.getAttributeAsString(roleNameAttr);
RoleContainerModel roleContainer = getTargetRoleContainer(); RoleContainerModel roleContainer = getTargetRoleContainer(realm);
RoleModel role = roleContainer.getRole(roleName); RoleModel role = roleContainer.getRole(roleName);
if (role == null) { if (role == null) {
@ -104,13 +104,13 @@ public class RoleLDAPStorageMapper extends AbstractLDAPStorageMapper implements
} }
@Override @Override
public void onRegisterUserToLDAP(LDAPObject ldapUser, UserModel localUser) { public void onRegisterUserToLDAP(LDAPObject ldapUser, UserModel localUser, RealmModel realm) {
} }
// Sync roles from LDAP to Keycloak DB // Sync roles from LDAP to Keycloak DB
@Override @Override
public SynchronizationResult syncDataFromFederationProviderToKeycloak() { public SynchronizationResult syncDataFromFederationProviderToKeycloak(RealmModel realm) {
SynchronizationResult syncResult = new SynchronizationResult() { SynchronizationResult syncResult = new SynchronizationResult() {
@Override @Override
@ -126,7 +126,7 @@ public class RoleLDAPStorageMapper extends AbstractLDAPStorageMapper implements
LDAPQuery ldapRoleQuery = createRoleQuery(); LDAPQuery ldapRoleQuery = createRoleQuery();
List<LDAPObject> ldapRoles = LDAPUtils.loadAllLDAPObjects(ldapRoleQuery, ldapProvider); List<LDAPObject> ldapRoles = LDAPUtils.loadAllLDAPObjects(ldapRoleQuery, ldapProvider);
RoleContainerModel roleContainer = getTargetRoleContainer(); RoleContainerModel roleContainer = getTargetRoleContainer(realm);
String rolesRdnAttr = config.getRoleNameLdapAttribute(); String rolesRdnAttr = config.getRoleNameLdapAttribute();
for (LDAPObject ldapRole : ldapRoles) { for (LDAPObject ldapRole : ldapRoles) {
String roleName = ldapRole.getAttributeAsString(rolesRdnAttr); String roleName = ldapRole.getAttributeAsString(rolesRdnAttr);
@ -146,7 +146,7 @@ public class RoleLDAPStorageMapper extends AbstractLDAPStorageMapper implements
// Sync roles from Keycloak back to LDAP // Sync roles from Keycloak back to LDAP
@Override @Override
public SynchronizationResult syncDataFromKeycloakToFederationProvider() { public SynchronizationResult syncDataFromKeycloakToFederationProvider(RealmModel realm) {
SynchronizationResult syncResult = new SynchronizationResult() { SynchronizationResult syncResult = new SynchronizationResult() {
@Override @Override
@ -175,7 +175,7 @@ public class RoleLDAPStorageMapper extends AbstractLDAPStorageMapper implements
} }
RoleContainerModel roleContainer = getTargetRoleContainer(); RoleContainerModel roleContainer = getTargetRoleContainer(realm);
Set<RoleModel> keycloakRoles = roleContainer.getRoles(); Set<RoleModel> keycloakRoles = roleContainer.getRoles();
for (RoleModel keycloakRole : keycloakRoles) { for (RoleModel keycloakRole : keycloakRoles) {
@ -220,7 +220,7 @@ public class RoleLDAPStorageMapper extends AbstractLDAPStorageMapper implements
return ldapQuery; return ldapQuery;
} }
protected RoleContainerModel getTargetRoleContainer() { protected RoleContainerModel getTargetRoleContainer(RealmModel realm) {
boolean realmRolesMapping = config.isRealmRolesMapping(); boolean realmRolesMapping = config.isRealmRolesMapping();
if (realmRolesMapping) { if (realmRolesMapping) {
return realm; return realm;
@ -273,14 +273,14 @@ public class RoleLDAPStorageMapper extends AbstractLDAPStorageMapper implements
} }
@Override @Override
public UserModel proxy(LDAPObject ldapUser, UserModel delegate) { public UserModel proxy(LDAPObject ldapUser, UserModel delegate, RealmModel realm) {
final LDAPGroupMapperMode mode = config.getMode(); final LDAPGroupMapperMode mode = config.getMode();
// For IMPORT mode, all operations are performed against local DB // For IMPORT mode, all operations are performed against local DB
if (mode == LDAPGroupMapperMode.IMPORT) { if (mode == LDAPGroupMapperMode.IMPORT) {
return delegate; return delegate;
} else { } else {
return new LDAPRoleMappingsUserDelegate(delegate, ldapUser); return new LDAPRoleMappingsUserDelegate(realm, delegate, ldapUser);
} }
} }
@ -295,16 +295,18 @@ public class RoleLDAPStorageMapper extends AbstractLDAPStorageMapper implements
public class LDAPRoleMappingsUserDelegate extends UserModelDelegate { public class LDAPRoleMappingsUserDelegate extends UserModelDelegate {
private final RealmModel realm;
private final LDAPObject ldapUser; private final LDAPObject ldapUser;
private final RoleContainerModel roleContainer; private final RoleContainerModel roleContainer;
// Avoid loading role mappings from LDAP more times per-request // Avoid loading role mappings from LDAP more times per-request
private Set<RoleModel> cachedLDAPRoleMappings; private Set<RoleModel> cachedLDAPRoleMappings;
public LDAPRoleMappingsUserDelegate(UserModel user, LDAPObject ldapUser) { public LDAPRoleMappingsUserDelegate(RealmModel realm, UserModel user, LDAPObject ldapUser) {
super(user); super(user);
this.realm = realm;
this.ldapUser = ldapUser; this.ldapUser = ldapUser;
this.roleContainer = getTargetRoleContainer(); this.roleContainer = getTargetRoleContainer(realm);
} }
@Override @Override

View file

@ -194,8 +194,8 @@ public class RoleLDAPStorageMapperFactory extends AbstractLDAPStorageMapperFacto
} }
@Override @Override
protected AbstractLDAPStorageMapper createMapper(ComponentModel mapperModel, LDAPStorageProvider federationProvider, RealmModel realm) { protected AbstractLDAPStorageMapper createMapper(ComponentModel mapperModel, LDAPStorageProvider federationProvider) {
return new RoleLDAPStorageMapper(mapperModel, federationProvider, realm, this); return new RoleLDAPStorageMapper(mapperModel, federationProvider, this);
} }
protected UserRolesRetrieveStrategy getUserRolesRetrieveStrategy(String strategyKey) { protected UserRolesRetrieveStrategy getUserRolesRetrieveStrategy(String strategyKey) {

View file

@ -51,8 +51,8 @@ public class MSADUserAccountControlStorageMapper extends AbstractLDAPStorageMapp
private static final Pattern AUTH_EXCEPTION_REGEX = Pattern.compile(".*AcceptSecurityContext error, data ([0-9a-f]*), v.*"); private static final Pattern AUTH_EXCEPTION_REGEX = Pattern.compile(".*AcceptSecurityContext error, data ([0-9a-f]*), v.*");
private static final Pattern AUTH_INVALID_NEW_PASSWORD = Pattern.compile(".*error code ([0-9a-f]+) .*WILL_NOT_PERFORM.*"); private static final Pattern AUTH_INVALID_NEW_PASSWORD = Pattern.compile(".*error code ([0-9a-f]+) .*WILL_NOT_PERFORM.*");
public MSADUserAccountControlStorageMapper(ComponentModel mapperModel, LDAPStorageProvider ldapProvider, RealmModel realm) { public MSADUserAccountControlStorageMapper(ComponentModel mapperModel, LDAPStorageProvider ldapProvider) {
super(mapperModel, ldapProvider, realm); super(mapperModel, ldapProvider);
ldapProvider.setUpdater(this); ldapProvider.setUpdater(this);
} }
@ -95,22 +95,22 @@ public class MSADUserAccountControlStorageMapper extends AbstractLDAPStorageMapp
} }
@Override @Override
public UserModel proxy(LDAPObject ldapUser, UserModel delegate) { public UserModel proxy(LDAPObject ldapUser, UserModel delegate, RealmModel realm) {
return new MSADUserModelDelegate(delegate, ldapUser); return new MSADUserModelDelegate(delegate, ldapUser);
} }
@Override @Override
public void onRegisterUserToLDAP(LDAPObject ldapUser, UserModel localUser) { public void onRegisterUserToLDAP(LDAPObject ldapUser, UserModel localUser, RealmModel realm) {
} }
@Override @Override
public void onImportUserFromLDAP(LDAPObject ldapUser, UserModel user, boolean isCreate) { public void onImportUserFromLDAP(LDAPObject ldapUser, UserModel user, RealmModel realm, boolean isCreate) {
} }
@Override @Override
public boolean onAuthenticationFailure(LDAPObject ldapUser, UserModel user, AuthenticationException ldapException) { public boolean onAuthenticationFailure(LDAPObject ldapUser, UserModel user, AuthenticationException ldapException, RealmModel realm) {
String exceptionMessage = ldapException.getMessage(); String exceptionMessage = ldapException.getMessage();
Matcher m = AUTH_EXCEPTION_REGEX.matcher(exceptionMessage); Matcher m = AUTH_EXCEPTION_REGEX.matcher(exceptionMessage);
if (m.matches()) { if (m.matches()) {

View file

@ -56,7 +56,7 @@ public class MSADUserAccountControlStorageMapperFactory extends AbstractLDAPStor
} }
@Override @Override
protected AbstractLDAPStorageMapper createMapper(ComponentModel mapperModel, LDAPStorageProvider federationProvider, RealmModel realm) { protected AbstractLDAPStorageMapper createMapper(ComponentModel mapperModel, LDAPStorageProvider federationProvider) {
return new MSADUserAccountControlStorageMapper(mapperModel, federationProvider, realm); return new MSADUserAccountControlStorageMapper(mapperModel, federationProvider);
} }
} }

View file

@ -52,8 +52,8 @@ public class MSADLDSUserAccountControlStorageMapper extends AbstractLDAPStorageM
private static final Pattern AUTH_EXCEPTION_REGEX = Pattern.compile(".*AcceptSecurityContext error, data ([0-9a-f]*), v.*"); private static final Pattern AUTH_EXCEPTION_REGEX = Pattern.compile(".*AcceptSecurityContext error, data ([0-9a-f]*), v.*");
private static final Pattern AUTH_INVALID_NEW_PASSWORD = Pattern.compile("(?s).*problem 1005 \\(CONSTRAINT_ATT_TYPE\\), data [0-9a-f]*, Att 23 \\(userPassword\\).*"); private static final Pattern AUTH_INVALID_NEW_PASSWORD = Pattern.compile("(?s).*problem 1005 \\(CONSTRAINT_ATT_TYPE\\), data [0-9a-f]*, Att 23 \\(userPassword\\).*");
public MSADLDSUserAccountControlStorageMapper(ComponentModel mapperModel, LDAPStorageProvider ldapProvider, RealmModel realm) { public MSADLDSUserAccountControlStorageMapper(ComponentModel mapperModel, LDAPStorageProvider ldapProvider) {
super(mapperModel, ldapProvider, realm); super(mapperModel, ldapProvider);
ldapProvider.setUpdater(this); ldapProvider.setUpdater(this);
} }
@ -94,22 +94,22 @@ public class MSADLDSUserAccountControlStorageMapper extends AbstractLDAPStorageM
} }
@Override @Override
public UserModel proxy(LDAPObject ldapUser, UserModel delegate) { public UserModel proxy(LDAPObject ldapUser, UserModel delegate, RealmModel realm) {
return new MSADUserModelDelegate(delegate, ldapUser); return new MSADUserModelDelegate(delegate, ldapUser);
} }
@Override @Override
public void onRegisterUserToLDAP(LDAPObject ldapUser, UserModel localUser) { public void onRegisterUserToLDAP(LDAPObject ldapUser, UserModel localUser, RealmModel realm) {
} }
@Override @Override
public void onImportUserFromLDAP(LDAPObject ldapUser, UserModel user, boolean isCreate) { public void onImportUserFromLDAP(LDAPObject ldapUser, UserModel user, RealmModel realm, boolean isCreate) {
} }
@Override @Override
public boolean onAuthenticationFailure(LDAPObject ldapUser, UserModel user, AuthenticationException ldapException) { public boolean onAuthenticationFailure(LDAPObject ldapUser, UserModel user, AuthenticationException ldapException, RealmModel realm) {
String exceptionMessage = ldapException.getMessage(); String exceptionMessage = ldapException.getMessage();
Matcher m = AUTH_EXCEPTION_REGEX.matcher(exceptionMessage); Matcher m = AUTH_EXCEPTION_REGEX.matcher(exceptionMessage);
if (m.matches()) { if (m.matches()) {

View file

@ -57,7 +57,7 @@ public class MSADLDSUserAccountControlStorageMapperFactory extends AbstractLDAPS
} }
@Override @Override
protected AbstractLDAPStorageMapper createMapper(ComponentModel mapperModel, LDAPStorageProvider federationProvider, RealmModel realm) { protected AbstractLDAPStorageMapper createMapper(ComponentModel mapperModel, LDAPStorageProvider federationProvider) {
return new MSADLDSUserAccountControlStorageMapper(mapperModel, federationProvider, realm); return new MSADLDSUserAccountControlStorageMapper(mapperModel, federationProvider);
} }
} }

View file

@ -182,7 +182,7 @@ public class DefaultKeycloakSession implements KeycloakSession {
@Override @Override
public <T extends Provider> T getProvider(Class<T> clazz, ComponentModel componentModel) { public <T extends Provider> T getProvider(Class<T> clazz, ComponentModel componentModel) {
String modelId = componentModel.getProviderType() + "::" + componentModel.getId(); String modelId = componentModel.getId();
Object found = getAttribute(modelId); Object found = getAttribute(modelId);
if (found != null) { if (found != null) {

View file

@ -147,19 +147,17 @@ public class UserStorageProviderResource {
if (parentModel == null) throw new NotFoundException("Parent model not found"); if (parentModel == null) throw new NotFoundException("Parent model not found");
ComponentModel mapperModel = realm.getComponent(mapperId); ComponentModel mapperModel = realm.getComponent(mapperId);
if (mapperModel == null) throw new NotFoundException("Mapper model not found"); if (mapperModel == null) throw new NotFoundException("Mapper model not found");
LDAPStorageMapper mapper = session.getProvider(LDAPStorageMapper.class, mapperModel);
ProviderFactory factory = session.getKeycloakSessionFactory().getProviderFactory(UserStorageProvider.class, parentModel.getProviderId());
LDAPStorageProviderFactory providerFactory = (LDAPStorageProviderFactory)factory; LDAPStorageProvider ldapProvider = (LDAPStorageProvider) session.getProvider(UserStorageProvider.class, parentModel);
LDAPStorageProvider federationProvider = providerFactory.create(session, parentModel); LDAPStorageMapper mapper = session.getProvider(LDAPStorageMapper.class, mapperModel);
ServicesLogger.LOGGER.syncingDataForMapper(mapperModel.getName(), mapperModel.getProviderId(), direction); ServicesLogger.LOGGER.syncingDataForMapper(mapperModel.getName(), mapperModel.getProviderId(), direction);
SynchronizationResult syncResult; SynchronizationResult syncResult;
if ("fedToKeycloak".equals(direction)) { if ("fedToKeycloak".equals(direction)) {
syncResult = mapper.syncDataFromFederationProviderToKeycloak(mapperModel, federationProvider, session, realm); syncResult = mapper.syncDataFromFederationProviderToKeycloak(realm);
} else if ("keycloakToFed".equals(direction)) { } else if ("keycloakToFed".equals(direction)) {
syncResult = mapper.syncDataFromKeycloakToFederationProvider(mapperModel, federationProvider, session, realm); syncResult = mapper.syncDataFromKeycloakToFederationProvider(realm);
} else { } else {
throw new BadRequestException("Unknown direction: " + direction); throw new BadRequestException("Unknown direction: " + direction);
} }

View file

@ -110,7 +110,7 @@ public abstract class AbstractPhotozExampleAdapterTest extends AbstractExampleAd
return exampleDeployment(PhotozClientAuthzTestApp.DEPLOYMENT_NAME); return exampleDeployment(PhotozClientAuthzTestApp.DEPLOYMENT_NAME);
} }
@Deployment(name = RESOURCE_SERVER_ID, managed = false) @Deployment(name = RESOURCE_SERVER_ID, managed = false, testable = false)
public static WebArchive deploymentResourceServer() throws IOException { public static WebArchive deploymentResourceServer() throws IOException {
return exampleDeployment(RESOURCE_SERVER_ID); return exampleDeployment(RESOURCE_SERVER_ID);
} }

View file

@ -6,6 +6,7 @@ import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.FindBy;
import static org.keycloak.testsuite.console.page.fragment.Breadcrumb.BREADCRUMB_XPATH; import static org.keycloak.testsuite.console.page.fragment.Breadcrumb.BREADCRUMB_XPATH;
import org.openqa.selenium.NoSuchElementException;
/** /**
* *
@ -73,6 +74,8 @@ public class Client extends Clients {
private WebElement sessionsLink; private WebElement sessionsLink;
@FindBy(linkText = "Installation") @FindBy(linkText = "Installation")
private WebElement installationLink; private WebElement installationLink;
@FindBy(linkText = "Service Account Roles")
private WebElement serviceAccountRoles;
public void settings() { public void settings() {
settingsLink.click(); settingsLink.click();
@ -102,6 +105,14 @@ public class Client extends Clients {
installationLink.click(); installationLink.click();
} }
public boolean isServiceAccountRolesDisplayed() {
try {
return serviceAccountRoles.isDisplayed();
} catch (NoSuchElementException ex) {
}
return false;
}
public WebElement getTabs() { public WebElement getTabs() {
return tabs; return tabs;
} }

View file

@ -22,6 +22,7 @@ import org.junit.Test;
import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.testsuite.console.page.clients.settings.ClientSettings; import org.keycloak.testsuite.console.page.clients.settings.ClientSettings;
import org.keycloak.testsuite.util.Timer; import org.keycloak.testsuite.util.Timer;
import org.openqa.selenium.By;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import java.util.ArrayList; import java.util.ArrayList;
@ -32,7 +33,6 @@ import static org.keycloak.testsuite.auth.page.login.Login.OIDC;
import static org.keycloak.testsuite.auth.page.login.Login.SAML; import static org.keycloak.testsuite.auth.page.login.Login.SAML;
import static org.keycloak.testsuite.console.page.clients.settings.ClientSettingsForm.OidcAccessType.BEARER_ONLY; import static org.keycloak.testsuite.console.page.clients.settings.ClientSettingsForm.OidcAccessType.BEARER_ONLY;
import static org.keycloak.testsuite.console.page.clients.settings.ClientSettingsForm.OidcAccessType.CONFIDENTIAL; import static org.keycloak.testsuite.console.page.clients.settings.ClientSettingsForm.OidcAccessType.CONFIDENTIAL;
import static org.keycloak.testsuite.console.page.clients.settings.ClientSettingsForm.SAMLClientSettingsForm.*;
import static org.keycloak.testsuite.util.WaitUtils.pause; import static org.keycloak.testsuite.util.WaitUtils.pause;
/** /**
@ -109,6 +109,28 @@ public class ClientSettingsTest extends AbstractClientTest {
assertClientSettingsEqual(newClient, found); assertClientSettingsEqual(newClient, found);
} }
//KEYCLOAK-4022
@Test
public void testOIDCConfidentialServiceAccountRolesTab() {
newClient = createClientRep("oidc-service-account-tab", OIDC);
createClient(newClient);
newClient.setRedirectUris(TEST_REDIRECT_URIs);
newClient.setPublicClient(false);
clientSettingsPage.form().setAccessType(CONFIDENTIAL);
clientSettingsPage.form().setServiceAccountsEnabled(true);
assertTrue(clientSettingsPage.form().isServiceAccountsEnabled());
//check if Service Account Roles tab is not present
assertFalse(clientSettingsPage.tabs().isServiceAccountRolesDisplayed());
clientSettingsPage.form().setRedirectUris(TEST_REDIRECT_URIs);
clientSettingsPage.form().save();
//should be there now
assertTrue(clientSettingsPage.tabs().getTabs().findElement(By.linkText("Service Account Roles")).isDisplayed());
}
@Test @Test
public void saveOIDCConfidentialWithoutRedirectURIs() { public void saveOIDCConfidentialWithoutRedirectURIs() {
newClient = createClientRep("oidc-confidential", OIDC); newClient = createClientRep("oidc-confidential", OIDC);

View file

@ -115,7 +115,7 @@ public class LDAPGroupMapper2WaySyncTest {
realm.updateComponent(mapperModel); realm.updateComponent(mapperModel);
// Sync from Keycloak into LDAP // Sync from Keycloak into LDAP
SynchronizationResult syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromKeycloakToFederationProvider(mapperModel, ldapProvider, session, realm); SynchronizationResult syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromKeycloakToFederationProvider(realm);
LDAPTestUtils.assertSyncEquals(syncResult, 4, 0, 0, 0); LDAPTestUtils.assertSyncEquals(syncResult, 4, 0, 0, 0);
} finally { } finally {
keycloakRule.stopSession(session, true); keycloakRule.stopSession(session, true);
@ -143,7 +143,7 @@ public class LDAPGroupMapper2WaySyncTest {
LDAPStorageProvider ldapProvider = LDAPTestUtils.getLdapProvider(session, ldapModel); LDAPStorageProvider ldapProvider = LDAPTestUtils.getLdapProvider(session, ldapModel);
// Sync from LDAP back into Keycloak // Sync from LDAP back into Keycloak
SynchronizationResult syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(mapperModel, ldapProvider, session, realm); SynchronizationResult syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(realm);
LDAPTestUtils.assertSyncEquals(syncResult, 4, 0, 0, 0); LDAPTestUtils.assertSyncEquals(syncResult, 4, 0, 0, 0);
// Assert groups are imported to keycloak. All are at top level // Assert groups are imported to keycloak. All are at top level
@ -179,7 +179,7 @@ public class LDAPGroupMapper2WaySyncTest {
realm.updateComponent(mapperModel); realm.updateComponent(mapperModel);
// Sync from Keycloak into LDAP // Sync from Keycloak into LDAP
SynchronizationResult syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromKeycloakToFederationProvider(mapperModel, ldapProvider, session, realm); SynchronizationResult syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromKeycloakToFederationProvider(realm);
LDAPTestUtils.assertSyncEquals(syncResult, 4, 0, 0, 0); LDAPTestUtils.assertSyncEquals(syncResult, 4, 0, 0, 0);
} finally { } finally {
keycloakRule.stopSession(session, true); keycloakRule.stopSession(session, true);
@ -207,7 +207,7 @@ public class LDAPGroupMapper2WaySyncTest {
LDAPStorageProvider ldapProvider = LDAPTestUtils.getLdapProvider(session, ldapModel); LDAPStorageProvider ldapProvider = LDAPTestUtils.getLdapProvider(session, ldapModel);
// Sync from LDAP back into Keycloak // Sync from LDAP back into Keycloak
SynchronizationResult syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(mapperModel, ldapProvider, session, realm); SynchronizationResult syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(realm);
LDAPTestUtils.assertSyncEquals(syncResult, 4, 0, 0, 0); LDAPTestUtils.assertSyncEquals(syncResult, 4, 0, 0, 0);
// Assert groups are imported to keycloak. All are at top level // Assert groups are imported to keycloak. All are at top level
@ -242,7 +242,7 @@ public class LDAPGroupMapper2WaySyncTest {
LDAPTestUtils.createLDAPGroup(session, realm, ldapModel, "group3"); LDAPTestUtils.createLDAPGroup(session, realm, ldapModel, "group3");
// Sync and assert our group is still in LDAP // Sync and assert our group is still in LDAP
SynchronizationResult syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromKeycloakToFederationProvider(mapperModel, ldapProvider, session, realm); SynchronizationResult syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromKeycloakToFederationProvider(realm);
LDAPTestUtils.assertSyncEquals(syncResult, 0, 4, 0, 0); LDAPTestUtils.assertSyncEquals(syncResult, 0, 4, 0, 0);
Assert.assertNotNull(LDAPTestUtils.getGroupMapper(mapperModel, ldapProvider, realm).loadLDAPGroupByName("group3")); Assert.assertNotNull(LDAPTestUtils.getGroupMapper(mapperModel, ldapProvider, realm).loadLDAPGroupByName("group3"));
@ -251,7 +251,7 @@ public class LDAPGroupMapper2WaySyncTest {
realm.updateComponent(mapperModel); realm.updateComponent(mapperModel);
// Sync and assert group removed from LDAP // Sync and assert group removed from LDAP
syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromKeycloakToFederationProvider(mapperModel, ldapProvider, session, realm); syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromKeycloakToFederationProvider(realm);
LDAPTestUtils.assertSyncEquals(syncResult, 0, 4, 1, 0); LDAPTestUtils.assertSyncEquals(syncResult, 0, 4, 1, 0);
Assert.assertNull(LDAPTestUtils.getGroupMapper(mapperModel, ldapProvider, realm).loadLDAPGroupByName("group3")); Assert.assertNull(LDAPTestUtils.getGroupMapper(mapperModel, ldapProvider, realm).loadLDAPGroupByName("group3"));
} }

View file

@ -147,7 +147,7 @@ public class LDAPGroupMapperSyncTest {
LDAPUtils.addMember(ldapProvider, MembershipType.DN, LDAPConstants.MEMBER, group12, group1, true); LDAPUtils.addMember(ldapProvider, MembershipType.DN, LDAPConstants.MEMBER, group12, group1, true);
try { try {
new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(mapperModel, ldapProvider, session, realm); new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(realm);
Assert.fail("Not expected group sync to pass"); Assert.fail("Not expected group sync to pass");
} catch (ModelException expected) { } catch (ModelException expected) {
Assert.assertTrue(expected.getMessage().contains("Recursion detected")); Assert.assertTrue(expected.getMessage().contains("Recursion detected"));
@ -157,7 +157,7 @@ public class LDAPGroupMapperSyncTest {
LDAPTestUtils.updateGroupMapperConfigOptions(mapperModel, GroupMapperConfig.PRESERVE_GROUP_INHERITANCE, "false"); LDAPTestUtils.updateGroupMapperConfigOptions(mapperModel, GroupMapperConfig.PRESERVE_GROUP_INHERITANCE, "false");
realm.updateComponent(mapperModel); realm.updateComponent(mapperModel);
new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(mapperModel, ldapProvider, session, realm); new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(realm);
// Assert groups are imported to keycloak. All are at top level // Assert groups are imported to keycloak. All are at top level
GroupModel kcGroup1 = KeycloakModelUtils.findGroupByPath(realm, "/group1"); GroupModel kcGroup1 = KeycloakModelUtils.findGroupByPath(realm, "/group1");
@ -206,7 +206,7 @@ public class LDAPGroupMapperSyncTest {
GroupLDAPStorageMapper groupMapper = LDAPTestUtils.getGroupMapper(mapperModel, ldapProvider, realm); GroupLDAPStorageMapper groupMapper = LDAPTestUtils.getGroupMapper(mapperModel, ldapProvider, realm);
// Sync groups with inheritance // Sync groups with inheritance
SynchronizationResult syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(mapperModel, ldapProvider, session, realm); SynchronizationResult syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(realm);
LDAPTestUtils.assertSyncEquals(syncResult, 3, 0, 0, 0); LDAPTestUtils.assertSyncEquals(syncResult, 3, 0, 0, 0);
// Assert groups are imported to keycloak including their inheritance from LDAP // Assert groups are imported to keycloak including their inheritance from LDAP
@ -232,7 +232,7 @@ public class LDAPGroupMapperSyncTest {
ldapProvider.getLdapIdentityStore().update(group12); ldapProvider.getLdapIdentityStore().update(group12);
// Sync and assert groups updated // Sync and assert groups updated
syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(mapperModel, ldapProvider, session, realm); syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(realm);
LDAPTestUtils.assertSyncEquals(syncResult, 0, 3, 0, 0); LDAPTestUtils.assertSyncEquals(syncResult, 0, 3, 0, 0);
// Assert attributes changed in keycloak // Assert attributes changed in keycloak
@ -254,7 +254,7 @@ public class LDAPGroupMapperSyncTest {
LDAPStorageProvider ldapProvider = LDAPTestUtils.getLdapProvider(session, ldapModel); LDAPStorageProvider ldapProvider = LDAPTestUtils.getLdapProvider(session, ldapModel);
// Sync groups with inheritance // Sync groups with inheritance
SynchronizationResult syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(mapperModel, ldapProvider, session, realm); SynchronizationResult syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(realm);
LDAPTestUtils.assertSyncEquals(syncResult, 3, 0, 0, 0); LDAPTestUtils.assertSyncEquals(syncResult, 3, 0, 0, 0);
// Assert groups are imported to keycloak including their inheritance from LDAP // Assert groups are imported to keycloak including their inheritance from LDAP
@ -271,7 +271,7 @@ public class LDAPGroupMapperSyncTest {
realm.moveGroup(model2, kcGroup1); realm.moveGroup(model2, kcGroup1);
// Sync groups again from LDAP. Nothing deleted // Sync groups again from LDAP. Nothing deleted
syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(mapperModel, ldapProvider, session, realm); syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(realm);
LDAPTestUtils.assertSyncEquals(syncResult, 0, 3, 0, 0); LDAPTestUtils.assertSyncEquals(syncResult, 0, 3, 0, 0);
Assert.assertNotNull(KeycloakModelUtils.findGroupByPath(realm, "/group1/group11")); Assert.assertNotNull(KeycloakModelUtils.findGroupByPath(realm, "/group1/group11"));
@ -284,7 +284,7 @@ public class LDAPGroupMapperSyncTest {
realm.updateComponent(mapperModel); realm.updateComponent(mapperModel);
// Sync groups again from LDAP. Assert LDAP non-existing groups deleted // Sync groups again from LDAP. Assert LDAP non-existing groups deleted
syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(mapperModel, ldapProvider, session, realm); syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(realm);
Assert.assertEquals(3, syncResult.getUpdated()); Assert.assertEquals(3, syncResult.getUpdated());
Assert.assertTrue(syncResult.getRemoved() == 2); Assert.assertTrue(syncResult.getRemoved() == 2);
@ -317,7 +317,7 @@ public class LDAPGroupMapperSyncTest {
LDAPTestUtils.removeAllLDAPUsers(ldapProvider, realm); LDAPTestUtils.removeAllLDAPUsers(ldapProvider, realm);
LDAPObject johnLdap = LDAPTestUtils.addLDAPUser(ldapProvider, realm, "johnkeycloak", "John", "Doe", "john@email.org", null, "1234"); LDAPObject johnLdap = LDAPTestUtils.addLDAPUser(ldapProvider, realm, "johnkeycloak", "John", "Doe", "john@email.org", null, "1234");
LDAPTestUtils.updateLDAPPassword(ldapProvider, johnLdap, "Password1"); LDAPTestUtils.updateLDAPPassword(ldapProvider, johnLdap, "Password1");
groupMapper.addGroupMappingInLDAP("group11", johnLdap); groupMapper.addGroupMappingInLDAP(realm, "group11", johnLdap);
// Assert groups not yet imported to Keycloak DB // Assert groups not yet imported to Keycloak DB
Assert.assertNull(KeycloakModelUtils.findGroupByPath(realm, "/group1")); Assert.assertNull(KeycloakModelUtils.findGroupByPath(realm, "/group1"));

View file

@ -103,7 +103,7 @@ public class LDAPGroupMapperTest {
// Sync LDAP groups to Keycloak DB // Sync LDAP groups to Keycloak DB
ComponentModel mapperModel = LDAPTestUtils.getSubcomponentByName(appRealm,ldapModel, "groupsMapper"); ComponentModel mapperModel = LDAPTestUtils.getSubcomponentByName(appRealm,ldapModel, "groupsMapper");
new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(mapperModel, ldapFedProvider, session, appRealm); new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(appRealm);
// Delete all LDAP users // Delete all LDAP users
LDAPTestUtils.removeAllLDAPUsers(ldapFedProvider, appRealm); LDAPTestUtils.removeAllLDAPUsers(ldapFedProvider, appRealm);
@ -220,8 +220,8 @@ public class LDAPGroupMapperTest {
GroupLDAPStorageMapper groupMapper = LDAPTestUtils.getGroupMapper(mapperModel, ldapProvider, appRealm); GroupLDAPStorageMapper groupMapper = LDAPTestUtils.getGroupMapper(mapperModel, ldapProvider, appRealm);
LDAPObject maryLdap = ldapProvider.loadLDAPUserByUsername(appRealm, "marykeycloak"); LDAPObject maryLdap = ldapProvider.loadLDAPUserByUsername(appRealm, "marykeycloak");
groupMapper.addGroupMappingInLDAP("group1", maryLdap); groupMapper.addGroupMappingInLDAP(appRealm, "group1", maryLdap);
groupMapper.addGroupMappingInLDAP("group11", maryLdap); groupMapper.addGroupMappingInLDAP(appRealm, "group11", maryLdap);
// Add some group mapping to model // Add some group mapping to model
mary.joinGroup(group12); mary.joinGroup(group12);
@ -282,8 +282,8 @@ public class LDAPGroupMapperTest {
GroupLDAPStorageMapper groupMapper = LDAPTestUtils.getGroupMapper(mapperModel, ldapProvider, appRealm); GroupLDAPStorageMapper groupMapper = LDAPTestUtils.getGroupMapper(mapperModel, ldapProvider, appRealm);
LDAPObject robLdap = ldapProvider.loadLDAPUserByUsername(appRealm, "robkeycloak"); LDAPObject robLdap = ldapProvider.loadLDAPUserByUsername(appRealm, "robkeycloak");
groupMapper.addGroupMappingInLDAP("group11", robLdap); groupMapper.addGroupMappingInLDAP(appRealm, "group11", robLdap);
groupMapper.addGroupMappingInLDAP("group12", robLdap); groupMapper.addGroupMappingInLDAP(appRealm, "group12", robLdap);
// Get user and check that he has requested groupa from LDAP // Get user and check that he has requested groupa from LDAP
UserModel rob = session.users().getUserByUsername("robkeycloak", appRealm); UserModel rob = session.users().getUserByUsername("robkeycloak", appRealm);
@ -349,7 +349,7 @@ public class LDAPGroupMapperTest {
LDAPUtils.addMember(ldapProvider, MembershipType.DN, LDAPConstants.MEMBER, group2, nonExistentLdapUser, true); LDAPUtils.addMember(ldapProvider, MembershipType.DN, LDAPConstants.MEMBER, group2, nonExistentLdapUser, true);
// 4 - Check group members. Just existing user rob should be present // 4 - Check group members. Just existing user rob should be present
groupMapper.syncDataFromFederationProviderToKeycloak(); groupMapper.syncDataFromFederationProviderToKeycloak(appRealm);
GroupModel kcGroup2 = KeycloakModelUtils.findGroupByPath(appRealm, "/group2"); GroupModel kcGroup2 = KeycloakModelUtils.findGroupByPath(appRealm, "/group2");
List<UserModel> groupUsers = session.users().getGroupMembers(appRealm, kcGroup2, 0, 5); List<UserModel> groupUsers = session.users().getGroupMembers(appRealm, kcGroup2, 0, 5);
Assert.assertEquals(1, groupUsers.size()); Assert.assertEquals(1, groupUsers.size());

View file

@ -238,11 +238,11 @@ public class LDAPTestUtils {
ComponentModel mapperModel = getSubcomponentByName(realm, providerModel, "realmRolesMapper"); ComponentModel mapperModel = getSubcomponentByName(realm, providerModel, "realmRolesMapper");
RoleLDAPStorageMapper roleMapper = getRoleMapper(mapperModel, ldapProvider, realm); RoleLDAPStorageMapper roleMapper = getRoleMapper(mapperModel, ldapProvider, realm);
roleMapper.syncDataFromFederationProviderToKeycloak(); roleMapper.syncDataFromFederationProviderToKeycloak(realm);
mapperModel = getSubcomponentByName(realm, providerModel, "financeRolesMapper"); mapperModel = getSubcomponentByName(realm, providerModel, "financeRolesMapper");
roleMapper = getRoleMapper(mapperModel, ldapProvider, realm); roleMapper = getRoleMapper(mapperModel, ldapProvider, realm);
roleMapper.syncDataFromFederationProviderToKeycloak(); roleMapper.syncDataFromFederationProviderToKeycloak(realm);
} }
public static void removeAllLDAPUsers(LDAPStorageProvider ldapProvider, RealmModel realm) { public static void removeAllLDAPUsers(LDAPStorageProvider ldapProvider, RealmModel realm) {
@ -296,11 +296,11 @@ public class LDAPTestUtils {
} }
public static GroupLDAPStorageMapper getGroupMapper(ComponentModel mapperModel, LDAPStorageProvider ldapProvider, RealmModel realm) { public static GroupLDAPStorageMapper getGroupMapper(ComponentModel mapperModel, LDAPStorageProvider ldapProvider, RealmModel realm) {
return new GroupLDAPStorageMapper(mapperModel, ldapProvider, realm, new GroupLDAPStorageMapperFactory()); return new GroupLDAPStorageMapper(mapperModel, ldapProvider, new GroupLDAPStorageMapperFactory());
} }
public static RoleLDAPStorageMapper getRoleMapper(ComponentModel mapperModel, LDAPStorageProvider ldapProvider, RealmModel realm) { public static RoleLDAPStorageMapper getRoleMapper(ComponentModel mapperModel, LDAPStorageProvider ldapProvider, RealmModel realm) {
return new RoleLDAPStorageMapper(mapperModel, ldapProvider, realm, new RoleLDAPStorageMapperFactory()); return new RoleLDAPStorageMapper(mapperModel, ldapProvider, new RoleLDAPStorageMapperFactory());
} }

View file

@ -46,7 +46,7 @@
<kc-tooltip>{{mapperType.helpText}}</kc-tooltip> <kc-tooltip>{{mapperType.helpText}}</kc-tooltip>
</div> </div>
<kc-component-config realm="realm" config="mapper.config" properties="mapperType.properties"></kc-component-config> <kc-component-config realm="realm" clients="clients" config="mapper.config" properties="mapperType.properties"></kc-component-config>
</fieldset> </fieldset>