KEYCLOAK-19056 EDIT MODE field should not be leave empty (#8380)

This commit is contained in:
Marek Posolda 2021-09-14 20:27:09 +02:00 committed by GitHub
parent 6d0708d263
commit 11e5f66c60
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 62 additions and 9 deletions

View file

@ -654,8 +654,8 @@ public class LDAPStorageProvider implements UserStorageProvider,
String password = input.getChallengeResponse();
LDAPObject ldapUser = loadAndValidateUser(realm, user);
if (ldapIdentityStore.getConfig().isValidatePasswordPolicy()) {
PolicyError error = session.getProvider(PasswordPolicyManagerProvider.class).validate(realm, user, password);
if (error != null) throw new ModelException(error.getMessage(), error.getParameters());
PolicyError error = session.getProvider(PasswordPolicyManagerProvider.class).validate(realm, user, password);
if (error != null) throw new ModelException(error.getMessage(), error.getParameters());
}
try {
LDAPOperationDecorator operationDecorator = null;

View file

@ -281,6 +281,18 @@ public class LDAPStorageProviderFactory implements UserStorageProviderFactory<LD
throw new ComponentValidationException("ldapErrorCantEnableStartTlsAndConnectionPooling");
}
// editMode is mandatory
if (config.get(LDAPConstants.EDIT_MODE) == null) {
throw new ComponentValidationException("ldapErrorEditModeMandatory");
}
// validatePasswordPolicy applicable only for WRITABLE mode
if (cfg.getEditMode() != UserStorageProvider.EditMode.WRITABLE) {
if (cfg.isValidatePasswordPolicy()) {
throw new ComponentValidationException("ldapErrorValidatePasswordPolicyAvailableForWritableOnly");
}
}
if (!userStorageModel.isImportEnabled() && cfg.getEditMode() == UserStorageProvider.EditMode.UNSYNCED) {
throw new ComponentValidationException("ldapErrorCantEnableUnsyncedAndImportOff");
}

View file

@ -233,7 +233,7 @@ public class UserStorageRestTest extends AbstractAdminTest {
@Test
public void testValidateAndCreateLdapProvider() {
public void testValidateAndCreateLdapProviderCustomSearchFilter() {
// Invalid filter
ComponentRepresentation ldapRep = createBasicLDAPProviderRep();
@ -271,6 +271,7 @@ public class UserStorageRestTest extends AbstractAdminTest {
ldapRep2.setProviderType(UserStorageProvider.class.getName());
ldapRep2.setConfig(new MultivaluedHashMap<>());
ldapRep2.getConfig().putSingle("priority", Integer.toString(2));
ldapRep2.getConfig().putSingle(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.UNSYNCED.name());
ldapRep2.getConfig().putSingle(LDAPConstants.BIND_DN, "cn=manager");
ldapRep2.getConfig().putSingle(LDAPConstants.BIND_CREDENTIAL, "password");
String id2 = createComponent(ldapRep2);
@ -284,6 +285,40 @@ public class UserStorageRestTest extends AbstractAdminTest {
removeComponent(id2);
}
@Test
public void testValidateAndCreateLdapProviderEditMode() {
// Test provider without editMode should fail
ComponentRepresentation ldapRep = createBasicLDAPProviderRep();
ldapRep.getConfig().remove(LDAPConstants.EDIT_MODE);
Response resp = realm.components().add(ldapRep);
Assert.assertEquals(400, resp.getStatus());
resp.close();
// Test provider with READ_ONLY edit mode and validatePasswordPolicy will fail
ldapRep = createBasicLDAPProviderRep();
ldapRep.getConfig().putSingle(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.READ_ONLY.name());
ldapRep.getConfig().putSingle(LDAPConstants.VALIDATE_PASSWORD_POLICY, "true");
resp = realm.components().add(ldapRep);
Assert.assertEquals(400, resp.getStatus());
resp.close();
// Test provider with UNSYNCED edit mode and validatePasswordPolicy will fail
ldapRep.getConfig().putSingle(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.UNSYNCED.name());
ldapRep.getConfig().putSingle(LDAPConstants.VALIDATE_PASSWORD_POLICY, "true");
resp = realm.components().add(ldapRep);
Assert.assertEquals(400, resp.getStatus());
resp.close();
// Test provider with WRITABLE edit mode and validatePasswordPolicy will fail
ldapRep.getConfig().putSingle(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.WRITABLE.name());
ldapRep.getConfig().putSingle(LDAPConstants.SYNC_REGISTRATIONS, "true");
String id1 = createComponent(ldapRep);
// Cleanup
removeComponent(id1);
}
@Test
public void testUpdateProvider() {
ComponentRepresentation ldapRep = createBasicLDAPProviderRep();
@ -392,6 +427,7 @@ public class UserStorageRestTest extends AbstractAdminTest {
ldapRep.setProviderType(UserStorageProvider.class.getName());
ldapRep.setConfig(new MultivaluedHashMap<>());
ldapRep.getConfig().putSingle("priority", Integer.toString(2));
ldapRep.getConfig().putSingle(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.WRITABLE.name());
return ldapRep;
}

View file

@ -56,7 +56,8 @@
"providerName": "ldap",
"priority": 1,
"config": {
"connectionUrl": "ldap://foo"
"connectionUrl": "ldap://foo",
"editMode": "WRITABLE"
}
},
{
@ -64,7 +65,8 @@
"providerName": "ldap",
"priority": 2,
"config": {
"connectionUrl": "ldap://bar"
"connectionUrl": "ldap://bar",
"editMode": "WRITABLE"
}
}
],

View file

@ -1184,7 +1184,7 @@ ldap.edit-mode.tooltip=READ_ONLY is a read-only LDAP store. WRITABLE means data
update-profile-first-login=Update Profile First Login
update-profile-first-login.tooltip=Update profile on first login
sync-registrations=Sync Registrations
ldap.sync-registrations.tooltip=Should newly created users be created within LDAP store? Priority effects which provider is chosen to sync the new user.
ldap.sync-registrations.tooltip=Should newly created users be created within LDAP store? Priority effects which provider is chosen to sync the new user. This setting is effectively appplied only with WRITABLE edit mode.
import-enabled=Import Users
ldap.import-enabled.tooltip=If true, LDAP users will be imported into Keycloak DB and synced by the configured sync policies.
vendor=Vendor
@ -1247,7 +1247,7 @@ ldap-connection-timeout=Connection Timeout
ldap.connection-timeout.tooltip=LDAP Connection Timeout in milliseconds
ldap-read-timeout=Read Timeout
ldap.read-timeout.tooltip=LDAP Read Timeout in milliseconds. This timeout applies for LDAP read operations
ldap.validate-password-policy.tooltip=Determines if Keycloak should validate the password with the realm password policy before updating it
ldap.validate-password-policy.tooltip=Determines if Keycloak should validate the password with the realm password policy before updating the LDAP mapped user. When this is false, Keycloak password policy would not be applied, which means that password will be updated on LDAP server unless LDAP server itself has some password policy rules. This setting is possible only with WRITABLE edit mode.
ldap.connection-pooling.tooltip=Determines if Keycloak should use connection pooling for accessing LDAP server
ldap.connection-pooling.authentication.tooltip=A list of space-separated authentication types of connections that may be pooled. Valid types are "none", "simple", and "DIGEST-MD5".
ldap.connection-pooling.debug.tooltip=A string that indicates the level of debug output to produce. Valid values are "fine" (trace connection creation and removal) and "all" (all debugging information).

View file

@ -11,6 +11,7 @@ invalidPasswordHistoryMessage=Invalid password: must not be equal to any of last
invalidPasswordBlacklistedMessage=Invalid password: password is blacklisted.
invalidPasswordGenericMessage=Invalid password: new password does not match password policies.
ldapErrorEditModeMandatory=Edit Mode is mandatory
ldapErrorInvalidCustomFilter=Custom configured LDAP filter does not start with "(" or does not end with ")".
ldapErrorConnectionTimeoutNotNumber=Connection Timeout must be a number
ldapErrorReadTimeoutNotNumber=Read Timeout must be a number
@ -21,6 +22,7 @@ ldapErrorCantWriteOnlyAndReadOnly=Can not set write-only and read-only together
ldapErrorCantEnableStartTlsAndConnectionPooling=Can not enable both StartTLS and connection pooling.
ldapErrorCantEnableUnsyncedAndImportOff=Can not disable Importing users when LDAP provider mode is UNSYNCED
ldapErrorMissingGroupsPathGroup=Groups path group does not exist - please create the group on specified path first
ldapErrorValidatePasswordPolicyAvailableForWritableOnly=Validate Password Policy is applicable only with WRITABLE edit mode
clientRedirectURIsFragmentError=Redirect URIs must not contain an URI fragment
clientRootURLFragmentError=Root URL must not contain an URL fragment

View file

@ -46,11 +46,12 @@
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="editMode">{{:: 'edit-mode' | translate}}</label>
<label class="col-md-2 control-label" for="editMode"><span class="required">*</span> {{:: 'edit-mode' | translate}}</label>
<div class="col-md-6">
<div>
<select class="form-control" id="editMode"
ng-model="instance.config['editMode'][0]">
ng-model="instance.config['editMode'][0]"
required>
<option>READ_ONLY</option>
<option>WRITABLE</option>
<option>UNSYNCED</option>