Browse Source

add pwmData schema attribute

jrivard@gmail.com 6 years ago
parent
commit
921e21ce30
33 changed files with 275 additions and 123 deletions
  1. 0 1
      server/src/main/java/password/pwm/AppProperty.java
  2. 3 3
      server/src/main/java/password/pwm/PwmApplication.java
  3. 3 3
      server/src/main/java/password/pwm/config/PwmSetting.java
  4. 2 2
      server/src/main/java/password/pwm/error/PwmError.java
  5. 1 1
      server/src/main/java/password/pwm/http/servlet/admin/AppDashboardData.java
  6. 6 6
      server/src/main/java/password/pwm/http/servlet/configmanager/DebugItemGenerator.java
  7. 2 1
      server/src/main/java/password/pwm/svc/PwmServiceEnum.java
  8. 4 4
      server/src/main/java/password/pwm/svc/node/DatabaseNodeDataService.java
  9. 5 15
      server/src/main/java/password/pwm/svc/node/LDAPNodeDataService.java
  10. 2 2
      server/src/main/java/password/pwm/svc/node/NodeDataServiceProvider.java
  11. 1 1
      server/src/main/java/password/pwm/svc/node/NodeInfo.java
  12. 20 20
      server/src/main/java/password/pwm/svc/node/NodeMachine.java
  13. 24 24
      server/src/main/java/password/pwm/svc/node/NodeService.java
  14. 6 6
      server/src/main/java/password/pwm/svc/node/NodeServiceSettings.java
  15. 2 2
      server/src/main/java/password/pwm/svc/node/NodeServiceStatistics.java
  16. 1 1
      server/src/main/java/password/pwm/svc/node/StoredNodeData.java
  17. 1 1
      server/src/main/java/password/pwm/svc/pwnotify/PwNotifyDbStorageService.java
  18. 68 4
      server/src/main/java/password/pwm/util/cli/commands/LdapSchemaExtendCommand.java
  19. 1 1
      server/src/main/java/password/pwm/util/java/ConditionalTaskExecutor.java
  20. 1 1
      server/src/main/java/password/pwm/util/secure/X509Utils.java
  21. 0 1
      server/src/main/resources/password/pwm/AppProperty.properties
  22. 4 4
      server/src/main/resources/password/pwm/config/PwmSetting.xml
  23. 1 1
      server/src/main/resources/password/pwm/i18n/Error.properties
  24. 8 8
      server/src/main/resources/password/pwm/i18n/PwmSetting.properties
  25. 2 1
      server/src/main/resources/password/pwm/ldap/schema/SchemaDefinition.properties
  26. 22 1
      webapp/src/build/ldif/AD-schema.ldif
  27. 10 0
      webapp/src/build/ldif/ApacheDS-schema.ldif
  28. 16 1
      webapp/src/build/ldif/OracleDS-schema.ldif
  29. 16 2
      webapp/src/build/ldif/edirectory-schema-update.ldif
  30. 15 1
      webapp/src/build/ldif/edirectory-schema.ldif
  31. 15 2
      webapp/src/build/ldif/edirectory-schema.sch
  32. 7 1
      webapp/src/build/ldif/openDJ-schema.ldif
  33. 6 1
      webapp/src/build/ldif/openldap.schema

+ 0 - 1
server/src/main/java/password/pwm/AppProperty.java

@@ -83,7 +83,6 @@ public enum AppProperty
     CLUSTER_DB_HEARTBEAT_SECONDS                    ( "cluster.db.heartbeatSeconds" ),
     CLUSTER_DB_HEARTBEAT_SECONDS                    ( "cluster.db.heartbeatSeconds" ),
     CLUSTER_DB_NODE_TIMEOUT_SECONDS                 ( "cluster.db.nodeTimeoutSeconds" ),
     CLUSTER_DB_NODE_TIMEOUT_SECONDS                 ( "cluster.db.nodeTimeoutSeconds" ),
     CLUSTER_DB_NODE_PURGE_SECONDS                   ( "cluster.db.nodePurgeSeconds" ),
     CLUSTER_DB_NODE_PURGE_SECONDS                   ( "cluster.db.nodePurgeSeconds" ),
-    CLUSTER_LDAP_ATTRIBUTES                         ( "cluster.ldap.attribute" ),
     CLUSTER_LDAP_HEARTBEAT_SECONDS                  ( "cluster.ldap.heartbeatSeconds" ),
     CLUSTER_LDAP_HEARTBEAT_SECONDS                  ( "cluster.ldap.heartbeatSeconds" ),
     CLUSTER_LDAP_NODE_TIMEOUT_SECONDS               ( "cluster.ldap.nodeTimeoutSeconds" ),
     CLUSTER_LDAP_NODE_TIMEOUT_SECONDS               ( "cluster.ldap.nodeTimeoutSeconds" ),
     CLUSTER_LDAP_NODE_PURGE_SECONDS                 ( "cluster.ldap.nodePurgeSeconds" ),
     CLUSTER_LDAP_NODE_PURGE_SECONDS                 ( "cluster.ldap.nodePurgeSeconds" ),

+ 3 - 3
server/src/main/java/password/pwm/PwmApplication.java

@@ -43,7 +43,7 @@ import password.pwm.ldap.search.UserSearchEngine;
 import password.pwm.svc.PwmService;
 import password.pwm.svc.PwmService;
 import password.pwm.svc.PwmServiceManager;
 import password.pwm.svc.PwmServiceManager;
 import password.pwm.svc.cache.CacheService;
 import password.pwm.svc.cache.CacheService;
-import password.pwm.svc.cluster.ClusterService;
+import password.pwm.svc.node.NodeService;
 import password.pwm.svc.email.EmailService;
 import password.pwm.svc.email.EmailService;
 import password.pwm.svc.event.AuditEvent;
 import password.pwm.svc.event.AuditEvent;
 import password.pwm.svc.event.AuditRecordFactory;
 import password.pwm.svc.event.AuditRecordFactory;
@@ -602,9 +602,9 @@ public class PwmApplication
         return ( UserSearchEngine ) pwmServiceManager.getService( UserSearchEngine.class );
         return ( UserSearchEngine ) pwmServiceManager.getService( UserSearchEngine.class );
     }
     }
 
 
-    public ClusterService getClusterService( )
+    public NodeService getClusterService( )
     {
     {
-        return ( ClusterService ) pwmServiceManager.getService( ClusterService.class );
+        return ( NodeService ) pwmServiceManager.getService( NodeService.class );
     }
     }
 
 
     public ErrorInformation getLastLocalDBFailure( )
     public ErrorInformation getLastLocalDBFailure( )

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

@@ -98,9 +98,9 @@ public enum PwmSetting
 
 
     // clustering
     // clustering
     CLUSTER_ENABLED(
     CLUSTER_ENABLED(
-            "cluster.enable", PwmSettingSyntax.BOOLEAN, PwmSettingCategory.CLUSTERING ),
+            "nodeService.enable", PwmSettingSyntax.BOOLEAN, PwmSettingCategory.CLUSTERING ),
     CLUSTER_STORAGE_MODE(
     CLUSTER_STORAGE_MODE(
-            "cluster.storageMode", PwmSettingSyntax.SELECT, PwmSettingCategory.CLUSTERING ),
+            "nodeService.storageMode", PwmSettingSyntax.SELECT, PwmSettingCategory.CLUSTERING ),
     SECURITY_LOGIN_SESSION_MODE(
     SECURITY_LOGIN_SESSION_MODE(
             "security.loginSession.mode", PwmSettingSyntax.SELECT, PwmSettingCategory.CLUSTERING ),
             "security.loginSession.mode", PwmSettingSyntax.SELECT, PwmSettingCategory.CLUSTERING ),
     SECURITY_MODULE_SESSION_MODE(
     SECURITY_MODULE_SESSION_MODE(
@@ -283,7 +283,7 @@ public enum PwmSetting
     LDAP_ATTRIBUTE_LANGUAGE(
     LDAP_ATTRIBUTE_LANGUAGE(
             "ldap.user.language.attribute", PwmSettingSyntax.STRING, PwmSettingCategory.LDAP_ATTRIBUTES ),
             "ldap.user.language.attribute", PwmSettingSyntax.STRING, PwmSettingCategory.LDAP_ATTRIBUTES ),
     LDAP_ATTRIBUTE_PWNOTIFY(
     LDAP_ATTRIBUTE_PWNOTIFY(
-            "ldap.user.pwNotify.attribute", PwmSettingSyntax.STRING, PwmSettingCategory.LDAP_ATTRIBUTES ),
+            "ldap.user.appData.attribute", PwmSettingSyntax.STRING, PwmSettingCategory.LDAP_ATTRIBUTES ),
     LDAP_AUTO_SET_LANGUAGE_VALUE(
     LDAP_AUTO_SET_LANGUAGE_VALUE(
             "ldap.user.language.autoSet", PwmSettingSyntax.SELECT, PwmSettingCategory.LDAP_ATTRIBUTES ),
             "ldap.user.language.autoSet", PwmSettingSyntax.SELECT, PwmSettingCategory.LDAP_ATTRIBUTES ),
     AUTO_ADD_OBJECT_CLASSES(
     AUTO_ADD_OBJECT_CLASSES(

+ 2 - 2
server/src/main/java/password/pwm/error/PwmError.java

@@ -303,8 +303,8 @@ public enum PwmError
             5091, "Error_FileTypeIncorrect", null ),
             5091, "Error_FileTypeIncorrect", null ),
     ERROR_FILE_TOO_LARGE(
     ERROR_FILE_TOO_LARGE(
             5092, "Error_FileTooLarge", null ),
             5092, "Error_FileTooLarge", null ),
-    ERROR_CLUSTER_SERVICE_ERROR(
-            5093, "Error_ClusterServiceError", null ),
+    ERROR_NODE_SERVICE_ERROR(
+            5093, "Error_NodeServiceError", null ),
     ERROR_WORDLIST_IMPORT_ERROR(
     ERROR_WORDLIST_IMPORT_ERROR(
             5094, "Error_WordlistImportError", null ),
             5094, "Error_WordlistImportError", null ),
     ERROR_PWNOTIFY_SERVICE_ERROR(
     ERROR_PWNOTIFY_SERVICE_ERROR(

+ 1 - 1
server/src/main/java/password/pwm/http/servlet/admin/AppDashboardData.java

@@ -36,7 +36,7 @@ import password.pwm.http.bean.DisplayElement;
 import password.pwm.i18n.Admin;
 import password.pwm.i18n.Admin;
 import password.pwm.i18n.Display;
 import password.pwm.i18n.Display;
 import password.pwm.svc.PwmService;
 import password.pwm.svc.PwmService;
-import password.pwm.svc.cluster.NodeInfo;
+import password.pwm.svc.node.NodeInfo;
 import password.pwm.svc.sessiontrack.SessionTrackService;
 import password.pwm.svc.sessiontrack.SessionTrackService;
 import password.pwm.util.i18n.LocaleHelper;
 import password.pwm.util.i18n.LocaleHelper;
 import password.pwm.util.java.FileSystemUtility;
 import password.pwm.util.java.FileSystemUtility;

+ 6 - 6
server/src/main/java/password/pwm/http/servlet/configmanager/DebugItemGenerator.java

@@ -41,7 +41,7 @@ import password.pwm.http.servlet.admin.UserDebugDataReader;
 import password.pwm.ldap.LdapDebugDataGenerator;
 import password.pwm.ldap.LdapDebugDataGenerator;
 import password.pwm.svc.PwmService;
 import password.pwm.svc.PwmService;
 import password.pwm.svc.cache.CacheService;
 import password.pwm.svc.cache.CacheService;
-import password.pwm.svc.cluster.ClusterService;
+import password.pwm.svc.node.NodeService;
 import password.pwm.util.LDAPPermissionCalculator;
 import password.pwm.util.LDAPPermissionCalculator;
 import password.pwm.util.java.FileSystemUtility;
 import password.pwm.util.java.FileSystemUtility;
 import password.pwm.util.java.JavaHelper;
 import password.pwm.util.java.JavaHelper;
@@ -676,15 +676,15 @@ public class DebugItemGenerator
         )
         )
                 throws Exception
                 throws Exception
         {
         {
-            final ClusterService clusterService = pwmApplication.getClusterService();
+            final NodeService nodeService = pwmApplication.getClusterService();
 
 
             final Map<String, Serializable> debugOutput = new LinkedHashMap<>();
             final Map<String, Serializable> debugOutput = new LinkedHashMap<>();
-            debugOutput.put( "status", clusterService.status() );
+            debugOutput.put( "status", nodeService.status() );
 
 
-            if ( clusterService.status() == PwmService.STATUS.OPEN )
+            if ( nodeService.status() == PwmService.STATUS.OPEN )
             {
             {
-                debugOutput.put( "isMaster", clusterService.isMaster() );
-                debugOutput.put( "nodes", new ArrayList<>( clusterService.nodes() ) );
+                debugOutput.put( "isMaster", nodeService.isMaster() );
+                debugOutput.put( "nodes", new ArrayList<>( nodeService.nodes() ) );
             }
             }
 
 
             outputStream.write( JsonUtil.serializeMap( debugOutput, JsonUtil.Flag.PrettyPrint ).getBytes( PwmConstants.DEFAULT_CHARSET ) );
             outputStream.write( JsonUtil.serializeMap( debugOutput, JsonUtil.Flag.PrettyPrint ).getBytes( PwmConstants.DEFAULT_CHARSET ) );

+ 2 - 1
server/src/main/java/password/pwm/svc/PwmServiceEnum.java

@@ -23,6 +23,7 @@
 package password.pwm.svc;
 package password.pwm.svc;
 
 
 import password.pwm.svc.email.EmailService;
 import password.pwm.svc.email.EmailService;
+import password.pwm.svc.node.NodeService;
 import password.pwm.svc.pwnotify.PwNotifyService;
 import password.pwm.svc.pwnotify.PwNotifyService;
 import password.pwm.svc.wordlist.SeedlistService;
 import password.pwm.svc.wordlist.SeedlistService;
 import password.pwm.svc.wordlist.WordlistService;
 import password.pwm.svc.wordlist.WordlistService;
@@ -59,7 +60,7 @@ public enum PwmServiceEnum
     UserSearchEngine( password.pwm.ldap.search.UserSearchEngine.class, Flag.StartDuringRuntimeInstance ),
     UserSearchEngine( password.pwm.ldap.search.UserSearchEngine.class, Flag.StartDuringRuntimeInstance ),
     PeopleSearchService( password.pwm.http.servlet.peoplesearch.PeopleSearchService.class ),
     PeopleSearchService( password.pwm.http.servlet.peoplesearch.PeopleSearchService.class ),
     TelemetryService( password.pwm.svc.telemetry.TelemetryService.class ),
     TelemetryService( password.pwm.svc.telemetry.TelemetryService.class ),
-    ClusterService( password.pwm.svc.cluster.ClusterService.class ),
+    ClusterService( NodeService.class ),
     PwExpiryNotifyService( PwNotifyService.class ),;
     PwExpiryNotifyService( PwNotifyService.class ),;
 
 
     private final Class<? extends PwmService> clazz;
     private final Class<? extends PwmService> clazz;

+ 4 - 4
server/src/main/java/password/pwm/svc/cluster/DatabaseClusterDataService.java → server/src/main/java/password/pwm/svc/node/DatabaseNodeDataService.java

@@ -20,7 +20,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
  */
 
 
-package password.pwm.svc.cluster;
+package password.pwm.svc.node;
 
 
 import password.pwm.PwmApplication;
 import password.pwm.PwmApplication;
 import password.pwm.error.PwmError;
 import password.pwm.error.PwmError;
@@ -36,16 +36,16 @@ import password.pwm.util.logging.PwmLogger;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Map;
 
 
-public class DatabaseClusterDataService implements ClusterDataServiceProvider
+public class DatabaseNodeDataService implements NodeDataServiceProvider
 {
 {
-    private static final PwmLogger LOGGER = PwmLogger.forClass( DatabaseClusterDataService.class );
+    private static final PwmLogger LOGGER = PwmLogger.forClass( DatabaseNodeDataService.class );
 
 
     private static final DatabaseTable TABLE = DatabaseTable.CLUSTER_STATE;
     private static final DatabaseTable TABLE = DatabaseTable.CLUSTER_STATE;
     private static final String KEY_PREFIX_NODE = "node-";
     private static final String KEY_PREFIX_NODE = "node-";
 
 
     private final PwmApplication pwmApplication;
     private final PwmApplication pwmApplication;
 
 
-    public DatabaseClusterDataService( final PwmApplication pwmApplication )
+    public DatabaseNodeDataService( final PwmApplication pwmApplication )
     {
     {
         this.pwmApplication = pwmApplication;
         this.pwmApplication = pwmApplication;
     }
     }

+ 5 - 15
server/src/main/java/password/pwm/svc/cluster/LDAPClusterDataService.java → server/src/main/java/password/pwm/svc/node/LDAPNodeDataService.java

@@ -20,12 +20,11 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
  */
 
 
-package password.pwm.svc.cluster;
+package password.pwm.svc.node;
 
 
 import com.novell.ldapchai.ChaiUser;
 import com.novell.ldapchai.ChaiUser;
 import com.novell.ldapchai.exception.ChaiException;
 import com.novell.ldapchai.exception.ChaiException;
 import lombok.Value;
 import lombok.Value;
-import password.pwm.AppProperty;
 import password.pwm.PwmApplication;
 import password.pwm.PwmApplication;
 import password.pwm.bean.UserIdentity;
 import password.pwm.bean.UserIdentity;
 import password.pwm.config.PwmSetting;
 import password.pwm.config.PwmSetting;
@@ -33,7 +32,6 @@ 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.JsonUtil;
 import password.pwm.util.java.JsonUtil;
-import password.pwm.util.java.StringUtil;
 import password.pwm.util.java.TimeDuration;
 import password.pwm.util.java.TimeDuration;
 import password.pwm.util.logging.PwmLogger;
 import password.pwm.util.logging.PwmLogger;
 
 
@@ -41,14 +39,14 @@ import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Map;
 import java.util.Set;
 import java.util.Set;
 
 
-public class LDAPClusterDataService implements ClusterDataServiceProvider
+public class LDAPNodeDataService implements NodeDataServiceProvider
 {
 {
-    private static final PwmLogger LOGGER = PwmLogger.forClass( LDAPClusterDataService.class );
+    private static final PwmLogger LOGGER = PwmLogger.forClass( LDAPNodeDataService.class );
 
 
     private final PwmApplication pwmApplication;
     private final PwmApplication pwmApplication;
     private static final String VALUE_PREFIX = "0006#.#.#";
     private static final String VALUE_PREFIX = "0006#.#.#";
 
 
-    public LDAPClusterDataService( final PwmApplication pwmApplication )
+    public LDAPNodeDataService( final PwmApplication pwmApplication )
     {
     {
         this.pwmApplication = pwmApplication;
         this.pwmApplication = pwmApplication;
     }
     }
@@ -171,15 +169,7 @@ public class LDAPClusterDataService implements ClusterDataServiceProvider
 
 
             chaiUser = pwmApplication.getProxiedChaiUser( userIdentity );
             chaiUser = pwmApplication.getProxiedChaiUser( userIdentity );
 
 
-            {
-                String ldapAttribute = pwmApplication.getConfig().readAppProperty( AppProperty.CLUSTER_LDAP_ATTRIBUTES );
-                if ( StringUtil.isEmpty( ldapAttribute ) )
-                {
-                    ldapAttribute = userIdentity.getLdapProfile( pwmApplication.getConfig() ).readSettingAsString( PwmSetting.CHALLENGE_USER_ATTRIBUTE );
-                }
-                attr = ldapAttribute;
-            }
-
+            attr = userIdentity.getLdapProfile( pwmApplication.getConfig() ).readSettingAsString( PwmSetting.LDAP_ATTRIBUTE_PWNOTIFY );
         }
         }
 
 
         static LDAPHelper createLDAPHelper( final PwmApplication pwmApplication ) throws PwmUnrecoverableException
         static LDAPHelper createLDAPHelper( final PwmApplication pwmApplication ) throws PwmUnrecoverableException

+ 2 - 2
server/src/main/java/password/pwm/svc/cluster/ClusterDataServiceProvider.java → server/src/main/java/password/pwm/svc/node/NodeDataServiceProvider.java

@@ -20,14 +20,14 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
  */
 
 
-package password.pwm.svc.cluster;
+package password.pwm.svc.node;
 
 
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.util.java.TimeDuration;
 import password.pwm.util.java.TimeDuration;
 
 
 import java.util.Map;
 import java.util.Map;
 
 
-public interface ClusterDataServiceProvider
+public interface NodeDataServiceProvider
 {
 {
     Map<String, StoredNodeData> readStoredData( ) throws PwmUnrecoverableException;
     Map<String, StoredNodeData> readStoredData( ) throws PwmUnrecoverableException;
 
 

+ 1 - 1
server/src/main/java/password/pwm/svc/cluster/NodeInfo.java → server/src/main/java/password/pwm/svc/node/NodeInfo.java

@@ -20,7 +20,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
  */
 
 
-package password.pwm.svc.cluster;
+package password.pwm.svc.node;
 
 
 import lombok.AccessLevel;
 import lombok.AccessLevel;
 import lombok.AllArgsConstructor;
 import lombok.AllArgsConstructor;

+ 20 - 20
server/src/main/java/password/pwm/svc/cluster/ClusterMachine.java → server/src/main/java/password/pwm/svc/node/NodeMachine.java

@@ -20,7 +20,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
  */
 
 
-package password.pwm.svc.cluster;
+package password.pwm.svc.node;
 
 
 import password.pwm.PwmApplication;
 import password.pwm.PwmApplication;
 import password.pwm.error.ErrorInformation;
 import password.pwm.error.ErrorInformation;
@@ -40,32 +40,32 @@ import java.util.TreeMap;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.ExecutorService;
 
 
-class ClusterMachine
+class NodeMachine
 {
 {
-    private static final PwmLogger LOGGER = PwmLogger.forClass( ClusterMachine.class );
+    private static final PwmLogger LOGGER = PwmLogger.forClass( NodeMachine.class );
 
 
     private final PwmApplication pwmApplication;
     private final PwmApplication pwmApplication;
     private final ExecutorService executorService;
     private final ExecutorService executorService;
-    private final ClusterDataServiceProvider clusterDataServiceProvider;
+    private final NodeDataServiceProvider clusterDataServiceProvider;
 
 
     private ErrorInformation lastError;
     private ErrorInformation lastError;
 
 
     private final Map<String, StoredNodeData> knownNodes = new ConcurrentHashMap<>();
     private final Map<String, StoredNodeData> knownNodes = new ConcurrentHashMap<>();
 
 
-    private final ClusterSettings settings;
-    private final ClusterStatistics clusterStatistics = new ClusterStatistics();
+    private final NodeServiceSettings settings;
+    private final NodeServiceStatistics nodeServiceStatistics = new NodeServiceStatistics();
 
 
-    ClusterMachine(
+    NodeMachine(
             final PwmApplication pwmApplication,
             final PwmApplication pwmApplication,
-            final ClusterDataServiceProvider clusterDataServiceProvider,
-            final ClusterSettings clusterSettings
+            final NodeDataServiceProvider clusterDataServiceProvider,
+            final NodeServiceSettings nodeServiceSettings
     )
     )
     {
     {
         this.pwmApplication = pwmApplication;
         this.pwmApplication = pwmApplication;
         this.clusterDataServiceProvider = clusterDataServiceProvider;
         this.clusterDataServiceProvider = clusterDataServiceProvider;
-        this.settings = clusterSettings;
+        this.settings = nodeServiceSettings;
 
 
-        this.executorService = JavaHelper.makeBackgroundExecutor( pwmApplication, ClusterMachine.class );
+        this.executorService = JavaHelper.makeBackgroundExecutor( pwmApplication, NodeMachine.class );
 
 
         pwmApplication.scheduleFixedRateJob( new HeartbeatProcess(), executorService, settings.getHeartbeatInterval(), settings.getHeartbeatInterval() );
         pwmApplication.scheduleFixedRateJob( new HeartbeatProcess(), executorService, settings.getHeartbeatInterval(), settings.getHeartbeatInterval() );
     }
     }
@@ -174,12 +174,12 @@ class ClusterMachine
             {
             {
                 final StoredNodeData storedNodeData = StoredNodeData.makeNew( pwmApplication );
                 final StoredNodeData storedNodeData = StoredNodeData.makeNew( pwmApplication );
                 clusterDataServiceProvider.writeNodeStatus( storedNodeData );
                 clusterDataServiceProvider.writeNodeStatus( storedNodeData );
-                clusterStatistics.getClusterWrites().incrementAndGet();
+                nodeServiceStatistics.getClusterWrites().incrementAndGet();
             }
             }
             catch ( PwmException e )
             catch ( PwmException e )
             {
             {
-                final String errorMsg = "error writing database cluster heartbeat: " + e.getMessage();
-                final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_CLUSTER_SERVICE_ERROR, errorMsg );
+                final String errorMsg = "error writing node service heartbeat: " + e.getMessage();
+                final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_NODE_SERVICE_ERROR, errorMsg );
                 lastError = errorInformation;
                 lastError = errorInformation;
                 LOGGER.error( lastError );
                 LOGGER.error( lastError );
             }
             }
@@ -191,12 +191,12 @@ class ClusterMachine
             {
             {
                 final Map<String, StoredNodeData> readNodeData = clusterDataServiceProvider.readStoredData();
                 final Map<String, StoredNodeData> readNodeData = clusterDataServiceProvider.readStoredData();
                 knownNodes.putAll( readNodeData );
                 knownNodes.putAll( readNodeData );
-                clusterStatistics.getClusterReads().incrementAndGet();
+                nodeServiceStatistics.getClusterReads().incrementAndGet();
             }
             }
             catch ( PwmException e )
             catch ( PwmException e )
             {
             {
                 final String errorMsg = "error reading node statuses: " + e.getMessage();
                 final String errorMsg = "error reading node statuses: " + e.getMessage();
-                final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_CLUSTER_SERVICE_ERROR, errorMsg );
+                final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_NODE_SERVICE_ERROR, errorMsg );
                 lastError = errorInformation;
                 lastError = errorInformation;
                 LOGGER.error( lastError );
                 LOGGER.error( lastError );
             }
             }
@@ -207,20 +207,20 @@ class ClusterMachine
             try
             try
             {
             {
                 final int purges = clusterDataServiceProvider.purgeOutdatedNodes( settings.getNodePurgeInterval() );
                 final int purges = clusterDataServiceProvider.purgeOutdatedNodes( settings.getNodePurgeInterval() );
-                clusterStatistics.getNodePurges().addAndGet( purges );
+                nodeServiceStatistics.getNodePurges().addAndGet( purges );
             }
             }
             catch ( PwmException e )
             catch ( PwmException e )
             {
             {
                 final String errorMsg = "error purging outdated node reference: " + e.getMessage();
                 final String errorMsg = "error purging outdated node reference: " + e.getMessage();
-                final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_CLUSTER_SERVICE_ERROR, errorMsg );
+                final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_NODE_SERVICE_ERROR, errorMsg );
                 lastError = errorInformation;
                 lastError = errorInformation;
                 LOGGER.error( lastError );
                 LOGGER.error( lastError );
             }
             }
         }
         }
     }
     }
 
 
-    public ClusterStatistics getClusterStatistics( )
+    public NodeServiceStatistics getNodeServiceStatistics( )
     {
     {
-        return clusterStatistics;
+        return nodeServiceStatistics;
     }
     }
 }
 }

+ 24 - 24
server/src/main/java/password/pwm/svc/cluster/ClusterService.java → server/src/main/java/password/pwm/svc/node/NodeService.java

@@ -20,7 +20,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
  */
 
 
-package password.pwm.svc.cluster;
+package password.pwm.svc.node;
 
 
 import password.pwm.PwmApplication;
 import password.pwm.PwmApplication;
 import password.pwm.bean.UserIdentity;
 import password.pwm.bean.UserIdentity;
@@ -42,14 +42,14 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.List;
 import java.util.Map;
 import java.util.Map;
 
 
-public class ClusterService implements PwmService
+public class NodeService implements PwmService
 {
 {
 
 
-    private static final PwmLogger LOGGER = PwmLogger.forClass( ClusterService.class );
+    private static final PwmLogger LOGGER = PwmLogger.forClass( NodeService.class );
 
 
     private PwmApplication pwmApplication;
     private PwmApplication pwmApplication;
     private STATUS status = STATUS.NEW;
     private STATUS status = STATUS.NEW;
-    private ClusterMachine clusterMachine;
+    private NodeMachine nodeMachine;
     private DataStorageMethod dataStore;
     private DataStorageMethod dataStore;
     private ErrorInformation startupError;
     private ErrorInformation startupError;
 
 
@@ -75,8 +75,8 @@ public class ClusterService implements PwmService
 
 
         try
         try
         {
         {
-            final ClusterSettings clusterSettings;
-            final ClusterDataServiceProvider clusterDataServiceProvider;
+            final NodeServiceSettings nodeServiceSettings;
+            final NodeDataServiceProvider clusterDataServiceProvider;
             dataStore = pwmApplication.getConfig().readSettingAsEnum( PwmSetting.CLUSTER_STORAGE_MODE, DataStorageMethod.class );
             dataStore = pwmApplication.getConfig().readSettingAsEnum( PwmSetting.CLUSTER_STORAGE_MODE, DataStorageMethod.class );
 
 
             if ( dataStore != null )
             if ( dataStore != null )
@@ -86,16 +86,16 @@ public class ClusterService implements PwmService
                     case DB:
                     case DB:
                     {
                     {
                         LOGGER.trace( () -> "starting database-backed cluster provider" );
                         LOGGER.trace( () -> "starting database-backed cluster provider" );
-                        clusterSettings = ClusterSettings.fromConfigForDB( pwmApplication.getConfig() );
-                        clusterDataServiceProvider = new DatabaseClusterDataService( pwmApplication );
+                        nodeServiceSettings = NodeServiceSettings.fromConfigForDB( pwmApplication.getConfig() );
+                        clusterDataServiceProvider = new DatabaseNodeDataService( pwmApplication );
                     }
                     }
                     break;
                     break;
 
 
                     case LDAP:
                     case LDAP:
                     {
                     {
                         LOGGER.trace( () -> "starting ldap-backed cluster provider" );
                         LOGGER.trace( () -> "starting ldap-backed cluster provider" );
-                        clusterSettings = ClusterSettings.fromConfigForLDAP( pwmApplication.getConfig() );
-                        clusterDataServiceProvider = new LDAPClusterDataService( pwmApplication );
+                        nodeServiceSettings = NodeServiceSettings.fromConfigForLDAP( pwmApplication.getConfig() );
+                        clusterDataServiceProvider = new LDAPNodeDataService( pwmApplication );
                     }
                     }
                     break;
                     break;
 
 
@@ -106,7 +106,7 @@ public class ClusterService implements PwmService
 
 
                 }
                 }
 
 
-                clusterMachine = new ClusterMachine( pwmApplication, clusterDataServiceProvider, clusterSettings );
+                nodeMachine = new NodeMachine( pwmApplication, clusterDataServiceProvider, nodeServiceSettings );
                 status = STATUS.OPEN;
                 status = STATUS.OPEN;
                 return;
                 return;
             }
             }
@@ -122,10 +122,10 @@ public class ClusterService implements PwmService
     @Override
     @Override
     public void close( )
     public void close( )
     {
     {
-        if ( clusterMachine != null )
+        if ( nodeMachine != null )
         {
         {
-            clusterMachine.close();
-            clusterMachine = null;
+            nodeMachine.close();
+            nodeMachine = null;
         }
         }
         status = STATUS.CLOSED;
         status = STATUS.CLOSED;
     }
     }
@@ -133,9 +133,9 @@ public class ClusterService implements PwmService
     @Override
     @Override
     public List<HealthRecord> healthCheck( )
     public List<HealthRecord> healthCheck( )
     {
     {
-        if ( clusterMachine != null )
+        if ( nodeMachine != null )
         {
         {
-            final ErrorInformation errorInformation = clusterMachine.getLastError();
+            final ErrorInformation errorInformation = nodeMachine.getLastError();
             if ( errorInformation != null )
             if ( errorInformation != null )
             {
             {
                 final HealthRecord healthRecord = HealthRecord.forMessage( HealthMessage.Cluster_Error, errorInformation.getDetailedErrorMsg() );
                 final HealthRecord healthRecord = HealthRecord.forMessage( HealthMessage.Cluster_Error, errorInformation.getDetailedErrorMsg() );
@@ -157,18 +157,18 @@ public class ClusterService implements PwmService
     {
     {
         final Map<String, String> props = new HashMap<>();
         final Map<String, String> props = new HashMap<>();
 
 
-        if ( clusterMachine != null )
+        if ( nodeMachine != null )
         {
         {
-            props.putAll( JsonUtil.deserializeStringMap( JsonUtil.serialize( clusterMachine.getClusterStatistics() ) ) );
+            props.putAll( JsonUtil.deserializeStringMap( JsonUtil.serialize( nodeMachine.getNodeServiceStatistics() ) ) );
         }
         }
         return new ServiceInfoBean( Collections.singleton( dataStore ), props );
         return new ServiceInfoBean( Collections.singleton( dataStore ), props );
     }
     }
 
 
     public boolean isMaster( )
     public boolean isMaster( )
     {
     {
-        if ( status == STATUS.OPEN && clusterMachine != null )
+        if ( status == STATUS.OPEN && nodeMachine != null )
         {
         {
-            return clusterMachine.isMaster();
+            return nodeMachine.isMaster();
         }
         }
 
 
         return false;
         return false;
@@ -176,9 +176,9 @@ public class ClusterService implements PwmService
 
 
     public List<NodeInfo> nodes( ) throws PwmUnrecoverableException
     public List<NodeInfo> nodes( ) throws PwmUnrecoverableException
     {
     {
-        if ( status == STATUS.OPEN && clusterMachine != null )
+        if ( status == STATUS.OPEN && nodeMachine != null )
         {
         {
-            return clusterMachine.nodes();
+            return nodeMachine.nodes();
         }
         }
         return Collections.emptyList();
         return Collections.emptyList();
     }
     }
@@ -192,7 +192,7 @@ public class ClusterService implements PwmService
             {
             {
                 final String msg = "LDAP storage type selected, but LDAP test user not defined.";
                 final String msg = "LDAP storage type selected, but LDAP test user not defined.";
                 LOGGER.debug( () -> msg );
                 LOGGER.debug( () -> msg );
-                startupError = new ErrorInformation( PwmError.ERROR_CLUSTER_SERVICE_ERROR, msg );
+                startupError = new ErrorInformation( PwmError.ERROR_NODE_SERVICE_ERROR, msg );
             }
             }
         }
         }
 
 
@@ -201,7 +201,7 @@ public class ClusterService implements PwmService
             {
             {
                 final String msg = "DB storage type selected, but remote DB is not configured.";
                 final String msg = "DB storage type selected, but remote DB is not configured.";
                 LOGGER.debug( () -> msg );
                 LOGGER.debug( () -> msg );
-                startupError = new ErrorInformation( PwmError.ERROR_CLUSTER_SERVICE_ERROR, msg );
+                startupError = new ErrorInformation( PwmError.ERROR_NODE_SERVICE_ERROR, msg );
             }
             }
         }
         }
     }
     }

+ 6 - 6
server/src/main/java/password/pwm/svc/cluster/ClusterSettings.java → server/src/main/java/password/pwm/svc/node/NodeServiceSettings.java

@@ -20,7 +20,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
  */
 
 
-package password.pwm.svc.cluster;
+package password.pwm.svc.node;
 
 
 import lombok.AccessLevel;
 import lombok.AccessLevel;
 import lombok.AllArgsConstructor;
 import lombok.AllArgsConstructor;
@@ -31,24 +31,24 @@ import password.pwm.util.java.TimeDuration;
 
 
 @Value
 @Value
 @AllArgsConstructor( access = AccessLevel.PRIVATE )
 @AllArgsConstructor( access = AccessLevel.PRIVATE )
-class ClusterSettings
+class NodeServiceSettings
 {
 {
     private final TimeDuration heartbeatInterval;
     private final TimeDuration heartbeatInterval;
     private final TimeDuration nodeTimeout;
     private final TimeDuration nodeTimeout;
     private final TimeDuration nodePurgeInterval;
     private final TimeDuration nodePurgeInterval;
 
 
-    static ClusterSettings fromConfigForDB( final Configuration configuration )
+    static NodeServiceSettings fromConfigForDB( final Configuration configuration )
     {
     {
-        return new ClusterSettings(
+        return new NodeServiceSettings(
                 TimeDuration.of( Integer.parseInt( configuration.readAppProperty( AppProperty.CLUSTER_DB_HEARTBEAT_SECONDS ) ), TimeDuration.Unit.SECONDS ),
                 TimeDuration.of( Integer.parseInt( configuration.readAppProperty( AppProperty.CLUSTER_DB_HEARTBEAT_SECONDS ) ), TimeDuration.Unit.SECONDS ),
                 TimeDuration.of( Integer.parseInt( configuration.readAppProperty( AppProperty.CLUSTER_DB_NODE_TIMEOUT_SECONDS ) ), TimeDuration.Unit.SECONDS ),
                 TimeDuration.of( Integer.parseInt( configuration.readAppProperty( AppProperty.CLUSTER_DB_NODE_TIMEOUT_SECONDS ) ), TimeDuration.Unit.SECONDS ),
                 TimeDuration.of( Integer.parseInt( configuration.readAppProperty( AppProperty.CLUSTER_DB_NODE_PURGE_SECONDS ) ), TimeDuration.Unit.SECONDS )
                 TimeDuration.of( Integer.parseInt( configuration.readAppProperty( AppProperty.CLUSTER_DB_NODE_PURGE_SECONDS ) ), TimeDuration.Unit.SECONDS )
         );
         );
     }
     }
 
 
-    static ClusterSettings fromConfigForLDAP( final Configuration configuration )
+    static NodeServiceSettings fromConfigForLDAP( final Configuration configuration )
     {
     {
-        return new ClusterSettings(
+        return new NodeServiceSettings(
                 TimeDuration.of( Integer.parseInt( configuration.readAppProperty( AppProperty.CLUSTER_LDAP_HEARTBEAT_SECONDS ) ), TimeDuration.Unit.SECONDS ),
                 TimeDuration.of( Integer.parseInt( configuration.readAppProperty( AppProperty.CLUSTER_LDAP_HEARTBEAT_SECONDS ) ), TimeDuration.Unit.SECONDS ),
                 TimeDuration.of( Integer.parseInt( configuration.readAppProperty( AppProperty.CLUSTER_LDAP_NODE_TIMEOUT_SECONDS ) ), TimeDuration.Unit.SECONDS ),
                 TimeDuration.of( Integer.parseInt( configuration.readAppProperty( AppProperty.CLUSTER_LDAP_NODE_TIMEOUT_SECONDS ) ), TimeDuration.Unit.SECONDS ),
                 TimeDuration.of( Integer.parseInt( configuration.readAppProperty( AppProperty.CLUSTER_LDAP_NODE_PURGE_SECONDS ) ), TimeDuration.Unit.SECONDS )
                 TimeDuration.of( Integer.parseInt( configuration.readAppProperty( AppProperty.CLUSTER_LDAP_NODE_PURGE_SECONDS ) ), TimeDuration.Unit.SECONDS )

+ 2 - 2
server/src/main/java/password/pwm/svc/cluster/ClusterStatistics.java → server/src/main/java/password/pwm/svc/node/NodeServiceStatistics.java

@@ -20,7 +20,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
  */
 
 
-package password.pwm.svc.cluster;
+package password.pwm.svc.node;
 
 
 import lombok.Value;
 import lombok.Value;
 
 
@@ -28,7 +28,7 @@ import java.io.Serializable;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicInteger;
 
 
 @Value
 @Value
-public class ClusterStatistics implements Serializable
+public class NodeServiceStatistics implements Serializable
 {
 {
     private final AtomicInteger clusterWrites = new AtomicInteger( 0 );
     private final AtomicInteger clusterWrites = new AtomicInteger( 0 );
     private final AtomicInteger clusterReads = new AtomicInteger( 0 );
     private final AtomicInteger clusterReads = new AtomicInteger( 0 );

+ 1 - 1
server/src/main/java/password/pwm/svc/cluster/StoredNodeData.java → server/src/main/java/password/pwm/svc/node/StoredNodeData.java

@@ -20,7 +20,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
  */
 
 
-package password.pwm.svc.cluster;
+package password.pwm.svc.node;
 
 
 import lombok.AccessLevel;
 import lombok.AccessLevel;
 import lombok.AllArgsConstructor;
 import lombok.AllArgsConstructor;

+ 1 - 1
server/src/main/java/password/pwm/svc/pwnotify/PwNotifyDbStorageService.java

@@ -49,7 +49,7 @@ class PwNotifyDbStorageService implements PwNotifyStorageService
         if ( !pwmApplication.getConfig().hasDbConfigured() )
         if ( !pwmApplication.getConfig().hasDbConfigured() )
         {
         {
             final String msg = "DB storage type selected, but remote DB is not configured.";
             final String msg = "DB storage type selected, but remote DB is not configured.";
-            throw PwmUnrecoverableException.newException( PwmError.ERROR_CLUSTER_SERVICE_ERROR, msg );
+            throw PwmUnrecoverableException.newException( PwmError.ERROR_NODE_SERVICE_ERROR, msg );
         }
         }
     }
     }
 
 

+ 68 - 4
server/src/main/java/password/pwm/util/cli/commands/LdapSchemaExtendCommand.java

@@ -23,14 +23,25 @@
 package password.pwm.util.cli.commands;
 package password.pwm.util.cli.commands;
 
 
 
 
+import com.novell.ldapchai.provider.ChaiConfiguration;
 import com.novell.ldapchai.provider.ChaiProvider;
 import com.novell.ldapchai.provider.ChaiProvider;
 import com.novell.ldapchai.provider.ChaiProviderFactory;
 import com.novell.ldapchai.provider.ChaiProviderFactory;
+import password.pwm.error.PwmOperationalException;
 import password.pwm.ldap.schema.SchemaManager;
 import password.pwm.ldap.schema.SchemaManager;
 import password.pwm.ldap.schema.SchemaOperationResult;
 import password.pwm.ldap.schema.SchemaOperationResult;
 import password.pwm.util.cli.CliParameters;
 import password.pwm.util.cli.CliParameters;
+import password.pwm.util.java.JavaHelper;
+import password.pwm.util.java.JsonUtil;
+import password.pwm.util.secure.X509Utils;
 
 
+import javax.net.ssl.X509TrustManager;
 import java.io.Console;
 import java.io.Console;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.cert.X509Certificate;
 import java.util.Arrays;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 
 
 public class LdapSchemaExtendCommand extends AbstractCliCommand
 public class LdapSchemaExtendCommand extends AbstractCliCommand
 {
 {
@@ -55,18 +66,71 @@ public class LdapSchemaExtendCommand extends AbstractCliCommand
             console.writer().flush();
             console.writer().flush();
             bindPW = new String( console.readPassword() );
             bindPW = new String( console.readPassword() );
         }
         }
-        final ChaiProviderFactory chaiProviderFactory = cliEnvironment.getPwmApplication().getLdapConnectionService().getChaiProviderFactory();
-        final ChaiProvider chaiProvider = chaiProviderFactory.newProvider( ldapUrl, bindDN, bindPW );
+
+        final X509TrustManager trustManager;
+        if ( isSecureLDAP( ldapUrl ) )
+        {
+            final List<X509Certificate> certificates = readCertificates( ldapUrl );
+            if ( JavaHelper.isEmpty( certificates ) )
+            {
+                out( "canceled" );
+                return;
+            }
+            trustManager = new X509Utils.CertMatchingTrustManager( cliEnvironment.getConfig(), certificates );
+        }
+        else
+        {
+            trustManager = null;
+        }
+
+        if ( !promptForContinue( "Proceeding may cause modificiations to your LDAP schema." ) )
+        {
+            return;
+        }
+
+        final ChaiProviderFactory chaiProviderFactory = ChaiProviderFactory.newProviderFactory( );
+        final ChaiConfiguration chaiConfiguration = ChaiConfiguration.builder( ldapUrl, bindDN, bindPW )
+                .setTrustManager( new X509TrustManager[]
+                        {
+                                trustManager,
+                        }
+                )
+                .build();
+        final ChaiProvider chaiProvider = chaiProviderFactory.newProvider( chaiConfiguration );
+
+        out( "beginning extension check" );
         final SchemaOperationResult operationResult = SchemaManager.extendSchema( chaiProvider );
         final SchemaOperationResult operationResult = SchemaManager.extendSchema( chaiProvider );
+
+        out( operationResult.getOperationLog() );
         final boolean checkOk = operationResult.isSuccess();
         final boolean checkOk = operationResult.isSuccess();
+
         if ( checkOk )
         if ( checkOk )
         {
         {
-            out( "schema extension complete.  all extensions in place = " + checkOk );
+            out( "schema extension completed successfully.\n" );
         }
         }
         else
         else
         {
         {
-            out( "schema extension did not complete.\n" + operationResult.getOperationLog() );
+            out( "schema extension did not complete.\n" );
+        }
+    }
+
+    private boolean isSecureLDAP( final String ldapUrl ) throws URISyntaxException
+    {
+        final URI ldapUri = new URI( ldapUrl );
+        return "ldaps".equalsIgnoreCase( ldapUri.getScheme() );
+    }
+
+    private List<X509Certificate> readCertificates( final String url )
+            throws URISyntaxException, PwmOperationalException
+    {
+        if ( isSecureLDAP( url ) )
+        {
+            out( "ldaps certificates from: " + url );
+            final List<X509Certificate> certificateList = X509Utils.readRemoteCertificates( new URI ( url ) );
+            out( JsonUtil.serializeCollection( X509Utils.makeDebugInfoMap( certificateList ), JsonUtil.Flag.PrettyPrint ) );
+            return certificateList;
         }
         }
+        return Collections.emptyList();
     }
     }
 
 
 
 

+ 1 - 1
server/src/main/java/password/pwm/util/java/ConditionalTaskExecutor.java

@@ -82,7 +82,7 @@ public class ConditionalTaskExecutor
     {
     {
         return new ConditionalTaskExecutor( task, new TimeDurationPredicate( timeDuration ) );
         return new ConditionalTaskExecutor( task, new TimeDurationPredicate( timeDuration ) );
     }
     }
-    
+
     public static class TimeDurationPredicate implements Supplier<Boolean>
     public static class TimeDurationPredicate implements Supplier<Boolean>
     {
     {
         private final TimeDuration timeDuration;
         private final TimeDuration timeDuration;

+ 1 - 1
server/src/main/java/password/pwm/util/secure/X509Utils.java

@@ -317,7 +317,7 @@ public abstract class X509Utils
                 }
                 }
                 if ( !certTrusted )
                 if ( !certTrusted )
                 {
                 {
-                    final String errorMsg = "server certificate {subject=" + loopCert.getSubjectDN().getName() + "} does not match a certificate in the"
+                    final String errorMsg = "server certificate {subject=" + loopCert.getSubjectDN().getName() + "} does not match a certificate in the "
                             + PwmConstants.PWM_APP_NAME + " configuration trust store.";
                             + PwmConstants.PWM_APP_NAME + " configuration trust store.";
                     throw new CertificateException( errorMsg );
                     throw new CertificateException( errorMsg );
                 }
                 }

+ 0 - 1
server/src/main/resources/password/pwm/AppProperty.properties

@@ -60,7 +60,6 @@ cluster.db.enable=true
 cluster.db.heartbeatSeconds=60
 cluster.db.heartbeatSeconds=60
 cluster.db.nodeTimeoutSeconds=600
 cluster.db.nodeTimeoutSeconds=600
 cluster.db.nodePurgeSeconds=86400
 cluster.db.nodePurgeSeconds=86400
-cluster.ldap.attribute=
 cluster.ldap.heartbeatSeconds=60
 cluster.ldap.heartbeatSeconds=60
 cluster.ldap.nodeTimeoutSeconds=600
 cluster.ldap.nodeTimeoutSeconds=600
 cluster.ldap.nodePurgeSeconds=86400
 cluster.ldap.nodePurgeSeconds=86400

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

@@ -1574,12 +1574,12 @@
             <value>28800</value>
             <value>28800</value>
         </default>
         </default>
     </setting>
     </setting>
-    <setting hidden="false" key="cluster.enable" level="2">
+    <setting hidden="false" key="nodeService.enable" level="2">
         <default>
         <default>
             <value>true</value>
             <value>true</value>
         </default>
         </default>
     </setting>
     </setting>
-    <setting hidden="false" key="cluster.storageMode" level="2">
+    <setting hidden="false" key="nodeService.storageMode" level="2">
         <default>
         <default>
             <value>LDAP</value>
             <value>LDAP</value>
         </default>
         </default>
@@ -3332,10 +3332,10 @@
             <value/>
             <value/>
         </default>
         </default>
     </setting>
     </setting>
-    <setting hidden="false" key="ldap.user.pwNotify.attribute" level="1">
+    <setting hidden="false" key="ldap.user.appData.attribute" level="1">
         <ldapPermission actor="proxy" access="write"/>
         <ldapPermission actor="proxy" access="write"/>
         <default>
         <default>
-            <value/>
+            <value>pwmData</value>
         </default>
         </default>
     </setting>
     </setting>
     <setting hidden="false" key="ldap.user.language.autoSet" level="1">
     <setting hidden="false" key="ldap.user.language.autoSet" level="1">

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

@@ -162,7 +162,7 @@ Error_PasswordOnlyBad=Password incorrect.  Please try again.
 Error_RecoverySequenceIncomplete=A problem occurred during the forgotten password sequence, please try again.
 Error_RecoverySequenceIncomplete=A problem occurred during the forgotten password sequence, please try again.
 Error_FileTypeIncorrect=The file type is not correct.
 Error_FileTypeIncorrect=The file type is not correct.
 Error_FileTooLarge=The file is too large.
 Error_FileTooLarge=The file is too large.
-Error_ClusterServiceError=An error occurred with the cluster service: %1%.   Check the log files for more information.
+Error_NodeServiceError=An error occurred with the node service: %1%.   Check the log files for more information.
 Error_RemoteErrorValue=Remote Error: %1%
 Error_RemoteErrorValue=Remote Error: %1%
 Error_WordlistImportError=An error occurred importing the wordlist: %1%
 Error_WordlistImportError=An error occurred importing the wordlist: %1%
 Error_PwNotifyServiceError=An error occurred while running the password notify service: %1%
 Error_PwNotifyServiceError=An error occurred while running the password notify service: %1%

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

@@ -267,8 +267,8 @@ Setting_Description_challenge.showConfirmation=Enable this option to show the re
 Setting_Description_challenge.token.sendMethod=Select the methods you want to use for sending the token code or new password to the user.
 Setting_Description_challenge.token.sendMethod=Select the methods you want to use for sending the token code or new password to the user.
 Setting_Description_challenge.userAttribute=Specify the attribute to use for response storage when storing responses in an LDAP directory.
 Setting_Description_challenge.userAttribute=Specify the attribute to use for response storage when storing responses in an LDAP directory.
 Setting_Description_changePassword.writeAttributes=Add actions to take after a user change password event occurs.  @PwmAppName@ invokes these actions just after writing the password.  You can use macros within the action and are expanded based on the logged in user.
 Setting_Description_changePassword.writeAttributes=Add actions to take after a user change password event occurs.  @PwmAppName@ invokes these actions just after writing the password.  You can use macros within the action and are expanded based on the logged in user.
-Setting_Description_cluster.enable=Enable cluster module.
-Setting_Description_cluster.storageMode=Data storage system used for cluster module.  <p>If <b>LDAP</b> is selected, a test user (<a data-gotoSettingLink\="ldap.testuser.username">@PwmSettingReference\:ldap.testuser.username@</a>) must be configured and the response storage attribute (<a data-gotoSettingLink\="ldap.testuser.username">@PwmSettingReference\:ldap.testuser.username@</a>) must be writable by the proxy user.</p><p>If <b>DATABASE</b> is selected then a database must be configured and available for @PwmAppName@ to operate.</p>  
+Setting_Description_nodeService.enable=Enable or Disable the node service.  The node service allows @PwmAppName@ to detect and identify when multiple application nodes are similar configured and can share user sessions.
+Setting_Description_nodeService.storageMode=Data storage system used for node service.  <p>If <b>LDAP</b> is selected, a test user (<a data-gotoSettingLink\="ldap.testuser.username">@PwmSettingReference\:ldap.testuser.username@</a>) must be configured and the response storage attribute (<a data-gotoSettingLink\="ldap.testuser.username">@PwmSettingReference\:ldap.testuser.username@</a>) must be writable by the proxy user.</p><p>If <b>DATABASE</b> is selected then a database must be configured and available for @PwmAppName@ to operate.</p>  
 Setting_Description_command.checkResponses.queryMatch=Controls which users are forced to setup responses.  Users that match this permission will be forced to setup responses. 
 Setting_Description_command.checkResponses.queryMatch=Controls which users are forced to setup responses.  Users that match this permission will be forced to setup responses. 
 Setting_Description_db.classname=Add the remote database JDBC driver class name.  Consult the database vendor to determine the correct class name for your database.<br/><br/><table><tr><td class\="key">Database Type</td><td class\="key">Example Class Name</td></tr><tr><td>MS-SQL</td><td>com.microsoft.sqlserver.jdbc.SQLServerDriver</td></tr><tr><td>MS-SQL using jTDS</td><td>net.sourceforge.jtds.jdbc.Driver</td></tr><tr><td>Oracle</td><td>oracle.jdbc.OracleDriver</td></tr></table><div class="footnote">The above are examples only, consult your database documentation for the proper setting value.</div>
 Setting_Description_db.classname=Add the remote database JDBC driver class name.  Consult the database vendor to determine the correct class name for your database.<br/><br/><table><tr><td class\="key">Database Type</td><td class\="key">Example Class Name</td></tr><tr><td>MS-SQL</td><td>com.microsoft.sqlserver.jdbc.SQLServerDriver</td></tr><tr><td>MS-SQL using jTDS</td><td>net.sourceforge.jtds.jdbc.Driver</td></tr><tr><td>Oracle</td><td>oracle.jdbc.OracleDriver</td></tr></table><div class="footnote">The above are examples only, consult your database documentation for the proper setting value.</div>
 Setting_Description_db.columnType.key=Specify the database column type for key columns.  @PwmAppName@ uses the column type only during schema creation.  All tables are two columns: a key and a value column.  For most databases the standard VARCHAR column format is appropriate for the key column.  Data stored in the key column generally is US-ASCII keys.
 Setting_Description_db.columnType.key=Specify the database column type for key columns.  @PwmAppName@ uses the column type only during schema creation.  All tables are two columns: a key and a value column.  For most databases the standard VARCHAR column format is appropriate for the key column.  Data stored in the key column generally is US-ASCII keys.
@@ -476,7 +476,7 @@ Setting_Description_ldap.serverCerts=Import the LDAP Server Certificates.  @PwmA
 Setting_Description_ldap.serverUrls=Add a list of LDAP servers in URL format that @PwmAppName@ uses for a fail-over configuration. @PwmAppName@ uses the servers in order of appearance in this list.  If the first server is unavailable @PwmAppName@ uses the next available server in the list.  @PwmAppName@ periodically checks the first server to see if it has become available.<ul><li>For secure SSL, use the "<i>ldaps\://servername\:636</i>" format</li><li>For plain-text servers, use "<i>ldap\://serverame\:389</i>" format (not recommended)</li></ul><p>When using secure connections, the Java virtual machine must trust the directory server, either because you have manually added the public key certificate from the tree to the Java keystore or you imported the certificate into the setting <i>LDAP Server Certificates</i>.<ul><li>Do not use a non-secure connection for anything but the most basic testing purposes (Many LDAP servers reject password operations on non-secure connections)</li><li>Do not use a load-balancing device for LDAP high availability, instead use the built in LDAP server fail-over functionality</li><li>Do not use a DNS round-robin address</li><li>Avoid using the network address, use the proper fully-qualified domain name address for the server</li></ul>
 Setting_Description_ldap.serverUrls=Add a list of LDAP servers in URL format that @PwmAppName@ uses for a fail-over configuration. @PwmAppName@ uses the servers in order of appearance in this list.  If the first server is unavailable @PwmAppName@ uses the next available server in the list.  @PwmAppName@ periodically checks the first server to see if it has become available.<ul><li>For secure SSL, use the "<i>ldaps\://servername\:636</i>" format</li><li>For plain-text servers, use "<i>ldap\://serverame\:389</i>" format (not recommended)</li></ul><p>When using secure connections, the Java virtual machine must trust the directory server, either because you have manually added the public key certificate from the tree to the Java keystore or you imported the certificate into the setting <i>LDAP Server Certificates</i>.<ul><li>Do not use a non-secure connection for anything but the most basic testing purposes (Many LDAP servers reject password operations on non-secure connections)</li><li>Do not use a load-balancing device for LDAP high availability, instead use the built in LDAP server fail-over functionality</li><li>Do not use a DNS round-robin address</li><li>Avoid using the network address, use the proper fully-qualified domain name address for the server</li></ul>
 Setting_Description_ldap.testuser.username=Specify the fully qualified DN of an LDAP test user that @PwmAppName@ uses to test functionality and for access to the LDAP directory. Configure this user similar to a normal user account with normal access privileges. @PwmAppName@ periodically uses this account to perform a health check, including changing the password of the account. <br/><br/><b>Using a test user account greatly increases the system's ability to detect and alert configuration and health issues.</b><br/><br/>@PwmAppName@ tests the following functionality (if enabled) using the test user account.<ul><li>Authentication</li><li>Password policy reading</li><li>Set password</li><li>Set Challenge/Responses</li><li>Load Challenge/Responses</li></ul>
 Setting_Description_ldap.testuser.username=Specify the fully qualified DN of an LDAP test user that @PwmAppName@ uses to test functionality and for access to the LDAP directory. Configure this user similar to a normal user account with normal access privileges. @PwmAppName@ periodically uses this account to perform a health check, including changing the password of the account. <br/><br/><b>Using a test user account greatly increases the system's ability to detect and alert configuration and health issues.</b><br/><br/>@PwmAppName@ tests the following functionality (if enabled) using the test user account.<ul><li>Authentication</li><li>Password policy reading</li><li>Set password</li><li>Set Challenge/Responses</li><li>Load Challenge/Responses</li></ul>
 Setting_Description_ldap.user.group.attribute=Specify an attribute on the user entry that references group entries.  The value of this attribute in the directory must be a LDAP DN.
 Setting_Description_ldap.user.group.attribute=Specify an attribute on the user entry that references group entries.  The value of this attribute in the directory must be a LDAP DN.
-Setting_Description_ldap.user.pwNotify.attribute=Specify an attribute that is used by @PwmAppName@ to store data for the password expiration notification service.
+Setting_Description_ldap.user.appData.attribute=Specify an attribute that is used by @PwmAppName@ to store data for the various application data including ldap node services and password password expiration notification service.
 Setting_Description_ldap.user.language.attribute=Attribute that contains the language of the user in RFC1766 format. (The same format used by web browsers and the HTTP Accept-Language header.)  This value is used only for user interactions when the user does not have an active web session such as an email notification.
 Setting_Description_ldap.user.language.attribute=Attribute that contains the language of the user in RFC1766 format. (The same format used by web browsers and the HTTP Accept-Language header.)  This value is used only for user interactions when the user does not have an active web session such as an email notification.
 Setting_Description_ldap.user.language.autoSet=When enabled, the user's effective locale for a web session will be written to the LDAP language attribute. 
 Setting_Description_ldap.user.language.autoSet=When enabled, the user's effective locale for a web session will be written to the LDAP language attribute. 
 Setting_Description_ldap.username.attr=Specify the attribute @PwmAppName@ uses for the user name. If blank, @PwmAppName@ uses the LDAP Naming Attribute.  This option allows fields that display or store the <b>User Name</b> or <b>User ID</b> of a user to show something other then the LDAP Naming Attribute if appropriate.  This value must be unique for this system.
 Setting_Description_ldap.username.attr=Specify the attribute @PwmAppName@ uses for the user name. If blank, @PwmAppName@ uses the LDAP Naming Attribute.  This option allows fields that display or store the <b>User Name</b> or <b>User ID</b> of a user to show something other then the LDAP Naming Attribute if appropriate.  This value must be unique for this system.
@@ -621,8 +621,8 @@ Setting_Description_pwm.securityKey=<p>Specify a Security Key used for cryptogra
 Setting_Description_pwm.seedlist.location=Specify the location of the seed list in the form of a valid URL. When @PwmAppName@ randomly generates passwords, it can generate a "friendly", random password suggestions to users.  It does this by using a "seed" word or words, and then modifying that word randomly until it is sufficiently complex and meets the configured rules computed for the user.<br/><br/>The value must be a valid URL, using the protocol "file" (local file system), "http", or "https".
 Setting_Description_pwm.seedlist.location=Specify the location of the seed list in the form of a valid URL. When @PwmAppName@ randomly generates passwords, it can generate a "friendly", random password suggestions to users.  It does this by using a "seed" word or words, and then modifying that word randomly until it is sufficiently complex and meets the configured rules computed for the user.<br/><br/>The value must be a valid URL, using the protocol "file" (local file system), "http", or "https".
 Setting_Description_pwm.selfURL=<p>The URL to this application, as seen by users. @PwmAppName@ uses the value in email macros and other user-facing communications.</p><p>The URL must use a valid fully qualified hostname. Do not use a network address.</p><p>In simple environments, the URL will be the base of the URL in the browser you are currently using to view this page, however in more complex environments the URL will typically be an upstream proxy, gateway or network device.</p><p>The URL should include the path to the base application, typically <code>/@Case:lower:[[@PwmAppName@]]@</code>.</p>
 Setting_Description_pwm.selfURL=<p>The URL to this application, as seen by users. @PwmAppName@ uses the value in email macros and other user-facing communications.</p><p>The URL must use a valid fully qualified hostname. Do not use a network address.</p><p>In simple environments, the URL will be the base of the URL in the browser you are currently using to view this page, however in more complex environments the URL will typically be an upstream proxy, gateway or network device.</p><p>The URL should include the path to the base application, typically <code>/@Case:lower:[[@PwmAppName@]]@</code>.</p>
 Setting_Description_pwm.wordlist.location=Specify a word list file URL for dictionary checking to prevent users from using commonly used words as passwords.   Using word lists is an important part of password security.  Word lists are used by intruders to guess common passwords.   The default word list included contains commonly used English passwords.  <br/><br/>The first time a startup occurs with a new word list setting, it takes some time to compile the word list into a database.  See the status screen and logs for progress information.  The word list file format is one or more text files containing a single word per line, enclosed in a ZIP file.  The String <i>\!\#comment\:</i> at the beginning of a line indicates a comment. <br/><br/>The value must be a valid URL, using the protocol "file" (local file system), "http", or "https".
 Setting_Description_pwm.wordlist.location=Specify a word list file URL for dictionary checking to prevent users from using commonly used words as passwords.   Using word lists is an important part of password security.  Word lists are used by intruders to guess common passwords.   The default word list included contains commonly used English passwords.  <br/><br/>The first time a startup occurs with a new word list setting, it takes some time to compile the word list into a database.  See the status screen and logs for progress information.  The word list file format is one or more text files containing a single word per line, enclosed in a ZIP file.  The String <i>\!\#comment\:</i> at the beginning of a line indicates a comment. <br/><br/>The value must be a valid URL, using the protocol "file" (local file system), "http", or "https".
-Setting_Description_pwNotify.storageMode=Select storage mode used by cluster module.
-Setting_Description_pwNotify.enable=<p>Enable password expiration notification service.  Operation of this service requires that a remote database be configured.  Status of this service can be viewed on the <code>Administration -> Dashboard -> Password Notification</code> page.  The service will nominally execute once per day on the cluster master server.</p><p>If a job is missed because of an @PwmAppName@, LDAP, or database service interuption it will be run within the next 24 hours as soon as service is restored.  Running a job more than once will not result in duplicate emails sent to the user.</p>
+Setting_Description_pwNotify.storageMode=Select storage mode used by node service module.
+Setting_Description_pwNotify.enable=<p>Enable password expiration notification service.  Operation of this service requires that a node service be configured.  Status of this service can be viewed on the <code>Administration -> Dashboard -> Password Notification</code> page.  The service will nominally execute once per day on the master node server.</p><p>If a job is missed because of an @PwmAppName@, LDAP, or database service interruption it will be run within the next 24 hours as soon as service is restored.  Running a job more than once will not result in duplicate emails sent to the user.</p><p>If a user's password expiration time changes since the last job, a new notification will be sent as appropriate.</p>
 Setting_Description_pwNotify.queryString=Users that will receive password expiration notifications.
 Setting_Description_pwNotify.queryString=Users that will receive password expiration notifications.
 Setting_Description_pwNotify.intervals=Expiration Notification Day Intervals.  The number of days before a user's password expiration before which an email notice will be set. 
 Setting_Description_pwNotify.intervals=Expiration Notification Day Intervals.  The number of days before a user's password expiration before which an email notice will be set. 
 Setting_Description_pwNotify.job.offSet=GMT job offset time.  The expiration notice job will normally be executed at 0:00 GMT.  This value can be adjusted to change the standard time of day the job is run.  
 Setting_Description_pwNotify.job.offSet=GMT job offset time.  The expiration notice job will normally be executed at 0:00 GMT.  This value can be adjusted to change the standard time of day the job is run.  
@@ -784,8 +784,8 @@ Setting_Label_challenge.showConfirmation=Show Response Confirmation
 Setting_Label_challenge.token.sendMethod=Token Send Method
 Setting_Label_challenge.token.sendMethod=Token Send Method
 Setting_Label_challenge.userAttribute=Response Storage Attribute
 Setting_Label_challenge.userAttribute=Response Storage Attribute
 Setting_Label_changePassword.writeAttributes=Post Password Change Actions
 Setting_Label_changePassword.writeAttributes=Post Password Change Actions
-Setting_Label_cluster.enable=Cluster Enabled
-Setting_Label_cluster.storageMode=Cluster Mode
+Setting_Label_nodeService.enable=Node Service Enabled
+Setting_Label_nodeService.storageMode=Node Service Storage Mode
 Setting_Label_command.checkResponses.queryMatch=Check Responses Match
 Setting_Label_command.checkResponses.queryMatch=Check Responses Match
 Setting_Label_db.classname=Database Class
 Setting_Label_db.classname=Database Class
 Setting_Label_db.columnType.key=Database Key Column Type
 Setting_Label_db.columnType.key=Database Key Column Type
@@ -993,7 +993,7 @@ Setting_Label_ldap.serverCerts=LDAP Certificates
 Setting_Label_ldap.serverUrls=LDAP URLs
 Setting_Label_ldap.serverUrls=LDAP URLs
 Setting_Label_ldap.testuser.username=LDAP Test User
 Setting_Label_ldap.testuser.username=LDAP Test User
 Setting_Label_ldap.user.group.attribute=User Group Attribute
 Setting_Label_ldap.user.group.attribute=User Group Attribute
-Setting_Label_ldap.user.pwNotify.attribute=Password Notify Service Attribute
+Setting_Label_ldap.user.appData.attribute=Application Data Attribute
 Setting_Label_ldap.user.language.attribute=User Language Attribute
 Setting_Label_ldap.user.language.attribute=User Language Attribute
 Setting_Label_ldap.user.language.autoSet=Auto Set User Language Attribute
 Setting_Label_ldap.user.language.autoSet=Auto Set User Language Attribute
 Setting_Label_ldap.username.attr=Attribute to use for User Name
 Setting_Label_ldap.username.attr=Attribute to use for User Name

+ 2 - 1
server/src/main/resources/password/pwm/ldap/schema/SchemaDefinition.properties

@@ -26,5 +26,6 @@ pwmLastPwdUpdate={schemaType:"attribute",name:"pwmLastPwdUpdate",definition:"( 1
 pwmGUID={schemaType:"attribute",name:"pwmGUID",definition:"( 1.3.6.1.4.1.35015.1.2.4 NAME 'pwmGUID' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )"}
 pwmGUID={schemaType:"attribute",name:"pwmGUID",definition:"( 1.3.6.1.4.1.35015.1.2.4 NAME 'pwmGUID' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )"}
 pwmToken={schemaType:"attribute",name:"pwmToken",definition:"( 1.3.6.1.4.1.35015.1.2.5 NAME 'pwmToken' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )"}
 pwmToken={schemaType:"attribute",name:"pwmToken",definition:"( 1.3.6.1.4.1.35015.1.2.5 NAME 'pwmToken' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )"}
 pwmOtpSecret={schemaType:"attribute",name:"pwmOtpSecret",definition:"( 1.3.6.1.4.1.35015.1.2.6 NAME 'pwmOtpSecret' SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )"}
 pwmOtpSecret={schemaType:"attribute",name:"pwmOtpSecret",definition:"( 1.3.6.1.4.1.35015.1.2.6 NAME 'pwmOtpSecret' SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )"}
+pwmData={schemaType:"attribute",name:"pwmData",definition:"( 1.3.6.1.4.1.35015.1.2.7 NAME 'pwmData' SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )"}
 
 
-pwmUser={schemaType:"objectclass",name:"pwmUser",definition:"( 1.3.6.1.4.1.35015.1.1.1 NAME 'pwmUser' AUXILIARY MAY ( pwmLastPwdUpdate $ pwmEventLog $ pwmResponseSet $ pwmGUID $ pwmToken $ pwmOtpSecret ) )"}
+pwmUser={schemaType:"objectclass",name:"pwmUser",definition:"( 1.3.6.1.4.1.35015.1.1.1 NAME 'pwmUser' AUXILIARY MAY ( pwmLastPwdUpdate $ pwmEventLog $ pwmResponseSet $ pwmGUID $ pwmToken $ pwmOtpSecret $ pwmData ) )"}

+ 22 - 1
webapp/src/build/ldif/AD-schema.ldif

@@ -112,7 +112,6 @@ adminDisplayName: pwmToken
 adminDescription: pwmToken
 adminDescription: pwmToken
 searchFlags: 1
 searchFlags: 1
 
 
-
 #------------------------------------------------------
 #------------------------------------------------------
 #-- Attribute:  	pwmOtpSecret
 #-- Attribute:  	pwmOtpSecret
 #-- Syntax:      	OCTET STRING
 #-- Syntax:      	OCTET STRING
@@ -133,6 +132,26 @@ adminDisplayName: pwmOtpSecret
 adminDescription: Stores the user's challenge/response answers
 adminDescription: Stores the user's challenge/response answers
 searchFlags: 1
 searchFlags: 1
 
 
+#------------------------------------------------------
+#-- Attribute:  	pwmData
+#-- Syntax:      	OCTET STRING
+#-- Description:	Stores application status data
+#------------------------------------------------------
+dn: CN=pwmData,CN=Schema,CN=Configuration,DC=x
+changetype: ntdsschemaadd
+objectClass: attributeSchema
+cn: pwmData
+attributeID: 1.3.6.1.4.1.35015.1.2.7
+attributeSyntax: 2.5.5.10
+isSingleValued: FALSE
+oMSyntax: 4
+isMemberOfPartialAttributeSet: FALSE
+lDAPDisplayName: pwmData
+showInAdvancedViewOnly: TRUE
+adminDisplayName: pwmData
+adminDescription:Stores application status data
+searchFlags: 1
+
 
 
 #------------------------------------------------------
 #------------------------------------------------------
 #--  Update the schema now
 #--  Update the schema now
@@ -163,6 +182,7 @@ mayContain: pwmEventLog
 mayContain: pwmGUID
 mayContain: pwmGUID
 mayContain: pwmToken
 mayContain: pwmToken
 mayContain: pwmOtpSecret
 mayContain: pwmOtpSecret
+mayContain: pwmData
 objectClassCategory: 3
 objectClassCategory: 3
 rDNAttID: cn
 rDNAttID: cn
 showInAdvancedViewOnly: TRUE
 showInAdvancedViewOnly: TRUE
@@ -196,6 +216,7 @@ add: mayContain
 mayContain: pwmGUID
 mayContain: pwmGUID
 mayContain: pwmToken
 mayContain: pwmToken
 mayContain: pwmOtpSecret
 mayContain: pwmOtpSecret
+mayContain: pwmData
 -
 -
 
 
 #------------------------------------------------------
 #------------------------------------------------------

+ 10 - 0
webapp/src/build/ldif/ApacheDS-schema.ldif

@@ -59,6 +59,15 @@ m-name: pwmOtpSecret
 m-syntax: 1.3.6.1.4.1.1466.115.121.1.40
 m-syntax: 1.3.6.1.4.1.1466.115.121.1.40
 m-length: 0
 m-length: 0
 
 
+dn: m-oid=1.3.6.1.4.1.35015.1.2.7, ou=attributeTypes, cn=pwm, ou=schema
+objectclass: metaAttributeType
+objectclass: metaTop
+objectclass: top
+m-oid: 1.3.6.1.4.1.35015.1.2.7
+m-name: pwmData
+m-syntax: 1.3.6.1.4.1.1466.115.121.1.40
+m-length: 0
+
 dn: ou=comparators, cn=pwm, ou=schema
 dn: ou=comparators, cn=pwm, ou=schema
 objectclass: organizationalUnit
 objectclass: organizationalUnit
 objectclass: top
 objectclass: top
@@ -111,6 +120,7 @@ m-may: pwmGUID
 m-may: pwmLastPwdUpdate
 m-may: pwmLastPwdUpdate
 m-may: pwmResponseSet
 m-may: pwmResponseSet
 m-may: pwmOtpSecret
 m-may: pwmOtpSecret
+m-may: pwmData
 
 
 dn: ou=syntaxCheckers, cn=pwm, ou=schema
 dn: ou=syntaxCheckers, cn=pwm, ou=schema
 objectclass: organizationalUnit
 objectclass: organizationalUnit

+ 16 - 1
webapp/src/build/ldif/OracleDS-schema.ldif

@@ -94,6 +94,21 @@ attributeTypes: (
   X-ORIGIN 'iPlanet Directory Server'
   X-ORIGIN 'iPlanet Directory Server'
  )
  )
 
 
+#------------------------------------------------------
+#-- Attribute:  	pwmData
+#-- Syntax:      	OCTET STRING
+#-- Description:    Application Status Data
+#------------------------------------------------------
+dn: cn=schema
+changetype: modify
+add: attributeTypes
+attributeTypes: (
+  1.3.6.1.4.1.35015.1.2.7
+  NAME 'pwmData'
+  DESC 'SSPR defined attribute type'
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
+  X-ORIGIN 'iPlanet Directory Server'
+ )
 
 
 #------------------------------------------------------
 #------------------------------------------------------
 #-- Class:        pwmUser
 #-- Class:        pwmUser
@@ -111,6 +126,6 @@ objectClasses: (
   NAME 'pwmUser'
   NAME 'pwmUser'
   DESC 'SSPR defined aux class'
   DESC 'SSPR defined aux class'
   AUXILIARY
   AUXILIARY
-  MAY ( pwmEventLog $ pwmResponseSet $ pwmLastPwdUpdate $ pwmGUID $ pwmToken $ pwmOtpSecret)
+  MAY ( pwmEventLog $ pwmResponseSet $ pwmLastPwdUpdate $ pwmGUID $ pwmToken $ pwmOtpSecret $ pwmData )
   X-ORIGIN 'SSPR Administrator'
   X-ORIGIN 'SSPR Administrator'
  )
  )

+ 16 - 2
webapp/src/build/ldif/edirectory-schema-update.ldif

@@ -80,11 +80,25 @@ attributeTypes: (
 -
 -
 add: attributeTypes
 add: attributeTypes
 attributeTypes: (
 attributeTypes: (
-  1.3.6.1.4.1.35015.1.2.5
+  1.3.6.1.4.1.35015.1.2.6
   NAME 'pwmOtpSecret'
   NAME 'pwmOtpSecret'
   SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
   SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
  )
  )
 
 
+dn: cn=schema
+changetype: modify
+delete: attributeTypes
+attributeTypes: (
+  NAME 'pwmData'
+ )
+-
+add: attributeTypes
+attributeTypes: (
+  1.3.6.1.4.1.35015.1.2.7
+  NAME 'pwmData'
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
+ )
+
 dn: cn=schema
 dn: cn=schema
 changetype: modify
 changetype: modify
 delete: objectClasses
 delete: objectClasses
@@ -98,5 +112,5 @@ objectClasses: (
   1.3.6.1.4.1.35015.1.1.1
   1.3.6.1.4.1.35015.1.1.1
   NAME 'pwmUser'
   NAME 'pwmUser'
   AUXILIARY
   AUXILIARY
-  MAY ( pwmLastPwdUpdate $ pwmEventLog $ pwmResponseSet $ pwmGUID $ pwmToken $ pwmOtpSecret )
+  MAY ( pwmLastPwdUpdate $ pwmEventLog $ pwmResponseSet $ pwmGUID $ pwmToken $ pwmOtpSecret $ pwmData )
  )
  )

+ 15 - 1
webapp/src/build/ldif/edirectory-schema.ldif

@@ -99,6 +99,20 @@ attributeTypes: (
   SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
   SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
  )
  )
 
 
+#------------------------------------------------------
+#-- Attribute:  	pwmData
+#-- Syntax:      	OCTET STRING
+#-- Description:    Stores application data
+#------------------------------------------------------
+dn: cn=schema
+changetype: modify
+add: attributeTypes
+attributeTypes: (
+  1.3.6.1.4.1.35015.1.2.7
+  NAME 'pwmData'
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
+ )
+
 #------------------------------------------------------
 #------------------------------------------------------
 #-- Class:        pwmUser
 #-- Class:        pwmUser
 #-- Description:  Aux class
 #-- Description:  Aux class
@@ -114,5 +128,5 @@ objectClasses: (
   1.3.6.1.4.1.35015.1.1.1
   1.3.6.1.4.1.35015.1.1.1
   NAME 'pwmUser'
   NAME 'pwmUser'
   AUXILIARY
   AUXILIARY
-  MAY ( pwmLastPwdUpdate $ pwmEventLog $ pwmResponseSet $ pwmGUID $ pwmToken $ pwmOtpSecret )
+  MAY ( pwmLastPwdUpdate $ pwmEventLog $ pwmResponseSet $ pwmGUID $ pwmToken $ pwmOtpSecret $ pwmData )
  )
  )

+ 15 - 2
webapp/src/build/ldif/edirectory-schema.sch

@@ -79,16 +79,29 @@ BEGIN
 	 ASN1ObjID 	{ 1 3 6 1 4 1 35015 1 2 6 } 
 	 ASN1ObjID 	{ 1 3 6 1 4 1 35015 1 2 6 } 
  }
  }
 
 
+-- attributeTypes: (
+--   1.3.6.1.4.1.35015.1.2.67
+--   NAME 'pwmData'
+--   SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
+--  )
+
+"pwmData" ATTRIBUTE ::=
+ {
+	 SyntaxID 	 SYN_OCTET_STRING,
+	 Flags 	{ DS_SYNC_IMMEDIATE },
+	 ASN1ObjID 	{ 1 3 6 1 4 1 35015 1 2 7 }
+ }
+
 -- objectClasses: ( 1.3.6.1.4.1.35015.1.1.1
 -- objectClasses: ( 1.3.6.1.4.1.35015.1.1.1
 --   NAME 'pwmUser' 
 --   NAME 'pwmUser' 
 --   AUXILIARY 
 --   AUXILIARY 
---   MAY ( pwmLastPwdUpdate $ pwmEventLog $ pwmResponseSet $ pwmGUID $ pwmToken $ pwmOtpSecret ) )
+--   MAY ( pwmLastPwdUpdate $ pwmEventLog $ pwmResponseSet $ pwmGUID $ pwmToken $ pwmOtpSecret $ pwmData ) )
 
 
 "pwmUser" OBJECT-CLASS ::=
 "pwmUser" OBJECT-CLASS ::=
  { 
  { 
 	 Operation 	ADD, 
 	 Operation 	ADD, 
 	 Flags 	{DS_AUXILIARY_CLASS}, 
 	 Flags 	{DS_AUXILIARY_CLASS}, 
-	 MayContain 	{ "pwmLastPwdUpdate", "pwmEventLog", "pwmResponseSet", "pwmGUID", "pwmToken", "pwmOtpSecret" },
+	 MayContain 	{ "pwmLastPwdUpdate", "pwmEventLog", "pwmResponseSet", "pwmGUID", "pwmToken", "pwmOtpSecret", "pwmData" },
 	 ASN1ObjID 	{ 1 3 6 1 4 1 35015 1 1 1 } 
 	 ASN1ObjID 	{ 1 3 6 1 4 1 35015 1 1 1 } 
  }
  }
 
 

+ 7 - 1
webapp/src/build/ldif/openDJ-schema.ldif

@@ -34,8 +34,14 @@ attributeTypes: ( 1.3.6.1.4.1.591242.2.2010.04.16.6
   SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
   SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
   EQUALITY octetStringMatch
   EQUALITY octetStringMatch
   X-ORIGIN 'PWM' )
   X-ORIGIN 'PWM' )
+attributeTypes: ( 1.3.6.1.4.1.591242.2.2010.04.16.7
+  NAME 'pwmData'
+  DESC 'Application status data'
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
+  EQUALITY octetStringMatch
+  X-ORIGIN 'PWM' )
 objectClasses: ( 1.3.6.1.4.1.591242.1.2010.04.16.1
 objectClasses: ( 1.3.6.1.4.1.591242.1.2010.04.16.1
   NAME 'pwmUser'
   NAME 'pwmUser'
   AUXILIARY
   AUXILIARY
-  MAY ( pwmLastPwdUpdate $ pwmEventLog $ pwmResponseSet $ pwmGUID $ pwmOtpSecret )
+  MAY ( pwmLastPwdUpdate $ pwmEventLog $ pwmResponseSet $ pwmGUID $ pwmOtpSecret $ pwmData )
   X-ORIGIN 'PWM' )
   X-ORIGIN 'PWM' )

+ 6 - 1
webapp/src/build/ldif/openldap.schema

@@ -31,8 +31,13 @@ attributetype ( 1.3.6.1.4.1.35015.1.2.6
         EQUALITY octetStringMatch
         EQUALITY octetStringMatch
         SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
         SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
 
 
+attributetype ( 1.3.6.1.4.1.35015.1.2.7
+        NAME 'pwmData'
+        EQUALITY octetStringMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
+
 objectclass ( 1.3.6.1.4.1.35015.1.1.1
 objectclass ( 1.3.6.1.4.1.35015.1.1.1
         NAME 'pwmUser'
         NAME 'pwmUser'
         AUXILIARY
         AUXILIARY
         MAY ( pwmLastPwdUpdate $ pwmEventLog $ pwmResponseSet $
         MAY ( pwmLastPwdUpdate $ pwmEventLog $ pwmResponseSet $
-                pwmOtpSecret $ pwmGUID ) )
+                pwmOtpSecret $ pwmGUID $ pwmData ) )