Bläddra i källkod

Merge pull request #233 from pwm-project/syslog-updates

Added the ability to have multiple syslog servers to handle the fail …
Jason 7 år sedan
förälder
incheckning
4990a19a02

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

@@ -656,7 +656,7 @@ public enum PwmSetting {
     AUDIT_EMAIL_USER_TO(
     AUDIT_EMAIL_USER_TO(
             "audit.userEvent.toAddress", PwmSettingSyntax.STRING_ARRAY, PwmSettingCategory.AUDIT_FORWARD),
             "audit.userEvent.toAddress", PwmSettingSyntax.STRING_ARRAY, PwmSettingCategory.AUDIT_FORWARD),
     AUDIT_SYSLOG_SERVERS(
     AUDIT_SYSLOG_SERVERS(
-            "audit.syslog.servers", PwmSettingSyntax.STRING, PwmSettingCategory.AUDIT_FORWARD),
+            "audit.syslog.servers", PwmSettingSyntax.STRING_ARRAY, PwmSettingCategory.AUDIT_FORWARD),
     AUDIT_SYSLOG_CERTIFICATES(
     AUDIT_SYSLOG_CERTIFICATES(
             "audit.syslog.certificates", PwmSettingSyntax.X509CERT, PwmSettingCategory.AUDIT_FORWARD),
             "audit.syslog.certificates", PwmSettingSyntax.X509CERT, PwmSettingCategory.AUDIT_FORWARD),
 
 

+ 29 - 18
server/src/main/java/password/pwm/config/function/SyslogCertImportFunction.java

@@ -54,33 +54,44 @@ public class SyslogCertImportFunction implements SettingUIFunction {
             final String profile,
             final String profile,
             final String extraData)
             final String extraData)
             throws PwmOperationalException, PwmUnrecoverableException {
             throws PwmOperationalException, PwmUnrecoverableException {
+        boolean error = false;
+        Exception exeception = null;
         final PwmApplication pwmApplication = pwmRequest.getPwmApplication();
         final PwmApplication pwmApplication = pwmRequest.getPwmApplication();
         final PwmSession pwmSession = pwmRequest.getPwmSession();
         final PwmSession pwmSession = pwmRequest.getPwmSession();
 
 
         final Set<X509Certificate> resultCertificates = new LinkedHashSet<>();
         final Set<X509Certificate> resultCertificates = new LinkedHashSet<>();
 
 
-        final String syslogConfigStr = (String)storedConfiguration.readSetting(PwmSetting.AUDIT_SYSLOG_SERVERS).toNativeObject();
-        if (syslogConfigStr != null && !syslogConfigStr.isEmpty()) {
-            final SyslogAuditService.SyslogConfig syslogConfig = SyslogAuditService.SyslogConfig.fromConfigString(syslogConfigStr);
-            if (syslogConfig != null) {
-                try {
-                    final List<X509Certificate> certs = X509Utils.readRemoteCertificates(syslogConfig.getHost(), syslogConfig.getPort());
-                    if (certs != null) {
-                        resultCertificates.addAll(certs);
+        final List<String> syslogConfigStrs = (List<String>)storedConfiguration.readSetting(PwmSetting.AUDIT_SYSLOG_SERVERS).toNativeObject();
+        if (syslogConfigStrs != null && !syslogConfigStrs.isEmpty()) {
+            for(String entry : syslogConfigStrs) {
+                if (entry.toUpperCase().startsWith("TLS")) {
+                    final SyslogAuditService.SyslogConfig syslogConfig = SyslogAuditService.SyslogConfig.fromConfigString(entry);
+                    if (syslogConfig != null) {
+                        try {
+                            final List<X509Certificate> certs = X509Utils.readRemoteCertificates(syslogConfig.getHost(), syslogConfig.getPort());
+                            if (certs != null) {
+                                resultCertificates.addAll(certs);
+                                error = false;
+                            }
+                        } catch (Exception e) {
+                            error = true;
+                            exeception = e;
+                        }
                     }
                     }
-                } catch (Exception e) {
-                    if (e instanceof PwmException) {
-                        throw new PwmOperationalException(((PwmException) e).getErrorInformation());
-                    }
-                    final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_UNKNOWN,"error importing certificates: " + e.getMessage());
-                    throw new PwmOperationalException(errorInformation);
                 }
                 }
-
             }
             }
         }
         }
 
 
-        final UserIdentity userIdentity = pwmSession.isAuthenticated() ? pwmSession.getUserInfo().getUserIdentity() : null;
-        storedConfiguration.writeSetting(setting, new X509CertificateValue(resultCertificates), userIdentity);
-        return Message.getLocalizedMessage(pwmSession.getSessionStateBean().getLocale(), Message.Success_Unknown, pwmApplication.getConfig());
+        if (false == error) {
+            final UserIdentity userIdentity = pwmSession.isAuthenticated() ? pwmSession.getUserInfo().getUserIdentity() : null;
+            storedConfiguration.writeSetting(setting, new X509CertificateValue(resultCertificates), userIdentity);
+            return Message.getLocalizedMessage(pwmSession.getSessionStateBean().getLocale(), Message.Success_Unknown, pwmApplication.getConfig());
+        } else {
+            if (exeception instanceof PwmException) {
+                throw new PwmOperationalException(((PwmException) exeception).getErrorInformation());
+            }
+            final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_UNKNOWN,"error importing certificates: " + exeception.getMessage());
+            throw new PwmOperationalException(errorInformation);
+        }
     }
     }
 }
 }

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

@@ -102,7 +102,7 @@ public class AuditService implements PwmService {
             return;
             return;
         }
         }
 
 
-        final String syslogConfigString = pwmApplication.getConfig().readSettingAsString(PwmSetting.AUDIT_SYSLOG_SERVERS);
+        final List<String> syslogConfigString = pwmApplication.getConfig().readSettingAsStringArray(PwmSetting.AUDIT_SYSLOG_SERVERS);
         if (syslogConfigString != null && !syslogConfigString.isEmpty()) {
         if (syslogConfigString != null && !syslogConfigString.isEmpty()) {
             try {
             try {
                 syslogManager = new SyslogAuditService(pwmApplication);
                 syslogManager = new SyslogAuditService(pwmApplication);

+ 22 - 18
server/src/main/java/password/pwm/svc/event/SyslogAuditService.java

@@ -82,6 +82,7 @@ public class SyslogAuditService {
 
 
 
 
     private final Configuration configuration;
     private final Configuration configuration;
+    private List<SyslogIF> syslogInstances = new ArrayList<>();
 
 
     public SyslogAuditService(final PwmApplication pwmApplication)
     public SyslogAuditService(final PwmApplication pwmApplication)
             throws LocalDBException
             throws LocalDBException
@@ -89,14 +90,17 @@ public class SyslogAuditService {
         this.configuration = pwmApplication.getConfig();
         this.configuration = pwmApplication.getConfig();
         this.certificates = configuration.readSettingAsCertificate(PwmSetting.AUDIT_SYSLOG_CERTIFICATES);
         this.certificates = configuration.readSettingAsCertificate(PwmSetting.AUDIT_SYSLOG_CERTIFICATES);
 
 
-        final String syslogConfigString = configuration.readSettingAsString(PwmSetting.AUDIT_SYSLOG_SERVERS);
-        final SyslogConfig syslogConfig;
+        final List<String> syslogConfigStringArray = configuration.readSettingAsStringArray(PwmSetting.AUDIT_SYSLOG_SERVERS);
+
         try {
         try {
-            syslogConfig = SyslogConfig.fromConfigString(syslogConfigString);
-            syslogInstance = makeSyslogInstance(syslogConfig);
-            LOGGER.trace("queued service running for " + syslogConfig);
+            for(String entry : syslogConfigStringArray) {
+                final SyslogConfig syslogCfg = SyslogConfig.fromConfigString(entry);
+                final SyslogIF syslogInstance = makeSyslogInstance(syslogCfg);
+                syslogInstances.add(syslogInstance);
+            }
+            LOGGER.trace("queued service running for syslog entries");
         } catch (IllegalArgumentException e) {
         } catch (IllegalArgumentException e) {
-            LOGGER.error("error parsing syslog configuration for '" + syslogConfigString + "', error: " + e.getMessage());
+            LOGGER.error("error parsing syslog configuration for  syslogConfigStrings ERROR: " + e.getMessage());
         }
         }
 
 
         final WorkQueueProcessor.Settings settings = WorkQueueProcessor.Settings.builder()
         final WorkQueueProcessor.Settings settings = WorkQueueProcessor.Settings.builder()
@@ -188,19 +192,19 @@ public class SyslogAuditService {
 
 
     private WorkQueueProcessor.ProcessResult processEvent(final String auditRecord) {
     private WorkQueueProcessor.ProcessResult processEvent(final String auditRecord) {
 
 
-        final SyslogIF syslogIF = syslogInstance;
-        try {
-            syslogIF.info(auditRecord);
-            LOGGER.trace("delivered syslog audit event: " + auditRecord);
-            lastError = null;
-            return WorkQueueProcessor.ProcessResult.SUCCESS;
-        } catch (Exception e) {
-            final String errorMsg = "error while sending syslog message to remote service: " + e.getMessage();
-            final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_SYSLOG_WRITE_ERROR, errorMsg, new String[]{e.getMessage()});
-            lastError = errorInformation;
-            LOGGER.error(errorInformation.toDebugStr());
+        for(SyslogIF syslogInstance : syslogInstances) {
+            try {
+                syslogInstance.info(auditRecord);
+                LOGGER.trace("delivered syslog audit event: " + auditRecord);
+                lastError = null;
+                return WorkQueueProcessor.ProcessResult.SUCCESS;
+            } catch (Exception e) {
+                final String errorMsg = "error while sending syslog message to remote service: " + e.getMessage();
+                final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_SYSLOG_WRITE_ERROR, errorMsg, new String[]{e.getMessage()});
+                lastError = errorInformation;
+                LOGGER.error(errorInformation.toDebugStr());
+            }
         }
         }
-
         return WorkQueueProcessor.ProcessResult.RETRY;
         return WorkQueueProcessor.ProcessResult.RETRY;
     }
     }
 
 

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

@@ -220,7 +220,7 @@ Setting_Description_activateUser.token.sendMethod=Select the methods used for se
 Setting_Description_activateUser.writePostAttributes=Add actions @PwmAppName@ executes after it actives the users and the users have changed or set their initial passwords.  Typically, use this to activate the account, as well as add some searchable indicator.<br/><br/>  You can use macros.
 Setting_Description_activateUser.writePostAttributes=Add actions @PwmAppName@ executes after it actives the users and the users have changed or set their initial passwords.  Typically, use this to activate the account, as well as add some searchable indicator.<br/><br/>  You can use macros.
 Setting_Description_activateUser.writePreAttributes=Add actions @PwmAppName@ executes after it activates the users but before it sets the password.  Typically, use this to activate the account, as well as add some searchable indicator.<br/><br/>  You can use macros.
 Setting_Description_activateUser.writePreAttributes=Add actions @PwmAppName@ executes after it activates the users but before it sets the password.  Typically, use this to activate the account, as well as add some searchable indicator.<br/><br/>  You can use macros.
 Setting_Description_audit.syslog.certificates=Import the TLS Certificate of syslog service.
 Setting_Description_audit.syslog.certificates=Import the TLS Certificate of syslog service.
-Setting_Description_audit.syslog.servers=Specify the connection information for the syslog audit server.  When configured, @PwmAppName@  forwards all audit events to the specified syslog server.  The format is <b>&lt;protocol&gt;</b>,<b>&lt;address&gt;</b>,<b>&lt;port&gt;</b>.  The value for <b>&lt;protocol&gt;</b> can be either <\b>UDP</b> or <b>TCP</b>.<br/><br/>Examples\:<table><tr><td>Protocol</td><td>Address</td><td>Port</td><td>Setting</td><tr><tr><td>UDP</td><td>127.0.0.1</td><td>514</td><td>udp,127.0.0.1,514</td><tr><tr><td>TCP</td><td>central-syslog.example.com</td><td>514</td><td>tcp,central-syslog.example.com,514</td><tr><tr><td>TLS</td><td>secure-syslog.example.com</td><td>6514</td><td>tls,central-syslog.example.com,6514</td><tr></table>
+Setting_Description_audit.syslog.servers=Specify one or more entries of the connection information for the syslog audit servers. When configured, @PwmAppName@ forwards all audit events to the specified syslog server entered as the first entry. If the first one fails then the others will be tried until there is a successful delivery. The format is <b>&lt;protocol&gt;</b>,<b>&lt;address&gt;</b>,<b>&lt;port&gt;</b>.  The value for <b>&lt;protocol&gt;</b> can be either <\b>UDP</b>, <b>TCP</b> or <b>TLS</b>. We recommend that UDP is used in the list as the last option because UDP does not report a failure.<br/><br/>Examples\:<table><tr><td>Protocol</td><td>Address</td><td>Port</td><td>Setting</td><tr><tr><td>UDP</td><td>127.0.0.1</td><td>514</td><td>udp,127.0.0.1,514</td><tr><tr><td>TCP</td><td>central-syslog.example.com</td><td>514</td><td>tcp,central-syslog.example.com,514</td><tr><tr><td>TLS</td><td>secure-syslog.example.com</td><td>6514</td><td>tls,central-syslog.example.com,6514</td><tr></table>
 Setting_Description_audit.system.eventList=Select system event types to record and act upon.
 Setting_Description_audit.system.eventList=Select system event types to record and act upon.
 Setting_Description_audit.user.eventList=Select user event types to record and act upon.
 Setting_Description_audit.user.eventList=Select user event types to record and act upon.
 Setting_Description_audit.userEvent.toAddress=Specify one or more email addresses that the system sends an email to when the User Audit events occur.
 Setting_Description_audit.userEvent.toAddress=Specify one or more email addresses that the system sends an email to when the User Audit events occur.