Explorar el Código

cef audit fixes

jrivard@gmail.com hace 6 años
padre
commit
5d52b5944e

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

@@ -76,6 +76,7 @@ public abstract class PwmConstants
     public static final String DEFAULT_CONFIG_FILE_FILENAME = readPwmConstantsBundle( "defaultConfigFilename" );
 
     public static final String PWM_APP_NAME = readPwmConstantsBundle( "pwm.appName" );
+    public static final String PWM_VENDOR_NAME = readPwmConstantsBundle( "pwm.vendorName" );
     public static final String PWM_URL_HOME = readPwmConstantsBundle( "url.pwm-home" );
 
     public static final String PWM_APP_NAME_VERSION = PWM_APP_NAME + " " + SERVLET_VERSION;

+ 77 - 36
server/src/main/java/password/pwm/svc/event/SyslogAuditService.java

@@ -70,6 +70,7 @@ import javax.net.SocketFactory;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.X509TrustManager;
 import java.io.Serializable;
+import java.net.URI;
 import java.security.KeyManagementException;
 import java.security.NoSuchAlgorithmException;
 import java.security.cert.X509Certificate;
@@ -79,6 +80,7 @@ import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 
 
 public class SyslogAuditService
@@ -365,6 +367,9 @@ public class SyslogAuditService
         return message.toString();
     }
 
+
+    private static final String CEF_EXTENSION_SEPARATOR = "|";
+
     private String convertAuditRecordToCEFMessage(
             final AuditRecord auditRecord,
             final Configuration configuration
@@ -372,12 +377,11 @@ public class SyslogAuditService
             throws PwmUnrecoverableException
     {
         final Map<String, Object> auditRecordMap = JsonUtil.deserializeMap( JsonUtil.serialize( auditRecord ) );
-        final String separator = "|";
 
         final String headerSeverity = configuration.readAppProperty( AppProperty.AUDIT_SYSLOG_CEF_HEADER_SEVERITY );
         final String headerProduct = configuration.readAppProperty( AppProperty.AUDIT_SYSLOG_CEF_HEADER_PRODUCT );
         final String headerVendor = configuration.readAppProperty( AppProperty.AUDIT_SYSLOG_CEF_HEADER_VENDOR );
-
+        final Optional<String> srcHost = deriveLocalServerHostname( configuration );
 
         final MacroMachine macroMachine = MacroMachine.forNonUserSpecific( pwmApplication, SessionLabel.SYSTEM_LABEL );
 
@@ -389,58 +393,71 @@ public class SyslogAuditService
 
         final StringBuilder cefOutput = new StringBuilder(  );
 
-        // cef declaration:version prefix
-        cefOutput.append( "CEF:0" );
+        // cef header
+        {
+            // cef declaration:version prefix
+            cefOutput.append( "CEF:0" );
+
+            // Device Vendor
+            cefOutput.append( CEF_EXTENSION_SEPARATOR );
+            cefOutput.append( macroMachine.expandMacros( headerVendor ) );
+
+            // Device Product
+            cefOutput.append( CEF_EXTENSION_SEPARATOR );
+            cefOutput.append( macroMachine.expandMacros( headerProduct ) );
 
-        // Device Vendor
-        cefOutput.append( separator );
-        cefOutput.append( macroMachine.expandMacros( headerVendor ) );
+            // Device Version
+            cefOutput.append( CEF_EXTENSION_SEPARATOR );
+            cefOutput.append( PwmConstants.SERVLET_VERSION );
 
-        // Device Product
-        cefOutput.append( separator );
-        cefOutput.append( macroMachine.expandMacros( headerProduct ) );
+            // Device Event Class ID
+            cefOutput.append( CEF_EXTENSION_SEPARATOR );
+            cefOutput.append( auditRecord.getEventCode() );
 
-        // Device Version
-        cefOutput.append( separator );
-        cefOutput.append( PwmConstants.SERVLET_VERSION );
+            // field name
+            cefOutput.append( CEF_EXTENSION_SEPARATOR );
+            cefOutput.append( auditFieldName );
+
+            // severity
+            cefOutput.append( CEF_EXTENSION_SEPARATOR );
+            cefOutput.append( macroMachine.expandMacros( headerSeverity ) );
+        }
 
-        // Device Event Class ID
-        cefOutput.append( separator );
-        cefOutput.append( auditRecord.getEventCode() );
+        cefOutput.append( CEF_EXTENSION_SEPARATOR );
 
-        // field name
-        cefOutput.append( separator );
-        cefOutput.append( auditFieldName );
+        srcHost.ifPresent( s -> appendCefValue( "dvchost", s, cefOutput ) );
 
-        // severity
-        cefOutput.append( separator );
-        cefOutput.append( macroMachine.expandMacros( headerSeverity ) );
+        appendCefValue( "dtz", "Zulu", cefOutput );
 
-        boolean extensionAdded = false;
         for ( final Map.Entry<String, String> entry : syslogCefExtensions.entrySet() )
         {
             final Object value = auditRecordMap.get( entry.getKey() );
             if ( value != null )
             {
-                if ( !extensionAdded )
-                {
-                    cefOutput.append( separator );
-                    extensionAdded = true;
-                }
-                else
-                {
-                    cefOutput.append( " " );
-                }
-                cefOutput.append( entry.getValue() );
-                cefOutput.append( "=" );
-                cefOutput.append( escapeCEFValue( value.toString() ) );
+                final String name = entry.getValue();
+                final String valueString = value.toString();
+                appendCefValue( name, valueString, cefOutput );
             }
         }
 
+        if ( cefOutput.substring( cefOutput.length() - CEF_EXTENSION_SEPARATOR.length() ).equals( CEF_EXTENSION_SEPARATOR ) )
+        {
+            cefOutput.replace( cefOutput.length() - CEF_EXTENSION_SEPARATOR.length(), cefOutput.length(), "" );
+        }
+
         return cefOutput.toString();
     }
 
-
+    private static void appendCefValue( final String name, final String value, final StringBuilder cefOutput )
+    {
+        if ( !StringUtil.isEmpty( value ) && !StringUtil.isEmpty( name ) )
+        {
+            cefOutput.append( " " );
+            cefOutput.append( name );
+            cefOutput.append( "=" );
+            cefOutput.append( escapeCEFValue( value ) );
+        }
+    }
 
     private static String escapeCEFValue( final String value )
     {
@@ -569,4 +586,28 @@ public class SyslogAuditService
         final Map<String, String> map = StringUtil.convertStringListToNameValuePair( pairs, keyValueSplitter );
         return Collections.unmodifiableMap( map );
     }
+
+    private static Optional<String> deriveLocalServerHostname( final Configuration configuration )
+    {
+        if ( configuration != null )
+        {
+            final String siteUrl = configuration.readSettingAsString( PwmSetting.PWM_SITE_URL );
+            if ( !StringUtil.isEmpty( siteUrl ) )
+            {
+                try
+                {
+                    final URI parsedUri = URI.create( siteUrl );
+                    {
+                        final String uriHost = parsedUri.getHost();
+                        return Optional.ofNullable( uriHost );
+                    }
+                }
+                catch ( IllegalArgumentException e )
+                {
+                    LOGGER.trace( () -> " error parsing siteURL hostname: " + e.getMessage() );
+                }
+            }
+        }
+        return Optional.empty();
+    }
 }

+ 17 - 0
server/src/main/java/password/pwm/util/macro/InternalMacros.java

@@ -50,6 +50,7 @@ public abstract class InternalMacros
         final Map<Class<? extends MacroImplementation>, MacroImplementation.Scope> defaultMacros = new HashMap<>();
         defaultMacros.put( PwmSettingReference.class, MacroImplementation.Scope.Static );
         defaultMacros.put( PwmAppName.class, MacroImplementation.Scope.Static );
+        defaultMacros.put( PwmVendorName.class, MacroImplementation.Scope.Static );
         defaultMacros.put( PwmContextPath.class, MacroImplementation.Scope.System );
         defaultMacros.put( EncodingMacro.class, MacroImplementation.Scope.Static );
         defaultMacros.put( CasingMacro.class, MacroImplementation.Scope.Static );
@@ -429,4 +430,20 @@ public abstract class InternalMacros
             return PwmConstants.PWM_APP_NAME;
         }
     }
+
+    public static class PwmVendorName extends InternalAbstractMacro
+    {
+        private static final Pattern PATTERN = Pattern.compile( "@PwmVendorName@" );
+
+        public Pattern getRegExPattern( )
+        {
+            return PATTERN;
+        }
+
+        public String replaceValue( final String matchValue, final MacroRequestInfo macroRequestInfo )
+                throws MacroParseException
+        {
+            return PwmConstants.PWM_VENDOR_NAME;
+        }
+    }
 }

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

@@ -32,10 +32,10 @@ application.wordlistRetryImportSeconds=600
 audit.events.emailFrom=Audit Event Notification <@DefaultEmailFromAddress@>
 audit.events.emailSubject=@PwmAppName@ - Audit Event - %EVENT%
 audit.events.localdb.maxBulkRemovals=301
-audit.syslog.cef.extensions=type,cat:eventCode,act:timestamp,rt:message,msg:narrative,reason:perpetratorID,suid:perpetratorDN,suser:sourceAddress,dvc:sourceHost,dvchost:targetID,duid:targetDN,duser
+audit.syslog.cef.extensions=type,cat\:eventCode,act\:timestamp,rt\:message,msg\:narrative,reason\:perpetratorID,suid\:perpetratorDN,suser\:sourceAddress,src\:sourceHost,srchost\:targetID,duid\:targetDN,duser
 audit.syslog.cef.header.product=@PwmAppName@
-audit.syslog.cef.header.severity=Unknown
-audit.syslog.cef.header.vendor=@PwmAppName@
+audit.syslog.cef.header.severity=Medium
+audit.syslog.cef.header.vendor=@PwmVendorName@
 audit.syslog.message.length=900
 audit.syslog.message.truncateMsg=[truncated]
 auth.allowSSOwithUnknownPassword=true

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

@@ -32,6 +32,7 @@ httpHeaderAuthorizationBasic=Basic
 defaultBadPasswordAttempt=BADPASSWORDATTEMPT
 log.removedValue=*hidden*
 pwm.appName=PWM
+pwm.vendorName=PWM
 trial=false
 url.pwm-home=https://github.com/pwm-project/pwm
 paramName.token=token