瀏覽代碼

audit system improvements

Jason Rivard 9 年之前
父節點
當前提交
df5982f150
共有 33 個文件被更改,包括 428 次插入306 次删除
  1. 13 15
      src/main/java/password/pwm/PwmApplication.java
  2. 6 5
      src/main/java/password/pwm/config/stored/ConfigurationReader.java
  3. 2 1
      src/main/java/password/pwm/http/servlet/ActivateUserServlet.java
  4. 2 1
      src/main/java/password/pwm/http/servlet/ChangePasswordServlet.java
  5. 2 1
      src/main/java/password/pwm/http/servlet/SetupOtpServlet.java
  6. 2 1
      src/main/java/password/pwm/http/servlet/SetupResponsesServlet.java
  7. 2 1
      src/main/java/password/pwm/http/servlet/UpdateProfileServlet.java
  8. 12 11
      src/main/java/password/pwm/http/servlet/helpdesk/HelpdeskServlet.java
  9. 38 0
      src/main/java/password/pwm/i18n/Admin.java
  10. 2 1
      src/main/java/password/pwm/i18n/Message.java
  11. 8 2
      src/main/java/password/pwm/ldap/auth/LDAPAuthenticationRequest.java
  12. 43 34
      src/main/java/password/pwm/svc/event/AuditEvent.java
  13. 8 2
      src/main/java/password/pwm/svc/event/AuditRecord.java
  14. 179 0
      src/main/java/password/pwm/svc/event/AuditRecordFactory.java
  15. 2 113
      src/main/java/password/pwm/svc/event/AuditService.java
  16. 1 36
      src/main/java/password/pwm/svc/event/HelpdeskAuditRecord.java
  17. 1 1
      src/main/java/password/pwm/svc/event/LdapXmlUserHistory.java
  18. 1 10
      src/main/java/password/pwm/svc/event/SystemAuditRecord.java
  19. 0 26
      src/main/java/password/pwm/svc/event/UserAuditRecord.java
  20. 22 13
      src/main/java/password/pwm/svc/intruder/IntruderManager.java
  21. 9 6
      src/main/java/password/pwm/svc/token/TokenService.java
  22. 7 6
      src/main/java/password/pwm/util/logging/PwmLogger.java
  23. 3 2
      src/main/java/password/pwm/util/operations/PasswordUtility.java
  24. 3 2
      src/main/java/password/pwm/ws/server/rest/RestChallengesServer.java
  25. 1 1
      src/main/resources/password/pwm/AppProperty.properties
  26. 8 6
      src/main/resources/password/pwm/config/PwmSetting.xml
  27. 36 1
      src/main/resources/password/pwm/i18n/Admin.properties
  28. 2 1
      src/main/resources/password/pwm/i18n/Message.properties
  29. 1 1
      src/main/resources/password/pwm/i18n/Message_es.properties
  30. 1 1
      src/main/resources/password/pwm/i18n/Message_pt_BR.properties
  31. 1 1
      src/main/resources/password/pwm/i18n/Message_sv.properties
  32. 1 1
      src/main/resources/password/pwm/i18n/Message_zh_TW.properties
  33. 9 3
      src/main/webapp/public/resources/js/admin.js

+ 13 - 15
src/main/java/password/pwm/PwmApplication.java

@@ -42,6 +42,7 @@ import password.pwm.svc.PwmService;
 import password.pwm.svc.PwmServiceManager;
 import password.pwm.svc.cache.CacheService;
 import password.pwm.svc.event.AuditEvent;
+import password.pwm.svc.event.AuditRecordFactory;
 import password.pwm.svc.event.AuditService;
 import password.pwm.svc.event.SystemAuditRecord;
 import password.pwm.svc.intruder.IntruderManager;
@@ -258,10 +259,9 @@ public class PwmApplication {
                 LOGGER.warn("configuration checksum does not match previously seen checksum, configuration has been modified since last startup");
                 if (this.getAuditManager() != null) {
                     final String modifyMessage = "configuration was modified directly (not using ConfigEditor UI)";
-                    this.getAuditManager().submit(SystemAuditRecord.create(
+                    this.getAuditManager().submit(new AuditRecordFactory(this).createSystemAuditRecord(
                             AuditEvent.MODIFY_CONFIGURATION,
-                            modifyMessage,
-                            this.getInstanceID()
+                            modifyMessage
                     ));
                 }
             }
@@ -283,15 +283,14 @@ public class PwmApplication {
         }
 
         // send system audit event
-        final SystemAuditRecord auditRecord = SystemAuditRecord.create(
-                AuditEvent.STARTUP,
-                null,
-                getInstanceID()
-        );
         try {
+            final SystemAuditRecord auditRecord = new AuditRecordFactory(this).createSystemAuditRecord(
+                    AuditEvent.STARTUP,
+                    null
+            );
             getAuditManager().submit(auditRecord);
         } catch (PwmException e) {
-            LOGGER.warn("unable to submit alert event " + JsonUtil.serialize(auditRecord));
+            LOGGER.warn("unable to submit start alert event " + e.getMessage());
         }
 
         try {
@@ -588,17 +587,16 @@ public class PwmApplication {
         LOGGER.warn("shutting down");
         {
             // send system audit event
-            final SystemAuditRecord auditRecord = SystemAuditRecord.create(
-                    AuditEvent.SHUTDOWN,
-                    null,
-                    getInstanceID()
-            );
             try {
+                final SystemAuditRecord auditRecord = new AuditRecordFactory(this).createSystemAuditRecord(
+                        AuditEvent.SHUTDOWN,
+                        null
+                );
                 if (getAuditManager() != null) {
                     getAuditManager().submit(auditRecord);
                 }
             } catch (PwmException e) {
-                LOGGER.warn("unable to submit alert event " + JsonUtil.serialize(auditRecord));
+                LOGGER.warn("unable to submit shutdown alert event " + e.getMessage());
             }
         }
 

+ 6 - 5
src/main/java/password/pwm/config/stored/ConfigurationReader.java

@@ -34,7 +34,8 @@ import password.pwm.error.PwmError;
 import password.pwm.error.PwmOperationalException;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.svc.event.AuditEvent;
-import password.pwm.svc.event.SystemAuditRecord;
+import password.pwm.svc.event.AuditRecord;
+import password.pwm.svc.event.AuditRecordFactory;
 import password.pwm.util.FileSystemUtility;
 import password.pwm.util.Helper;
 import password.pwm.util.JsonUtil;
@@ -210,11 +211,11 @@ public class ConfigurationReader {
                 if (sessionLabel != null && sessionLabel.getUserIdentity() != null) {
                     modifyMessage += " by " + sessionLabel.getUserIdentity().toDisplayString();
                 }
-                pwmApplication.getAuditManager().submit(SystemAuditRecord.create(
+                final AuditRecord auditRecord = new AuditRecordFactory(pwmApplication).createSystemAuditRecord(
                         AuditEvent.MODIFY_CONFIGURATION,
-                        modifyMessage,
-                        pwmApplication.getInstanceID()
-                ));
+                        modifyMessage
+                );
+                pwmApplication.getAuditManager().submit(auditRecord);
             }
 
             if (backupDirectory != null) {

+ 2 - 1
src/main/java/password/pwm/http/servlet/ActivateUserServlet.java

@@ -47,6 +47,7 @@ import password.pwm.ldap.auth.PwmAuthenticationSource;
 import password.pwm.ldap.auth.SessionAuthenticator;
 import password.pwm.svc.event.AuditEvent;
 import password.pwm.svc.event.AuditRecord;
+import password.pwm.svc.event.AuditRecordFactory;
 import password.pwm.svc.stats.Statistic;
 import password.pwm.svc.token.TokenPayload;
 import password.pwm.svc.token.TokenService;
@@ -251,7 +252,7 @@ public class ActivateUserServlet extends AbstractPwmServlet {
 
         if (!activateUserBean.isAgreementPassed()) {
             activateUserBean.setAgreementPassed(true);
-            AuditRecord auditRecord = pwmRequest.getPwmApplication().getAuditManager().createUserAuditRecord(
+            AuditRecord auditRecord = new AuditRecordFactory(pwmRequest).createUserAuditRecord(
                     AuditEvent.AGREEMENT_PASSED,
                     pwmRequest.getUserInfoIfLoggedIn(),
                     pwmRequest.getSessionLabel(),

+ 2 - 1
src/main/java/password/pwm/http/servlet/ChangePasswordServlet.java

@@ -51,6 +51,7 @@ import password.pwm.ldap.PasswordChangeProgressChecker;
 import password.pwm.ldap.auth.AuthenticationType;
 import password.pwm.svc.event.AuditEvent;
 import password.pwm.svc.event.AuditRecord;
+import password.pwm.svc.event.AuditRecordFactory;
 import password.pwm.svc.stats.Statistic;
 import password.pwm.util.JsonUtil;
 import password.pwm.util.PasswordData;
@@ -261,7 +262,7 @@ public class ChangePasswordServlet extends AbstractPwmServlet {
         LOGGER.debug(pwmRequest, "user accepted password change agreement");
         if (!cpb.isAgreementPassed()) {
             cpb.setAgreementPassed(true);
-            AuditRecord auditRecord = pwmRequest.getPwmApplication().getAuditManager().createUserAuditRecord(
+            AuditRecord auditRecord = new AuditRecordFactory(pwmRequest).createUserAuditRecord(
                     AuditEvent.AGREEMENT_PASSED,
                     pwmRequest.getUserInfoIfLoggedIn(),
                     pwmRequest.getSessionLabel(),

+ 2 - 1
src/main/java/password/pwm/http/servlet/SetupOtpServlet.java

@@ -42,6 +42,7 @@ import password.pwm.http.bean.SetupOtpBean;
 import password.pwm.ldap.auth.AuthenticationType;
 import password.pwm.svc.PwmService;
 import password.pwm.svc.event.AuditEvent;
+import password.pwm.svc.event.AuditRecordFactory;
 import password.pwm.svc.event.UserAuditRecord;
 import password.pwm.svc.stats.Statistic;
 import password.pwm.util.JsonUtil;
@@ -210,7 +211,7 @@ public class SetupOtpServlet extends AbstractPwmServlet {
                 otpBean.setWritten(true);
 
                 // mark the event log
-                final UserAuditRecord auditRecord = pwmApplication.getAuditManager().createUserAuditRecord(
+                final UserAuditRecord auditRecord = new AuditRecordFactory(pwmRequest).createUserAuditRecord(
                         AuditEvent.SET_OTP_SECRET,
                         pwmSession.getUserInfoBean(),
                         pwmSession

+ 2 - 1
src/main/java/password/pwm/http/servlet/SetupResponsesServlet.java

@@ -34,6 +34,7 @@ import com.novell.ldapchai.provider.ChaiProvider;
 import password.pwm.Permission;
 import password.pwm.PwmApplication;
 import password.pwm.PwmConstants;
+import password.pwm.svc.event.AuditRecordFactory;
 import password.pwm.util.Validator;
 import password.pwm.bean.ResponseInfoBean;
 import password.pwm.bean.UserInfoBean;
@@ -211,7 +212,7 @@ public class SetupResponsesServlet extends AbstractPwmServlet {
             pwmRequest.getPwmApplication().getSessionStateService().clearBean(pwmRequest, SetupResponsesBean.class);
 
             // mark the event log
-            final UserAuditRecord auditRecord = pwmApplication.getAuditManager().createUserAuditRecord(
+            final UserAuditRecord auditRecord = new AuditRecordFactory(pwmRequest).createUserAuditRecord(
                     AuditEvent.CLEAR_RESPONSES,
                     pwmSession.getUserInfoBean(),
                     pwmSession

+ 2 - 1
src/main/java/password/pwm/http/servlet/UpdateProfileServlet.java

@@ -44,6 +44,7 @@ import password.pwm.ldap.UserDataReader;
 import password.pwm.ldap.UserStatusReader;
 import password.pwm.svc.event.AuditEvent;
 import password.pwm.svc.event.AuditRecord;
+import password.pwm.svc.event.AuditRecordFactory;
 import password.pwm.svc.stats.Statistic;
 import password.pwm.svc.token.TokenPayload;
 import password.pwm.svc.token.TokenService;
@@ -298,7 +299,7 @@ public class UpdateProfileServlet extends AbstractPwmServlet {
 
         if (!updateProfileBean.isAgreementPassed()) {
             updateProfileBean.setAgreementPassed(true);
-            AuditRecord auditRecord = pwmRequest.getPwmApplication().getAuditManager().createUserAuditRecord(
+            AuditRecord auditRecord = new AuditRecordFactory(pwmRequest).createUserAuditRecord(
                     AuditEvent.AGREEMENT_PASSED,
                     pwmRequest.getUserInfoIfLoggedIn(),
                     pwmRequest.getSessionLabel(),

+ 12 - 11
src/main/java/password/pwm/http/servlet/helpdesk/HelpdeskServlet.java

@@ -47,6 +47,7 @@ import password.pwm.i18n.Display;
 import password.pwm.i18n.Message;
 import password.pwm.ldap.*;
 import password.pwm.svc.event.AuditEvent;
+import password.pwm.svc.event.AuditRecordFactory;
 import password.pwm.svc.event.HelpdeskAuditRecord;
 import password.pwm.svc.intruder.IntruderManager;
 import password.pwm.svc.stats.Statistic;
@@ -322,7 +323,7 @@ public class HelpdeskServlet extends AbstractPwmServlet {
 
             // mark the event log
             {
-                final HelpdeskAuditRecord auditRecord = pwmRequest.getPwmApplication().getAuditManager().createHelpdeskAuditRecord(
+                final HelpdeskAuditRecord auditRecord = new AuditRecordFactory(pwmRequest).createHelpdeskAuditRecord(
                         AuditEvent.HELPDESK_ACTION,
                         pwmSession.getUserInfoBean().getUserIdentity(),
                         action.getName(),
@@ -383,7 +384,7 @@ public class HelpdeskServlet extends AbstractPwmServlet {
 
         // mark the event log
         {
-            final HelpdeskAuditRecord auditRecord = pwmApplication.getAuditManager().createHelpdeskAuditRecord(
+            final HelpdeskAuditRecord auditRecord = new AuditRecordFactory(pwmRequest).createHelpdeskAuditRecord(
                     AuditEvent.HELPDESK_DELETE_USER,
                     pwmSession.getUserInfoBean().getUserIdentity(),
                     null,
@@ -415,7 +416,7 @@ public class HelpdeskServlet extends AbstractPwmServlet {
 
         final UserIdentity userIdentity = UserIdentity.fromKey(userKey, pwmRequest.getPwmApplication()).canonicalized(pwmRequest.getPwmApplication());
         processDetailRequest(pwmRequest, helpdeskProfile, userIdentity);
-        final HelpdeskAuditRecord auditRecord = pwmRequest.getPwmApplication().getAuditManager().createHelpdeskAuditRecord(
+        final HelpdeskAuditRecord auditRecord = new AuditRecordFactory(pwmRequest).createHelpdeskAuditRecord(
                 AuditEvent.HELPDESK_VIEW_DETAIL,
                 pwmRequest.getPwmSession().getUserInfoBean().getUserIdentity(),
                 null,
@@ -653,7 +654,7 @@ public class HelpdeskServlet extends AbstractPwmServlet {
             chaiUser.unlockPassword();
             {
                 // mark the event log
-                final HelpdeskAuditRecord auditRecord = pwmRequest.getPwmApplication().getAuditManager().createHelpdeskAuditRecord(
+                final HelpdeskAuditRecord auditRecord = new AuditRecordFactory(pwmRequest).createHelpdeskAuditRecord(
                         AuditEvent.HELPDESK_UNLOCK_PASSWORD,
                         pwmRequest.getPwmSession().getUserInfoBean().getUserIdentity(),
                         null,
@@ -724,7 +725,7 @@ public class HelpdeskServlet extends AbstractPwmServlet {
 
             if (passed) {
                 final PwmSession pwmSession = pwmRequest.getPwmSession();
-                final HelpdeskAuditRecord auditRecord = pwmRequest.getPwmApplication().getAuditManager().createHelpdeskAuditRecord(
+                final HelpdeskAuditRecord auditRecord = new AuditRecordFactory(pwmRequest).createHelpdeskAuditRecord(
                         AuditEvent.HELPDESK_VERIFY_OTP,
                         pwmSession.getUserInfoBean().getUserIdentity(),
                         null,
@@ -738,7 +739,7 @@ public class HelpdeskServlet extends AbstractPwmServlet {
                 verificationStateBean.addRecord(userIdentity, IdentityVerificationMethod.OTP);
             } else {
                 final PwmSession pwmSession = pwmRequest.getPwmSession();
-                final HelpdeskAuditRecord auditRecord = pwmRequest.getPwmApplication().getAuditManager().createHelpdeskAuditRecord(
+                final HelpdeskAuditRecord auditRecord = new AuditRecordFactory(pwmRequest).createHelpdeskAuditRecord(
                         AuditEvent.HELPDESK_VERIFY_OTP_INCORRECT,
                         pwmSession.getUserInfoBean().getUserIdentity(),
                         null,
@@ -908,7 +909,7 @@ public class HelpdeskServlet extends AbstractPwmServlet {
 
         if (passed) {
             final PwmSession pwmSession = pwmRequest.getPwmSession();
-            final HelpdeskAuditRecord auditRecord = pwmRequest.getPwmApplication().getAuditManager().createHelpdeskAuditRecord(
+            final HelpdeskAuditRecord auditRecord = new AuditRecordFactory(pwmRequest).createHelpdeskAuditRecord(
                     AuditEvent.HELPDESK_VERIFY_TOKEN,
                     pwmSession.getUserInfoBean().getUserIdentity(),
                     null,
@@ -920,7 +921,7 @@ public class HelpdeskServlet extends AbstractPwmServlet {
             verificationStateBean.addRecord(userIdentity, IdentityVerificationMethod.TOKEN);
         } else {
             final PwmSession pwmSession = pwmRequest.getPwmSession();
-            final HelpdeskAuditRecord auditRecord = pwmRequest.getPwmApplication().getAuditManager().createHelpdeskAuditRecord(
+            final HelpdeskAuditRecord auditRecord = new AuditRecordFactory(pwmRequest).createHelpdeskAuditRecord(
                     AuditEvent.HELPDESK_VERIFY_TOKEN_INCORRECT,
                     pwmSession.getUserInfoBean().getUserIdentity(),
                     null,
@@ -968,7 +969,7 @@ public class HelpdeskServlet extends AbstractPwmServlet {
             service.clearOTPUserConfiguration(pwmRequest.getPwmSession(), userIdentity);
             {
                 // mark the event log
-                final HelpdeskAuditRecord auditRecord = pwmRequest.getPwmApplication().getAuditManager().createHelpdeskAuditRecord(
+                final HelpdeskAuditRecord auditRecord = new AuditRecordFactory(pwmRequest).createHelpdeskAuditRecord(
                         AuditEvent.HELPDESK_CLEAR_OTP_SECRET,
                         pwmRequest.getPwmSession().getUserInfoBean().getUserIdentity(),
                         null,
@@ -1152,7 +1153,7 @@ public class HelpdeskServlet extends AbstractPwmServlet {
 
         if (passed) {
             final PwmSession pwmSession = pwmRequest.getPwmSession();
-            final HelpdeskAuditRecord auditRecord = pwmRequest.getPwmApplication().getAuditManager().createHelpdeskAuditRecord(
+            final HelpdeskAuditRecord auditRecord = new AuditRecordFactory(pwmRequest).createHelpdeskAuditRecord(
                     AuditEvent.HELPDESK_VERIFY_ATTRIBUTES,
                     pwmSession.getUserInfoBean().getUserIdentity(),
                     null,
@@ -1164,7 +1165,7 @@ public class HelpdeskServlet extends AbstractPwmServlet {
             verificationStateBean.addRecord(userIdentity, IdentityVerificationMethod.ATTRIBUTES);
         } else {
             final PwmSession pwmSession = pwmRequest.getPwmSession();
-            final HelpdeskAuditRecord auditRecord = pwmRequest.getPwmApplication().getAuditManager().createHelpdeskAuditRecord(
+            final HelpdeskAuditRecord auditRecord = new AuditRecordFactory(pwmRequest).createHelpdeskAuditRecord(
                     AuditEvent.HELPDESK_VERIFY_ATTRIBUTES_INCORRECT,
                     pwmSession.getUserInfoBean().getUserIdentity(),
                     null,

+ 38 - 0
src/main/java/password/pwm/i18n/Admin.java

@@ -27,6 +27,44 @@ public enum Admin implements PwmDisplayBundle {
 
     Notice_TrialRestrictConfig,
 
+    EventLog_Narrative_Startup,
+    EventLog_Narrative_Shutdown,
+    EventLog_Narrative_FatalEvent,
+    EventLog_Narrative_ModifyConfiguration,
+    EventLog_Narrative_IntruderAttempt,
+    EventLog_Narrative_IntruderLockout,
+
+    EventLog_Narrative_Authenticate,
+    EventLog_Narrative_AgreementPassed,
+    EventLog_Narrative_ChangePassword,
+    EventLog_Narrative_UnlockPassword,
+    EventLog_Narrative_RecoverPassword,
+    EventLog_Narrative_SetupResponses,
+    Eventlog_Narrative_SetupOtpSecret,
+    EventLog_Narrative_ActivateUser,
+    EventLog_Narrative_CreateUser,
+    EventLog_Narrative_UpdateProfile,
+    EventLog_Narrative_IntruderUserLock,
+    EventLog_Narrative_IntruderUserAttempt,
+    EventLog_Narrative_TokenIssued,
+    EventLog_Narrative_TokenClaimed,
+    EventLog_Narrative_ClearResponses,
+    EventLog_Narrative_HelpdeskSetPassword,
+    EventLog_Narrative_HelpdeskUnlockPassword,
+    EventLog_Narrative_HelpdeskClearResponses,
+    EventLog_Narrative_HelpdeskClearOtpSecret,
+    EventLog_Narrative_HelpdeskAction,
+    EventLog_Narrative_HelpdeskDeleteUser,
+    EventLog_Narrative_HelpdeskViewDetail,
+    EventLog_Narrative_HelpdeskVerifyOtp,
+    EventLog_Narrative_HelpdeskVerifyOtpIncorrect,
+    EventLog_Narrative_HelpdeskVerifyToken,
+    EventLog_Narrative_HelpdeskVerifyTokenIncorrect,
+    EventLog_Narrative_HelpdeskVerifyAttributes,
+    EventLog_Narrative_HelpdeskVerifyAttributesIncorrect,
+
+
+
     ;
 
     @Override

+ 2 - 1
src/main/java/password/pwm/i18n/Message.java

@@ -72,7 +72,8 @@ public enum Message implements PwmDisplayBundle {
     EventLog_ActivateUser(null),
     EventLog_CreateUser(null),
     EventLog_UpdateProfile(null),
-    EventLog_IntruderUser(null),
+    EventLog_IntruderUserLock(null),
+    EventLog_IntruderUserAttempt(null),
     EventLog_TokenIssued(null),
     EventLog_TokenClaimed(null),
     EventLog_ClearResponses(null),

+ 8 - 2
src/main/java/password/pwm/ldap/auth/LDAPAuthenticationRequest.java

@@ -42,6 +42,8 @@ import password.pwm.error.PwmOperationalException;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.ldap.LdapOperationsHelper;
 import password.pwm.svc.event.AuditEvent;
+import password.pwm.svc.event.AuditRecord;
+import password.pwm.svc.event.AuditRecordFactory;
 import password.pwm.svc.intruder.IntruderManager;
 import password.pwm.svc.intruder.RecordType;
 import password.pwm.svc.stats.Statistic;
@@ -51,6 +53,7 @@ import password.pwm.util.RandomPasswordGenerator;
 import password.pwm.util.TimeDuration;
 import password.pwm.util.logging.PwmLogLevel;
 import password.pwm.util.logging.PwmLogger;
+import password.pwm.util.macro.MacroMachine;
 import password.pwm.util.operations.PasswordUtility;
 
 import java.util.Collections;
@@ -256,13 +259,16 @@ class LDAPAuthenticationRequest implements AuthenticationRequest {
         debugMsg.append(", using proxy connection: ").append(useProxy);
         debugMsg.append(", returning bind dn: ").append(returnProvider == null ? "none" : returnProvider.getChaiConfiguration().getSetting(ChaiSetting.BIND_DN));
         log(PwmLogLevel.INFO, debugMsg);
-        pwmApplication.getAuditManager().submit(pwmApplication.getAuditManager().createUserAuditRecord(
+
+        final MacroMachine macroMachine = MacroMachine.forUser(pwmApplication, PwmConstants.DEFAULT_LOCALE, sessionLabel, userIdentity);
+        final AuditRecord auditRecord = new AuditRecordFactory(pwmApplication, macroMachine).createUserAuditRecord(
                 AuditEvent.AUTHENTICATE,
                 this.userIdentity,
                 makeAuditLogMessage(returnAuthType),
                 sessionLabel.getSrcAddress(),
                 sessionLabel.getSrcHostname()
-        ));
+        );
+        pwmApplication.getAuditManager().submit(auditRecord);
 
         return authenticationResult;
     }

+ 43 - 34
src/main/java/password/pwm/svc/event/AuditEvent.java

@@ -23,62 +23,67 @@
 package password.pwm.svc.event;
 
 import password.pwm.config.Configuration;
+import password.pwm.i18n.Admin;
 import password.pwm.i18n.Message;
+import password.pwm.i18n.PwmDisplayBundle;
 
 import java.util.Locale;
 
 public enum AuditEvent {
 
     // system events
-    STARTUP(Message.EventLog_Startup, Type.SYSTEM),
-    SHUTDOWN(Message.EventLog_Shutdown, Type.SYSTEM),
-    FATAL_EVENT(Message.EventLog_FatalEvent, Type.SYSTEM),
-    MODIFY_CONFIGURATION(Message.EventLog_ModifyConfiguration, Type.SYSTEM),
-    INTRUDER_LOCK(Message.EventLog_IntruderLockout, Type.SYSTEM),
-    INTRUDER_ATTEMPT(Message.EventLog_IntruderAttempt, Type.SYSTEM),
+    STARTUP(                        Message.EventLog_Startup,                           Admin.EventLog_Narrative_Startup,                          Type.SYSTEM),
+    SHUTDOWN(                       Message.EventLog_Shutdown,                          Admin.EventLog_Narrative_Shutdown,                         Type.SYSTEM),
+    FATAL_EVENT(                    Message.EventLog_FatalEvent,                        Admin.EventLog_Narrative_FatalEvent,                       Type.SYSTEM),
+    MODIFY_CONFIGURATION(           Message.EventLog_ModifyConfiguration,               Admin.EventLog_Narrative_ModifyConfiguration,              Type.SYSTEM),
+    INTRUDER_LOCK(                  Message.EventLog_IntruderLockout,                   Admin.EventLog_Narrative_IntruderLockout,                  Type.SYSTEM),
+    INTRUDER_ATTEMPT(               Message.EventLog_IntruderAttempt,                   Admin.EventLog_Narrative_IntruderAttempt,                  Type.SYSTEM),
 
     // user events not stored in user event history
-    AUTHENTICATE(Message.EventLog_Authenticate, Type.USER),
-    AGREEMENT_PASSED(Message.EventLog_AgreementPassed, Type.USER),
-    TOKEN_ISSUED(Message.EventLog_TokenIssued, Type.USER),
-    TOKEN_CLAIMED(Message.EventLog_TokenClaimed, Type.USER),
-    CLEAR_RESPONSES(Message.EventLog_ClearResponses, Type.USER),
+    AUTHENTICATE(                   Message.EventLog_Authenticate,                      Admin.EventLog_Narrative_Authenticate,                     Type.USER),
+    AGREEMENT_PASSED(               Message.EventLog_AgreementPassed,                   Admin.EventLog_Narrative_AgreementPassed,                  Type.USER),
+    TOKEN_ISSUED(                   Message.EventLog_TokenIssued,                       Admin.EventLog_Narrative_TokenIssued,                      Type.USER),
+    TOKEN_CLAIMED(                  Message.EventLog_TokenClaimed,                      Admin.EventLog_Narrative_TokenClaimed,                     Type.USER),
+    CLEAR_RESPONSES(                Message.EventLog_ClearResponses,                    Admin.EventLog_Narrative_ClearResponses,                   Type.USER),
 
     // user events stored in user event history
-    CHANGE_PASSWORD(Message.EventLog_ChangePassword, Type.USER),
-    UNLOCK_PASSWORD(Message.EventLog_UnlockPassword, Type.USER),
-    RECOVER_PASSWORD(Message.EventLog_RecoverPassword, Type.USER),
-    SET_RESPONSES(Message.EventLog_SetupResponses, Type.USER),
-    SET_OTP_SECRET(Message.Eventlog_SetupOtpSecret, Type.USER),
-    ACTIVATE_USER(Message.EventLog_ActivateUser, Type.USER),
-    CREATE_USER(Message.EventLog_CreateUser, Type.USER),
-    UPDATE_PROFILE(Message.EventLog_UpdateProfile, Type.USER),
-    INTRUDER_USER(Message.EventLog_IntruderUser, Type.USER),
+    CHANGE_PASSWORD(                Message.EventLog_ChangePassword,                    Admin.EventLog_Narrative_ChangePassword,                   Type.USER),
+    UNLOCK_PASSWORD(                Message.EventLog_UnlockPassword,                    Admin.EventLog_Narrative_UnlockPassword,                   Type.USER),
+    RECOVER_PASSWORD(               Message.EventLog_RecoverPassword,                   Admin.EventLog_Narrative_RecoverPassword,                  Type.USER),
+    SET_RESPONSES(                  Message.EventLog_SetupResponses,                    Admin.EventLog_Narrative_SetupResponses,                   Type.USER),
+    SET_OTP_SECRET(                 Message.Eventlog_SetupOtpSecret,                    Admin.Eventlog_Narrative_SetupOtpSecret,                   Type.USER),
+    ACTIVATE_USER(                  Message.EventLog_ActivateUser,                      Admin.EventLog_Narrative_ActivateUser,                     Type.USER),
+    CREATE_USER(                    Message.EventLog_CreateUser,                        Admin.EventLog_Narrative_CreateUser,                       Type.USER),
+    UPDATE_PROFILE(                 Message.EventLog_UpdateProfile,                     Admin.EventLog_Narrative_UpdateProfile,                    Type.USER),
+    INTRUDER_USER_LOCK(             Message.EventLog_IntruderUserLock,                  Admin.EventLog_Narrative_IntruderUserLock,                 Type.USER),
+    INTRUDER_USER_ATTEMPT(          Message.EventLog_IntruderUserAttempt,               Admin.EventLog_Narrative_IntruderUserAttempt,              Type.USER),
 
     // helpdesk events
-    HELPDESK_SET_PASSWORD(Message.EventLog_HelpdeskSetPassword, Type.HELPDESK),
-    HELPDESK_UNLOCK_PASSWORD(Message.EventLog_HelpdeskUnlockPassword, Type.HELPDESK),
-    HELPDESK_CLEAR_RESPONSES(Message.EventLog_HelpdeskClearResponses, Type.HELPDESK),
-    HELPDESK_CLEAR_OTP_SECRET(Message.EventLog_HelpdeskClearOtpSecret, Type.HELPDESK),
-    HELPDESK_ACTION(Message.EventLog_HelpdeskAction, Type.HELPDESK),
-    HELPDESK_DELETE_USER(Message.EventLog_HelpdeskDeleteUser, Type.HELPDESK),
-    HELPDESK_VIEW_DETAIL(Message.EventLog_HelpdeskViewDetail, Type.HELPDESK),
-    HELPDESK_VERIFY_OTP(Message.EventLog_HelpdeskVerifyOtp, Type.HELPDESK),
-    HELPDESK_VERIFY_OTP_INCORRECT(Message.EventLog_HelpdeskVerifyOtpIncorrect, Type.HELPDESK),
-    HELPDESK_VERIFY_TOKEN(Message.EventLog_HelpdeskVerifyToken, Type.HELPDESK),
-    HELPDESK_VERIFY_TOKEN_INCORRECT(Message.EventLog_HelpdeskVerifyTokenIncorrect, Type.HELPDESK),
-    HELPDESK_VERIFY_ATTRIBUTES(Message.EventLog_HelpdeskVerifyAttributes, Type.HELPDESK),
-    HELPDESK_VERIFY_ATTRIBUTES_INCORRECT(Message.EventLog_HelpdeskVerifyAttributesIncorrect, Type.HELPDESK),
+    HELPDESK_SET_PASSWORD(          Message.EventLog_HelpdeskSetPassword,               Admin.EventLog_Narrative_HelpdeskSetPassword,              Type.HELPDESK),
+    HELPDESK_UNLOCK_PASSWORD(       Message.EventLog_HelpdeskUnlockPassword,            Admin.EventLog_Narrative_HelpdeskUnlockPassword,           Type.HELPDESK),
+    HELPDESK_CLEAR_RESPONSES(       Message.EventLog_HelpdeskClearResponses,            Admin.EventLog_Narrative_HelpdeskClearResponses,           Type.HELPDESK),
+    HELPDESK_CLEAR_OTP_SECRET(      Message.EventLog_HelpdeskClearOtpSecret,            Admin.EventLog_Narrative_HelpdeskClearOtpSecret,           Type.HELPDESK),
+    HELPDESK_ACTION(                Message.EventLog_HelpdeskAction,                    Admin.EventLog_Narrative_HelpdeskAction,                   Type.HELPDESK),
+    HELPDESK_DELETE_USER(           Message.EventLog_HelpdeskDeleteUser,                Admin.EventLog_Narrative_HelpdeskDeleteUser,               Type.HELPDESK),
+    HELPDESK_VIEW_DETAIL(           Message.EventLog_HelpdeskViewDetail,                Admin.EventLog_Narrative_HelpdeskViewDetail,               Type.HELPDESK),
+    HELPDESK_VERIFY_OTP(            Message.EventLog_HelpdeskVerifyOtp,                 Admin.EventLog_Narrative_HelpdeskVerifyOtp,                Type.HELPDESK),
+    HELPDESK_VERIFY_OTP_INCORRECT(  Message.EventLog_HelpdeskVerifyOtpIncorrect,        Admin.EventLog_Narrative_HelpdeskVerifyOtpIncorrect,       Type.HELPDESK),
+    HELPDESK_VERIFY_TOKEN(          Message.EventLog_HelpdeskVerifyToken,               Admin.EventLog_Narrative_HelpdeskVerifyToken,              Type.HELPDESK),
+    HELPDESK_VERIFY_TOKEN_INCORRECT(Message.EventLog_HelpdeskVerifyTokenIncorrect,      Admin.EventLog_Narrative_HelpdeskVerifyTokenIncorrect,     Type.HELPDESK),
+    HELPDESK_VERIFY_ATTRIBUTES(          Message.EventLog_HelpdeskVerifyAttributes,          Admin.EventLog_Narrative_HelpdeskVerifyAttributes,         Type.HELPDESK),
+    HELPDESK_VERIFY_ATTRIBUTES_INCORRECT(Message.EventLog_HelpdeskVerifyAttributesIncorrect, Admin.EventLog_Narrative_HelpdeskVerifyAttributesIncorrect,Type.HELPDESK),
 
 
     ;
 
     final private Message message;
+    final private PwmDisplayBundle narrative;
     private Type type;
 
-    AuditEvent(final Message message, final Type type) {
+    AuditEvent(final Message message, final PwmDisplayBundle narrative, final Type type) {
         this.message = message;
         this.type = type;
+        this.narrative = narrative;
     }
 
     public Message getMessage() {
@@ -106,6 +111,10 @@ public enum AuditEvent {
         return Message.getLocalizedMessage(locale,this.getMessage(),config);
     }
 
+    public PwmDisplayBundle getNarrative() {
+        return narrative;
+    }
+
     public Type getType() {
         return type;
     }

+ 8 - 2
src/main/java/password/pwm/svc/event/AuditRecord.java

@@ -22,9 +22,10 @@
 
 package password.pwm.svc.event;
 
+import password.pwm.util.secure.PwmRandom;
+
 import java.io.Serializable;
 import java.util.Date;
-import java.util.UUID;
 
 public abstract class AuditRecord implements Serializable {
     protected AuditEvent.Type type;
@@ -32,6 +33,7 @@ public abstract class AuditRecord implements Serializable {
     protected String guid;
     protected Date timestamp = new Date();
     protected String message;
+    protected String narrative;
 
     protected AuditRecord(
             final Date timestamp,
@@ -43,7 +45,7 @@ public abstract class AuditRecord implements Serializable {
         this.message = message;
 
         this.timestamp = timestamp;
-        this.guid = UUID.randomUUID().toString();
+        this.guid = PwmRandom.getInstance().randomUUID().toString();
     }
 
 
@@ -70,4 +72,8 @@ public abstract class AuditRecord implements Serializable {
     public String getGuid() {
         return guid;
     }
+
+    public String getNarrative() {
+        return narrative;
+    }
 }

+ 179 - 0
src/main/java/password/pwm/svc/event/AuditRecordFactory.java

@@ -0,0 +1,179 @@
+package password.pwm.svc.event;
+
+import password.pwm.PwmApplication;
+import password.pwm.PwmConstants;
+import password.pwm.bean.SessionLabel;
+import password.pwm.bean.UserIdentity;
+import password.pwm.bean.UserInfoBean;
+import password.pwm.error.PwmUnrecoverableException;
+import password.pwm.http.PwmRequest;
+import password.pwm.http.PwmSession;
+import password.pwm.i18n.PwmDisplayBundle;
+import password.pwm.ldap.LdapOperationsHelper;
+import password.pwm.util.JsonUtil;
+import password.pwm.util.LocaleHelper;
+import password.pwm.util.logging.PwmLogger;
+import password.pwm.util.macro.MacroMachine;
+
+import java.util.Date;
+import java.util.Map;
+
+public class AuditRecordFactory {
+    private final static PwmLogger LOGGER = PwmLogger.forClass(AuditRecordFactory.class);
+
+    private final PwmApplication pwmApplication;
+    private final MacroMachine macroMachine;
+
+    public AuditRecordFactory(PwmApplication pwmApplication) throws PwmUnrecoverableException {
+        this.pwmApplication = pwmApplication;
+        this.macroMachine = MacroMachine.forNonUserSpecific(pwmApplication, null);
+    }
+
+    public AuditRecordFactory(final PwmApplication pwmApplication, final MacroMachine macroMachine) {
+        this.pwmApplication = pwmApplication;
+        this.macroMachine = macroMachine;
+    }
+
+    public AuditRecordFactory(final PwmApplication pwmApplication, final PwmSession pwmSession) throws PwmUnrecoverableException {
+        this.pwmApplication = pwmApplication;
+        this.macroMachine = pwmSession.getSessionManager().getMacroMachine(pwmApplication);
+    }
+    public AuditRecordFactory(final PwmRequest pwmRequest) throws PwmUnrecoverableException {
+        this.pwmApplication = pwmRequest.getPwmApplication();
+        this.macroMachine = pwmRequest.getPwmSession().getSessionManager().getMacroMachine(pwmApplication);
+    }
+
+    public HelpdeskAuditRecord createHelpdeskAuditRecord(
+            final AuditEvent eventCode,
+            final UserIdentity perpetrator,
+            final String message,
+            final UserIdentity target,
+            final String sourceAddress,
+            final String sourceHost
+    )
+    {
+        String perpUserDN = null, perpUserID = null, perpLdapProfile = null, targetUserDN = null, targetUserID = null, targetLdapProfile = null;
+        if (perpetrator != null) {
+            perpUserDN = perpetrator.getUserDN();
+            perpLdapProfile = perpetrator.getLdapProfileID();
+            try {
+                perpUserID = LdapOperationsHelper.readLdapUsernameValue(pwmApplication,perpetrator);
+            } catch (Exception e) {
+                LOGGER.error("unable to read userID for " + perpetrator + ", error: " + e.getMessage());
+            }
+        }
+        if (target != null) {
+            targetUserDN = target.getUserDN();
+            targetLdapProfile = target.getLdapProfileID();
+            try {
+                targetUserID = LdapOperationsHelper.readLdapUsernameValue(pwmApplication,target);
+            } catch (Exception e) {
+                LOGGER.error("unable to read userID for " + perpetrator + ", error: " + e.getMessage());
+            }
+        }
+
+        final HelpdeskAuditRecord record = new HelpdeskAuditRecord(new Date(), eventCode, perpUserID, perpUserDN, perpLdapProfile, message, targetUserID, targetUserDN,
+                targetLdapProfile, sourceAddress, sourceHost);
+        record.narrative = makeNarrativeString(record);
+        return record;
+    }
+
+    public UserAuditRecord createUserAuditRecord(
+            final AuditEvent eventCode,
+            final UserIdentity perpetrator,
+            final String message,
+            final String sourceAddress,
+            final String sourceHost
+    )
+    {
+        String perpUserDN = null, perpUserID = null, perpLdapProfile = null;
+        if (perpetrator != null) {
+            perpUserDN = perpetrator.getUserDN();
+            perpLdapProfile = perpetrator.getLdapProfileID();
+            try {
+                perpUserID = LdapOperationsHelper.readLdapUsernameValue(pwmApplication,perpetrator);
+            } catch (Exception e) {
+                LOGGER.error("unable to read userID for " + perpetrator + ", error: " + e.getMessage());
+            }
+        }
+
+        final UserAuditRecord record = new UserAuditRecord(new Date(), eventCode, perpUserID, perpUserDN, perpLdapProfile, message, sourceAddress, sourceHost);
+        record.narrative = this.makeNarrativeString(record);
+        return record;
+    }
+
+    public SystemAuditRecord createSystemAuditRecord(
+            final AuditEvent eventCode,
+            final String message
+    )
+    {
+        final SystemAuditRecord record = new SystemAuditRecord(eventCode, message, pwmApplication.getInstanceID());
+        record.narrative = this.makeNarrativeString(record);
+        return record;
+    }
+
+    public UserAuditRecord createUserAuditRecord(
+            final AuditEvent eventCode,
+            final UserIdentity perpetrator,
+            final SessionLabel sessionLabel
+    )
+    {
+        return createUserAuditRecord(
+                eventCode,
+                perpetrator,
+                sessionLabel,
+                null
+        );
+    }
+
+    public UserAuditRecord createUserAuditRecord(
+            final AuditEvent eventCode,
+            final UserIdentity perpetrator,
+            final SessionLabel sessionLabel,
+            final String message
+    )
+    {
+        return createUserAuditRecord(
+                eventCode,
+                perpetrator,
+                message,
+                sessionLabel != null ? sessionLabel.getSrcAddress() : null,
+                sessionLabel != null ? sessionLabel.getSrcHostname() : null
+        );
+    }
+
+    public UserAuditRecord createUserAuditRecord(
+            final AuditEvent eventCode,
+            final UserInfoBean userInfoBean,
+            final PwmSession pwmSession
+    )
+    {
+        return createUserAuditRecord(
+                eventCode,
+                userInfoBean.getUserIdentity(),
+                null,
+                pwmSession.getSessionStateBean().getSrcAddress(),
+                pwmSession.getSessionStateBean().getSrcHostname()
+        );
+    }
+
+
+    private String makeNarrativeString(AuditRecord auditRecord) {
+        final PwmDisplayBundle pwmDisplayBundle = auditRecord.getEventCode().getNarrative();
+
+        String outputString = LocaleHelper.getLocalizedMessage(PwmConstants.DEFAULT_LOCALE, pwmDisplayBundle, pwmApplication.getConfig());
+
+        if (macroMachine != null) {
+            outputString = macroMachine.expandMacros(outputString);
+        }
+
+        final Map<String,String> recordFields = JsonUtil.deserializeStringMap(JsonUtil.serialize(auditRecord));
+        for (final String key : recordFields.keySet()) {
+            final String value = recordFields.get(key);
+            final String parametrizedKey = "%" + key + "%";
+            outputString = outputString.replace(parametrizedKey, value);
+        }
+
+        return outputString;
+    }
+}

+ 2 - 113
src/main/java/password/pwm/svc/event/AuditService.java

@@ -29,7 +29,6 @@ import password.pwm.PwmApplicationMode;
 import password.pwm.PwmConstants;
 import password.pwm.bean.EmailItemBean;
 import password.pwm.bean.SessionLabel;
-import password.pwm.bean.UserIdentity;
 import password.pwm.bean.UserInfoBean;
 import password.pwm.config.Configuration;
 import password.pwm.config.PwmSetting;
@@ -40,7 +39,6 @@ import password.pwm.health.HealthRecord;
 import password.pwm.health.HealthStatus;
 import password.pwm.health.HealthTopic;
 import password.pwm.http.PwmSession;
-import password.pwm.ldap.LdapOperationsHelper;
 import password.pwm.svc.PwmService;
 import password.pwm.util.*;
 import password.pwm.util.localdb.LocalDB;
@@ -68,116 +66,6 @@ public class AuditService implements PwmService {
     public AuditService() {
     }
 
-    public HelpdeskAuditRecord createHelpdeskAuditRecord(
-            final AuditEvent eventCode,
-            final UserIdentity perpetrator,
-            final String message,
-            final UserIdentity target,
-            final String sourceAddress,
-            final String sourceHost
-    )
-    {
-        String perpUserDN = null, perpUserID = null, perpLdapProfile = null, targetUserDN = null, targetUserID = null, targetLdapProfile = null;
-        if (perpetrator != null) {
-            perpUserDN = perpetrator.getUserDN();
-            perpLdapProfile = perpetrator.getLdapProfileID();
-            try {
-                perpUserID = LdapOperationsHelper.readLdapUsernameValue(pwmApplication,perpetrator);
-            } catch (Exception e) {
-                LOGGER.error("unable to read userID for " + perpetrator + ", error: " + e.getMessage());
-            }
-        }
-        if (target != null) {
-            targetUserDN = target.getUserDN();
-            targetLdapProfile = target.getLdapProfileID();
-            try {
-                targetUserID = LdapOperationsHelper.readLdapUsernameValue(pwmApplication,target);
-            } catch (Exception e) {
-                LOGGER.error("unable to read userID for " + perpetrator + ", error: " + e.getMessage());
-            }
-        }
-
-        return HelpdeskAuditRecord.create(eventCode, perpUserID, perpUserDN, perpLdapProfile, message, targetUserID, targetUserDN,
-                targetLdapProfile, sourceAddress, sourceHost);
-    }
-
-    public UserAuditRecord createUserAuditRecord(
-            final AuditEvent eventCode,
-            final UserIdentity perpetrator,
-            final String message,
-            final String sourceAddress,
-            final String sourceHost
-    )
-    {
-        String perpUserDN = null, perpUserID = null, perpLdapProfile = null, targetUserDN = null, targetUserID = null, targetLdapProfile = null;
-        if (perpetrator != null) {
-            perpUserDN = perpetrator.getUserDN();
-            perpLdapProfile = perpetrator.getLdapProfileID();
-            try {
-                perpUserID = LdapOperationsHelper.readLdapUsernameValue(pwmApplication,perpetrator);
-            } catch (Exception e) {
-                LOGGER.error("unable to read userID for " + perpetrator + ", error: " + e.getMessage());
-            }
-        }
-
-        return HelpdeskAuditRecord.create(eventCode, perpUserID, perpUserDN, perpLdapProfile, message, targetUserID, targetUserDN,
-                targetLdapProfile, sourceAddress, sourceHost);
-    }
-
-    public SystemAuditRecord createSystemAuditRecord(
-            final AuditEvent eventCode,
-            final String message
-    )
-    {
-        return SystemAuditRecord.create(eventCode, message, pwmApplication.getInstanceID());
-    }
-
-    public UserAuditRecord createUserAuditRecord(
-            final AuditEvent eventCode,
-            final UserIdentity perpetrator,
-            final SessionLabel sessionLabel
-    )
-    {
-        return createUserAuditRecord(
-                eventCode,
-                perpetrator,
-                sessionLabel,
-                null
-        );
-    }
-
-    public UserAuditRecord createUserAuditRecord(
-            final AuditEvent eventCode,
-            final UserIdentity perpetrator,
-            final SessionLabel sessionLabel,
-            final String message
-    )
-    {
-        return createUserAuditRecord(
-                eventCode,
-                perpetrator,
-                message,
-                sessionLabel != null ? sessionLabel.getSrcAddress() : null,
-                sessionLabel != null ? sessionLabel.getSrcHostname() : null
-        );
-    }
-
-    public UserAuditRecord createUserAuditRecord(
-            final AuditEvent eventCode,
-            final UserInfoBean userInfoBean,
-            final PwmSession pwmSession
-    )
-    {
-        return createUserAuditRecord(
-                eventCode,
-                userInfoBean.getUserIdentity(),
-                null,
-                pwmSession.getSessionStateBean().getSrcAddress(),
-                pwmSession.getSessionStateBean().getSrcHostname()
-        );
-    }
-
-
     public STATUS status() {
         return status;
     }
@@ -368,7 +256,8 @@ public class AuditService implements PwmService {
     public void submit(final AuditEvent auditEvent, final UserInfoBean userInfoBean, final PwmSession pwmSession)
             throws PwmUnrecoverableException
     {
-        final UserAuditRecord auditRecord = createUserAuditRecord(auditEvent, userInfoBean, pwmSession);
+        final AuditRecordFactory auditRecordFactory = new AuditRecordFactory(pwmApplication, pwmSession.getSessionManager().getMacroMachine(pwmApplication));
+        final UserAuditRecord auditRecord = auditRecordFactory.createUserAuditRecord(auditEvent, userInfoBean, pwmSession);
         submit(auditRecord);
     }
 

+ 1 - 36
src/main/java/password/pwm/svc/event/HelpdeskAuditRecord.java

@@ -29,7 +29,7 @@ public class HelpdeskAuditRecord extends UserAuditRecord {
     protected String targetDN;
     protected String targetLdapProfile;
 
-    private HelpdeskAuditRecord(
+    HelpdeskAuditRecord(
             final Date timestamp,
             final AuditEvent eventCode,
             final String perpetratorID,
@@ -54,41 +54,6 @@ public class HelpdeskAuditRecord extends UserAuditRecord {
     }
 
 
-    static HelpdeskAuditRecord create(
-            final AuditEvent eventCode,
-            final String perpetratorID,
-            final String perpetratorDN,
-            final String perpetratorLdapProfile,
-            final String message,
-            final String targetID,
-            final String targetDN,
-            final String targetLdapProfile,
-            final String sourceAddress,
-            final String sourceHost
-    )
-    {
-        return new HelpdeskAuditRecord(new Date(), eventCode, perpetratorID, perpetratorDN, perpetratorLdapProfile, message, targetID, targetDN,
-                targetLdapProfile, sourceAddress, sourceHost);
-    }
-
-    static UserAuditRecord create(
-            final Date timestamp,
-            final AuditEvent eventCode,
-            final String perpetratorID,
-            final String perpetratorDN,
-            final String perpetratorLdapProfile,
-            final String message,
-            final String targetID,
-            final String targetDN,
-            final String targetLdapProfile,
-            final String sourceAddress,
-            final String sourceHost
-    )
-    {
-        return new HelpdeskAuditRecord(timestamp, eventCode, perpetratorID, perpetratorDN, perpetratorLdapProfile, message, targetID, targetDN,
-                targetLdapProfile, sourceAddress, sourceHost);
-    }
-
     public String getTargetID() {
         return targetID;
     }

+ 1 - 1
src/main/java/password/pwm/svc/event/LdapXmlUserHistory.java

@@ -309,7 +309,7 @@ class LdapXmlUserHistory implements UserHistoryStore, Serializable {
         }
 
         public UserAuditRecord asAuditRecord(final UserInfoBean userInfoBean) {
-            return UserAuditRecord.create(
+            return new UserAuditRecord(
                     new Date(this.getTimestamp()),
                     this.getAuditEvent(),
                     null,

+ 1 - 10
src/main/java/password/pwm/svc/event/SystemAuditRecord.java

@@ -28,7 +28,7 @@ public class SystemAuditRecord extends AuditRecord implements Serializable {
 
     protected String instance;
 
-    private SystemAuditRecord(
+    SystemAuditRecord(
             final AuditEvent eventCode,
             final String message,
             final String instance
@@ -37,15 +37,6 @@ public class SystemAuditRecord extends AuditRecord implements Serializable {
         this.instance = instance;
     }
 
-    public static SystemAuditRecord create(
-            final AuditEvent eventCode,
-            final String message,
-            final String instance
-    )
-    {
-        return new SystemAuditRecord(eventCode, message, instance);
-    }
-
     public String getInstance() {
         return instance;
     }

+ 0 - 26
src/main/java/password/pwm/svc/event/UserAuditRecord.java

@@ -53,32 +53,6 @@ public class UserAuditRecord extends AuditRecord implements Serializable {
         this.sourceHost = sourceHost;
     }
 
-    static UserAuditRecord create(
-            final AuditEvent eventCode,
-            final String perpetratorID,
-            final String perpetratorDN,
-            final String perpetratorLdapProfile,
-            final String message,
-            final String sourceAddress,
-            final String sourceHost
-    )
-    {
-        return new UserAuditRecord(new Date(), eventCode, perpetratorID, perpetratorDN, perpetratorLdapProfile, message, sourceAddress, sourceHost);
-    }
-
-    static UserAuditRecord create(
-            final Date timestamp,
-            final AuditEvent eventCode,
-            final String perpetratorID,
-            final String perpetratorDN,
-            final String perpetratorLdapProfile,
-            final String message,
-            final String sourceAddress,
-            final String sourceHost
-    )
-    {
-        return new UserAuditRecord(timestamp, eventCode, perpetratorID, perpetratorDN, perpetratorLdapProfile, message, sourceAddress, sourceHost);
-    }
 
     public String getPerpetratorID() {
         return perpetratorID;

+ 22 - 13
src/main/java/password/pwm/svc/intruder/IntruderManager.java

@@ -43,6 +43,7 @@ import password.pwm.ldap.LdapUserDataReader;
 import password.pwm.ldap.UserStatusReader;
 import password.pwm.svc.PwmService;
 import password.pwm.svc.event.AuditEvent;
+import password.pwm.svc.event.AuditRecordFactory;
 import password.pwm.svc.event.SystemAuditRecord;
 import password.pwm.svc.event.UserAuditRecord;
 import password.pwm.svc.stats.Statistic;
@@ -307,12 +308,21 @@ public class IntruderManager implements Serializable, PwmService {
         final RecordManager manager = recordManagers.get(recordType);
         manager.markSubject(subject);
 
-        { // send intruder attempt audit event
+        if (recordType == RecordType.USER_ID) {
+            final UserIdentity userIdentity = UserIdentity.fromKey(subject, pwmApplication);
+            final UserAuditRecord auditRecord = new AuditRecordFactory(pwmApplication).createUserAuditRecord(
+                    AuditEvent.INTRUDER_USER_ATTEMPT,
+                    userIdentity,
+                    sessionLabel
+            );
+            pwmApplication.getAuditManager().submit(auditRecord);
+            sendAlert(manager.readIntruderRecord(subject), sessionLabel);
+        } else { // send intruder attempt audit event
             final Map<String,Object> messageObj = new LinkedHashMap<>();
             messageObj.put("type", recordType);
             messageObj.put("subject", subject);
             final String message = JsonUtil.serializeMap(messageObj);
-            final SystemAuditRecord auditRecord = pwmApplication.getAuditManager().createSystemAuditRecord(AuditEvent.INTRUDER_ATTEMPT,message);
+            final SystemAuditRecord auditRecord = new AuditRecordFactory(pwmApplication).createSystemAuditRecord(AuditEvent.INTRUDER_ATTEMPT,message);
             pwmApplication.getAuditManager().submit(auditRecord);
         }
 
@@ -320,26 +330,25 @@ public class IntruderManager implements Serializable, PwmService {
             check(recordType, subject);
         } catch (PwmUnrecoverableException e) {
             if (!manager.isAlerted(subject) ) {
-                { // send intruder attempt lock event
-                    final Map<String,Object> messageObj = new LinkedHashMap<>();
-                    messageObj.put("type", recordType);
-                    messageObj.put("subject", subject);
-                    final String message = JsonUtil.serializeMap(messageObj);
-                    final SystemAuditRecord auditRecord = pwmApplication.getAuditManager().createSystemAuditRecord(AuditEvent.INTRUDER_LOCK,message);
-                    pwmApplication.getAuditManager().submit(auditRecord);
-                }
-
                 if (recordType == RecordType.USER_ID) {
                     final UserIdentity userIdentity = UserIdentity.fromKey(subject, pwmApplication);
-                    final UserAuditRecord auditRecord = pwmApplication.getAuditManager().createUserAuditRecord(
-                            AuditEvent.INTRUDER_USER,
+                    final UserAuditRecord auditRecord = new AuditRecordFactory(pwmApplication).createUserAuditRecord(
+                            AuditEvent.INTRUDER_USER_LOCK,
                             userIdentity,
                             sessionLabel
                     );
                     pwmApplication.getAuditManager().submit(auditRecord);
                     sendAlert(manager.readIntruderRecord(subject), sessionLabel);
+                } else {  // send intruder attempt lock event
+                    final Map<String,Object> messageObj = new LinkedHashMap<>();
+                    messageObj.put("type", recordType);
+                    messageObj.put("subject", subject);
+                    final String message = JsonUtil.serializeMap(messageObj);
+                    final SystemAuditRecord auditRecord = new AuditRecordFactory(pwmApplication).createSystemAuditRecord(AuditEvent.INTRUDER_LOCK,message);
+                    pwmApplication.getAuditManager().submit(auditRecord);
                 }
 
+
                 manager.markAlerted(subject);
                 final StatisticsManager statisticsManager = pwmApplication.getStatisticsManager();
                 if (statisticsManager != null && statisticsManager.status() == STATUS.OPEN) {

+ 9 - 6
src/main/java/password/pwm/svc/token/TokenService.java

@@ -41,6 +41,8 @@ import password.pwm.http.PwmSession;
 import password.pwm.ldap.auth.SessionAuthenticator;
 import password.pwm.svc.PwmService;
 import password.pwm.svc.event.AuditEvent;
+import password.pwm.svc.event.AuditRecord;
+import password.pwm.svc.event.AuditRecordFactory;
 import password.pwm.svc.intruder.RecordType;
 import password.pwm.svc.stats.Statistic;
 import password.pwm.svc.stats.StatisticsManager;
@@ -209,13 +211,13 @@ public class TokenService implements PwmService {
 
         LOGGER.trace(sessionLabel, "generated token type=" + tokenPayload.getName());
 
-        pwmApplication.getAuditManager().submit(pwmApplication.getAuditManager().createUserAuditRecord(
+        final AuditRecord auditRecord = new AuditRecordFactory(pwmApplication).createUserAuditRecord(
                 AuditEvent.TOKEN_ISSUED,
                 tokenPayload.getUserIdentity(),
                 sessionLabel,
                 JsonUtil.serialize(tokenPayload)
-        ));
-
+        );
+        pwmApplication.getAuditManager().submit(auditRecord);
         return tokenKey;
     }
 
@@ -232,13 +234,14 @@ public class TokenService implements PwmService {
         if (tokenPayload == null || tokenPayload.getUserIdentity() == null) {
             return;
         }
-
-        pwmApplication.getAuditManager().submit(pwmApplication.getAuditManager().createUserAuditRecord(
+        final AuditRecord auditRecord = new AuditRecordFactory(pwmApplication).createUserAuditRecord(
                 AuditEvent.TOKEN_CLAIMED,
                 tokenPayload.getUserIdentity(),
                 pwmSession.getLabel(),
                 JsonUtil.serialize(tokenPayload)
-        ));
+        );
+        pwmApplication.getAuditManager().submit(auditRecord);
+
 
         StatisticsManager.incrementStat(pwmApplication, Statistic.TOKENS_PASSSED);
     }

+ 7 - 6
src/main/java/password/pwm/util/logging/PwmLogger.java

@@ -25,14 +25,15 @@ package password.pwm.util.logging;
 import org.apache.log4j.RollingFileAppender;
 import password.pwm.PwmApplication;
 import password.pwm.PwmConstants;
+import password.pwm.bean.LoginInfoBean;
 import password.pwm.bean.SessionLabel;
 import password.pwm.error.ErrorInformation;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.http.PwmRequest;
 import password.pwm.http.PwmSession;
-import password.pwm.bean.LoginInfoBean;
 import password.pwm.svc.event.AuditEvent;
-import password.pwm.svc.event.SystemAuditRecord;
+import password.pwm.svc.event.AuditRecord;
+import password.pwm.svc.event.AuditRecordFactory;
 import password.pwm.util.JsonUtil;
 
 import java.io.IOException;
@@ -164,11 +165,11 @@ public class PwmLogger {
                     messageInfo.put("errorMessage",logEvent.getMessage());
 
                     final String messageInfoStr = JsonUtil.serializeMap(messageInfo);
-                    pwmApplication.getAuditManager().submit(SystemAuditRecord.create(
+                    final AuditRecord auditRecord = new AuditRecordFactory(pwmApplication).createSystemAuditRecord(
                             AuditEvent.FATAL_EVENT,
-                            messageInfoStr,
-                            pwmApplication.getInstanceID()
-                    ));
+                            messageInfoStr
+                    );
+                    pwmApplication.getAuditManager().submit(auditRecord);
                 }
             }
         } catch (Exception e2) {

+ 3 - 2
src/main/java/password/pwm/util/operations/PasswordUtility.java

@@ -54,6 +54,7 @@ import password.pwm.svc.cache.CacheKey;
 import password.pwm.svc.cache.CachePolicy;
 import password.pwm.svc.cache.CacheService;
 import password.pwm.svc.event.AuditEvent;
+import password.pwm.svc.event.AuditRecordFactory;
 import password.pwm.svc.event.HelpdeskAuditRecord;
 import password.pwm.svc.stats.Statistic;
 import password.pwm.util.*;
@@ -429,7 +430,7 @@ public class PasswordUtility {
 
         // mark the event log
         {
-            final HelpdeskAuditRecord auditRecord = pwmApplication.getAuditManager().createHelpdeskAuditRecord(
+            final HelpdeskAuditRecord auditRecord = new AuditRecordFactory(pwmApplication, pwmSession).createHelpdeskAuditRecord(
                     AuditEvent.HELPDESK_SET_PASSWORD,
                     pwmSession.getUserInfoBean().getUserIdentity(),
                     null,
@@ -482,7 +483,7 @@ public class PasswordUtility {
             pwmApplication.getCrService().clearResponses(pwmSession, proxiedUser, userGUID);
 
             // mark the event log
-            final HelpdeskAuditRecord auditRecord = pwmApplication.getAuditManager().createHelpdeskAuditRecord(
+            final HelpdeskAuditRecord auditRecord = new AuditRecordFactory(pwmApplication, pwmSession).createHelpdeskAuditRecord(
                     AuditEvent.HELPDESK_CLEAR_RESPONSES,
                     pwmSession.getUserInfoBean().getUserIdentity(),
                     null,

+ 3 - 2
src/main/java/password/pwm/ws/server/rest/RestChallengesServer.java

@@ -39,6 +39,7 @@ import password.pwm.error.*;
 import password.pwm.i18n.Message;
 import password.pwm.ldap.LdapOperationsHelper;
 import password.pwm.svc.event.AuditEvent;
+import password.pwm.svc.event.AuditRecordFactory;
 import password.pwm.svc.event.HelpdeskAuditRecord;
 import password.pwm.svc.event.UserAuditRecord;
 import password.pwm.svc.stats.Statistic;
@@ -333,7 +334,7 @@ public class RestChallengesServer extends AbstractRestServer {
                 userGUID = restRequestBean.getPwmSession().getUserInfoBean().getUserGuid();
 
                 // mark the event log
-                final UserAuditRecord auditRecord = restRequestBean.getPwmApplication().getAuditManager().createUserAuditRecord(
+                final UserAuditRecord auditRecord = new AuditRecordFactory(restRequestBean.getPwmApplication(), restRequestBean.getPwmSession()).createUserAuditRecord(
                         AuditEvent.CLEAR_RESPONSES,
                         restRequestBean.getPwmSession().getUserInfoBean(),
                         restRequestBean.getPwmSession()
@@ -352,7 +353,7 @@ public class RestChallengesServer extends AbstractRestServer {
                         false);
 
                 // mark the event log
-                final HelpdeskAuditRecord auditRecord = restRequestBean.getPwmApplication().getAuditManager().createHelpdeskAuditRecord(
+                final HelpdeskAuditRecord auditRecord = new AuditRecordFactory(restRequestBean.getPwmApplication(), restRequestBean.getPwmSession()).createHelpdeskAuditRecord(
                         AuditEvent.HELPDESK_CLEAR_RESPONSES,
                         restRequestBean.getPwmSession().getUserInfoBean().getUserIdentity(),
                         null,

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

@@ -146,7 +146,7 @@ ldap.password.change.self.enable=true
 ldap.password.change.helpdesk.enable=true
 ldap.guid.pattern=@UUID@
 ldap.browser.maxEntries=1000
-ldap.search.paging.enable=auto
+ldap.search.paging.enable=false
 ldap.search.paging.size=500
 localdb.aggressiveCompact.enabled=false
 localdb.compression.enabled=true

+ 8 - 6
src/main/resources/password/pwm/config/PwmSetting.xml

@@ -1443,8 +1443,8 @@
             <option value="SHUTDOWN">Shutdown</option>
             <option value="FATAL_EVENT">Fatal Event</option>
             <option value="MODIFY_CONFIGURATION">Modify Configuration</option>
-            <option value="INTRUDER_ATTEMPT">Intruder Attempt</option>
-            <option value="INTRUDER_LOCK">Intruder Lock</option>
+            <option value="INTRUDER_ATTEMPT">Non-User Intruder Attempt</option>
+            <option value="INTRUDER_LOCK">Non-User Intruder Lock</option>
         </options>
     </setting>
     <setting hidden="false" key="audit.userEvent.toAddress" level="1">
@@ -1463,7 +1463,7 @@
             <value>ACTIVATE_USER</value>
             <value>CREATE_USER</value>
             <value>UPDATE_PROFILE</value>
-            <value>INTRUDER_USER</value>
+            <value>INTRUDER_USER_LOCK</value>
             <value>TOKEN_ISSUED</value>
             <value>TOKEN_CLAIMED</value>
             <value>CLEAR_RESPONSES</value>
@@ -1492,7 +1492,8 @@
             <option value="ACTIVATE_USER">Activate User</option>
             <option value="CREATE_USER">New User</option>
             <option value="UPDATE_PROFILE">Update Profile</option>
-            <option value="INTRUDER_USER">Intruder Lock User</option>
+            <option value="INTRUDER_USER_LOCK">Intruder User Lock</option>
+            <option value="INTRUDER_USER_ATTEMPT">Intruder User Attempt</option>
             <option value="TOKEN_ISSUED">Token Issued</option>
             <option value="TOKEN_CLAIMED">Token Claimed</option>
             <option value="CLEAR_RESPONSES">Clear Responses</option>
@@ -1748,7 +1749,7 @@
             <value>ACTIVATE_USER</value>
             <value>CREATE_USER</value>
             <value>UPDATE_PROFILE</value>
-            <value>INTRUDER_USER</value>
+            <value>INTRUDER_USER_LOCK</value>
             <value>CLEAR_RESPONSES</value>
             <value>HELPDESK_SET_PASSWORD</value>
             <value>HELPDESK_UNLOCK_PASSWORD</value>
@@ -1768,7 +1769,8 @@
             <option value="ACTIVATE_USER">Activate User</option>
             <option value="CREATE_USER">New User</option>
             <option value="UPDATE_PROFILE">Update Profile</option>
-            <option value="INTRUDER_USER">Intruder Lock User</option>
+            <option value="INTRUDER_USER_LOCK">Intruder User Lock</option>
+            <option value="INTRUDER_USER_ATTEMPT">Intruder User Attempt</option>
             <option value="TOKEN_ISSUED">Token Issued</option>
             <option value="TOKEN_CLAIMED">Token Claimed</option>
             <option value="CLEAR_RESPONSES">Clear Responses</option>

+ 36 - 1
src/main/resources/password/pwm/i18n/Admin.properties

@@ -112,6 +112,7 @@ Field_Audit_SourceAddress=Source Address
 Field_Audit_SourceHost=Source Host
 Field_Audit_Instance=Instance
 Field_Audit_GUID=Record GUID
+Field_Audit_Narrative=Narrative
 Field_CurrentTime=Current Time
 Field_InstallTime=Install Time
 Field_StartTime=Start Time
@@ -306,4 +307,38 @@ Field_CurrentPubVersion=Current Published Version
 Field_UpTime=Up Time
 Field_SiteURL=Site URL
 Field_InstanceID=Instance ID
-Field_ChaiAPIVersion=Chai API Version
+Field_ChaiAPIVersion=Chai API Version
+EventLog_Narrative_Startup=@PwmAppName@ has started up
+EventLog_Narrative_Shutdown=@PwmAppName@ has been shutdown
+EventLog_Narrative_FatalEvent=A fatal event has occurred; data: %message%
+EventLog_Narrative_ModifyConfiguration=%perpetratorID% (%perpetratorDN%) has modified the configuration
+EventLog_Narrative_IntruderAttempt=Non user-specific intruder attempt (Details: %message%)
+EventLog_Narrative_IntruderLockout=Non user-specific intruder lockout (Details: %message%)
+EventLog_Narrative_ActivateUser=%perpetratorID% (%perpetratorDN%) has activated their account
+EventLog_Narrative_Authenticate=%perpetratorID% (%perpetratorDN%) has authenticated
+EventLog_Narrative_AgreementPassed=%perpetratorID% (%perpetratorDN%) has agreed to agreement text
+EventLog_Narrative_ChangePassword=%perpetratorID% (%perpetratorDN%) has changed their password
+EventLog_Narrative_UnlockPassword=%perpetratorID% (%perpetratorDN%) has unlocked their password
+EventLog_Narrative_CreateUser=%perpetratorID% (%targetDN%) has completed self registration
+EventLog_Narrative_HelpdeskAction=%targetID% (%targetDN%) had an action invoked by help desk operator %perpetratorID% (%perpetratorDN%), details: %message%
+EventLog_Narrative_HelpdeskClearResponses=Stored responses for %targetID% (%targetDN%) cleared by help desk operator %perpetratorID% (%perpetratorDN%)
+EventLog_Narrative_HelpdeskClearOtpSecret=OTP secret for %targetID% (%targetDN%) cleared by help desk operator %perpetratorID% (%perpetratorDN%)
+EventLog_Narrative_HelpdeskSetPassword=Password for %targetID% (%targetDN%) set by help desk operator %perpetratorID% (%perpetratorDN%)
+EventLog_Narrative_HelpdeskUnlockPassword=password has be unlocked for %targetID% (%targetDN%) by help desk operator %perpetratorID% (%perpetratorDN%)
+EventLog_Narrative_HelpdeskDeleteUser=%targetID% (%targetDN%) has been deleted by help desk operator %perpetratorID% (%perpetratorDN%)
+EventLog_Narrative_HelpdeskViewDetail=Details of %targetID% (%targetDN%) have been viewed by help desk operator %perpetratorID% (%perpetratorDN%)
+EventLog_Narrative_HelpdeskVerifyOtp=OTP secret for %targetID% (%targetDN%) verified by help desk operator %perpetratorID% (%perpetratorDN%)
+EventLog_Narrative_HelpdeskVerifyOtpIncorrect=OTP secret verification for %targetID% (%targetDN%) failure by help desk operator %perpetratorID% (%perpetratorDN%)
+EventLog_Narrative_HelpdeskVerifyToken=Token verified for %targetID% (%targetDN%) by help desk operator %perpetratorID% (%perpetratorDN%)
+EventLog_Narrative_HelpdeskVerifyTokenIncorrect=Incorrect token verification %targetID% (%targetDN%) by help desk operator %perpetratorID% (%perpetratorDN%)
+EventLog_Narrative_HelpdeskVerifyAttributes=Attributes for %targetID% (%targetDN%) verified by help desk operator %perpetratorID% (%perpetratorDN%)
+EventLog_Narrative_HelpdeskVerifyAttributesIncorrect=Attributes for %targetID% (%targetDN%) verified incorrect by help desk operator %perpetratorID% (%perpetratorDN%)
+EventLog_Narrative_IntruderUserLock=%perpetratorID% (%perpetratorDN%) account has been intruder locked
+EventLog_Narrative_IntruderUserAttempt=%perpetratorID% (%perpetratorDN%) account has had an invalid login attempt (intruder attempt)
+EventLog_Narrative_TokenIssued=A token has been issued
+EventLog_Narrative_TokenClaimed=A token has been claimed
+EventLog_Narrative_ClearResponses=%perpetratorID% (%perpetratorDN%) has cleared their own stored responses
+EventLog_Narrative_RecoverPassword=%perpetratorID% (%perpetratorDN%) has verified their identity via forgotten password
+EventLog_Narrative_SetupResponses=%perpetratorID% (%perpetratorDN%) has saved their own stored responses
+Eventlog_Narrative_SetupOtpSecret=%perpetratorID% (%perpetratorDN%) has completed an OTP enrollment
+EventLog_Narrative_UpdateProfile=%perpetratorID% (%perpetratorDN%) has updated their profile data

+ 2 - 1
src/main/resources/password/pwm/i18n/Message.properties

@@ -45,7 +45,8 @@ EventLog_HelpdeskVerifyToken=Helpdesk Verify Token
 EventLog_HelpdeskVerifyTokenIncorrect=Helpdesk Incorrect Token Verify
 EventLog_HelpdeskVerifyAttributes=Helpdesk Verify Attributes
 EventLog_HelpdeskVerifyAttributesIncorrect=Helpdesk Incorrect Attributes Verify
-EventLog_IntruderUser=Intruder User Lockout
+EventLog_IntruderUserAttempt=Intruder User Attempt
+EventLog_IntruderUserLock=Intruder User Lockout
 EventLog_TokenIssued=Token Issued
 EventLog_TokenClaimed=Token Claimed
 EventLog_ClearResponses=Clear Responses

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

@@ -40,7 +40,7 @@ EventLog_HelpdeskUnlockPassword=Desbloquear contrase\u00f1a con el Servicio de a
 EventLog_HelpdeskDeleteUser=Suprimir usuario de servicio de ayuda t\u00e9cnica
 EventLog_HelpdeskViewDetail=Detalle de la vista de la l\u00ednea de asistencia
 EventLog_HelpdeskVerifyOtp=Verificar contrase\u00f1a para una vez con el servicio de ayuda t\u00e9cnica
-EventLog_IntruderUser=Bloqueo de usuario intruso
+EventLog_IntruderUserLock=Bloqueo de usuario intruso
 EventLog_TokenIssued=Se emiti\u00f3 un testigo
 EventLog_TokenClaimed=Se reclam\u00f3 un testigo
 EventLog_ClearResponses=Borrar respuestas

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

@@ -40,7 +40,7 @@ EventLog_HelpdeskUnlockPassword=Desbloquear Senha do Suporte T\u00e9cnico
 EventLog_HelpdeskDeleteUser=Apagar Usu\u00e1rio do Suporte T\u00e9cnico
 EventLog_HelpdeskViewDetail=Detalhe de Exibi\u00e7\u00e3o da Central de Atendimento
 EventLog_HelpdeskVerifyOtp=OTP de Verifica\u00e7\u00e3o da Central de Atendimento
-EventLog_IntruderUser=Bloqueio de Usu\u00e1rio Intruso
+EventLog_IntruderUserLock=Bloqueio de Usu\u00e1rio Intruso
 EventLog_TokenIssued=Token Emitido
 EventLog_TokenClaimed=Token Requerido
 EventLog_ClearResponses=Limpar Respostas

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

@@ -40,7 +40,7 @@ EventLog_HelpdeskUnlockPassword=Supportavdelningen l\u00e5ser upp l\u00f6senord
 EventLog_HelpdeskDeleteUser=Supportavdelningen tar bort anv\u00e4ndare
 EventLog_HelpdeskViewDetail=Supportavdelningen visar information
 EventLog_HelpdeskVerifyOtp=Supportavdelningen verifierar eng\u00e5ngsl\u00f6senord
-EventLog_IntruderUser=Utest\u00e4ngning av st\u00f6rande anv\u00e4ndare
+EventLog_IntruderUserLock=Utest\u00e4ngning av st\u00f6rande anv\u00e4ndare
 EventLog_TokenIssued=Token utf\u00e4rdad
 EventLog_TokenClaimed=Token inl\u00f6st
 EventLog_ClearResponses=Rensa svar

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

@@ -40,7 +40,7 @@ EventLog_HelpdeskUnlockPassword=\u670d\u52d9\u53f0\u89e3\u9664\u9396\u5b9a\u5bc6
 EventLog_HelpdeskDeleteUser=\u670d\u52d9\u53f0\u522a\u9664\u4f7f\u7528\u8005
 EventLog_HelpdeskViewDetail=\u670d\u52d9\u53f0\u6aa2\u8996\u8a73\u7d30\u8cc7\u6599
 EventLog_HelpdeskVerifyOtp=\u670d\u52d9\u53f0\u9a57\u8b49 OTP
-EventLog_IntruderUser=\u4fb5\u5165\u8005\u4f7f\u7528\u8005\u9396\u5b9a
+EventLog_IntruderUserLock=\u4fb5\u5165\u8005\u4f7f\u7528\u8005\u9396\u5b9a
 EventLog_TokenIssued=\u5df2\u7c3d\u767c\u8a18\u865f
 EventLog_TokenClaimed=\u5df2\u8981\u6c42\u8a18\u865f
 EventLog_ClearResponses=\u6e05\u9664\u56de\u61c9

+ 9 - 3
src/main/webapp/public/resources/js/admin.js

@@ -404,7 +404,8 @@ PWM_ADMIN.auditUserHeaders = function() {
         "message": PWM_ADMIN.showString('Field_Audit_Message'),
         "sourceAddress": PWM_ADMIN.showString('Field_Audit_SourceAddress'),
         "sourceHost": PWM_ADMIN.showString('Field_Audit_SourceHost'),
-        "guid": PWM_ADMIN.showString('Field_Audit_GUID')
+        "guid": PWM_ADMIN.showString('Field_Audit_GUID'),
+        "narrative": PWM_ADMIN.showString('Field_Audit_Narrative')   
     };
 };
 
@@ -421,7 +422,8 @@ PWM_ADMIN.auditHelpdeskHeaders = function() {
         "targetLdapProfile": PWM_ADMIN.showString('Field_Audit_TargetLdapProfile'),
         "sourceAddress": PWM_ADMIN.showString('Field_Audit_SourceAddress'),
         "sourceHost": PWM_ADMIN.showString('Field_Audit_SourceHost'),
-        "guid": PWM_ADMIN.showString('Field_Audit_GUID')
+        "guid": PWM_ADMIN.showString('Field_Audit_GUID'),
+        "narrative": PWM_ADMIN.showString('Field_Audit_Narrative')
     };
 };
 
@@ -431,7 +433,8 @@ PWM_ADMIN.auditSystemHeaders = function() {
         "eventCode":PWM_ADMIN.showString('Field_Audit_EventCode'),
         "message":PWM_ADMIN.showString('Field_Audit_Message'),
         "instance":PWM_ADMIN.showString('Field_Audit_Instance'),
-        "guid":PWM_ADMIN.showString('Field_Audit_GUID')
+        "guid":PWM_ADMIN.showString('Field_Audit_GUID'),
+        "narrative":PWM_ADMIN.showString('Field_Audit_Narrative')
     };
 };
 
@@ -452,6 +455,7 @@ PWM_ADMIN.initAuditGrid=function() {
             PWM_MAIN.getObject('auditUserGrid-hider-menu-check-message').click();
             PWM_MAIN.getObject('auditUserGrid-hider-menu-check-sourceHost').click();
             PWM_MAIN.getObject('auditUserGrid-hider-menu-check-guid').click();
+            PWM_MAIN.getObject('auditUserGrid-hider-menu-check-narrative').click();
 
             PWM_MAIN.getObject('auditHelpdeskGrid-hider-menu-check-perpetratorDN').click();
             PWM_MAIN.getObject('auditHelpdeskGrid-hider-menu-check-perpetratorLdapProfile').click();
@@ -460,9 +464,11 @@ PWM_ADMIN.initAuditGrid=function() {
             PWM_MAIN.getObject('auditHelpdeskGrid-hider-menu-check-targetLdapProfile').click();
             PWM_MAIN.getObject('auditHelpdeskGrid-hider-menu-check-sourceHost').click();
             PWM_MAIN.getObject('auditHelpdeskGrid-hider-menu-check-guid').click();
+            PWM_MAIN.getObject('auditHelpdeskGrid-hider-menu-check-narrative').click();
 
             PWM_MAIN.getObject('auditSystemGrid-hider-menu-check-instance').click();
             PWM_MAIN.getObject('auditSystemGrid-hider-menu-check-guid').click();
+            PWM_MAIN.getObject('auditSystemGrid-hider-menu-check-narrative').click();
             PWM_ADMIN.refreshAuditGridData();
 
             PWM_VAR['auditUserGrid'].on(".dgrid-row:click", function(evt){