Merge pull request #67 from ljacqu/unit-tests

Unit tests
This commit is contained in:
Gabriele C 2015-11-20 23:23:49 +01:00
commit 4d2e48ede7
4 changed files with 324 additions and 55 deletions

34
pom.xml
View File

@ -76,6 +76,8 @@
</includes>
</resource>
</resources>
<sourceDirectory>src/main/java</sourceDirectory>
<testSourceDirectory>test/main/java</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@ -589,13 +591,33 @@
<optional>true</optional>
</dependency>
<!-- String comparison library. Used for dynamic help system. -->
<dependency>
<groupId>net.ricecode</groupId>
<artifactId>string-similarity</artifactId>
<version>1.0.0</version>
<!-- Unit testing -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>java-hamcrest</artifactId>
<scope>test</scope>
<version>2.0.0.0</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
<version>2.0.5-beta</version>
</dependency>
<!-- String comparison library. Used for dynamic help system. -->
<dependency>
<groupId>net.ricecode</groupId>
<artifactId>string-similarity</artifactId>
<version>1.0.0</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
</dependency>
</dependencies>
</project>

View File

@ -6,80 +6,50 @@ import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.Logger;
import org.apache.logging.log4j.message.Message;
import fr.xephi.authme.util.StringUtils;
/**
*
* Implements a filter for Log4j to skip sensitive AuthMe commands.
* @author Xephi59
*/
public class Log4JFilter implements org.apache.logging.log4j.core.Filter {
/** List of commands (lower-case) to skip. */
private static final String[] COMMANDS_TO_SKIP = { "/login ", "/l ", "/reg ", "/changepassword ",
"/unregister ", "/authme register ", "/authme changepassword ", "/authme reg ", "/authme cp ",
"/register " };
/** Constructor. */
public Log4JFilter() {
}
@Override
public Result filter(LogEvent record) {
try {
if (record == null || record.getMessage() == null)
return Result.NEUTRAL;
String logM = record.getMessage().getFormattedMessage().toLowerCase();
if (!logM.contains("issued server command:"))
return Result.NEUTRAL;
if (!logM.contains("/login ") && !logM.contains("/l ") && !logM.contains("/reg ") && !logM.contains("/changepassword ") && !logM.contains("/unregister ") && !logM.contains("/authme register ") && !logM.contains("/authme changepassword ") && !logM.contains("/authme reg ") && !logM.contains("/authme cp ") && !logM.contains("/register "))
return Result.NEUTRAL;
return Result.DENY;
} catch (NullPointerException npe) {
return Result.NEUTRAL;
}
if (record == null) {
return Result.NEUTRAL;
}
return validateMessage(record.getMessage());
}
@Override
public Result filter(Logger arg0, Level arg1, Marker arg2, String message,
Object... arg4) {
try {
if (message == null)
return Result.NEUTRAL;
String logM = message.toLowerCase();
if (!logM.contains("issued server command:"))
return Result.NEUTRAL;
if (!logM.contains("/login ") && !logM.contains("/l ") && !logM.contains("/reg ") && !logM.contains("/changepassword ") && !logM.contains("/unregister ") && !logM.contains("/authme register ") && !logM.contains("/authme changepassword ") && !logM.contains("/authme reg ") && !logM.contains("/authme cp ") && !logM.contains("/register "))
return Result.NEUTRAL;
return Result.DENY;
} catch (NullPointerException npe) {
return Result.NEUTRAL;
}
return validateMessage(message);
}
@Override
public Result filter(Logger arg0, Level arg1, Marker arg2, Object message,
Throwable arg4) {
try {
if (message == null)
return Result.NEUTRAL;
String logM = message.toString().toLowerCase();
if (!logM.contains("issued server command:"))
return Result.NEUTRAL;
if (!logM.contains("/login ") && !logM.contains("/l ") && !logM.contains("/reg ") && !logM.contains("/changepassword ") && !logM.contains("/unregister ") && !logM.contains("/authme register ") && !logM.contains("/authme changepassword ") && !logM.contains("/authme reg ") && !logM.contains("/authme cp ") && !logM.contains("/register "))
return Result.NEUTRAL;
return Result.DENY;
} catch (NullPointerException npe) {
return Result.NEUTRAL;
}
if (message == null) {
return Result.NEUTRAL;
}
return validateMessage(message.toString());
}
@Override
public Result filter(Logger arg0, Level arg1, Marker arg2, Message message,
Throwable arg4) {
try {
if (message == null)
return Result.NEUTRAL;
String logM = message.getFormattedMessage().toLowerCase();
if (!logM.contains("issued server command:"))
return Result.NEUTRAL;
if (!logM.contains("/login ") && !logM.contains("/l ") && !logM.contains("/reg ") && !logM.contains("/changepassword ") && !logM.contains("/unregister ") && !logM.contains("/authme register ") && !logM.contains("/authme changepassword ") && !logM.contains("/authme reg ") && !logM.contains("/authme cp ") && !logM.contains("/register "))
return Result.NEUTRAL;
return Result.DENY;
} catch (NullPointerException npe) {
return Result.NEUTRAL;
}
return validateMessage(message);
}
@Override
@ -92,4 +62,39 @@ public class Log4JFilter implements org.apache.logging.log4j.core.Filter {
return Result.NEUTRAL;
}
/**
* Validates a Message instance and returns the {@link Result} value
* depending depending on whether the message contains sensitive AuthMe
* data.
*
* @param message the Message object to verify
* @return the Result value
*/
private static Result validateMessage(Message message) {
if (message == null) {
return Result.NEUTRAL;
}
return validateMessage(message.getFormattedMessage());
}
/**
* Validates a message and returns the {@link Result} value depending
* depending on whether the message contains sensitive AuthMe data.
*
* @param message the message to verify
* @return the Result value
*/
private static Result validateMessage(String message) {
if (message == null) {
return Result.NEUTRAL;
}
String lowerMessage = message.toLowerCase();
if (lowerMessage.contains("issued server command:")
&& StringUtils.containsAny(lowerMessage, COMMANDS_TO_SKIP)) {
return Result.DENY;
}
return Result.NEUTRAL;
}
}

View File

@ -25,4 +25,16 @@ public class StringUtils {
// Determine the difference value, return the result
return Math.abs(service.score(first, second) - 1.0);
}
public static boolean containsAny(String str, String... pieces) {
if (str == null) {
return false;
}
for (String piece : pieces) {
if (str.contains(piece)) {
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,230 @@
package fr.xephi.authme;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.when;
import org.apache.logging.log4j.core.Filter.Result;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.message.Message;
import org.junit.Test;
import org.mockito.Mockito;
/**
* Test for {@link Log4JFilter}.
*/
public class Log4JFilterTest {
private final Log4JFilter log4JFilter = new Log4JFilter();
private static final String SENSITIVE_COMMAND = "User issued server command: /login pass pass";
private static final String NORMAL_COMMAND = "User issued server command: /help";
private static final String OTHER_COMMAND = "Starting the server... Write /l for logs";
// ---------
// Test the filter(LogEvent) method
// ---------
@Test
public void shouldFilterSensitiveLogEvent() {
// given
Message message = mockMessage(SENSITIVE_COMMAND);
LogEvent event = Mockito.mock(LogEvent.class);
when(event.getMessage()).thenReturn(message);
// when
Result result = log4JFilter.filter(event);
// then
assertThat(result, equalTo(Result.DENY));
}
@Test
public void shouldNotFilterIrrelevantLogEvent() {
// given
Message message = mockMessage(NORMAL_COMMAND);
LogEvent event = Mockito.mock(LogEvent.class);
when(event.getMessage()).thenReturn(message);
// when
Result result = log4JFilter.filter(event);
// then
assertThat(result, equalTo(Result.NEUTRAL));
}
@Test
public void shouldNotFilterNonCommandLogEvent() {
// given
Message message = mockMessage(OTHER_COMMAND);
LogEvent event = Mockito.mock(LogEvent.class);
when(event.getMessage()).thenReturn(message);
// when
Result result = log4JFilter.filter(event);
// then
assertThat(result, equalTo(Result.NEUTRAL));
}
@Test
public void shouldNotFilterLogEventWithNullMessage() {
// given
Message message = mockMessage(null);
LogEvent event = Mockito.mock(LogEvent.class);
when(event.getMessage()).thenReturn(message);
// when
Result result = log4JFilter.filter(event);
// then
assertThat(result, equalTo(Result.NEUTRAL));
}
@Test
public void shouldNotFilterWhenLogEventIsNull() {
// given / when
Result result = log4JFilter.filter(null);
// then
assertThat(result, equalTo(Result.NEUTRAL));
}
// ----------
// Test filter(Logger, Level, Marker, String, Object...)
// ----------
@Test
public void shouldFilterSensitiveStringMessage() {
// given / when
Result result = log4JFilter.filter(null, null, null, SENSITIVE_COMMAND, new Object[0]);
// then
assertThat(result, equalTo(Result.DENY));
}
@Test
public void shouldNotFilterNormalStringMessage() {
// given / when
Result result = log4JFilter.filter(null, null, null, NORMAL_COMMAND, new Object[0]);
// then
assertThat(result, equalTo(Result.NEUTRAL));
}
@Test
public void shouldNotFilterNonCommandStringMessage() {
// given / when
Result result = log4JFilter.filter(null, null, null, OTHER_COMMAND, new Object[0]);
// then
assertThat(result, equalTo(Result.NEUTRAL));
}
@Test
public void shouldReturnNeutralForNullMessage() {
// given / when
Result result = log4JFilter.filter(null, null, null, null, new Object[0]);
// then
assertThat(result, equalTo(Result.NEUTRAL));
}
// --------
// Test filter(Logger, Level, Marker, Object, Throwable)
// --------
@Test
public void shouldFilterSensitiveObjectMessage() {
// given / when
Result result = log4JFilter.filter(null, null, null, SENSITIVE_COMMAND, new Exception());
// then
assertThat(result, equalTo(Result.DENY));
}
@Test
public void shouldNotFilterNullObjectParam() {
// given / when
Result result = log4JFilter.filter(null, null, null, (Object) null, new Exception());
// then
assertThat(result, equalTo(Result.NEUTRAL));
}
@Test
public void shouldNotFilterIrrelevantMessage() {
// given / when
Result result = log4JFilter.filter(null, null, null, OTHER_COMMAND, new Exception());
// then
assertThat(result, equalTo(Result.NEUTRAL));
}
@Test
public void shouldNotFilterNonSensitiveCommand() {
// given / when
Result result = log4JFilter.filter(null, null, null, NORMAL_COMMAND, new Exception());
// then
assertThat(result, equalTo(Result.NEUTRAL));
}
// --------
// Test filter(Logger, Level, Marker, Message, Throwable)
// --------
@Test
public void shouldFilterSensitiveMessage() {
// given
Message message = mockMessage(SENSITIVE_COMMAND);
// when
Result result = log4JFilter.filter(null, null, null, message, new Exception());
// then
assertThat(result, equalTo(Result.DENY));
}
@Test
public void shouldNotFilterNonSensitiveMessage() {
// given
Message message = mockMessage(NORMAL_COMMAND);
// when
Result result = log4JFilter.filter(null, null, null, message, new Exception());
// then
assertThat(result, equalTo(Result.NEUTRAL));
}
@Test
public void shouldNotFilterNonCommandMessage() {
// given
Message message = mockMessage(OTHER_COMMAND);
// when
Result result = log4JFilter.filter(null, null, null, message, new Exception());
// then
assertThat(result, equalTo(Result.NEUTRAL));
}
@Test
public void shouldNotFilterNullMessage() {
// given / when
Result result = log4JFilter.filter(null, null, null, (Message) null, new Exception());
// then
assertThat(result, equalTo(Result.NEUTRAL));
}
/**
* Mocks a {@link Message} object and makes it return the given formatted message.
*
* @param formattedMessage the formatted message the mock should return
* @return Message mock
*/
private static Message mockMessage(String formattedMessage) {
Message message = Mockito.mock(Message.class);
when(message.getFormattedMessage()).thenReturn(formattedMessage);
return message;
}
}