diff --git a/configuration/esapi/ESAPI.properties b/configuration/esapi/ESAPI.properties index 030f61588..977c071f1 100644 --- a/configuration/esapi/ESAPI.properties +++ b/configuration/esapi/ESAPI.properties @@ -400,6 +400,8 @@ Logger.LogServerIP=true Logger.UserInfo=true # Determines whether ESAPI should log the session id and client IP. Logger.ClientInfo=true +# Determines whether ESAPI should log the event type or not +Logger.OmitEventTypeInLogs=false #=========================================================================== # ESAPI Intrusion Detection diff --git a/src/main/java/org/owasp/esapi/PropNames.java b/src/main/java/org/owasp/esapi/PropNames.java index 2f3f8ee49..fd91db397 100644 --- a/src/main/java/org/owasp/esapi/PropNames.java +++ b/src/main/java/org/owasp/esapi/PropNames.java @@ -111,6 +111,7 @@ public final class PropNames { public static final String LOG_ENCODING_REQUIRED = "Logger.LogEncodingRequired"; public static final String LOG_APPLICATION_NAME = "Logger.LogApplicationName"; public static final String LOG_SERVER_IP = "Logger.LogServerIP"; + public static final String OMIT_EVENT_TYPE_IN_LOGS = "Logger.OmitEventTypeInLogs"; public static final String VALIDATION_PROPERTIES = "Validator.ConfigurationFile"; public static final String VALIDATION_PROPERTIES_MULTIVALUED = "Validator.ConfigurationFile.MultiValued"; diff --git a/src/main/java/org/owasp/esapi/logging/appender/LogPrefixAppender.java b/src/main/java/org/owasp/esapi/logging/appender/LogPrefixAppender.java index 20f692ebf..02f1962b7 100644 --- a/src/main/java/org/owasp/esapi/logging/appender/LogPrefixAppender.java +++ b/src/main/java/org/owasp/esapi/logging/appender/LogPrefixAppender.java @@ -15,7 +15,11 @@ package org.owasp.esapi.logging.appender; +import org.owasp.esapi.ESAPI; import org.owasp.esapi.Logger.EventType; +import org.owasp.esapi.errors.ConfigurationException; + +import static org.owasp.esapi.PropNames.OMIT_EVENT_TYPE_IN_LOGS; /** * LogAppender Implementation which can prefix the common logger information for @@ -35,6 +39,18 @@ public class LogPrefixAppender implements LogAppender { private final boolean logApplicationName; /** Application Name to record. */ private final String appName; + /** Whether to omit event type in logs or not. */ + private static boolean omitEventTypeInLogs; + + static { + + try { + omitEventTypeInLogs = + ESAPI.securityConfiguration().getBooleanProp(OMIT_EVENT_TYPE_IN_LOGS); + } catch (ConfigurationException ex) { + omitEventTypeInLogs = false; + } + } /** * Ctr. @@ -67,7 +83,7 @@ public String appendTo(String logName, EventType eventType, String message) { serverInfoSupplier.setLogServerIp(logServerIp); serverInfoSupplier.setLogApplicationName(logApplicationName, appName); - String eventTypeMsg = eventTypeSupplier.get().trim(); + String eventTypeMsg = omitEventTypeInLogs ? "" : eventTypeSupplier.get().trim(); String userInfoMsg = userInfoSupplier.get().trim(); String clientInfoMsg = clientInfoSupplier.get().trim(); String serverInfoMsg = serverInfoSupplier.get().trim(); @@ -81,7 +97,7 @@ public String appendTo(String logName, EventType eventType, String message) { String[] optionalPrefixContent = new String[] {userInfoMsg + clientInfoMsg, serverInfoMsg}; StringBuilder logPrefix = new StringBuilder(); - //EventType is always appended + logPrefix.append(eventTypeMsg); for (String element : optionalPrefixContent) { @@ -91,6 +107,7 @@ public String appendTo(String logName, EventType eventType, String message) { } } - return String.format(RESULT_FORMAT, logPrefix.toString(), message); + String prefix = logPrefix.toString().trim(); + return prefix.isEmpty() ? message : String.format(RESULT_FORMAT, prefix, message); } } diff --git a/src/test/java/org/owasp/esapi/logging/appender/LogPrefixAppenderOmitEventTypeInLogsTest.java b/src/test/java/org/owasp/esapi/logging/appender/LogPrefixAppenderOmitEventTypeInLogsTest.java new file mode 100644 index 000000000..b3b79fb63 --- /dev/null +++ b/src/test/java/org/owasp/esapi/logging/appender/LogPrefixAppenderOmitEventTypeInLogsTest.java @@ -0,0 +1,124 @@ +package org.owasp.esapi.logging.appender; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; +import org.junit.runner.RunWith; +import org.owasp.esapi.ESAPI; +import org.owasp.esapi.Logger; +import org.owasp.esapi.Logger.EventType; +import org.owasp.esapi.SecurityConfiguration; +import org.owasp.esapi.SecurityConfigurationWrapper; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; +import static org.owasp.esapi.PropNames.OMIT_EVENT_TYPE_IN_LOGS; +import static org.powermock.api.mockito.PowerMockito.whenNew; + +@RunWith(PowerMockRunner.class) +@PrepareForTest(LogPrefixAppender.class) +public class LogPrefixAppenderOmitEventTypeInLogsTest { + private static final String EMPTY_RESULT = " "; + private static final String ETL_RESULT = "EVENT_TYPE"; + private static final String CIS_RESULT = "CLIENT_INFO"; + private static final String UIS_RESULT = "USER_INFO"; + private static final String SIS_RESULT = "SERVER_INFO"; + + @Rule + public TestName testName = new TestName(); + + private String testLoggerName = testName.getMethodName() + "-LOGGER"; + private String testLogMessage = testName.getMethodName() + "-MESSAGE"; + private String testApplicationName = testName.getMethodName() + "-APPLICATION_NAME"; + private EventType testEventType = Logger.EVENT_UNSPECIFIED; + + private EventTypeLogSupplier etlsSpy; + private ClientInfoSupplier cisSpy; + private UserInfoSupplier uisSpy; + private ServerInfoSupplier sisSpy; + + private static class ConfOverride extends SecurityConfigurationWrapper { + private final boolean desiredReturn; + + ConfOverride(SecurityConfiguration orig, boolean desiredReturn) { + super(orig); + this.desiredReturn = desiredReturn; + } + + @Override + public Boolean getBooleanProp(String propName) { + // Would it be better making this file a static import? + if (propName.equals(OMIT_EVENT_TYPE_IN_LOGS)) { + return desiredReturn; + } else { + return false; + } + } + } + + @Before + public void buildSupplierSpies() { + etlsSpy = spy(new EventTypeLogSupplier(Logger.EVENT_UNSPECIFIED)); + uisSpy = spy(new UserInfoSupplier()); + cisSpy = spy(new ClientInfoSupplier()); + sisSpy = spy(new ServerInfoSupplier(testName.getMethodName())); + + testLoggerName = testName.getMethodName() + "-LOGGER"; + testLogMessage = testName.getMethodName() + "-MESSAGE"; + testApplicationName = testName.getMethodName() + "-APPLICATION_NAME"; + + ESAPI.override( + new LogPrefixAppenderOmitEventTypeInLogsTest.ConfOverride(ESAPI.securityConfiguration(), true) + ); + } + @Test + public void testLongContentWithOmitEventTypeInLogs() throws Exception { + runTest(ETL_RESULT, EMPTY_RESULT, EMPTY_RESULT, EMPTY_RESULT, ""); + } + + @Test + public void testLongContentWithOmitEventTypeInLogsAndUserInfo() throws Exception { + runTest(ETL_RESULT, UIS_RESULT, EMPTY_RESULT, EMPTY_RESULT, "[USER_INFO]"); + } + + @Test + public void testLongContentWithOmitEventTypeInLogsAndClientInfo() throws Exception { + runTest(ETL_RESULT, EMPTY_RESULT, CIS_RESULT, EMPTY_RESULT, "[CLIENT_INFO]"); + } + + @Test + public void testLongContentWithOmitEventTypeInLogsAndServerInfo() throws Exception { + runTest(ETL_RESULT, EMPTY_RESULT, EMPTY_RESULT, SIS_RESULT, "[-> SERVER_INFO]"); + } + + private void runTest(String typeResult, String userResult, String clientResult, String serverResult, String exResult) throws Exception{ + when(etlsSpy.get()).thenReturn(typeResult); + when(uisSpy.get()).thenReturn(userResult); + when(cisSpy.get()).thenReturn(clientResult); + when(sisSpy.get()).thenReturn(serverResult); + + whenNew(EventTypeLogSupplier.class).withArguments(testEventType).thenReturn(etlsSpy); + whenNew(UserInfoSupplier.class).withNoArguments().thenReturn(uisSpy); + whenNew(ClientInfoSupplier.class).withNoArguments().thenReturn(cisSpy); + whenNew(ServerInfoSupplier.class).withArguments(testLoggerName).thenReturn(sisSpy); + + //Since everything is mocked these booleans don't much matter aside from the later verifies + LogPrefixAppender lpa = new LogPrefixAppender(false, false, false, false, null); + + String actualResult = lpa.appendTo(testLoggerName, testEventType, testLogMessage); + + StringBuilder expectedResult = new StringBuilder(); + if (!exResult.isEmpty()) { + expectedResult.append(exResult); + expectedResult.append(" "); + } + expectedResult.append(testName.getMethodName()); + expectedResult.append("-MESSAGE"); + + assertEquals(expectedResult.toString() , actualResult); + } +} diff --git a/src/test/java/org/owasp/esapi/logging/appender/LogPrefixAppenderTest.java b/src/test/java/org/owasp/esapi/logging/appender/LogPrefixAppenderTest.java index bc733ec2e..4e188e9fc 100644 --- a/src/test/java/org/owasp/esapi/logging/appender/LogPrefixAppenderTest.java +++ b/src/test/java/org/owasp/esapi/logging/appender/LogPrefixAppenderTest.java @@ -145,6 +145,11 @@ public void testLogContentWhenUserInfoEmptyAndClientInfoEmptyAndServerInfoEmpty( runTest(ETL_RESULT, EMPTY_RESULT, EMPTY_RESULT, EMPTY_RESULT, "[EVENT_TYPE]"); } + @Test + public void testLongContentWithoutOmitEventTypeInLogs() throws Exception { + runTest(ETL_RESULT, EMPTY_RESULT, EMPTY_RESULT, EMPTY_RESULT, "[EVENT_TYPE]"); + } + private void runTest(String typeResult, String userResult, String clientResult, String serverResult, String exResult) throws Exception{ when(etlsSpy.get()).thenReturn(typeResult); diff --git a/src/test/resources/esapi/ESAPI.properties b/src/test/resources/esapi/ESAPI.properties index 9ab844622..cf38c7633 100644 --- a/src/test/resources/esapi/ESAPI.properties +++ b/src/test/resources/esapi/ESAPI.properties @@ -431,6 +431,8 @@ Logger.LogServerIP=true Logger.UserInfo=true # Determines whether ESAPI should log the session id and client IP. Logger.ClientInfo=true +# Determines whether ESAPI should log the event type or not +Logger.OmitEventTypeInLogs=false #=========================================================================== # ESAPI Intrusion Detection