port kerberos

This commit is contained in:
Bill Burke 2016-11-21 11:33:44 -05:00
parent 8794416241
commit 19575b2c8f
37 changed files with 321 additions and 255 deletions

View file

@ -28,6 +28,10 @@
<artifactId>keycloak-kerberos-federation</artifactId>
<name>Keycloak Kerberos Federation</name>
<description />
<properties>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
</properties>
<dependencies>
<dependency>

View file

@ -19,7 +19,6 @@ package org.keycloak.federation.kerberos;
import org.keycloak.common.constants.KerberosConstants;
import org.keycloak.component.ComponentModel;
import org.keycloak.models.UserFederationProviderModel;
import java.util.Map;
@ -30,45 +29,32 @@ import java.util.Map;
*/
public abstract class CommonKerberosConfig {
protected UserFederationProviderModel providerModel;
protected ComponentModel componentModel;
public CommonKerberosConfig(UserFederationProviderModel userFederationProvider) {
this.providerModel = userFederationProvider;
}
public CommonKerberosConfig(ComponentModel componentModel) {
this.componentModel = componentModel;
}
// Should be always true for KerberosFederationProvider
public boolean isAllowKerberosAuthentication() {
if (providerModel != null) return Boolean.valueOf(getConfig().get(KerberosConstants.ALLOW_KERBEROS_AUTHENTICATION));
else return Boolean.valueOf(componentModel.getConfig().getFirst(KerberosConstants.ALLOW_KERBEROS_AUTHENTICATION));
return Boolean.valueOf(componentModel.getConfig().getFirst(KerberosConstants.ALLOW_KERBEROS_AUTHENTICATION));
}
public String getKerberosRealm() {
if (providerModel != null) return getConfig().get(KerberosConstants.KERBEROS_REALM);
else return componentModel.getConfig().getFirst(KerberosConstants.KERBEROS_REALM);
return componentModel.getConfig().getFirst(KerberosConstants.KERBEROS_REALM);
}
public String getServerPrincipal() {
if (providerModel != null) return getConfig().get(KerberosConstants.SERVER_PRINCIPAL);
else return componentModel.getConfig().getFirst(KerberosConstants.SERVER_PRINCIPAL);
return componentModel.getConfig().getFirst(KerberosConstants.SERVER_PRINCIPAL);
}
public String getKeyTab() {
if (providerModel != null) return getConfig().get(KerberosConstants.KEYTAB);
else return componentModel.getConfig().getFirst(KerberosConstants.KEYTAB);
return componentModel.getConfig().getFirst(KerberosConstants.KEYTAB);
}
public boolean isDebug() {
if (providerModel != null) return Boolean.valueOf(getConfig().get(KerberosConstants.DEBUG));
else return Boolean.valueOf(componentModel.getConfig().getFirst(KerberosConstants.DEBUG));
return Boolean.valueOf(componentModel.getConfig().getFirst(KerberosConstants.DEBUG));
}
protected Map<String, String> getConfig() {
return providerModel.getConfig();
}
}

View file

@ -18,9 +18,12 @@
package org.keycloak.federation.kerberos;
import org.keycloak.common.constants.KerberosConstants;
import org.keycloak.component.ComponentModel;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProvider.EditMode;
/**
* Configuration specific to {@link KerberosFederationProvider}
@ -29,25 +32,25 @@ import org.keycloak.models.UserFederationProviderModel;
*/
public class KerberosConfig extends CommonKerberosConfig {
public KerberosConfig(UserFederationProviderModel userFederationProvider) {
super(userFederationProvider);
public KerberosConfig(ComponentModel component) {
super(component);
}
public UserFederationProvider.EditMode getEditMode() {
String editModeString = getConfig().get(LDAPConstants.EDIT_MODE);
public EditMode getEditMode() {
String editModeString = componentModel.getConfig().getFirst(LDAPConstants.EDIT_MODE);
if (editModeString == null) {
return UserFederationProvider.EditMode.UNSYNCED;
return EditMode.UNSYNCED;
} else {
return UserFederationProvider.EditMode.valueOf(editModeString);
return EditMode.valueOf(editModeString);
}
}
public boolean isAllowPasswordAuthentication() {
return Boolean.valueOf(getConfig().get(KerberosConstants.ALLOW_PASSWORD_AUTHENTICATION));
return Boolean.valueOf(componentModel.getConfig().getFirst(KerberosConstants.ALLOW_PASSWORD_AUTHENTICATION));
}
public boolean isUpdateProfileFirstLogin() {
return Boolean.valueOf(getConfig().get(KerberosConstants.UPDATE_PROFILE_FIRST_LOGIN));
return Boolean.valueOf(componentModel.getConfig().getFirst(KerberosConstants.UPDATE_PROFILE_FIRST_LOGIN));
}
}

View file

@ -19,7 +19,10 @@ package org.keycloak.federation.kerberos;
import org.jboss.logging.Logger;
import org.keycloak.common.constants.KerberosConstants;
import org.keycloak.credential.CredentialAuthentication;
import org.keycloak.credential.CredentialInput;
import org.keycloak.credential.CredentialInputUpdater;
import org.keycloak.credential.CredentialInputValidator;
import org.keycloak.credential.CredentialModel;
import org.keycloak.federation.kerberos.impl.KerberosUsernamePasswordAuthenticator;
import org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator;
@ -34,6 +37,10 @@ import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserManager;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.user.ImportedUserValidation;
import org.keycloak.storage.user.UserLookupProvider;
import java.util.Collections;
import java.util.HashMap;
@ -45,17 +52,22 @@ import java.util.Set;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class KerberosFederationProvider implements UserFederationProvider {
public class KerberosFederationProvider implements UserStorageProvider,
UserLookupProvider,
CredentialInputValidator,
CredentialInputUpdater,
CredentialAuthentication,
ImportedUserValidation {
private static final Logger logger = Logger.getLogger(KerberosFederationProvider.class);
public static final String KERBEROS_PRINCIPAL = "KERBEROS_PRINCIPAL";
protected KeycloakSession session;
protected UserFederationProviderModel model;
protected UserStorageProviderModel model;
protected KerberosConfig kerberosConfig;
protected KerberosFederationProviderFactory factory;
public KerberosFederationProvider(KeycloakSession session,UserFederationProviderModel model, KerberosFederationProviderFactory factory) {
public KerberosFederationProvider(KeycloakSession session, UserStorageProviderModel model, KerberosFederationProviderFactory factory) {
this.session = session;
this.model = model;
this.kerberosConfig = new KerberosConfig(model);
@ -63,35 +75,20 @@ public class KerberosFederationProvider implements UserFederationProvider {
}
@Override
public UserModel validateAndProxy(RealmModel realm, UserModel local) {
if (!isValid(realm, local)) {
public UserModel validate(RealmModel realm, UserModel user) {
if (!isValid(realm, user)) {
return null;
}
if (kerberosConfig.getEditMode() == EditMode.READ_ONLY) {
return new ReadOnlyKerberosUserModelDelegate(local, this);
return new ReadOnlyKerberosUserModelDelegate(user, this);
} else {
return local;
return user;
}
}
@Override
public boolean synchronizeRegistrations() {
return false;
}
@Override
public UserModel register(RealmModel realm, UserModel user) {
return null;
}
@Override
public boolean removeUser(RealmModel realm, UserModel user) {
return true;
}
@Override
public UserModel getUserByUsername(RealmModel realm, String username) {
public UserModel getUserByUsername(String username, RealmModel realm) {
KerberosUsernamePasswordAuthenticator authenticator = factory.createKerberosUsernamePasswordAuthenticator(kerberosConfig);
if (authenticator.isUserAvailable(username)) {
// Case when method was called with username including kerberos realm like john@REALM.ORG . Authenticator already checked that kerberos realm was correct
@ -106,18 +103,13 @@ public class KerberosFederationProvider implements UserFederationProvider {
}
@Override
public UserModel getUserByEmail(RealmModel realm, String email) {
public UserModel getUserByEmail(String email, RealmModel realm) {
return null;
}
@Override
public List<UserModel> searchByAttributes(Map<String, String> attributes, RealmModel realm, int maxResults) {
return Collections.emptyList();
}
@Override
public List<UserModel> getGroupMembers(RealmModel realm, GroupModel group, int firstResult, int maxResults) {
return Collections.emptyList();
public UserModel getUserById(String id, RealmModel realm) {
return null;
}
@Override
@ -135,7 +127,6 @@ public class KerberosFederationProvider implements UserFederationProvider {
}
@Override
public boolean isValid(RealmModel realm, UserModel local) {
// KerberosUsernamePasswordAuthenticator.isUserAvailable is an overhead, so avoid it for now
@ -143,13 +134,6 @@ public class KerberosFederationProvider implements UserFederationProvider {
return kerberosPrincipal.equalsIgnoreCase(local.getFirstAttribute(KERBEROS_PRINCIPAL));
}
@Override
public Set<String> getSupportedCredentialTypes() {
Set<String> supportedCredTypes = new HashSet<String>();
supportedCredTypes.add(UserCredentialModel.KERBEROS);
return supportedCredTypes;
}
@Override
public boolean updateCredential(RealmModel realm, UserModel user, CredentialInput input) {
if (!(input instanceof UserCredentialModel) || !CredentialModel.PASSWORD.equals(input.getType())) return false;
@ -174,6 +158,11 @@ public class KerberosFederationProvider implements UserFederationProvider {
return credentialType.equals(CredentialModel.KERBEROS) || (kerberosConfig.isAllowPasswordAuthentication() && credentialType.equals(CredentialModel.PASSWORD));
}
@Override
public boolean supportsCredentialAuthenticationFor(String type) {
return CredentialModel.KERBEROS.equals(type);
}
@Override
public boolean isConfiguredFor(RealmModel realm, UserModel user, String credentialType) {
return supportsCredentialType(credentialType);
@ -199,7 +188,9 @@ public class KerberosFederationProvider implements UserFederationProvider {
}
@Override
public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel credential) {
public CredentialValidationOutput authenticate(RealmModel realm, CredentialInput input) {
if (!(input instanceof UserCredentialModel)) return null;
UserCredentialModel credential = (UserCredentialModel)input;
if (credential.getType().equals(UserCredentialModel.KERBEROS)) {
String spnegoToken = credential.getValue();
SPNEGOAuthenticator spnegoAuthenticator = factory.createSPNEGOAuthenticator(spnegoToken, kerberosConfig);
@ -226,7 +217,7 @@ public class KerberosFederationProvider implements UserFederationProvider {
}
} else {
return CredentialValidationOutput.failed();
return null;
}
}
@ -243,22 +234,23 @@ public class KerberosFederationProvider implements UserFederationProvider {
* @return user if found or successfully created. Null if user with same username already exists, but is not linked to this provider
*/
protected UserModel findOrCreateAuthenticatedUser(RealmModel realm, String username) {
UserModel user = session.userStorage().getUserByUsername(username, realm);
UserModel user = session.userLocalStorage().getUserByUsername(username, realm);
if (user != null) {
user = session.users().getUserById(user.getId(), realm); // make sure we get a cached instance
logger.debug("Kerberos authenticated user " + username + " found in Keycloak storage");
if (!model.getId().equals(user.getFederationLink())) {
logger.warn("User with username " + username + " already exists, but is not linked to provider [" + model.getDisplayName() + "]");
logger.warn("User with username " + username + " already exists, but is not linked to provider [" + model.getName() + "]");
return null;
} else {
UserModel proxied = validateAndProxy(realm, user);
UserModel proxied = validate(realm, user);
if (proxied != null) {
return proxied;
} else {
logger.warn("User with username " + username + " already exists and is linked to provider [" + model.getDisplayName() +
logger.warn("User with username " + username + " already exists and is linked to provider [" + model.getName() +
"] but kerberos principal is not correct. Kerberos principal on user is: " + user.getFirstAttribute(KERBEROS_PRINCIPAL));
logger.warn("Will re-create user");
new UserManager(session).removeUser(realm, user, session.userStorage());
new UserManager(session).removeUser(realm, user, session.userLocalStorage());
}
}
}
@ -272,7 +264,7 @@ public class KerberosFederationProvider implements UserFederationProvider {
String email = username + "@" + kerberosConfig.getKerberosRealm().toLowerCase();
logger.debugf("Creating kerberos user: %s, email: %s to local Keycloak storage", username, email);
UserModel user = session.userStorage().addUser(realm, username);
UserModel user = session.userLocalStorage().addUser(realm, username);
user.setEnabled(true);
user.setEmail(email);
user.setFederationLink(model.getId());
@ -282,6 +274,6 @@ public class KerberosFederationProvider implements UserFederationProvider {
user.addRequiredAction(UserModel.RequiredAction.UPDATE_PROFILE);
}
return validateAndProxy(realm, user);
return validate(realm, user);
}
}

View file

@ -19,18 +19,29 @@ package org.keycloak.federation.kerberos;
import org.jboss.logging.Logger;
import org.keycloak.Config;
import org.keycloak.common.constants.KerberosConstants;
import org.keycloak.component.ComponentModel;
import org.keycloak.component.ComponentValidationException;
import org.keycloak.federation.kerberos.impl.KerberosServerSubjectAuthenticator;
import org.keycloak.federation.kerberos.impl.KerberosUsernamePasswordAuthenticator;
import org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderFactory;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserFederationSyncResult;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.provider.ProviderConfigurationBuilder;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderFactory;
import org.keycloak.storage.UserStorageProviderModel;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Set;
/**
@ -39,18 +50,14 @@ import java.util.Set;
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class KerberosFederationProviderFactory implements UserFederationProviderFactory {
public class KerberosFederationProviderFactory implements UserStorageProviderFactory<KerberosFederationProvider> {
private static final Logger logger = Logger.getLogger(KerberosFederationProviderFactory.class);
public static final String PROVIDER_NAME = "kerberos";
@Override
public UserFederationProvider getInstance(KeycloakSession session, UserFederationProviderModel model) {
return new KerberosFederationProvider(session, model, this);
}
@Override
public Set<String> getConfigurationOptions() {
return Collections.emptySet();
public KerberosFederationProvider create(KeycloakSession session, ComponentModel model) {
return new KerberosFederationProvider(session, new UserStorageProviderModel(model), this);
}
@Override
@ -58,23 +65,62 @@ public class KerberosFederationProviderFactory implements UserFederationProvider
return PROVIDER_NAME;
}
@Override
public UserFederationSyncResult syncAllUsers(KeycloakSessionFactory sessionFactory, String realmId, UserFederationProviderModel model) {
logger.warn("Sync users not supported for this provider");
return UserFederationSyncResult.empty();
protected static final List<ProviderConfigProperty> configProperties;
static {
configProperties = getConfigProps();
}
@Override
public UserFederationSyncResult syncChangedUsers(KeycloakSessionFactory sessionFactory, String realmId, UserFederationProviderModel model, Date lastSync) {
logger.warn("Sync users not supported for this provider");
return UserFederationSyncResult.empty();
private static List<ProviderConfigProperty> getConfigProps() {
return ProviderConfigurationBuilder.create()
.property().name(KerberosConstants.KERBEROS_REALM)
.label("kerberos-realm")
.helpText("kerberos-realm.tooltip")
.type(ProviderConfigProperty.STRING_TYPE)
.add()
.property().name(KerberosConstants.SERVER_PRINCIPAL)
.label("server-principal")
.helpText("server-principal.tooltip")
.type(ProviderConfigProperty.STRING_TYPE)
.add()
.property().name(KerberosConstants.KEYTAB)
.label("keytab")
.helpText("keytab.tooltip")
.type(ProviderConfigProperty.STRING_TYPE)
.add()
.property().name(KerberosConstants.DEBUG)
.label("debug")
.helpText("debug.tooltip")
.type(ProviderConfigProperty.BOOLEAN_TYPE)
.defaultValue("false")
.add()
.property().name(KerberosConstants.ALLOW_PASSWORD_AUTHENTICATION)
.label("allow-password-authentication")
.helpText("allow-password-authentication.tooltip")
.type(ProviderConfigProperty.BOOLEAN_TYPE)
.defaultValue("false")
.add()
.property().name(LDAPConstants.EDIT_MODE)
.label("edit-mode")
.helpText("edit-mode.tooltip")
.type(ProviderConfigProperty.LIST_TYPE)
.options(UserStorageProvider.EditMode.READ_ONLY.toString(), UserStorageProvider.EditMode.UNSYNCED.toString())
.add()
.property().name(KerberosConstants.UPDATE_PROFILE_FIRST_LOGIN)
.label("update-profile-first-login")
.helpText("update-profile-first-login.tooltip")
.type(ProviderConfigProperty.BOOLEAN_TYPE)
.defaultValue("false")
.add()
.build();
}
@Override
public UserFederationProvider create(KeycloakSession session) {
throw new IllegalAccessError("Illegal to call this method");
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public void init(Config.Scope config) {

View file

@ -19,6 +19,7 @@ package org.keycloak.storage.ldap;
import org.keycloak.common.util.MultivaluedHashMap;
import org.keycloak.models.LDAPConstants;
import org.keycloak.storage.UserStorageProvider;
import javax.naming.directory.SearchControls;
import java.util.Collection;
@ -171,12 +172,12 @@ public class LDAPConfig {
return null;
}
public LDAPStorageProviderFactory.EditMode getEditMode() {
public UserStorageProvider.EditMode getEditMode() {
String editModeString = config.getFirst(LDAPConstants.EDIT_MODE);
if (editModeString == null) {
return LDAPStorageProviderFactory.EditMode.READ_ONLY;
return UserStorageProvider.EditMode.READ_ONLY;
} else {
return LDAPStorageProviderFactory.EditMode.valueOf(editModeString);
return UserStorageProvider.EditMode.valueOf(editModeString);
}
}
}

View file

@ -85,7 +85,7 @@ public class LDAPStorageProvider implements UserStorageProvider,
protected KeycloakSession session;
protected ComponentModel model;
protected LDAPIdentityStore ldapIdentityStore;
protected LDAPStorageProviderFactory.EditMode editMode;
protected EditMode editMode;
protected LDAPProviderKerberosConfig kerberosConfig;
protected PasswordUpdated updater;
@ -117,7 +117,7 @@ public class LDAPStorageProvider implements UserStorageProvider,
return this.ldapIdentityStore;
}
public LDAPStorageProviderFactory.EditMode getEditMode() {
public EditMode getEditMode() {
return editMode;
}
@ -174,12 +174,12 @@ public class LDAPStorageProvider implements UserStorageProvider,
}
public boolean synchronizeRegistrations() {
return "true".equalsIgnoreCase(model.getConfig().getFirst(LDAPConstants.SYNC_REGISTRATIONS)) && editMode == LDAPStorageProviderFactory.EditMode.WRITABLE;
return "true".equalsIgnoreCase(model.getConfig().getFirst(LDAPConstants.SYNC_REGISTRATIONS)) && editMode == UserStorageProvider.EditMode.WRITABLE;
}
@Override
public UserModel addUser(RealmModel realm, String username) {
if (editMode == LDAPStorageProviderFactory.EditMode.READ_ONLY || editMode == LDAPStorageProviderFactory.EditMode.UNSYNCED) throw new IllegalStateException("Registration is not supported by this ldap server");
if (editMode == UserStorageProvider.EditMode.READ_ONLY || editMode == UserStorageProvider.EditMode.UNSYNCED) throw new IllegalStateException("Registration is not supported by this ldap server");
if (!synchronizeRegistrations()) throw new IllegalStateException("Registration is not supported by this ldap server");
UserModel user = session.userLocalStorage().addUser(realm, username);
user.setFederationLink(model.getId());
@ -193,7 +193,7 @@ public class LDAPStorageProvider implements UserStorageProvider,
@Override
public boolean removeUser(RealmModel realm, UserModel user) {
if (editMode == LDAPStorageProviderFactory.EditMode.READ_ONLY || editMode == LDAPStorageProviderFactory.EditMode.UNSYNCED) {
if (editMode == UserStorageProvider.EditMode.READ_ONLY || editMode == UserStorageProvider.EditMode.UNSYNCED) {
logger.warnf("User '%s' can't be deleted in LDAP as editMode is '%s'. Deleting user just from Keycloak DB, but he will be re-imported from LDAP again once searched in Keycloak", user.getUsername(), editMode.toString());
return true;
}
@ -479,10 +479,10 @@ public class LDAPStorageProvider implements UserStorageProvider,
@Override
public boolean updateCredential(RealmModel realm, UserModel user, CredentialInput input) {
if (!CredentialModel.PASSWORD.equals(input.getType()) || ! (input instanceof UserCredentialModel)) return false;
if (editMode == LDAPStorageProviderFactory.EditMode.READ_ONLY) {
if (editMode == UserStorageProvider.EditMode.READ_ONLY) {
throw new ModelReadOnlyException("Federated storage is not writable");
} else if (editMode == LDAPStorageProviderFactory.EditMode.WRITABLE) {
} else if (editMode == UserStorageProvider.EditMode.WRITABLE) {
LDAPIdentityStore ldapIdentityStore = getLdapIdentityStore();
UserCredentialModel cred = (UserCredentialModel)input;
String password = cred.getValue();

View file

@ -63,27 +63,6 @@ import java.util.List;
*/
public class LDAPStorageProviderFactory implements UserStorageProviderFactory<LDAPStorageProvider>, ImportSynchronization {
/**
* Optional type that can be by implementations to describe edit mode of federation storage
*
*/
public enum EditMode {
/**
* federation storage is read-only
*/
READ_ONLY,
/**
* federation storage is writable
*
*/
WRITABLE,
/**
* updates to user are stored locally and not synced with federation storage.
*
*/
UNSYNCED
}
private static final Logger logger = Logger.getLogger(LDAPStorageProviderFactory.class);
public static final String PROVIDER_NAME = LDAPConstants.LDAP_PROVIDER;
@ -100,7 +79,7 @@ public class LDAPStorageProviderFactory implements UserStorageProviderFactory<LD
boolean readOnly = false;
if (parent != null) {
LDAPConfig config = new LDAPConfig(parent.getConfig());
readOnly = config.getEditMode() != LDAPStorageProviderFactory.EditMode.WRITABLE;
readOnly = config.getEditMode() != UserStorageProvider.EditMode.WRITABLE;
}
@ -229,11 +208,11 @@ public class LDAPStorageProviderFactory implements UserStorageProviderFactory<LD
LDAPConfig ldapConfig = new LDAPConfig(model.getConfig());
boolean activeDirectory = ldapConfig.isActiveDirectory();
EditMode editMode = ldapConfig.getEditMode();
String readOnly = String.valueOf(editMode == EditMode.READ_ONLY || editMode == EditMode.UNSYNCED);
UserStorageProvider.EditMode editMode = ldapConfig.getEditMode();
String readOnly = String.valueOf(editMode == UserStorageProvider.EditMode.READ_ONLY || editMode == UserStorageProvider.EditMode.UNSYNCED);
String usernameLdapAttribute = ldapConfig.getUsernameLdapAttribute();
String alwaysReadValueFromLDAP = String.valueOf(editMode==EditMode.READ_ONLY || editMode== EditMode.WRITABLE);
String alwaysReadValueFromLDAP = String.valueOf(editMode== UserStorageProvider.EditMode.READ_ONLY || editMode== UserStorageProvider.EditMode.WRITABLE);
ComponentModel mapperModel;
mapperModel = KeycloakModelUtils.createComponentModel("username", model.getId(), UserAttributeLDAPStorageMapperFactory.PROVIDER_ID, LDAPStorageMapper.class.getName(),
@ -259,7 +238,7 @@ public class LDAPStorageProviderFactory implements UserStorageProviderFactory<LD
realm.addComponentModel(mapperModel);
} else {
if (editMode == EditMode.WRITABLE) {
if (editMode == UserStorageProvider.EditMode.WRITABLE) {
// For AD deployments with "sAMAccountName" as username and writable, we need to map "cn" as username as well (this is needed so we can register new users from KC into LDAP) and we will map "givenName" to first name.
mapperModel = KeycloakModelUtils.createComponentModel("first name", model.getId(), UserAttributeLDAPStorageMapperFactory.PROVIDER_ID,LDAPStorageMapper.class.getName(),

View file

@ -21,8 +21,8 @@ import org.keycloak.component.ComponentModel;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.ldap.LDAPStorageProvider;
import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
import org.keycloak.storage.ldap.idm.model.LDAPObject;
import org.keycloak.storage.ldap.idm.query.Condition;
import org.keycloak.storage.ldap.idm.query.internal.EqualCondition;
@ -84,7 +84,7 @@ public class FullNameLDAPStorageMapper extends AbstractLDAPStorageMapper {
@Override
public UserModel proxy(LDAPObject ldapUser, UserModel delegate) {
if (ldapProvider.getEditMode() == LDAPStorageProviderFactory.EditMode.WRITABLE && !isReadOnly()) {
if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE && !isReadOnly()) {
TxAwareLDAPUserModelDelegate txDelegate = new TxAwareLDAPUserModelDelegate(delegate, ldapProvider, ldapUser) {

View file

@ -22,17 +22,13 @@ import org.keycloak.component.ComponentValidationException;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.provider.ProviderConfigurationBuilder;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.ldap.LDAPConfig;
import org.keycloak.storage.ldap.LDAPStorageProvider;
import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@ -51,7 +47,7 @@ public class FullNameLDAPStorageMapperFactory extends AbstractLDAPStorageMapperF
boolean readOnly = false;
if (parent != null) {
LDAPConfig config = new LDAPConfig(parent.getConfig());
readOnly = config.getEditMode() != LDAPStorageProviderFactory.EditMode.WRITABLE;
readOnly = config.getEditMode() != UserStorageProvider.EditMode.WRITABLE;
}
@ -107,9 +103,9 @@ public class FullNameLDAPStorageMapperFactory extends AbstractLDAPStorageMapperF
}
LDAPConfig cfg = new LDAPConfig(parent.getConfig());
LDAPStorageProviderFactory.EditMode editMode = cfg.getEditMode();
UserStorageProvider.EditMode editMode = cfg.getEditMode();
if (writeOnly && cfg.getEditMode() != LDAPStorageProviderFactory.EditMode.WRITABLE) {
if (writeOnly && cfg.getEditMode() != UserStorageProvider.EditMode.WRITABLE) {
throw new ComponentValidationException("ldapErrorCantWriteOnlyForReadOnlyLdap");
}
if (writeOnly && readOnly) {

View file

@ -29,8 +29,8 @@ import org.keycloak.models.utils.UserModelDelegate;
import org.keycloak.models.utils.reflection.Property;
import org.keycloak.models.utils.reflection.PropertyCriteria;
import org.keycloak.models.utils.reflection.PropertyQueries;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.ldap.LDAPStorageProvider;
import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
import org.keycloak.storage.ldap.idm.model.LDAPObject;
import org.keycloak.storage.ldap.idm.query.Condition;
import org.keycloak.storage.ldap.idm.query.internal.LDAPQuery;
@ -179,7 +179,7 @@ public class UserAttributeLDAPStorageMapper extends AbstractLDAPStorageMapper {
final boolean isMandatoryInLdap = parseBooleanParameter(mapperModel, IS_MANDATORY_IN_LDAP);
// For writable mode, we want to propagate writing of attribute to LDAP as well
if (ldapProvider.getEditMode() == LDAPStorageProviderFactory.EditMode.WRITABLE && !isReadOnly()) {
if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE && !isReadOnly()) {
delegate = new TxAwareLDAPUserModelDelegate(delegate, ldapProvider, ldapUser) {

View file

@ -21,17 +21,13 @@ import org.keycloak.component.ComponentModel;
import org.keycloak.component.ComponentValidationException;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.provider.ProviderConfigurationBuilder;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.ldap.LDAPConfig;
import org.keycloak.storage.ldap.LDAPStorageProvider;
import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@ -50,7 +46,7 @@ public class UserAttributeLDAPStorageMapperFactory extends AbstractLDAPStorageMa
String readOnly = "false";
if (parent != null) {
LDAPConfig ldapConfig = new LDAPConfig(parent.getConfig());
readOnly = ldapConfig.getEditMode() == LDAPStorageProviderFactory.EditMode.WRITABLE ? "false" : "true";
readOnly = ldapConfig.getEditMode() == UserStorageProvider.EditMode.WRITABLE ? "false" : "true";
}
return ProviderConfigurationBuilder.create()
.property().name(UserAttributeLDAPStorageMapper.USER_MODEL_ATTRIBUTE)

View file

@ -22,14 +22,11 @@ import org.keycloak.component.ComponentValidationException;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.provider.ProviderConfigurationBuilder;
import org.keycloak.representations.idm.UserFederationMapperSyncConfigRepresentation;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.ldap.LDAPConfig;
import org.keycloak.storage.ldap.LDAPStorageProvider;
import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
import org.keycloak.storage.ldap.LDAPUtils;
import org.keycloak.storage.ldap.mappers.AbstractLDAPStorageMapper;
import org.keycloak.storage.ldap.mappers.AbstractLDAPStorageMapperFactory;
@ -80,7 +77,7 @@ public class GroupLDAPStorageMapperFactory extends AbstractLDAPStorageMapperFact
if (parent != null) {
LDAPConfig config = new LDAPConfig(parent.getConfig());
roleObjectClasses = config.isActiveDirectory() ? LDAPConstants.GROUP : LDAPConstants.GROUP_OF_NAMES;
mode = config.getEditMode() == LDAPStorageProviderFactory.EditMode.WRITABLE ? LDAPGroupMapperMode.LDAP_ONLY.toString() : LDAPGroupMapperMode.READ_ONLY.toString();
mode = config.getEditMode() == UserStorageProvider.EditMode.WRITABLE ? LDAPGroupMapperMode.LDAP_ONLY.toString() : LDAPGroupMapperMode.READ_ONLY.toString();
}
return ProviderConfigurationBuilder.create()
.property().name(GroupMapperConfig.GROUPS_DN)

View file

@ -22,14 +22,11 @@ import org.keycloak.component.ComponentValidationException;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.provider.ProviderConfigurationBuilder;
import org.keycloak.representations.idm.UserFederationMapperSyncConfigRepresentation;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.ldap.LDAPConfig;
import org.keycloak.storage.ldap.LDAPStorageProvider;
import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
import org.keycloak.storage.ldap.LDAPUtils;
import org.keycloak.storage.ldap.mappers.AbstractLDAPStorageMapper;
import org.keycloak.storage.ldap.mappers.AbstractLDAPStorageMapperFactory;
@ -80,7 +77,7 @@ public class RoleLDAPStorageMapperFactory extends AbstractLDAPStorageMapperFacto
if (parent != null) {
LDAPConfig config = new LDAPConfig(parent.getConfig());
roleObjectClasses = config.isActiveDirectory() ? LDAPConstants.GROUP : LDAPConstants.GROUP_OF_NAMES;
mode = config.getEditMode() == LDAPStorageProviderFactory.EditMode.WRITABLE ? LDAPGroupMapperMode.LDAP_ONLY.toString() : LDAPGroupMapperMode.READ_ONLY.toString();
mode = config.getEditMode() == UserStorageProvider.EditMode.WRITABLE ? LDAPGroupMapperMode.LDAP_ONLY.toString() : LDAPGroupMapperMode.READ_ONLY.toString();
}
return ProviderConfigurationBuilder.create()
.property().name(RoleMapperConfig.ROLES_DN)

View file

@ -25,8 +25,8 @@ import org.keycloak.models.ModelException;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.UserModelDelegate;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.ldap.LDAPStorageProvider;
import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
import org.keycloak.storage.ldap.idm.model.LDAPObject;
import org.keycloak.storage.ldap.idm.query.internal.LDAPQuery;
import org.keycloak.storage.ldap.mappers.AbstractLDAPStorageMapper;
@ -64,7 +64,7 @@ public class MSADUserAccountControlStorageMapper extends AbstractLDAPStorageMapp
// This needs to be read-only and can be set to writable just on demand
query.addReturningReadOnlyLdapAttribute(LDAPConstants.PWD_LAST_SET);
if (ldapProvider.getEditMode() != LDAPStorageProviderFactory.EditMode.WRITABLE) {
if (ldapProvider.getEditMode() != UserStorageProvider.EditMode.WRITABLE) {
query.addReturningReadOnlyLdapAttribute(LDAPConstants.USER_ACCOUNT_CONTROL);
}
}
@ -119,7 +119,7 @@ public class MSADUserAccountControlStorageMapper extends AbstractLDAPStorageMapp
protected boolean processAuthErrorCode(String errorCode, UserModel user) {
logger.debugf("MSAD Error code is '%s' after failed LDAP login of user '%s'", errorCode, user.getUsername());
if (ldapProvider.getEditMode() == LDAPStorageProviderFactory.EditMode.WRITABLE) {
if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE) {
if (errorCode.equals("532") || errorCode.equals("773")) {
// User needs to change his MSAD password. Allow him to login, but add UPDATE_PASSWORD required action
user.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
@ -200,7 +200,7 @@ public class MSADUserAccountControlStorageMapper extends AbstractLDAPStorageMapp
// Always update DB
super.setEnabled(enabled);
if (ldapProvider.getEditMode() == LDAPStorageProviderFactory.EditMode.WRITABLE && getPwdLastSet() > 0) {
if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE && getPwdLastSet() > 0) {
logger.debugf("Going to propagate enabled=%s for ldapUser '%s' to MSAD", enabled, ldapUser.getDn().toString());
UserAccountControl control = getUserAccountControl(ldapUser);
@ -225,7 +225,7 @@ public class MSADUserAccountControlStorageMapper extends AbstractLDAPStorageMapp
// Always update DB
super.addRequiredAction(action);
if (ldapProvider.getEditMode() == LDAPStorageProviderFactory.EditMode.WRITABLE && RequiredAction.UPDATE_PASSWORD.toString().equals(action)) {
if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE && RequiredAction.UPDATE_PASSWORD.toString().equals(action)) {
logger.debugf("Going to propagate required action UPDATE_PASSWORD to MSAD for ldap user '%s' ", ldapUser.getDn().toString());
// Normally it's read-only
@ -247,7 +247,7 @@ public class MSADUserAccountControlStorageMapper extends AbstractLDAPStorageMapp
// Always update DB
super.removeRequiredAction(action);
if (ldapProvider.getEditMode() == LDAPStorageProviderFactory.EditMode.WRITABLE && RequiredAction.UPDATE_PASSWORD.toString().equals(action)) {
if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE && RequiredAction.UPDATE_PASSWORD.toString().equals(action)) {
// Don't set pwdLastSet in MSAD when it is new user
UserAccountControl accountControl = getUserAccountControl(ldapUser);
@ -267,7 +267,7 @@ public class MSADUserAccountControlStorageMapper extends AbstractLDAPStorageMapp
public Set<String> getRequiredActions() {
Set<String> requiredActions = super.getRequiredActions();
if (ldapProvider.getEditMode() == LDAPStorageProviderFactory.EditMode.WRITABLE) {
if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE) {
if (getPwdLastSet() == 0 || getUserAccountControl(ldapUser).has(UserAccountControl.PASSWORD_EXPIRED)) {
requiredActions = new HashSet<>(requiredActions);
requiredActions.add(RequiredAction.UPDATE_PASSWORD.toString());

View file

@ -1 +1,18 @@
#
# 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.
#
org.keycloak.storage.ldap.LDAPStorageProviderFactory

View file

@ -1,3 +1,20 @@
#
# 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.
#
org.keycloak.storage.ldap.mappers.FullNameLDAPStorageMapperFactory
org.keycloak.storage.ldap.mappers.HardcodedLDAPRoleStorageMapperFactory
org.keycloak.storage.ldap.mappers.membership.group.GroupLDAPStorageMapperFactory

View file

@ -31,12 +31,13 @@ import java.sql.ResultSet;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class PortLdapUserFedToComponentModel extends AbstractUserFedToComponent {
public class MigrateUserFedToComponent extends AbstractUserFedToComponent {
@Override
protected void generateStatementsImpl() throws CustomChangeException {
String providerId = LDAPConstants.LDAP_PROVIDER;
convertFedProviderToComponent(LDAPConstants.LDAP_PROVIDER, "org.keycloak.storage.ldap.mappers.LDAPStorageMapper");
convertFedProviderToComponent("kerberos", null);
}
@Override

View file

@ -19,7 +19,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="bburke@redhat.com" id="2.4.0">
<customChange class="org.keycloak.connections.jpa.updater.liquibase.custom.PortLdapUserFedToComponentModel"/>
<customChange class="org.keycloak.connections.jpa.updater.liquibase.custom.MigrateUserFedToComponent"/>
</changeSet>
</databaseChangeLog>

View file

@ -49,6 +49,7 @@ public class Update2_4_0 extends Update {
public void update(KeycloakSession session) {
portUserFedMappersToComponent(LDAPConstants.LDAP_PROVIDER, "org.keycloak.storage.ldap.mappers.LDAPStorageMapper");
portUserFedToComponent(LDAPConstants.LDAP_PROVIDER);
portUserFedToComponent("kerberos");
}
public void portUserFedToComponent(String providerId) {

View file

@ -362,6 +362,7 @@ public class RepresentationToModel {
// providers to convert to component model
Set<String> convertSet = new HashSet<>();
convertSet.add(LDAPConstants.LDAP_PROVIDER);
convertSet.add("kerberos");
Map<String, String> mapperConvertSet = new HashMap<>();
mapperConvertSet.put(LDAPConstants.LDAP_PROVIDER, "org.keycloak.storage.ldap.mappers.LDAPStorageMapper");

View file

@ -26,8 +26,31 @@ import org.keycloak.provider.Provider;
* @version $Revision: 1 $
*/
public interface UserStorageProvider extends Provider {
void preRemove(RealmModel realm);
void preRemove(RealmModel realm, GroupModel group);
void preRemove(RealmModel realm, RoleModel role);
/**
* Optional type that can be by implementations to describe edit mode of federation storage
*
*/
enum EditMode {
/**
* federation storage is read-only
*/
READ_ONLY,
/**
* federation storage is writable
*
*/
WRITABLE,
/**
* updates to user are stored locally and not synced with federation storage.
*
*/
UNSYNCED
}
}

View file

@ -45,6 +45,7 @@ import org.keycloak.models.UserModel;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.UserFederationProviderRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.testsuite.AssertEvents;
import org.keycloak.testsuite.adapter.AbstractServletsAdapterTest;
import org.keycloak.testsuite.adapter.page.KerberosPortal;
@ -89,7 +90,7 @@ public abstract class AbstractKerberosAdapterTest extends AbstractServletsAdapte
protected abstract String getConnectionPropertiesLocation();
protected abstract CommonKerberosConfig getKerberosConfig(UserFederationProviderModel model);
protected abstract CommonKerberosConfig getKerberosConfig(UserStorageProviderModel model);
@Deployment(name = KerberosPortal.DEPLOYMENT_NAME)
protected static WebArchive kerberosPortal() {
@ -116,8 +117,8 @@ public abstract class AbstractKerberosAdapterTest extends AbstractServletsAdapte
ldapEmbeddedServer.init();
ldapEmbeddedServer.start();
}
UserFederationProviderModel model = new UserFederationProviderModel();
model.setConfig(ldapTestConfiguration.getLDAPConfig());
UserStorageProviderModel model = new UserStorageProviderModel();
model.setConfig(AbstractKerberosStandaloneAdapterTest.toComponentConfig(ldapTestConfiguration.getLDAPConfig()));
spnegoSchemeFactory = new KeycloakSPNegoSchemeFactory(getKerberosConfig(model));
initHttpClient(true);
removeAllUsers();

View file

@ -21,12 +21,16 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.keycloak.common.constants.KerberosConstants;
import org.keycloak.common.util.MultivaluedHashMap;
import org.keycloak.federation.kerberos.CommonKerberosConfig;
import org.keycloak.federation.kerberos.KerberosConfig;
import org.keycloak.federation.kerberos.KerberosFederationProviderFactory;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.representations.idm.ComponentRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.UserFederationProviderRepresentation;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderModel;
import javax.ws.rs.core.Response;
import java.util.Arrays;
@ -39,28 +43,36 @@ import java.util.Map;
*/
public abstract class AbstractKerberosStandaloneAdapterTest extends AbstractKerberosAdapterTest {
public static MultivaluedHashMap<String, String> toComponentConfig(Map<String, String> ldapConfig) {
MultivaluedHashMap<String, String> config = new MultivaluedHashMap<>();
for (Map.Entry<String, String> entry : ldapConfig.entrySet()) {
config.add(entry.getKey(), entry.getValue());
}
return config;
}
protected static final String PROVIDER_CONFIG_LOCATION = "kerberos-standalone-connection.properties";
@Before
public void init() throws Exception{
Map<String,String> ldapConfig = getConfig();
UserFederationProviderRepresentation userFederationProviderRepresentation = new UserFederationProviderRepresentation();
userFederationProviderRepresentation.setProviderName(KerberosFederationProviderFactory.PROVIDER_NAME);
userFederationProviderRepresentation.setConfig(ldapConfig);
userFederationProviderRepresentation.setPriority(0);
userFederationProviderRepresentation.setDisplayName("kerberos-standalone");
userFederationProviderRepresentation.setFullSyncPeriod(-1);
userFederationProviderRepresentation.setChangedSyncPeriod(-1);
userFederationProviderRepresentation.setLastSync(0);
RealmRepresentation realmRepresentation = testRealmResource().toRepresentation();
realmRepresentation.setUserFederationProviders(Arrays.asList(userFederationProviderRepresentation));
Map<String,String> ldapConfig = getConfig();
ComponentRepresentation component = new ComponentRepresentation();
component.setName("kerberos-standalone");
component.setParentId(realmRepresentation.getId());
component.setProviderId(KerberosFederationProviderFactory.PROVIDER_NAME);
component.setProviderType(UserStorageProvider.class.getName());
component.setConfig(toComponentConfig(ldapConfig));
component.getConfig().putSingle("priority", "0");
testRealmResource().components().add(component);
realmRepresentation.setEventsEnabled(true);
testRealmResource().update(realmRepresentation);
}
@Override
protected CommonKerberosConfig getKerberosConfig(UserFederationProviderModel model) {
protected CommonKerberosConfig getKerberosConfig(UserStorageProviderModel model) {
return new KerberosConfig(model);
}

View file

@ -31,6 +31,7 @@ import org.junit.Test;
import org.keycloak.adapters.HttpClientBuilder;
import org.keycloak.authentication.authenticators.browser.SpnegoAuthenticator;
import org.keycloak.common.constants.KerberosConstants;
import org.keycloak.component.ComponentModel;
import org.keycloak.events.Details;
import org.keycloak.federation.kerberos.CommonKerberosConfig;
import org.keycloak.models.ClientModel;
@ -44,6 +45,7 @@ import org.keycloak.models.UserModel;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.protocol.oidc.mappers.UserSessionNoteMapper;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.testsuite.AssertEvents;
import org.keycloak.testsuite.OAuthClient;
import org.keycloak.testsuite.pages.AccountPasswordPage;
@ -179,7 +181,7 @@ public abstract class AbstractKerberosTest {
AssertEvents events = getAssertEvents();
// Change editMode to READ_ONLY
updateProviderEditMode(UserFederationProvider.EditMode.READ_ONLY);
updateProviderEditMode(UserStorageProvider.EditMode.READ_ONLY);
// Login with username/password from kerberos
changePasswordPage.open();
@ -200,7 +202,7 @@ public abstract class AbstractKerberosTest {
Assert.assertTrue(driver.getPageSource().contains("You can't update your password as your account is read only"));
// Change editMode to UNSYNCED
updateProviderEditMode(UserFederationProvider.EditMode.UNSYNCED);
updateProviderEditMode(UserStorageProvider.EditMode.UNSYNCED);
// Successfully change password now
changePasswordPage.changePassword("theduke", "newPass", "newPass");
@ -382,15 +384,15 @@ public abstract class AbstractKerberosTest {
}
protected void updateProviderEditMode(UserFederationProvider.EditMode editMode) {
protected void updateProviderEditMode(UserStorageProvider.EditMode editMode) {
KeycloakRule keycloakRule = getKeycloakRule();
KeycloakSession session = keycloakRule.startSession();
try {
RealmModel realm = session.realms().getRealm("test");
UserFederationProviderModel kerberosProviderModel = realm.getUserFederationProviders().get(0);
kerberosProviderModel.getConfig().put(LDAPConstants.EDIT_MODE, editMode.toString());
realm.updateUserFederationProvider(kerberosProviderModel);
ComponentModel kerberosProviderModel = realm.getComponents(realm.getId(), UserStorageProvider.class.getName()).get(0);
kerberosProviderModel.getConfig().putSingle(LDAPConstants.EDIT_MODE, editMode.toString());
realm.updateComponent(kerberosProviderModel);
} finally {
keycloakRule.stopSession(session, true);
}

View file

@ -19,11 +19,14 @@ package org.keycloak.testsuite.federation;
import org.junit.Assert;
import org.junit.ClassRule;
import org.junit.FixMethodOrder;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.RuleChain;
import org.junit.rules.TestRule;
import org.junit.runners.MethodSorters;
import org.keycloak.common.constants.KerberosConstants;
import org.keycloak.common.util.MultivaluedHashMap;
import org.keycloak.federation.kerberos.CommonKerberosConfig;
import org.keycloak.federation.kerberos.KerberosConfig;
import org.keycloak.federation.kerberos.KerberosFederationProviderFactory;
@ -32,7 +35,10 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
import org.keycloak.testsuite.AssertEvents;
import org.keycloak.testsuite.federation.storage.ldap.LDAPTestUtils;
import org.keycloak.testsuite.rule.KerberosRule;
import org.keycloak.testsuite.rule.KeycloakRule;
import org.keycloak.testsuite.rule.WebRule;
@ -47,11 +53,12 @@ import java.util.Map;
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class KerberosStandaloneTest extends AbstractKerberosTest {
private static final String PROVIDER_CONFIG_LOCATION = "kerberos/kerberos-standalone-connection.properties";
private static UserFederationProviderModel kerberosModel;
private static UserStorageProviderModel kerberosModel;
private static KerberosRule kerberosRule = new KerberosRule(PROVIDER_CONFIG_LOCATION);
@ -69,7 +76,18 @@ public class KerberosStandaloneTest extends AbstractKerberosTest {
Map<String,String> kerberosConfig = kerberosRule.getConfig();
kerberosModel = appRealm.addUserFederationProvider(KerberosFederationProviderFactory.PROVIDER_NAME, kerberosConfig, 0, "kerberos-standalone", -1, -1, 0);
MultivaluedHashMap<String, String> config = LDAPTestUtils.toComponentConfig(kerberosConfig);
UserStorageProviderModel model = new UserStorageProviderModel();
model.setLastSync(0);
model.setChangedSyncPeriod(-1);
model.setFullSyncPeriod(-1);
model.setName("kerberos-standalone");
model.setPriority(0);
model.setProviderId(KerberosFederationProviderFactory.PROVIDER_NAME);
model.setConfig(config);
kerberosModel = new UserStorageProviderModel(appRealm.addComponentModel(model));
}
}) {
@ -119,6 +137,18 @@ public class KerberosStandaloneTest extends AbstractKerberosTest {
assertUser("hnelson", "hnelson@keycloak.org", null, null, false);
}
@Test
@Override
public void spnegoCaseInsensitiveTest() throws Exception {
super.spnegoCaseInsensitiveTest();
}
@Test
@Override
public void credentialDelegationTest() throws Exception {
super.credentialDelegationTest();
}
@Test
@Override
public void usernamePasswordLoginTest() throws Exception {
@ -131,9 +161,9 @@ public class KerberosStandaloneTest extends AbstractKerberosTest {
KeycloakSession session = keycloakRule.startSession();
try {
RealmModel realm = session.realms().getRealm("test");
UserFederationProviderModel kerberosProviderModel = realm.getUserFederationProviders().get(0);
kerberosProviderModel.getConfig().put(KerberosConstants.UPDATE_PROFILE_FIRST_LOGIN, "true");
realm.updateUserFederationProvider(kerberosProviderModel);
UserStorageProviderModel kerberosProviderModel = realm.getUserStorageProviders().get(0);
kerberosProviderModel.getConfig().putSingle(KerberosConstants.UPDATE_PROFILE_FIRST_LOGIN, "true");
realm.updateComponent(kerberosProviderModel);
} finally {
keycloakRule.stopSession(session, true);
}
@ -153,9 +183,9 @@ public class KerberosStandaloneTest extends AbstractKerberosTest {
session = keycloakRule.startSession();
try {
RealmModel realm = session.realms().getRealm("test");
UserFederationProviderModel kerberosProviderModel = realm.getUserFederationProviders().get(0);
kerberosProviderModel.getConfig().put(KerberosConstants.UPDATE_PROFILE_FIRST_LOGIN, "false");
realm.updateUserFederationProvider(kerberosProviderModel);
UserStorageProviderModel kerberosProviderModel = realm.getUserStorageProviders().get(0);
kerberosProviderModel.getConfig().putSingle(KerberosConstants.UPDATE_PROFILE_FIRST_LOGIN, "false");
realm.updateComponent(kerberosProviderModel);
} finally {
keycloakRule.stopSession(session, true);
}

View file

@ -47,7 +47,6 @@ import org.keycloak.utils.CredentialHelper;
import javax.ws.rs.core.Response;
import java.net.URL;
import java.util.Map;
/**
* Test of LDAPFederationProvider (Kerberos backed by LDAP)
@ -73,7 +72,7 @@ public class KerberosLdapTest extends AbstractKerberosTest {
.servletClass(KerberosCredDelegServlet.class).adapterConfigPath(url.getPath())
.role("user").deployApplication();
MultivaluedHashMap<String, String> ldapConfig = LDAPTestUtils.toLdapConfig(kerberosRule.getConfig());
MultivaluedHashMap<String, String> ldapConfig = LDAPTestUtils.toComponentConfig(kerberosRule.getConfig());
UserStorageProviderModel model = new UserStorageProviderModel();
model.setLastSync(0);
model.setChangedSyncPeriod(-1);
@ -135,42 +134,13 @@ public class KerberosLdapTest extends AbstractKerberosTest {
super.usernamePasswordLoginTest();
}
protected void updateProviderEditMode(LDAPStorageProviderFactory.EditMode editMode) {
KeycloakRule keycloakRule = getKeycloakRule();
KeycloakSession session = keycloakRule.startSession();
try {
RealmModel realm = session.realms().getRealm("test");
ComponentModel kerberosProviderModel = realm.getComponents(realm.getId(), UserStorageProvider.class.getName()).get(0);
kerberosProviderModel.getConfig().putSingle(LDAPConstants.EDIT_MODE, editMode.toString());
realm.updateComponent(kerberosProviderModel);
} finally {
keycloakRule.stopSession(session, true);
}
}
@Override
protected void updateProviderEditMode(UserFederationProvider.EditMode editMode) {
switch (editMode) {
case WRITABLE:
updateProviderEditMode(LDAPStorageProviderFactory.EditMode.WRITABLE);
break;
case READ_ONLY:
updateProviderEditMode(LDAPStorageProviderFactory.EditMode.READ_ONLY);
break;
case UNSYNCED:
updateProviderEditMode(LDAPStorageProviderFactory.EditMode.UNSYNCED);
break;
}
}
@Test
public void writableEditModeTest() throws Exception {
KeycloakRule keycloakRule = getKeycloakRule();
AssertEvents events = getAssertEvents();
// Change editMode to WRITABLE
updateProviderEditMode(LDAPStorageProviderFactory.EditMode.WRITABLE);
updateProviderEditMode(UserStorageProvider.EditMode.WRITABLE);
// Login with username/password from kerberos
changePasswordPage.open();

View file

@ -25,6 +25,7 @@ import org.junit.Test;
import org.junit.runners.MethodSorters;
import org.keycloak.common.util.MultivaluedHashMap;
import org.keycloak.component.ComponentModel;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.ldap.LDAPStorageProvider;
import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
@ -41,8 +42,6 @@ import org.keycloak.storage.user.SynchronizationResult;
import org.keycloak.testsuite.rule.KeycloakRule;
import org.keycloak.testsuite.rule.LDAPRule;
import java.util.Map;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@ -62,7 +61,7 @@ public class LDAPGroupMapper2WaySyncTest {
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
MultivaluedHashMap<String,String> ldapConfig = LDAPTestUtils.getLdapRuleConfig(ldapRule);
ldapConfig.putSingle(LDAPConstants.SYNC_REGISTRATIONS, "true");
ldapConfig.putSingle(LDAPConstants.EDIT_MODE, LDAPStorageProviderFactory.EditMode.WRITABLE.toString());
ldapConfig.putSingle(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.WRITABLE.toString());
ldapConfig.putSingle(LDAPConstants.BATCH_SIZE_FOR_SYNC, "4"); // Issues with pagination on ApacheDS
UserStorageProviderModel model = new UserStorageProviderModel();
model.setLastSync(0);

View file

@ -27,6 +27,7 @@ import org.junit.rules.TestRule;
import org.junit.runners.MethodSorters;
import org.keycloak.common.util.MultivaluedHashMap;
import org.keycloak.component.ComponentModel;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.ldap.LDAPStorageProvider;
import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
@ -50,7 +51,6 @@ import org.keycloak.testsuite.rule.KeycloakRule;
import org.keycloak.testsuite.rule.LDAPRule;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
@ -70,7 +70,7 @@ public class LDAPGroupMapperSyncTest {
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
MultivaluedHashMap<String,String> ldapConfig = LDAPTestUtils.getLdapRuleConfig(ldapRule);
ldapConfig.putSingle(LDAPConstants.SYNC_REGISTRATIONS, "true");
ldapConfig.putSingle(LDAPConstants.EDIT_MODE, LDAPStorageProviderFactory.EditMode.WRITABLE.toString());
ldapConfig.putSingle(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.WRITABLE.toString());
UserStorageProviderModel model = new UserStorageProviderModel();
model.setLastSync(0);
model.setChangedSyncPeriod(-1);

View file

@ -26,6 +26,7 @@ import org.junit.rules.TestRule;
import org.junit.runners.MethodSorters;
import org.keycloak.common.util.MultivaluedHashMap;
import org.keycloak.component.ComponentModel;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.ldap.LDAPConfig;
import org.keycloak.storage.ldap.LDAPStorageProvider;
@ -50,7 +51,6 @@ import org.keycloak.testsuite.rule.KeycloakRule;
import org.keycloak.testsuite.rule.LDAPRule;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
@ -73,7 +73,7 @@ public class LDAPGroupMapperTest {
MultivaluedHashMap<String,String> ldapConfig = LDAPTestUtils.getLdapRuleConfig(ldapRule);
ldapConfig.putSingle(LDAPConstants.SYNC_REGISTRATIONS, "true");
ldapConfig.putSingle(LDAPConstants.EDIT_MODE, LDAPStorageProviderFactory.EditMode.WRITABLE.toString());
ldapConfig.putSingle(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.WRITABLE.toString());
UserStorageProviderModel model = new UserStorageProviderModel();
model.setLastSync(0);
model.setChangedSyncPeriod(-1);

View file

@ -32,13 +32,12 @@ import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
import org.keycloak.protocol.oidc.mappers.UserAttributeMapper;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.ldap.LDAPStorageProvider;
import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
@ -57,7 +56,6 @@ import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@ -77,7 +75,7 @@ public class LDAPMultipleAttributesTest {
@Override
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
MultivaluedHashMap<String,String> ldapConfig = LDAPTestUtils.getLdapRuleConfig(ldapRule);
ldapConfig.putSingle(LDAPConstants.EDIT_MODE, LDAPStorageProviderFactory.EditMode.WRITABLE.toString());
ldapConfig.putSingle(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.WRITABLE.toString());
UserStorageProviderModel model = new UserStorageProviderModel();
model.setLastSync(0);

View file

@ -65,7 +65,6 @@ import org.keycloak.testsuite.rule.WebRule;
import org.openqa.selenium.WebDriver;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.assertEquals;
@ -88,7 +87,7 @@ public class LDAPProvidersIntegrationTest {
MultivaluedHashMap<String,String> ldapConfig = LDAPTestUtils.getLdapRuleConfig(ldapRule);
ldapConfig.putSingle(LDAPConstants.SYNC_REGISTRATIONS, "true");
ldapConfig.putSingle(LDAPConstants.EDIT_MODE, LDAPStorageProviderFactory.EditMode.WRITABLE.toString());
ldapConfig.putSingle(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.WRITABLE.toString());
UserStorageProviderModel model = new UserStorageProviderModel();
model.setLastSync(0);
model.setChangedSyncPeriod(-1);
@ -670,7 +669,7 @@ public class LDAPProvidersIntegrationTest {
RealmModel appRealm = session.realms().getRealmByName("test");
UserStorageProviderModel model = new UserStorageProviderModel(ldapModel);
model.getConfig().putSingle(LDAPConstants.EDIT_MODE, LDAPStorageProviderFactory.EditMode.READ_ONLY.toString());
model.getConfig().putSingle(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.READ_ONLY.toString());
appRealm.updateComponent(model);
UserModel user = session.users().getUserByUsername("johnkeycloak", appRealm);
Assert.assertNotNull(user);
@ -710,7 +709,7 @@ public class LDAPProvidersIntegrationTest {
session = keycloakRule.startSession();
try {
RealmModel appRealm = session.realms().getRealmByName("test");
Assert.assertEquals(LDAPStorageProviderFactory.EditMode.WRITABLE.toString(), appRealm.getComponent(ldapModel.getId()).getConfig().getFirst(LDAPConstants.EDIT_MODE));
Assert.assertEquals(UserStorageProvider.EditMode.WRITABLE.toString(), appRealm.getComponent(ldapModel.getId()).getConfig().getFirst(LDAPConstants.EDIT_MODE));
} finally {
keycloakRule.stopSession(session, false);
}
@ -829,7 +828,7 @@ public class LDAPProvidersIntegrationTest {
RealmModel appRealm = session.realms().getRealmByName("test");
UserStorageProviderModel model = new UserStorageProviderModel(ldapModel);
model.getConfig().putSingle(LDAPConstants.EDIT_MODE, LDAPStorageProviderFactory.EditMode.UNSYNCED.toString());
model.getConfig().putSingle(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.UNSYNCED.toString());
appRealm.updateComponent(model);
UserModel user = session.users().getUserByUsername("johnkeycloak", appRealm);
Assert.assertNotNull(user);
@ -860,7 +859,7 @@ public class LDAPProvidersIntegrationTest {
session = keycloakRule.startSession();
try {
RealmModel appRealm = session.realms().getRealmByName("test");
Assert.assertEquals(LDAPStorageProviderFactory.EditMode.WRITABLE.toString(), appRealm.getComponent(ldapModel.getId()).getConfig().getFirst(LDAPConstants.EDIT_MODE));
Assert.assertEquals(UserStorageProvider.EditMode.WRITABLE.toString(), appRealm.getComponent(ldapModel.getId()).getConfig().getFirst(LDAPConstants.EDIT_MODE));
} finally {
keycloakRule.stopSession(session, false);
}

View file

@ -27,6 +27,7 @@ import org.junit.rules.TestRule;
import org.junit.runners.MethodSorters;
import org.keycloak.common.util.MultivaluedHashMap;
import org.keycloak.component.ComponentModel;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.ldap.LDAPStorageProvider;
import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
@ -52,7 +53,6 @@ import org.keycloak.testsuite.rule.WebResource;
import org.keycloak.testsuite.rule.WebRule;
import org.openqa.selenium.WebDriver;
import java.util.Map;
import java.util.Set;
/**
@ -73,7 +73,7 @@ public class LDAPRoleMappingsTest {
MultivaluedHashMap<String,String> ldapConfig = LDAPTestUtils.getLdapRuleConfig(ldapRule);
ldapConfig.putSingle(LDAPConstants.SYNC_REGISTRATIONS, "true");
ldapConfig.putSingle(LDAPConstants.EDIT_MODE, LDAPStorageProviderFactory.EditMode.WRITABLE.toString());
ldapConfig.putSingle(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.WRITABLE.toString());
UserStorageProviderModel model = new UserStorageProviderModel();
model.setLastSync(0);
model.setChangedSyncPeriod(-1);

View file

@ -28,6 +28,7 @@ import org.keycloak.common.util.MultivaluedHashMap;
import org.keycloak.common.util.Time;
import org.keycloak.component.ComponentModel;
import org.keycloak.services.managers.UserStorageSyncManager;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.ldap.idm.model.LDAPObject;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
@ -44,8 +45,6 @@ import org.keycloak.storage.user.SynchronizationResult;
import org.keycloak.testsuite.rule.KeycloakRule;
import org.keycloak.testsuite.rule.LDAPRule;
import java.util.Map;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@ -65,7 +64,7 @@ public class LDAPSyncTest {
MultivaluedHashMap<String,String> ldapConfig = LDAPTestUtils.getLdapRuleConfig(ldapRule);
ldapConfig.putSingle(LDAPConstants.SYNC_REGISTRATIONS, "false");
ldapConfig.putSingle(LDAPConstants.EDIT_MODE, LDAPStorageProviderFactory.EditMode.WRITABLE.toString());
ldapConfig.putSingle(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.WRITABLE.toString());
UserStorageProviderModel model = new UserStorageProviderModel();
model.setLastSync(0);
model.setChangedSyncPeriod(-1);

View file

@ -20,7 +20,7 @@ package org.keycloak.testsuite.federation.storage.ldap;
import org.jboss.logging.Logger;
import org.keycloak.common.constants.KerberosConstants;
import org.keycloak.models.LDAPConstants;
import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
import org.keycloak.storage.UserStorageProvider;
import java.io.File;
import java.io.InputStream;
@ -79,7 +79,7 @@ public class LDAPTestConfiguration {
DEFAULT_VALUES.put(LDAPConstants.BATCH_SIZE_FOR_SYNC, String.valueOf(LDAPConstants.DEFAULT_BATCH_SIZE_FOR_SYNC));
DEFAULT_VALUES.put(LDAPConstants.USERNAME_LDAP_ATTRIBUTE, null);
DEFAULT_VALUES.put(LDAPConstants.USER_OBJECT_CLASSES, null);
DEFAULT_VALUES.put(LDAPConstants.EDIT_MODE, LDAPStorageProviderFactory.EditMode.READ_ONLY.toString());
DEFAULT_VALUES.put(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.READ_ONLY.toString());
DEFAULT_VALUES.put(KerberosConstants.ALLOW_KERBEROS_AUTHENTICATION, "false");
DEFAULT_VALUES.put(KerberosConstants.KERBEROS_REALM, "KEYCLOAK.ORG");

View file

@ -31,7 +31,6 @@ import org.keycloak.models.utils.UserModelDelegate;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.ldap.LDAPStorageProvider;
import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
import org.keycloak.storage.ldap.LDAPUtils;
import org.keycloak.storage.ldap.idm.model.LDAPObject;
import org.keycloak.storage.ldap.idm.query.internal.LDAPQuery;
@ -62,11 +61,11 @@ import java.util.Set;
public class LDAPTestUtils {
public static MultivaluedHashMap<String, String> getLdapRuleConfig(LDAPRule ldapRule) {
Map<String,String> ldapConfig = ldapRule.getConfig();
return toLdapConfig(ldapConfig);
return toComponentConfig(ldapConfig);
}
public static MultivaluedHashMap<String, String> toLdapConfig(Map<String, String> ldapConfig) {
public static MultivaluedHashMap<String, String> toComponentConfig(Map<String, String> ldapConfig) {
MultivaluedHashMap<String, String> config = new MultivaluedHashMap<>();
for (Map.Entry<String, String> entry : ldapConfig.entrySet()) {
config.add(entry.getKey(), entry.getValue());