Browse Source

new user profile ldap profile setting

Jason Rivard 5 years ago
parent
commit
08db118b1d

+ 21 - 9
server/src/main/java/password/pwm/config/Configuration.java

@@ -73,6 +73,7 @@ import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.i18n.PwmLocaleBundle;
 import password.pwm.i18n.PwmLocaleBundle;
 import password.pwm.util.PasswordData;
 import password.pwm.util.PasswordData;
 import password.pwm.util.i18n.LocaleHelper;
 import password.pwm.util.i18n.LocaleHelper;
+import password.pwm.util.java.LazySupplier;
 import password.pwm.util.java.StringUtil;
 import password.pwm.util.java.StringUtil;
 import password.pwm.util.logging.PwmLogLevel;
 import password.pwm.util.logging.PwmLogLevel;
 import password.pwm.util.logging.PwmLogger;
 import password.pwm.util.logging.PwmLogger;
@@ -97,6 +98,7 @@ import java.util.Objects;
 import java.util.Optional;
 import java.util.Optional;
 import java.util.Set;
 import java.util.Set;
 import java.util.TreeMap;
 import java.util.TreeMap;
+import java.util.function.Supplier;
 
 
 /**
 /**
  * @author Jason D. Rivard
  * @author Jason D. Rivard
@@ -107,6 +109,8 @@ public class Configuration implements SettingReader
 
 
     private final StoredConfiguration storedConfiguration;
     private final StoredConfiguration storedConfiguration;
 
 
+    private final ConfigurationSuppliers configurationSuppliers = new ConfigurationSuppliers();
+
     private DataCache dataCache = new DataCache();
     private DataCache dataCache = new DataCache();
 
 
     public Configuration( final StoredConfiguration storedConfiguration )
     public Configuration( final StoredConfiguration storedConfiguration )
@@ -138,7 +142,7 @@ public class Configuration implements SettingReader
 
 
     public Map<String, LdapProfile> getLdapProfiles( )
     public Map<String, LdapProfile> getLdapProfiles( )
     {
     {
-        return getProfileMap( ProfileDefinition.LdapProfile, LdapProfile.class );
+        return configurationSuppliers.ldapProfilesSupplier.get();
     }
     }
 
 
     public EmailItemBean readSettingAsEmail( final PwmSetting setting, final Locale locale )
     public EmailItemBean readSettingAsEmail( final PwmSetting setting, final Locale locale )
@@ -797,14 +801,6 @@ public class Configuration implements SettingReader
 
 
     public LdapProfile getDefaultLdapProfile( ) throws PwmUnrecoverableException
     public LdapProfile getDefaultLdapProfile( ) throws PwmUnrecoverableException
     {
     {
-        if ( getLdapProfiles().isEmpty() )
-        {
-            throw new PwmUnrecoverableException( new ErrorInformation( PwmError.CONFIG_FORMAT_ERROR, null, new String[]
-                    {
-                            "no ldap profiles are defined",
-                    }
-            ) );
-        }
         return getLdapProfiles().values().iterator().next();
         return getLdapProfiles().values().iterator().next();
     }
     }
 
 
@@ -991,6 +987,22 @@ public class Configuration implements SettingReader
         return readValue;
         return readValue;
     }
     }
 
 
+    private class ConfigurationSuppliers
+    {
+        private final Supplier<Map<String, LdapProfile>> ldapProfilesSupplier = new LazySupplier<>( () ->
+        {
+            final Map<String, LdapProfile> map = new LinkedHashMap<>();
+            for ( final Map.Entry<String, LdapProfile> entry : getProfileMap( ProfileDefinition.LdapProfile, LdapProfile.class ).entrySet() )
+            {
+                if ( entry.getValue().isEnabled() )
+                {
+                    map.put( entry.getKey(), entry.getValue() );
+                }
+            }
+            return Collections.unmodifiableMap( map );
+        } );
+    }
+
     private static class DataCache
     private static class DataCache
     {
     {
         private final Map<String, Map<Locale, PwmPasswordPolicy>> cachedPasswordPolicy = new LinkedHashMap<>();
         private final Map<String, Map<Locale, PwmPasswordPolicy>> cachedPasswordPolicy = new LinkedHashMap<>();

+ 12 - 8
server/src/main/java/password/pwm/config/PwmSetting.java

@@ -835,14 +835,22 @@ public enum PwmSetting
     // new user settings
     // new user settings
     NEWUSER_ENABLE(
     NEWUSER_ENABLE(
             "newUser.enable", PwmSettingSyntax.BOOLEAN, PwmSettingCategory.NEWUSER_SETTINGS ),
             "newUser.enable", PwmSettingSyntax.BOOLEAN, PwmSettingCategory.NEWUSER_SETTINGS ),
+
     NEWUSER_PROFILE_LIST(
     NEWUSER_PROFILE_LIST(
             "newUser.profile.list", PwmSettingSyntax.PROFILE, PwmSettingCategory.INTERNAL ),
             "newUser.profile.list", PwmSettingSyntax.PROFILE, PwmSettingCategory.INTERNAL ),
+
+    NEWUSER_FORM(
+            "newUser.form", PwmSettingSyntax.FORM, PwmSettingCategory.NEWUSER_PROFILE ),
+    NEWUSER_LDAP_PROFILE(
+            "newUser.ldapProfile", PwmSettingSyntax.STRING, PwmSettingCategory.NEWUSER_PROFILE ),
     NEWUSER_CONTEXT(
     NEWUSER_CONTEXT(
             "newUser.createContext", PwmSettingSyntax.STRING, PwmSettingCategory.NEWUSER_PROFILE ),
             "newUser.createContext", PwmSettingSyntax.STRING, PwmSettingCategory.NEWUSER_PROFILE ),
     NEWUSER_AGREEMENT_MESSAGE(
     NEWUSER_AGREEMENT_MESSAGE(
             "display.newuser.agreement", PwmSettingSyntax.LOCALIZED_TEXT_AREA, PwmSettingCategory.NEWUSER_PROFILE ),
             "display.newuser.agreement", PwmSettingSyntax.LOCALIZED_TEXT_AREA, PwmSettingCategory.NEWUSER_PROFILE ),
-    NEWUSER_FORM(
-            "newUser.form", PwmSettingSyntax.FORM, PwmSettingCategory.NEWUSER_PROFILE ),
+    NEWUSER_PROFILE_DISPLAY_NAME(
+            "newUser.profile.displayName", PwmSettingSyntax.LOCALIZED_STRING, PwmSettingCategory.NEWUSER_PROFILE ),
+    NEWUSER_PROFILE_DISPLAY_VISIBLE(
+            "newUser.profile.visible", PwmSettingSyntax.BOOLEAN, PwmSettingCategory.NEWUSER_PROFILE ),
     NEWUSER_WRITE_ATTRIBUTES(
     NEWUSER_WRITE_ATTRIBUTES(
             "newUser.writeAttributes", PwmSettingSyntax.ACTION, PwmSettingCategory.NEWUSER_PROFILE ),
             "newUser.writeAttributes", PwmSettingSyntax.ACTION, PwmSettingCategory.NEWUSER_PROFILE ),
     NEWUSER_DELETE_ON_FAIL(
     NEWUSER_DELETE_ON_FAIL(
@@ -854,17 +862,13 @@ public enum PwmSetting
     NEWUSER_EMAIL_VERIFICATION(
     NEWUSER_EMAIL_VERIFICATION(
             "newUser.email.verification", PwmSettingSyntax.BOOLEAN, PwmSettingCategory.NEWUSER_PROFILE ),
             "newUser.email.verification", PwmSettingSyntax.BOOLEAN, PwmSettingCategory.NEWUSER_PROFILE ),
     NEWUSER_SMS_VERIFICATION(
     NEWUSER_SMS_VERIFICATION(
-        "newUser.sms.verification", PwmSettingSyntax.BOOLEAN, PwmSettingCategory.NEWUSER_PROFILE ),
+            "newUser.sms.verification", PwmSettingSyntax.BOOLEAN, PwmSettingCategory.NEWUSER_PROFILE ),
     NEWUSER_EXTERNAL_VERIFICATION(
     NEWUSER_EXTERNAL_VERIFICATION(
-        "newUser.external.verification", PwmSettingSyntax.BOOLEAN, PwmSettingCategory.NEWUSER_PROFILE ),
+            "newUser.external.verification", PwmSettingSyntax.BOOLEAN, PwmSettingCategory.NEWUSER_PROFILE ),
     NEWUSER_PASSWORD_POLICY_USER(
     NEWUSER_PASSWORD_POLICY_USER(
             "newUser.passwordPolicy.user", PwmSettingSyntax.STRING, PwmSettingCategory.NEWUSER_PROFILE ),
             "newUser.passwordPolicy.user", PwmSettingSyntax.STRING, PwmSettingCategory.NEWUSER_PROFILE ),
     NEWUSER_MINIMUM_WAIT_TIME(
     NEWUSER_MINIMUM_WAIT_TIME(
             "newUser.minimumWaitTime", PwmSettingSyntax.DURATION, PwmSettingCategory.NEWUSER_PROFILE ),
             "newUser.minimumWaitTime", PwmSettingSyntax.DURATION, PwmSettingCategory.NEWUSER_PROFILE ),
-    NEWUSER_PROFILE_DISPLAY_NAME(
-            "newUser.profile.displayName", PwmSettingSyntax.LOCALIZED_STRING, PwmSettingCategory.NEWUSER_PROFILE ),
-    NEWUSER_PROFILE_DISPLAY_VISIBLE(
-            "newUser.profile.visible", PwmSettingSyntax.BOOLEAN, PwmSettingCategory.NEWUSER_PROFILE ),
     NEWUSER_REDIRECT_URL(
     NEWUSER_REDIRECT_URL(
             "newUser.redirectUrl", PwmSettingSyntax.STRING, PwmSettingCategory.NEWUSER_PROFILE ),
             "newUser.redirectUrl", PwmSettingSyntax.STRING, PwmSettingCategory.NEWUSER_PROFILE ),
     NEWUSER_PROMPT_FOR_PASSWORD(
     NEWUSER_PROMPT_FOR_PASSWORD(

+ 18 - 0
server/src/main/java/password/pwm/config/profile/LdapProfile.java

@@ -31,6 +31,8 @@ import password.pwm.config.PwmSetting;
 import password.pwm.config.StoredValue;
 import password.pwm.config.StoredValue;
 import password.pwm.config.stored.StoredConfiguration;
 import password.pwm.config.stored.StoredConfiguration;
 import password.pwm.config.value.data.UserPermission;
 import password.pwm.config.value.data.UserPermission;
+import password.pwm.error.ErrorInformation;
+import password.pwm.error.PwmError;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.svc.cache.CacheKey;
 import password.pwm.svc.cache.CacheKey;
 import password.pwm.svc.cache.CachePolicy;
 import password.pwm.svc.cache.CachePolicy;
@@ -111,6 +113,7 @@ public class LdapProfile extends AbstractProfile implements Profile
 
 
     public ChaiProvider getProxyChaiProvider( final PwmApplication pwmApplication ) throws PwmUnrecoverableException
     public ChaiProvider getProxyChaiProvider( final PwmApplication pwmApplication ) throws PwmUnrecoverableException
     {
     {
+        verifyIsEnabled();
         return pwmApplication.getProxyChaiProvider( this.getIdentifier() );
         return pwmApplication.getProxyChaiProvider( this.getIdentifier() );
     }
     }
 
 
@@ -215,6 +218,21 @@ public class LdapProfile extends AbstractProfile implements Profile
         }
         }
     }
     }
 
 
+    private void verifyIsEnabled()
+            throws PwmUnrecoverableException
+    {
+        if ( !isEnabled() )
+        {
+            final String msg = "ldap profile '" + getIdentifier() + "' is not enabled";
+            throw new PwmUnrecoverableException( new ErrorInformation( PwmError.ERROR_SERVICE_NOT_AVAILABLE, msg ) );
+        }
+    }
+
+    public boolean isEnabled()
+    {
+        return readSettingAsBoolean( PwmSetting.LDAP_PROFILE_ENABLED );
+    }
+
     @Override
     @Override
     public String toString()
     public String toString()
     {
     {

+ 29 - 3
server/src/main/java/password/pwm/config/profile/NewUserProfile.java

@@ -34,6 +34,7 @@ import password.pwm.config.stored.StoredConfiguration;
 import password.pwm.error.ErrorInformation;
 import password.pwm.error.ErrorInformation;
 import password.pwm.error.PwmError;
 import password.pwm.error.PwmError;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.error.PwmUnrecoverableException;
+import password.pwm.util.java.StringUtil;
 import password.pwm.util.java.TimeDuration;
 import password.pwm.util.java.TimeDuration;
 import password.pwm.util.password.PasswordUtility;
 import password.pwm.util.password.PasswordUtility;
 
 
@@ -51,9 +52,12 @@ public class NewUserProfile extends AbstractProfile implements Profile
     private Instant newUserPasswordPolicyCacheTime;
     private Instant newUserPasswordPolicyCacheTime;
     private final Map<Locale, PwmPasswordPolicy> newUserPasswordPolicyCache = new HashMap<>();
     private final Map<Locale, PwmPasswordPolicy> newUserPasswordPolicyCache = new HashMap<>();
 
 
-    protected NewUserProfile( final String identifier, final Map<PwmSetting, StoredValue> storedValueMap )
+    private final StoredConfiguration storedConfiguration;
+
+    protected NewUserProfile( final String identifier, final Map<PwmSetting, StoredValue> storedValueMap, final StoredConfiguration storedConfiguration )
     {
     {
         super( identifier, storedValueMap );
         super( identifier, storedValueMap );
+        this.storedConfiguration = storedConfiguration;
     }
     }
 
 
     @Override
     @Override
@@ -117,7 +121,7 @@ public class NewUserProfile extends AbstractProfile implements Profile
                 lookupDN = configuredNewUserPasswordDN;
                 lookupDN = configuredNewUserPasswordDN;
             }
             }
 
 
-            if ( lookupDN.isEmpty() )
+            if ( StringUtil.isEmpty( lookupDN ) )
             {
             {
                 throw new PwmUnrecoverableException( new ErrorInformation(
                 throw new PwmUnrecoverableException( new ErrorInformation(
                         PwmError.ERROR_INVALID_CONFIG,
                         PwmError.ERROR_INVALID_CONFIG,
@@ -172,7 +176,29 @@ public class NewUserProfile extends AbstractProfile implements Profile
         @Override
         @Override
         public Profile makeFromStoredConfiguration( final StoredConfiguration storedConfiguration, final String identifier )
         public Profile makeFromStoredConfiguration( final StoredConfiguration storedConfiguration, final String identifier )
         {
         {
-            return new NewUserProfile( identifier, makeValueMap( storedConfiguration, identifier, PROFILE_TYPE.getCategory() ) );
+            return new NewUserProfile( identifier, makeValueMap( storedConfiguration, identifier, PROFILE_TYPE.getCategory() ), storedConfiguration );
+        }
+    }
+
+    public LdapProfile getLdapProfile()
+            throws PwmUnrecoverableException
+    {
+        final Configuration configuration = new Configuration( storedConfiguration );
+        final String configuredProfile = readSettingAsString( PwmSetting.NEWUSER_LDAP_PROFILE );
+        if ( !StringUtil.isEmpty( configuredProfile ) )
+        {
+            final LdapProfile ldapProfile = configuration.getLdapProfiles().get( configuredProfile );
+            if ( ldapProfile == null )
+            {
+                throw new PwmUnrecoverableException( new ErrorInformation( PwmError.CONFIG_FORMAT_ERROR, null, new String[]
+                        {
+                                "configured ldap profile for new user profile is invalid.  check setting "
+                                        + PwmSetting.NEWUSER_LDAP_PROFILE.toMenuLocationDebug( this.getIdentifier(), PwmConstants.DEFAULT_LOCALE ),
+                                }
+                ) );
+            }
+            return ldapProfile;
         }
         }
+        return new Configuration( storedConfiguration ).getDefaultLdapProfile();
     }
     }
 }
 }

+ 33 - 1
server/src/main/java/password/pwm/health/ConfigurationChecker.java

@@ -138,7 +138,8 @@ public class ConfigurationChecker implements HealthChecker
             VerifyResponseLdapAttribute.class,
             VerifyResponseLdapAttribute.class,
             VerifyDbConfiguredIfNeeded.class,
             VerifyDbConfiguredIfNeeded.class,
             VerifyIfDeprecatedSendMethodValuesUsed.class,
             VerifyIfDeprecatedSendMethodValuesUsed.class,
-            VerifyIfDeprecatedJsFormOptionUsed.class
+            VerifyIfDeprecatedJsFormOptionUsed.class,
+            VerifyNewUserLdapProfile.class
     ) );
     ) );
 
 
     static class VerifyBasicConfigs implements ConfigHealthCheck
     static class VerifyBasicConfigs implements ConfigHealthCheck
@@ -174,6 +175,11 @@ public class ConfigurationChecker implements HealthChecker
                 records.add( HealthRecord.forMessage( HealthMessage.Config_ShowDetailedErrors, PwmSetting.DISPLAY_SHOW_DETAILED_ERRORS.toMenuLocationDebug( null, locale ) ) );
                 records.add( HealthRecord.forMessage( HealthMessage.Config_ShowDetailedErrors, PwmSetting.DISPLAY_SHOW_DETAILED_ERRORS.toMenuLocationDebug( null, locale ) ) );
             }
             }
 
 
+            if ( config.getLdapProfiles().isEmpty() )
+            {
+                records.add( HealthRecord.forMessage( HealthMessage.Config_NoLdapProfiles ) );
+            }
+
             for ( final LdapProfile ldapProfile : config.getLdapProfiles().values() )
             for ( final LdapProfile ldapProfile : config.getLdapProfiles().values() )
             {
             {
                 final String testUserDN = ldapProfile.readSettingAsString( PwmSetting.LDAP_TEST_USER_DN );
                 final String testUserDN = ldapProfile.readSettingAsString( PwmSetting.LDAP_TEST_USER_DN );
@@ -380,6 +386,31 @@ public class ConfigurationChecker implements HealthChecker
         }
         }
     }
     }
 
 
+    static class VerifyNewUserLdapProfile implements ConfigHealthCheck
+    {
+        @Override
+        public List<HealthRecord> healthCheck( final Configuration config, final Locale locale )
+        {
+            final List<HealthRecord> records = new ArrayList<>();
+            for ( final NewUserProfile newUserProfile : config.getNewUserProfiles().values() )
+            {
+                final String configuredProfile = newUserProfile.readSettingAsString( PwmSetting.NEWUSER_LDAP_PROFILE );
+                if ( !StringUtil.isEmpty( configuredProfile ) )
+                {
+                    final LdapProfile ldapProfile = config.getLdapProfiles().get( configuredProfile );
+
+                    if ( ldapProfile == null )
+                    {
+                        records.add( HealthRecord.forMessage(
+                                HealthMessage.Config_InvalidLdapProfile,
+                                PwmSetting.NEWUSER_LDAP_PROFILE.toMenuLocationDebug( newUserProfile.getIdentifier(), locale ) ) );
+                    }
+                }
+            }
+            return Collections.unmodifiableList( records );
+        }
+    }
+
     static class VerifyIfDeprecatedJsFormOptionUsed implements ConfigHealthCheck
     static class VerifyIfDeprecatedJsFormOptionUsed implements ConfigHealthCheck
     {
     {
         @Override
         @Override
@@ -512,6 +543,7 @@ public class ConfigurationChecker implements HealthChecker
         }
         }
     }
     }
 
 
+
     interface ConfigHealthCheck
     interface ConfigHealthCheck
     {
     {
         List<HealthRecord> healthCheck(
         List<HealthRecord> healthCheck(

+ 3 - 0
server/src/main/java/password/pwm/health/HealthMessage.java

@@ -71,6 +71,9 @@ public enum HealthMessage
     Config_Certificate( HealthStatus.WARN, HealthTopic.Configuration ),
     Config_Certificate( HealthStatus.WARN, HealthTopic.Configuration ),
     Config_InvalidSendMethod( HealthStatus.CAUTION, HealthTopic.Configuration ),
     Config_InvalidSendMethod( HealthStatus.CAUTION, HealthTopic.Configuration ),
     Config_DeprecatedJSForm( HealthStatus.CONFIG, HealthTopic.Configuration ),
     Config_DeprecatedJSForm( HealthStatus.CONFIG, HealthTopic.Configuration ),
+    Config_InvalidLdapProfile( HealthStatus.CONFIG, HealthTopic.Configuration ),
+    Config_NoLdapProfiles( HealthStatus.CONFIG, HealthTopic.Configuration ),
+
     LDAP_VendorsNotSame( HealthStatus.CONFIG, HealthTopic.LDAP ),
     LDAP_VendorsNotSame( HealthStatus.CONFIG, HealthTopic.LDAP ),
     LDAP_OK( HealthStatus.GOOD, HealthTopic.LDAP ),
     LDAP_OK( HealthStatus.GOOD, HealthTopic.LDAP ),
     LDAP_RecentlyUnreachable( HealthStatus.CAUTION, HealthTopic.LDAP ),
     LDAP_RecentlyUnreachable( HealthStatus.CAUTION, HealthTopic.LDAP ),

+ 1 - 1
server/src/main/java/password/pwm/health/LDAPHealthChecker.java

@@ -924,7 +924,7 @@ public class LDAPHealthChecker implements HealthChecker
 
 
             try
             try
             {
             {
-                final LdapProfile ldapProfile = configuration.getDefaultLdapProfile();
+                final LdapProfile ldapProfile = newUserProfile.getLdapProfile();
                 if ( NewUserProfile.TEST_USER_CONFIG_VALUE.equals( policyUserStr ) )
                 if ( NewUserProfile.TEST_USER_CONFIG_VALUE.equals( policyUserStr ) )
                 {
                 {
                     final UserIdentity testUser = ldapProfile.getTestUser( pwmApplication );
                     final UserIdentity testUser = ldapProfile.getTestUser( pwmApplication );

+ 1 - 0
server/src/main/java/password/pwm/http/servlet/newuser/NewUserServlet.java

@@ -280,6 +280,7 @@ public class NewUserServlet extends ControlledPwmServlet
             {
             {
                 final MacroMachine macroMachine = NewUserUtils.createMacroMachineForNewUser(
                 final MacroMachine macroMachine = NewUserUtils.createMacroMachineForNewUser(
                         pwmApplication,
                         pwmApplication,
+                        newUserProfile,
                         pwmRequest.getLabel(),
                         pwmRequest.getLabel(),
                         newUserBean.getNewUserForm(),
                         newUserBean.getNewUserForm(),
                         null
                         null

+ 18 - 13
server/src/main/java/password/pwm/http/servlet/newuser/NewUserUtils.java

@@ -166,11 +166,11 @@ class NewUserUtils
 
 
         // add the auto-add object classes
         // add the auto-add object classes
         {
         {
-            final LdapProfile defaultLDAPProfile = pwmApplication.getConfig().getDefaultLdapProfile();
+            final LdapProfile defaultLDAPProfile = newUserProfile.getLdapProfile();
             createObjectClasses.addAll( defaultLDAPProfile.readSettingAsStringArray( PwmSetting.AUTO_ADD_OBJECT_CLASSES ) );
             createObjectClasses.addAll( defaultLDAPProfile.readSettingAsStringArray( PwmSetting.AUTO_ADD_OBJECT_CLASSES ) );
         }
         }
 
 
-        final ChaiProvider chaiProvider = pwmApplication.getConfig().getDefaultLdapProfile().getProxyChaiProvider( pwmApplication );
+        final ChaiProvider chaiProvider = newUserProfile.getLdapProfile().getProxyChaiProvider( pwmApplication );
         try
         try
         {
         {
             // create the ldap entry
             // create the ldap entry
@@ -306,7 +306,7 @@ class NewUserUtils
         remoteWriteFormData( pwmRequest, newUserForm );
         remoteWriteFormData( pwmRequest, newUserForm );
 
 
         // authenticate the user to pwm
         // authenticate the user to pwm
-        final UserIdentity userIdentity = new UserIdentity( newUserDN, pwmApplication.getConfig().getDefaultLdapProfile().getIdentifier() );
+        final UserIdentity userIdentity = new UserIdentity( newUserDN, newUserProfile.getLdapProfile().getIdentifier() );
         final SessionAuthenticator sessionAuthenticator = new SessionAuthenticator( pwmApplication, pwmRequest, PwmAuthenticationSource.NEW_USER_REGISTRATION );
         final SessionAuthenticator sessionAuthenticator = new SessionAuthenticator( pwmApplication, pwmRequest, PwmAuthenticationSource.NEW_USER_REGISTRATION );
         sessionAuthenticator.authenticateUser( userIdentity, userPassword );
         sessionAuthenticator.authenticateUser( userIdentity, userPassword );
 
 
@@ -349,8 +349,9 @@ class NewUserUtils
     {
     {
         try
         try
         {
         {
+            final NewUserProfile newUserProfile = NewUserServlet.getNewUserProfile( pwmRequest );
             NewUserUtils.LOGGER.warn( pwmRequest, () -> "deleting ldap user account " + userDN );
             NewUserUtils.LOGGER.warn( pwmRequest, () -> "deleting ldap user account " + userDN );
-            pwmRequest.getConfig().getDefaultLdapProfile().getProxyChaiProvider( pwmRequest.getPwmApplication() ).deleteEntry( userDN );
+            newUserProfile.getLdapProfile().getProxyChaiProvider( pwmRequest.getPwmApplication() ).deleteEntry( userDN );
             NewUserUtils.LOGGER.warn( pwmRequest, () -> "ldap user account " + userDN + " has been deleted" );
             NewUserUtils.LOGGER.warn( pwmRequest, () -> "ldap user account " + userDN + " has been deleted" );
         }
         }
         catch ( final ChaiUnavailableException | ChaiOperationException e )
         catch ( final ChaiUnavailableException | ChaiOperationException e )
@@ -367,8 +368,8 @@ class NewUserUtils
     )
     )
             throws PwmUnrecoverableException, ChaiUnavailableException
             throws PwmUnrecoverableException, ChaiUnavailableException
     {
     {
-        final MacroMachine macroMachine = createMacroMachineForNewUser( pwmRequest.getPwmApplication(), pwmRequest.getLabel(), formValues, null );
         final NewUserProfile newUserProfile = NewUserServlet.getNewUserProfile( pwmRequest );
         final NewUserProfile newUserProfile = NewUserServlet.getNewUserProfile( pwmRequest );
+        final MacroMachine macroMachine = createMacroMachineForNewUser( pwmRequest.getPwmApplication(), newUserProfile, pwmRequest.getLabel(), formValues, null );
         final List<String> configuredNames = newUserProfile.readSettingAsStringArray( PwmSetting.NEWUSER_USERNAME_DEFINITION );
         final List<String> configuredNames = newUserProfile.readSettingAsStringArray( PwmSetting.NEWUSER_USERNAME_DEFINITION );
         final List<String> failedValues = new ArrayList<>();
         final List<String> failedValues = new ArrayList<>();
 
 
@@ -378,7 +379,7 @@ class NewUserUtils
 
 
         if ( configuredNames == null || configuredNames.isEmpty() || configuredNames.iterator().next().isEmpty() )
         if ( configuredNames == null || configuredNames.isEmpty() || configuredNames.iterator().next().isEmpty() )
         {
         {
-            final String namingAttribute = pwmRequest.getConfig().getDefaultLdapProfile().readSettingAsString( PwmSetting.LDAP_NAMING_ATTRIBUTE );
+            final String namingAttribute = newUserProfile.getLdapProfile().readSettingAsString( PwmSetting.LDAP_NAMING_ATTRIBUTE );
             String namingValue = null;
             String namingValue = null;
             for ( final String formKey : formValues.getFormData().keySet() )
             for ( final String formKey : formValues.getFormData().keySet() )
             {
             {
@@ -412,7 +413,7 @@ class NewUserUtils
                 if ( !testIfEntryNameExists( pwmRequest, expandedName ) )
                 if ( !testIfEntryNameExists( pwmRequest, expandedName ) )
                 {
                 {
                     NewUserUtils.LOGGER.trace( pwmRequest, () -> "generated entry name for new user is unique: " + expandedName );
                     NewUserUtils.LOGGER.trace( pwmRequest, () -> "generated entry name for new user is unique: " + expandedName );
-                    final String namingAttribute = pwmRequest.getConfig().getDefaultLdapProfile().readSettingAsString( PwmSetting.LDAP_NAMING_ATTRIBUTE );
+                    final String namingAttribute = newUserProfile.getLdapProfile().readSettingAsString( PwmSetting.LDAP_NAMING_ATTRIBUTE );
                     final String escapedName = StringUtil.escapeLdapDN( expandedName );
                     final String escapedName = StringUtil.escapeLdapDN( expandedName );
                     generatedDN = namingAttribute + "=" + escapedName + "," + expandedContext;
                     generatedDN = namingAttribute + "=" + escapedName + "," + expandedContext;
                     NewUserUtils.LOGGER.debug( pwmRequest, () -> "generated dn for new user: " + generatedDN );
                     NewUserUtils.LOGGER.debug( pwmRequest, () -> "generated dn for new user: " + generatedDN );
@@ -488,6 +489,7 @@ class NewUserUtils
 
 
     static UserInfoBean createUserInfoBeanForNewUser(
     static UserInfoBean createUserInfoBeanForNewUser(
             final PwmApplication pwmApplication,
             final PwmApplication pwmApplication,
+            final NewUserProfile newUserProfile,
             final NewUserForm newUserForm
             final NewUserForm newUserForm
     )
     )
         throws PwmUnrecoverableException
         throws PwmUnrecoverableException
@@ -495,10 +497,10 @@ class NewUserUtils
     {
     {
         final Map<String, String> formValues = newUserForm.getFormData();
         final Map<String, String> formValues = newUserForm.getFormData();
 
 
-        final String emailAddressAttribute = pwmApplication.getConfig().getDefaultLdapProfile().readSettingAsString(
+        final String emailAddressAttribute = newUserProfile.getLdapProfile().readSettingAsString(
             PwmSetting.EMAIL_USER_MAIL_ATTRIBUTE );
             PwmSetting.EMAIL_USER_MAIL_ATTRIBUTE );
 
 
-        final String usernameAttribute = pwmApplication.getConfig().getDefaultLdapProfile().readSettingAsString( PwmSetting.LDAP_USERNAME_ATTRIBUTE );
+        final String usernameAttribute = newUserProfile.getLdapProfile().readSettingAsString( PwmSetting.LDAP_USERNAME_ATTRIBUTE );
 
 
         return UserInfoBean.builder()
         return UserInfoBean.builder()
             .userEmailAddress( formValues.get( emailAddressAttribute ) )
             .userEmailAddress( formValues.get( emailAddressAttribute ) )
@@ -509,6 +511,7 @@ class NewUserUtils
 
 
     static MacroMachine createMacroMachineForNewUser(
     static MacroMachine createMacroMachineForNewUser(
             final PwmApplication pwmApplication,
             final PwmApplication pwmApplication,
+            final NewUserProfile newUserProfile,
             final SessionLabel sessionLabel,
             final SessionLabel sessionLabel,
             final NewUserForm newUserForm,
             final NewUserForm newUserForm,
             final TokenDestinationItem tokenDestinationItem
             final TokenDestinationItem tokenDestinationItem
@@ -518,7 +521,7 @@ class NewUserUtils
         final LoginInfoBean stubLoginBean = new LoginInfoBean();
         final LoginInfoBean stubLoginBean = new LoginInfoBean();
         stubLoginBean.setUserCurrentPassword( newUserForm.getNewUserPassword() );
         stubLoginBean.setUserCurrentPassword( newUserForm.getNewUserPassword() );
 
 
-        final UserInfoBean stubUserBean = createUserInfoBeanForNewUser( pwmApplication, newUserForm );
+        final UserInfoBean stubUserBean = createUserInfoBeanForNewUser( pwmApplication, newUserProfile, newUserForm );
 
 
         final MacroMachine.StringReplacer stringReplacer = tokenDestinationItem == null
         final MacroMachine.StringReplacer stringReplacer = tokenDestinationItem == null
                 ? null
                 ? null
@@ -622,7 +625,7 @@ class NewUserUtils
             throws PwmUnrecoverableException
             throws PwmUnrecoverableException
     {
     {
         final List<FormConfiguration> formFields = newUserProfile.readSettingAsForm( PwmSetting.NEWUSER_FORM );
         final List<FormConfiguration> formFields = newUserProfile.readSettingAsForm( PwmSetting.NEWUSER_FORM );
-        final LdapProfile defaultLDAPProfile = pwmRequest.getConfig().getDefaultLdapProfile();
+        final LdapProfile defaultLDAPProfile = newUserProfile.getLdapProfile();
 
 
         final Map<String, TokenDestinationItem.Type> workingMap = new LinkedHashMap<>( FormUtility.identifyFormItemsNeedingPotentialTokenValidation(
         final Map<String, TokenDestinationItem.Type> workingMap = new LinkedHashMap<>( FormUtility.identifyFormItemsNeedingPotentialTokenValidation(
                 defaultLDAPProfile,
                 defaultLDAPProfile,
@@ -695,7 +698,8 @@ class NewUserUtils
     )
     )
             throws PwmUnrecoverableException
             throws PwmUnrecoverableException
     {
     {
-        final UserInfo userInfo = createUserInfoBeanForNewUser( pwmRequest.getPwmApplication(), newUserBean.getNewUserForm() );
+        final NewUserProfile newUserProfile = NewUserServlet.getNewUserProfile( pwmRequest );
+        final UserInfo userInfo = createUserInfoBeanForNewUser( pwmRequest.getPwmApplication(), newUserProfile, newUserBean.getNewUserForm() );
 
 
         final VerificationMethodSystem remoteMethod;
         final VerificationMethodSystem remoteMethod;
         if ( newUserBean.getRemoteRecoveryMethod() == null )
         if ( newUserBean.getRemoteRecoveryMethod() == null )
@@ -756,6 +760,7 @@ class NewUserUtils
                     final Map<String, String> tokenPayloadMap = NewUserFormUtils.toTokenPayload( pwmRequest, newUserBean );
                     final Map<String, String> tokenPayloadMap = NewUserFormUtils.toTokenPayload( pwmRequest, newUserBean );
                     final MacroMachine macroMachine = createMacroMachineForNewUser(
                     final MacroMachine macroMachine = createMacroMachineForNewUser(
                             pwmRequest.getPwmApplication(),
                             pwmRequest.getPwmApplication(),
+                            newUserProfile,
                             pwmRequest.getLabel(),
                             pwmRequest.getLabel(),
                             newUserBean.getNewUserForm(),
                             newUserBean.getNewUserForm(),
                             tokenDestinationItem );
                             tokenDestinationItem );
@@ -800,7 +805,7 @@ class NewUserUtils
         }
         }
 
 
         final List<FormConfiguration> formFields = newUserProfile.readSettingAsForm( PwmSetting.NEWUSER_FORM );
         final List<FormConfiguration> formFields = newUserProfile.readSettingAsForm( PwmSetting.NEWUSER_FORM );
-        final LdapProfile defaultLDAPProfile = pwmRequest.getConfig().getDefaultLdapProfile();
+        final LdapProfile defaultLDAPProfile = newUserProfile.getLdapProfile();
 
 
         final Map<String, TokenDestinationItem.Type> tokenTypeMap = FormUtility.identifyFormItemsNeedingPotentialTokenValidation(
         final Map<String, TokenDestinationItem.Type> tokenTypeMap = FormUtility.identifyFormItemsNeedingPotentialTokenValidation(
                 defaultLDAPProfile,
                 defaultLDAPProfile,

+ 5 - 0
server/src/main/resources/password/pwm/config/PwmSetting.xml

@@ -2687,6 +2687,11 @@
             <value>default</value>
             <value>default</value>
         </default>
         </default>
     </setting>
     </setting>
+    <setting hidden="false" key="newUser.ldapProfile" level="1" required="true">
+        <default>
+            <value/>
+        </default>
+    </setting>
     <setting hidden="false" key="newUser.createContext" level="1" required="true">
     <setting hidden="false" key="newUser.createContext" level="1" required="true">
         <flag>ldapDNsyntax</flag>
         <flag>ldapDNsyntax</flag>
         <default>
         <default>

+ 2 - 0
server/src/main/resources/password/pwm/i18n/Health.properties

@@ -62,6 +62,8 @@ HealthMessage_Config_DNValueValidity=LDAP DN configuration setting %1% issue: %2
 HealthMessage_Config_Certificate=Certificate for setting %1% issue: %2%
 HealthMessage_Config_Certificate=Certificate for setting %1% issue: %2%
 HealthMessage_Config_InvalidSendMethod=The send method '%1%' is no longer available for setting %2%.  Please modify the configuration to use an alternate value.
 HealthMessage_Config_InvalidSendMethod=The send method '%1%' is no longer available for setting %2%.  Please modify the configuration to use an alternate value.
 HealthMessage_Config_DeprecatedJSForm=The javascript form option in the form setting %1% has been deprecated and will be removed in a future version.  Use the setting %2% instead.
 HealthMessage_Config_DeprecatedJSForm=The javascript form option in the form setting %1% has been deprecated and will be removed in a future version.  Use the setting %2% instead.
+HealthMessage_Config_InvalidLdapProfile=The configured LDAP profile is invalid or inactive for setting %1%.
+HealthMessage_Config_NoLdapProfiles=There are no enabled LDAP Profiles configured.
 HealthMessage_LDAP_VendorsNotSame=LDAP directories of different vendor types are in use.  This configuration may cause undesirable side effects and is not supported.  %1%
 HealthMessage_LDAP_VendorsNotSame=LDAP directories of different vendor types are in use.  This configuration may cause undesirable side effects and is not supported.  %1%
 HealthMessage_LDAP_Ad_History_Asn_Missing=%1% is enabled, but the server at %2% does not support this feature.  Check to be sure it is upgraded to Windows Server 2008 R2 SP1 or greater.  Password changes against this server may fail until this is resolved.
 HealthMessage_LDAP_Ad_History_Asn_Missing=%1% is enabled, but the server at %2% does not support this feature.  Check to be sure it is upgraded to Windows Server 2008 R2 SP1 or greater.  Password changes against this server may fail until this is resolved.
 HealthMessage_LDAP_RecentlyUnreachable=LDAP profile %1% was recently unavailable (%2% ago at %3%): %4%
 HealthMessage_LDAP_RecentlyUnreachable=LDAP profile %1% was recently unavailable (%2% ago at %3%): %4%

+ 3 - 1
server/src/main/resources/password/pwm/i18n/PwmSetting.properties

@@ -498,7 +498,8 @@ Setting_Description_network.allowMultiIPSession=Enable this option to allow @Pwm
 Setting_Description_network.ip.permittedRange=Enable this option to have @PwmAppName@ only permit connections originating from the specified IP address ranges.  If disabled (default), @PwmAppName@ permits any source IP address. <p>Supported range specifications are\:<p><ul><li>Full IPv4 address, such as <b>12.34.56.78</b></li><li>Full IPv6 address, such as <b>2001\:18e8\:3\:171\:218\:8bff\:fe2a\:56a4</b></li><li>Partial IPv4 address, such as <b>12.34</b> (which matches any IP addres starting <b>12.34</b></li><li>IPv4 network/netmask, such as <b>18.25.0.0/255.255.0.0</b></li><li>IPv4 or IPv6 CIDR slash notation, such as <b>18.25.0.0/16</b> or <b>2001\:18e8\:3\:171\:\:/64</b></li></ul>
 Setting_Description_network.ip.permittedRange=Enable this option to have @PwmAppName@ only permit connections originating from the specified IP address ranges.  If disabled (default), @PwmAppName@ permits any source IP address. <p>Supported range specifications are\:<p><ul><li>Full IPv4 address, such as <b>12.34.56.78</b></li><li>Full IPv6 address, such as <b>2001\:18e8\:3\:171\:218\:8bff\:fe2a\:56a4</b></li><li>Partial IPv4 address, such as <b>12.34</b> (which matches any IP addres starting <b>12.34</b></li><li>IPv4 network/netmask, such as <b>18.25.0.0/255.255.0.0</b></li><li>IPv4 or IPv6 CIDR slash notation, such as <b>18.25.0.0/16</b> or <b>2001\:18e8\:3\:171\:\:/64</b></li></ul>
 Setting_Description_network.requiredHttpHeaders=<p>If specified, any HTTP/S request sent to this @PwmAppName@ application server must include these headers.  This feature is useful if you have an upstream security gateway, proxy or web server and wish to only allow sessions from the gateway, and deny direct access to this @PwmAppName@ application server from clients.</p><p>The settings must be in <code>name\=value</code> format.  If the upstream security gateway, proxy or web server is not setting these name/value headers, you will no longer be able to access this @PwmAppName@ application server.</p><p><b>WARNING:</b>If the client you are using to access this server is not setting the headers configured here, this @PwmAppName@ server will become inaccessible.</p>
 Setting_Description_network.requiredHttpHeaders=<p>If specified, any HTTP/S request sent to this @PwmAppName@ application server must include these headers.  This feature is useful if you have an upstream security gateway, proxy or web server and wish to only allow sessions from the gateway, and deny direct access to this @PwmAppName@ application server from clients.</p><p>The settings must be in <code>name\=value</code> format.  If the upstream security gateway, proxy or web server is not setting these name/value headers, you will no longer be able to access this @PwmAppName@ application server.</p><p><b>WARNING:</b>If the client you are using to access this server is not setting the headers configured here, this @PwmAppName@ server will become inaccessible.</p>
 Setting_Description_network.reverseDNS.enable=Enable this option to have @PwmAppName@ use its reverse DNS system to record the hostname of the client.  In some cases this can cause performance issues so you can disable it if you do not requrie it.
 Setting_Description_network.reverseDNS.enable=Enable this option to have @PwmAppName@ use its reverse DNS system to record the hostname of the client.  In some cases this can cause performance issues so you can disable it if you do not requrie it.
-Setting_Description_newUser.createContext=Specify the LDAP context where you would like @PwmAppName@ to create new users. You can use macros in this setting. @PwmAppName@ uses the default LDAP profile when creating new user.
+Setting_Description_newUser.createContext=Specify the LDAP context where you would like @PwmAppName@ to create new users. You can use macros in this setting.
+Setting_Description_newUser.ldapProfile=Specify the LDAP profile where you would like @PwmAppName@ to create new users. If blank, the default LDAP profile will be used when creating new user.
 Setting_Description_newUser.deleteOnFail=Enable this option to have @PwmAppName@ delete the new user account if the creation fails for some reason.  It deletes the (potentially partially-created) "broken" account in LDAP.
 Setting_Description_newUser.deleteOnFail=Enable this option to have @PwmAppName@ delete the new user account if the creation fails for some reason.  It deletes the (potentially partially-created) "broken" account in LDAP.
 Setting_Description_newUser.email.verification=Enable this option to have @PwmAppName@ send an email to the new user's email address before it creates the account.  The new user must verify receipt of the email before @PwmAppName@ creates the account. All of your email settings must also be filled out before this will work. Testing the email settings should take place to verify that this email will be sent.
 Setting_Description_newUser.email.verification=Enable this option to have @PwmAppName@ send an email to the new user's email address before it creates the account.  The new user must verify receipt of the email before @PwmAppName@ creates the account. All of your email settings must also be filled out before this will work. Testing the email settings should take place to verify that this email will be sent.
 Setting_Description_newUser.enable=Enable this option to allow @PwmAppName@ to display the new user registration.
 Setting_Description_newUser.enable=Enable this option to allow @PwmAppName@ to display the new user registration.
@@ -1027,6 +1028,7 @@ Setting_Label_network.ip.permittedRange=Permitted IP Network Addresses
 Setting_Label_network.requiredHttpHeaders=Required HTTP Headers
 Setting_Label_network.requiredHttpHeaders=Required HTTP Headers
 Setting_Label_network.reverseDNS.enable=Enable Reverse DNS
 Setting_Label_network.reverseDNS.enable=Enable Reverse DNS
 Setting_Label_newUser.createContext=Creation Context
 Setting_Label_newUser.createContext=Creation Context
+Setting_Label_newUser.ldapProfile=LDAP Profile
 Setting_Label_newUser.deleteOnFail=Delete On Creation Failure
 Setting_Label_newUser.deleteOnFail=Delete On Creation Failure
 Setting_Label_newUser.email.verification=Enable New User Email Verification
 Setting_Label_newUser.email.verification=Enable New User Email Verification
 Setting_Label_newUser.enable=Enable New User Registration
 Setting_Label_newUser.enable=Enable New User Registration