瀏覽代碼

minor refactoring, pwmsetting xml caching

Jason Rivard 7 年之前
父節點
當前提交
d4eed3c7fe

+ 1 - 1
client/pom.xml

@@ -86,7 +86,7 @@
             <plugin>
             <plugin>
                 <groupId>com.github.eirslett</groupId>
                 <groupId>com.github.eirslett</groupId>
                 <artifactId>frontend-maven-plugin</artifactId>
                 <artifactId>frontend-maven-plugin</artifactId>
-                <version>1.5</version>
+                <version>1.6</version>
                 <configuration>
                 <configuration>
                     <nodeVersion>v8.9.4</nodeVersion>
                     <nodeVersion>v8.9.4</nodeVersion>
                     <npmVersion>5.6.0</npmVersion>
                     <npmVersion>5.6.0</npmVersion>

+ 3 - 3
server/pom.xml

@@ -700,7 +700,7 @@
         <dependency>
         <dependency>
             <groupId>org.apache.httpcomponents</groupId>
             <groupId>org.apache.httpcomponents</groupId>
             <artifactId>httpclient</artifactId>
             <artifactId>httpclient</artifactId>
-            <version>4.5.5</version>
+            <version>4.5.6</version>
         </dependency>
         </dependency>
         <dependency>
         <dependency>
             <groupId>org.graylog2</groupId>
             <groupId>org.graylog2</groupId>
@@ -730,12 +730,12 @@
         <dependency>
         <dependency>
             <groupId>org.bouncycastle</groupId>
             <groupId>org.bouncycastle</groupId>
             <artifactId>bcprov-jdk15on</artifactId>
             <artifactId>bcprov-jdk15on</artifactId>
-            <version>1.59</version>
+            <version>1.60</version>
         </dependency>
         </dependency>
         <dependency>
         <dependency>
             <groupId>org.bouncycastle</groupId>
             <groupId>org.bouncycastle</groupId>
             <artifactId>bcpkix-jdk15on</artifactId>
             <artifactId>bcpkix-jdk15on</artifactId>
-            <version>1.59</version>
+            <version>1.60</version>
         </dependency>
         </dependency>
         <dependency>
         <dependency>
             <groupId>javax.xml</groupId>
             <groupId>javax.xml</groupId>

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

@@ -183,6 +183,7 @@ public enum AppProperty
     HEALTHCHECK_MAX_FORCE_WAIT                      ( "healthCheck.maximumForceCheckWaitSeconds" ),
     HEALTHCHECK_MAX_FORCE_WAIT                      ( "healthCheck.maximumForceCheckWaitSeconds" ),
     HEALTH_CERTIFICATE_WARN_SECONDS                 ( "health.certificate.warnSeconds" ),
     HEALTH_CERTIFICATE_WARN_SECONDS                 ( "health.certificate.warnSeconds" ),
     HEALTH_LDAP_CAUTION_DURATION_MS                 ( "health.ldap.cautionDurationMS" ),
     HEALTH_LDAP_CAUTION_DURATION_MS                 ( "health.ldap.cautionDurationMS" ),
+    HEALTH_LDAP_PROXY_WARN_PW_EXPIRE_SECONDS        ( "health.ldap.proxy.pwExpireWarnSeconds" ),
     HEALTH_JAVA_MAX_THREADS                         ( "health.java.maxThreads" ),
     HEALTH_JAVA_MAX_THREADS                         ( "health.java.maxThreads" ),
     HEALTH_JAVA_MIN_HEAP_BYTES                      ( "health.java.minHeapBytes" ),
     HEALTH_JAVA_MIN_HEAP_BYTES                      ( "health.java.minHeapBytes" ),
     HELPDESK_TOKEN_MAX_AGE                          ( "helpdesk.token.maxAgeSeconds" ),
     HELPDESK_TOKEN_MAX_AGE                          ( "helpdesk.token.maxAgeSeconds" ),

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

@@ -42,6 +42,7 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Map;
 import java.util.Set;
 import java.util.Set;
+import java.util.function.Supplier;
 import java.util.regex.Pattern;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
 import java.util.regex.PatternSyntaxException;
 
 
@@ -1214,16 +1215,16 @@ public enum PwmSetting
     private final PwmSettingCategory category;
     private final PwmSettingCategory category;
 
 
     // cached values read from XML file
     // cached values read from XML file
-    private JavaHelper.SimpleReference<List<TemplateSetAssociation>> defaultValues;
-    private JavaHelper.SimpleReference<List<TemplateSetAssociation>> examples;
-    private JavaHelper.SimpleReference<Map<String, String>> options;
-    private JavaHelper.SimpleReference<Collection<PwmSettingFlag>> flags;
-    private JavaHelper.SimpleReference<Map<PwmSettingProperty, String>> properties;
-    private JavaHelper.SimpleReference<Collection<LDAPPermissionInfo>> ldapPermissionInfos;
-    private JavaHelper.SimpleReference<Boolean> required;
-    private JavaHelper.SimpleReference<Boolean> hidden;
-    private JavaHelper.SimpleReference<Integer> level;
-    private JavaHelper.SimpleReference<Pattern> pattern;
+    private transient Supplier<List<TemplateSetAssociation>> defaultValues;
+    private transient Supplier<List<TemplateSetAssociation>> examples;
+    private transient Supplier<Map<String, String>> options;
+    private transient Supplier<Collection<PwmSettingFlag>> flags;
+    private transient Supplier<Map<PwmSettingProperty, String>> properties;
+    private transient Supplier<Collection<LDAPPermissionInfo>> ldapPermissionInfo;
+    private transient Supplier<Boolean> required;
+    private transient Supplier<Boolean> hidden;
+    private transient Supplier<Integer> level;
+    private transient Supplier<Pattern> pattern;
 
 
     PwmSetting(
     PwmSetting(
             final String key,
             final String key,
@@ -1280,7 +1281,8 @@ public enum PwmSetting
             {
             {
                 throw new IllegalStateException( "no default value for setting " + this.getKey() );
                 throw new IllegalStateException( "no default value for setting " + this.getKey() );
             }
             }
-            defaultValues = new JavaHelper.SimpleReference<>( Collections.unmodifiableList( returnObj ) );
+            final List<TemplateSetAssociation> finalObj = Collections.unmodifiableList( returnObj );
+            defaultValues = ( ) -> finalObj;
         }
         }
         return defaultValues.get();
         return defaultValues.get();
     }
     }
@@ -1326,7 +1328,8 @@ public enum PwmSetting
                     }
                     }
                 }
                 }
             }
             }
-            options = new JavaHelper.SimpleReference<>( Collections.unmodifiableMap( returnList ) );
+            final Map<String, String> finalList = Collections.unmodifiableMap( returnList );
+            options = ( ) -> Collections.unmodifiableMap( finalList );
         }
         }
 
 
         return options.get( );
         return options.get( );
@@ -1359,7 +1362,8 @@ public enum PwmSetting
                     }
                     }
                 }
                 }
             }
             }
-            properties = new JavaHelper.SimpleReference<>( Collections.unmodifiableMap( newProps ) );
+            final Map<PwmSettingProperty, String> finalProps = Collections.unmodifiableMap( newProps );
+            properties = ( ) -> finalProps;
         }
         }
 
 
         return properties.get();
         return properties.get();
@@ -1387,14 +1391,15 @@ public enum PwmSetting
                 }
                 }
 
 
             }
             }
-            flags = new JavaHelper.SimpleReference<>( Collections.unmodifiableCollection( returnObj ) );
+            final Collection<PwmSettingFlag> finalObj = Collections.unmodifiableCollection( returnObj );
+            flags = ( ) -> finalObj;
         }
         }
         return flags.get();
         return flags.get();
     }
     }
 
 
     public Collection<LDAPPermissionInfo> getLDAPPermissionInfo( )
     public Collection<LDAPPermissionInfo> getLDAPPermissionInfo( )
     {
     {
-        if ( ldapPermissionInfos == null )
+        if ( ldapPermissionInfo == null )
         {
         {
             final Element settingElement = PwmSettingXml.readSettingXml( this );
             final Element settingElement = PwmSettingXml.readSettingXml( this );
             final List<Element> permissionElements = settingElement.getChildren( PwmSettingXml.XML_ELEMENT_LDAP_PERMISSION );
             final List<Element> permissionElements = settingElement.getChildren( PwmSettingXml.XML_ELEMENT_LDAP_PERMISSION );
@@ -1420,10 +1425,11 @@ public enum PwmSetting
                     }
                     }
                 }
                 }
             }
             }
-            ldapPermissionInfos = new JavaHelper.SimpleReference<>( Collections.unmodifiableList( returnObj ) );
+            final List<LDAPPermissionInfo> finalObj = Collections.unmodifiableList( returnObj );
+            ldapPermissionInfo = ( ) -> finalObj;
         }
         }
 
 
-        return ldapPermissionInfos.get();
+        return ldapPermissionInfo.get();
     }
     }
 
 
     public String getLabel( final Locale locale )
     public String getLabel( final Locale locale )
@@ -1458,7 +1464,8 @@ public enum PwmSetting
             {
             {
                 returnObj.add( new TemplateSetAssociation( "", Collections.emptySet() ) );
                 returnObj.add( new TemplateSetAssociation( "", Collections.emptySet() ) );
             }
             }
-            examples = new JavaHelper.SimpleReference<>( Collections.unmodifiableList( returnObj ) );
+            final List<TemplateSetAssociation> exampleOutput = Collections.unmodifiableList( returnObj );
+            examples = ( ) -> exampleOutput;
         }
         }
 
 
         return ( String ) associationForTempleSet( examples.get(), template ).getObject();
         return ( String ) associationForTempleSet( examples.get(), template ).getObject();
@@ -1470,7 +1477,8 @@ public enum PwmSetting
         {
         {
             final Element settingElement = PwmSettingXml.readSettingXml( this );
             final Element settingElement = PwmSettingXml.readSettingXml( this );
             final Attribute requiredAttribute = settingElement.getAttribute( "required" );
             final Attribute requiredAttribute = settingElement.getAttribute( "required" );
-            required = new JavaHelper.SimpleReference<>( requiredAttribute != null && "true".equalsIgnoreCase( requiredAttribute.getValue() ) );
+            final boolean requiredOutput = requiredAttribute != null && "true".equalsIgnoreCase( requiredAttribute.getValue() );
+            required = ( ) -> requiredOutput;
         }
         }
         return required.get();
         return required.get();
     }
     }
@@ -1481,8 +1489,8 @@ public enum PwmSetting
         {
         {
             final Element settingElement = PwmSettingXml.readSettingXml( this );
             final Element settingElement = PwmSettingXml.readSettingXml( this );
             final Attribute requiredAttribute = settingElement.getAttribute( "hidden" );
             final Attribute requiredAttribute = settingElement.getAttribute( "hidden" );
-            final boolean hidden = requiredAttribute != null && "true".equalsIgnoreCase( requiredAttribute.getValue() ) || this.getCategory().isHidden();
-            this.hidden = new JavaHelper.SimpleReference<>( hidden );
+            final boolean outputHidden = requiredAttribute != null && "true".equalsIgnoreCase( requiredAttribute.getValue() ) || this.getCategory().isHidden();
+            hidden = ( ) -> outputHidden;
         }
         }
         return hidden.get();
         return hidden.get();
     }
     }
@@ -1493,7 +1501,8 @@ public enum PwmSetting
         {
         {
             final Element settingElement = PwmSettingXml.readSettingXml( this );
             final Element settingElement = PwmSettingXml.readSettingXml( this );
             final Attribute levelAttribute = settingElement.getAttribute( "level" );
             final Attribute levelAttribute = settingElement.getAttribute( "level" );
-            level = new JavaHelper.SimpleReference<>( levelAttribute != null ? Integer.parseInt( levelAttribute.getValue() ) : 0 );
+            final int outputLevel = levelAttribute != null ? Integer.parseInt( levelAttribute.getValue() ) : 0;
+            level = ( ) -> outputLevel;
         }
         }
         return level.get();
         return level.get();
     }
     }
@@ -1508,7 +1517,8 @@ public enum PwmSetting
             {
             {
                 try
                 try
                 {
                 {
-                    pattern = new JavaHelper.SimpleReference<>( Pattern.compile( regexNode.getText() ) );
+                    final Pattern output = Pattern.compile( regexNode.getText() );
+                    pattern = ( ) -> output;
                 }
                 }
                 catch ( PatternSyntaxException e )
                 catch ( PatternSyntaxException e )
                 {
                 {
@@ -1519,7 +1529,8 @@ public enum PwmSetting
             }
             }
             if ( pattern == null )
             if ( pattern == null )
             {
             {
-                pattern = new JavaHelper.SimpleReference<>( Pattern.compile( ".*", Pattern.DOTALL ) );
+                final Pattern output = Pattern.compile( ".*", Pattern.DOTALL );
+                pattern = ( ) -> output;
             }
             }
         }
         }
 
 

+ 13 - 11
server/src/main/java/password/pwm/config/PwmSettingCategory.java

@@ -26,7 +26,6 @@ import org.jdom2.Attribute;
 import org.jdom2.Element;
 import org.jdom2.Element;
 import password.pwm.i18n.Config;
 import password.pwm.i18n.Config;
 import password.pwm.util.LocaleHelper;
 import password.pwm.util.LocaleHelper;
-import password.pwm.util.java.JavaHelper;
 
 
 import java.util.ArrayList;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collection;
@@ -36,6 +35,7 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Map;
 import java.util.TreeMap;
 import java.util.TreeMap;
+import java.util.function.Supplier;
 
 
 public enum PwmSettingCategory
 public enum PwmSettingCategory
 {
 {
@@ -185,10 +185,10 @@ public enum PwmSettingCategory
 
 
     private final PwmSettingCategory parent;
     private final PwmSettingCategory parent;
 
 
-    private JavaHelper.SimpleReference<PwmSetting> profileSetting;
-    private JavaHelper.SimpleReference<Integer> level;
-    private JavaHelper.SimpleReference<Boolean> hidden;
-    private JavaHelper.SimpleReference<Boolean> isTopLevelProfile;
+    private transient Supplier<PwmSetting> profileSetting;
+    private transient Supplier<Integer> level;
+    private transient Supplier<Boolean> hidden;
+    private transient Supplier<Boolean> isTopLevelProfile;
 
 
 
 
     PwmSettingCategory( final PwmSettingCategory parent )
     PwmSettingCategory( final PwmSettingCategory parent )
@@ -211,7 +211,7 @@ public enum PwmSettingCategory
         if ( profileSetting == null )
         if ( profileSetting == null )
         {
         {
             final PwmSetting setting = readProfileSettingFromXml( true );
             final PwmSetting setting = readProfileSettingFromXml( true );
-            profileSetting = new JavaHelper.SimpleReference<>( setting );
+            profileSetting = ( ) -> setting;
         }
         }
         return profileSetting.get();
         return profileSetting.get();
     }
     }
@@ -225,7 +225,8 @@ public enum PwmSettingCategory
     {
     {
         if ( isTopLevelProfile == null )
         if ( isTopLevelProfile == null )
         {
         {
-            isTopLevelProfile = new JavaHelper.SimpleReference<>( readProfileSettingFromXml( false ) != null );
+            final boolean output = readProfileSettingFromXml( false ) != null;
+            isTopLevelProfile = ( ) -> output;
         }
         }
         return isTopLevelProfile.get();
         return isTopLevelProfile.get();
     }
     }
@@ -248,7 +249,8 @@ public enum PwmSettingCategory
         {
         {
             final Element settingElement = PwmSettingXml.readCategoryXml( this );
             final Element settingElement = PwmSettingXml.readCategoryXml( this );
             final Attribute levelAttribute = settingElement.getAttribute( "level" );
             final Attribute levelAttribute = settingElement.getAttribute( "level" );
-            level = new JavaHelper.SimpleReference<>( levelAttribute != null ? Integer.parseInt( levelAttribute.getValue() ) : 0 );
+            final int output = levelAttribute != null ? Integer.parseInt( levelAttribute.getValue() ) : 0;
+            level = ( ) -> output;
         }
         }
         return level.get();
         return level.get();
     }
     }
@@ -261,7 +263,7 @@ public enum PwmSettingCategory
             final Attribute hiddenElement = settingElement.getAttribute( "hidden" );
             final Attribute hiddenElement = settingElement.getAttribute( "hidden" );
             if ( hiddenElement != null && "true".equalsIgnoreCase( hiddenElement.getValue() ) )
             if ( hiddenElement != null && "true".equalsIgnoreCase( hiddenElement.getValue() ) )
             {
             {
-                hidden = new JavaHelper.SimpleReference<>( true );
+                hidden = () -> true;
             }
             }
             else
             else
             {
             {
@@ -269,13 +271,13 @@ public enum PwmSettingCategory
                 {
                 {
                     if ( parentCategory.isHidden() )
                     if ( parentCategory.isHidden() )
                     {
                     {
-                        hidden = new JavaHelper.SimpleReference<>( true );
+                        hidden = () -> true;
                     }
                     }
                 }
                 }
             }
             }
             if ( hidden == null )
             if ( hidden == null )
             {
             {
-                hidden = new JavaHelper.SimpleReference<>( false );
+                hidden = () -> false;
             }
             }
         }
         }
         return hidden.get();
         return hidden.get();

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

@@ -36,6 +36,7 @@ public enum HealthMessage
     LDAP_AD_Unsecure( HealthStatus.WARN, HealthTopic.LDAP ),
     LDAP_AD_Unsecure( HealthStatus.WARN, HealthTopic.LDAP ),
     LDAP_AD_StaticIP( HealthStatus.WARN, HealthTopic.LDAP ),
     LDAP_AD_StaticIP( HealthStatus.WARN, HealthTopic.LDAP ),
     LDAP_ProxyTestSameUser( HealthStatus.WARN, HealthTopic.Configuration ),
     LDAP_ProxyTestSameUser( HealthStatus.WARN, HealthTopic.Configuration ),
+    LDAP_ProxyUserPwExpired( HealthStatus.WARN, HealthTopic.LDAP ),
     LDAP_TestUserUnavailable( HealthStatus.CAUTION, HealthTopic.LDAP ),
     LDAP_TestUserUnavailable( HealthStatus.CAUTION, HealthTopic.LDAP ),
     LDAP_TestUserUnexpected( HealthStatus.WARN, HealthTopic.LDAP ),
     LDAP_TestUserUnexpected( HealthStatus.WARN, HealthTopic.LDAP ),
     LDAP_TestUserError( HealthStatus.WARN, HealthTopic.LDAP ),
     LDAP_TestUserError( HealthStatus.WARN, HealthTopic.LDAP ),

+ 26 - 7
server/src/main/java/password/pwm/health/LDAPStatusChecker.java

@@ -79,6 +79,7 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Map;
 import java.util.Set;
 import java.util.Set;
+import java.util.concurrent.TimeUnit;
 
 
 public class LDAPStatusChecker implements HealthChecker
 public class LDAPStatusChecker implements HealthChecker
 {
 {
@@ -313,12 +314,12 @@ public class LDAPStatusChecker implements HealthChecker
 
 
                         {
                         {
                             final boolean withinMinLifetime = PasswordUtility.isPasswordWithinMinimumLifetimeImpl(
                             final boolean withinMinLifetime = PasswordUtility.isPasswordWithinMinimumLifetimeImpl(
-                                            theUser,
-                                            SessionLabel.HEALTH_SESSION_LABEL,
-                                            passwordPolicy,
-                                            pwdLastModified,
-                                            passwordStatus
-                                    );
+                                    theUser,
+                                    SessionLabel.HEALTH_SESSION_LABEL,
+                                    passwordPolicy,
+                                    pwdLastModified,
+                                    passwordStatus
+                            );
                             if ( withinMinLifetime )
                             if ( withinMinLifetime )
                             {
                             {
                                 LOGGER.trace( SessionLabel.HEALTH_SESSION_LABEL, "skipping test user password set due to password being within minimum lifetime" );
                                 LOGGER.trace( SessionLabel.HEALTH_SESSION_LABEL, "skipping test user password set due to password being within minimum lifetime" );
@@ -485,9 +486,27 @@ public class LDAPStatusChecker implements HealthChecker
                     return Collections.singletonList( new HealthRecord( HealthStatus.WARN, HealthTopic.LDAP, "Missing Proxy User Password" ) );
                     return Collections.singletonList( new HealthRecord( HealthStatus.WARN, HealthTopic.LDAP, "Missing Proxy User Password" ) );
                 }
                 }
                 chaiProvider = LdapOperationsHelper.createChaiProvider( pwmApplication, SessionLabel.HEALTH_SESSION_LABEL, ldapProfile, config, proxyDN, proxyPW );
                 chaiProvider = LdapOperationsHelper.createChaiProvider( pwmApplication, SessionLabel.HEALTH_SESSION_LABEL, ldapProfile, config, proxyDN, proxyPW );
-                final ChaiEntry adminEntry = chaiProvider.getEntryFactory().newChaiEntry( proxyDN );
+                final ChaiUser adminEntry = chaiProvider.getEntryFactory().newChaiUser( proxyDN );
                 adminEntry.exists();
                 adminEntry.exists();
                 directoryVendor = chaiProvider.getDirectoryVendor();
                 directoryVendor = chaiProvider.getDirectoryVendor();
+
+                if ( adminEntry.isPasswordExpired() )
+                {
+                    final Instant passwordExpireDate = adminEntry.readPasswordExpirationDate();
+                    final TimeDuration maxPwExpireTime = TimeDuration.of(
+                            Integer.parseInt( config.readAppProperty( AppProperty.HEALTH_LDAP_PROXY_WARN_PW_EXPIRE_SECONDS ) ),
+                            TimeUnit.SECONDS );
+                    final TimeDuration expirationDuration = TimeDuration.fromCurrent( passwordExpireDate  );
+                    if ( maxPwExpireTime.isLongerThan( expirationDuration ) )
+                    {
+                        return Collections.singletonList( HealthRecord.forMessage(
+                                HealthMessage.LDAP_ProxyUserPwExpired,
+                                adminEntry.getEntryDN(),
+                                expirationDuration.asLongString( PwmConstants.DEFAULT_LOCALE )
+                        ) );
+                    }
+                }
+
             }
             }
             catch ( ChaiException e )
             catch ( ChaiException e )
             {
             {

+ 2 - 1
server/src/main/java/password/pwm/http/IdleTimeoutCalculator.java

@@ -88,7 +88,8 @@ public class IdleTimeoutCalculator
         else
         else
         {
         {
             final UserInfo userInfo = pwmSession.getUserInfo();
             final UserInfo userInfo = pwmSession.getUserInfo();
-            final boolean userIsAdmin = pwmSession.getSessionManager().checkPermission( pwmApplication, Permission.PWMADMIN );
+            final boolean userIsAdmin = pwmSession.isAuthenticated()
+                    && pwmSession.getSessionManager().checkPermission( pwmApplication, Permission.PWMADMIN );
             final Set<MaxIdleTimeoutResult> loggedInResults = figureMaxAuthUserTimeout( configuration, userInfo, userIsAdmin );
             final Set<MaxIdleTimeoutResult> loggedInResults = figureMaxAuthUserTimeout( configuration, userInfo, userIsAdmin );
             results.addAll( loggedInResults );
             results.addAll( loggedInResults );
         }
         }

+ 2 - 15
server/src/main/java/password/pwm/http/PwmSession.java

@@ -40,14 +40,12 @@ import password.pwm.ldap.auth.AuthenticationType;
 import password.pwm.svc.stats.Statistic;
 import password.pwm.svc.stats.Statistic;
 import password.pwm.svc.stats.StatisticsManager;
 import password.pwm.svc.stats.StatisticsManager;
 import password.pwm.util.LocaleHelper;
 import password.pwm.util.LocaleHelper;
+import password.pwm.util.java.JavaHelper;
 import password.pwm.util.java.JsonUtil;
 import password.pwm.util.java.JsonUtil;
 import password.pwm.util.java.TimeDuration;
 import password.pwm.util.java.TimeDuration;
 import password.pwm.util.logging.PwmLogger;
 import password.pwm.util.logging.PwmLogger;
 import password.pwm.util.secure.PwmRandom;
 import password.pwm.util.secure.PwmRandom;
 
 
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.ObjectOutputStream;
 import java.io.Serializable;
 import java.io.Serializable;
 import java.math.BigInteger;
 import java.math.BigInteger;
 import java.time.Instant;
 import java.time.Instant;
@@ -357,17 +355,6 @@ public class PwmSession implements Serializable
 
 
     public int size( )
     public int size( )
     {
     {
-        try ( ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream() )
-        {
-            final ObjectOutputStream out = new ObjectOutputStream( byteArrayOutputStream );
-            out.writeObject( this );
-            out.flush();
-            return byteArrayOutputStream.toByteArray().length;
-        }
-        catch ( IOException e )
-        {
-            LOGGER.debug( this, "exception while estimating session size: " + e.getMessage() );
-            return 0;
-        }
+        return ( int ) JavaHelper.sizeof( this );
     }
     }
 }
 }

+ 17 - 8
server/src/main/java/password/pwm/util/java/JavaHelper.java

@@ -34,9 +34,11 @@ import javax.annotation.CheckReturnValue;
 import java.io.ByteArrayOutputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStream;
+import java.io.ObjectOutputStream;
 import java.io.OutputStream;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
 import java.io.PrintWriter;
+import java.io.Serializable;
 import java.io.StringWriter;
 import java.io.StringWriter;
 import java.lang.management.LockInfo;
 import java.lang.management.LockInfo;
 import java.lang.management.MonitorInfo;
 import java.lang.management.MonitorInfo;
@@ -622,18 +624,25 @@ public class JavaHelper
         return Optional.empty();
         return Optional.empty();
     }
     }
 
 
-    public static class SimpleReference<T>
+    /**
+     * Very naive implementation to get a rough order estimate of object memory size, used for debug
+     * purposes only.
+     * @param object object to be analyzed
+     * @return size of object (very rough estimate)
+     */
+    public static long sizeof( final Serializable object )
     {
     {
-        T reference;
-
-        public SimpleReference( final T reference )
+        try ( ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream() )
         {
         {
-            this.reference = reference;
+            final ObjectOutputStream out = new ObjectOutputStream( byteArrayOutputStream );
+            out.writeObject( object );
+            out.flush();
+            return byteArrayOutputStream.toByteArray().length;
         }
         }
-
-        public T get( )
+        catch ( IOException e )
         {
         {
-            return reference;
+            LOGGER.debug( "exception while estimating session size: " + e.getMessage() );
+            return 0;
         }
         }
     }
     }
 }
 }

+ 5 - 0
server/src/main/java/password/pwm/util/java/TimeDuration.java

@@ -567,6 +567,11 @@ public class TimeDuration implements Comparable, Serializable
         return new TimeDuration( duration.get( ChronoUnit.MILLIS ) );
         return new TimeDuration( duration.get( ChronoUnit.MILLIS ) );
     }
     }
 
 
+    public static TimeDuration of ( final long value, final TimeUnit timeUnit )
+    {
+        return new TimeDuration( value, timeUnit );
+    }
+
     private static class TimeDetail implements Serializable
     private static class TimeDetail implements Serializable
     {
     {
         private final long milliseconds;
         private final long milliseconds;

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

@@ -93,7 +93,12 @@ public class HttpsServerCertificateManager
     }
     }
 
 
 
 
-    public static KeyStore keyStoreForApplication( final PwmApplication pwmApplication, final PasswordData passwordData, final String alias ) throws PwmUnrecoverableException
+    public static KeyStore keyStoreForApplication(
+            final PwmApplication pwmApplication,
+            final PasswordData passwordData,
+            final String alias
+    )
+            throws PwmUnrecoverableException
     {
     {
         KeyStore keyStore = null;
         KeyStore keyStore = null;
         keyStore = exportKey( pwmApplication.getConfig(), KeyStoreFormat.JKS, passwordData, alias );
         keyStore = exportKey( pwmApplication.getConfig(), KeyStoreFormat.JKS, passwordData, alias );

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

@@ -94,6 +94,7 @@ healthCheck.maximumRecordAgeSeconds=300
 healthCheck.maximumForceCheckWaitSeconds=30
 healthCheck.maximumForceCheckWaitSeconds=30
 health.certificate.warnSeconds=2592000
 health.certificate.warnSeconds=2592000
 health.ldap.cautionDurationMS=10800000
 health.ldap.cautionDurationMS=10800000
+health.ldap.proxy.pwExpireWarnSeconds=2592000
 health.java.maxThreads=1000
 health.java.maxThreads=1000
 health.java.minHeapBytes=67108864
 health.java.minHeapBytes=67108864
 helpdesk.token.maxAgeSeconds=300
 helpdesk.token.maxAgeSeconds=300

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

@@ -24,6 +24,7 @@ HealthMessage_NoData=Health data is not currently available.  Please check again
 HealthMessage_LDAP_OK=All configured LDAP servers are reachable
 HealthMessage_LDAP_OK=All configured LDAP servers are reachable
 HealthMessage_LDAP_No_Connection=Unable to connect to LDAP server %1%, error: %2%
 HealthMessage_LDAP_No_Connection=Unable to connect to LDAP server %1%, error: %2%
 HealthMessage_LDAP_ProxyTestSameUser=%1% setting is the same value as the %2% setting
 HealthMessage_LDAP_ProxyTestSameUser=%1% setting is the same value as the %2% setting
+HealthMessage_LDAP_ProxyUserPwExpired=Proxy user %1% password will expire within %2%.  The proxy user password should never expire. 
 HealthMessage_LDAP_TestUserUnavailable=LDAP unavailable error while testing ldap test user %1%, error: %2%
 HealthMessage_LDAP_TestUserUnavailable=LDAP unavailable error while testing ldap test user %1%, error: %2%
 HealthMessage_LDAP_TestUserUnexpected=Unexpected error while testing ldap test user %1%, error: %2%
 HealthMessage_LDAP_TestUserUnexpected=Unexpected error while testing ldap test user %1%, error: %2%
 HealthMessage_LDAP_TestUserError=error verifying test user account %1%, error: %2%
 HealthMessage_LDAP_TestUserError=error verifying test user account %1%, error: %2%