Skip to content

Commit

Permalink
filter password query parameter in access log (#919)
Browse files Browse the repository at this point in the history
* filter password query parameter in access log

* compile the regex

* Added more test cases

* should replace password no matter the occurance

* should filter apikey no matter the occurance in the url string

* undo unintentional commits

Co-authored-by: Ed Shryane <eshryane@ripe.net>
  • Loading branch information
dadepo and eshryane authored Nov 6, 2021
1 parent a3b27ce commit a298282
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package net.ripe.db.whois.api.httpserver;

import org.eclipse.jetty.server.Slf4jRequestLogWriter;

import java.io.IOException;
import java.util.regex.Pattern;

public class FilteredSlf4jRequestLogWriter extends Slf4jRequestLogWriter {
private final String keyToFilter;
// Replace value passed to apikey with "FILTERED" but leave the last 3 characters if its API keys
private static final Pattern ApiKeyPattern = Pattern.compile("(?<=(?i)(apikey=))(.+?(?=\\S{3}[&|\\s]))");
private static final Pattern PasswordPattern = Pattern.compile("(?<=(?i)(password=))([^&]*)");

public FilteredSlf4jRequestLogWriter(String keyToFilter) {
this.keyToFilter = keyToFilter;
}

@Override
public void write(String requestEntry) throws IOException {
String filtered;

if (keyToFilter != null && keyToFilter.equalsIgnoreCase("apikey")) {
filtered = ApiKeyPattern.matcher(requestEntry).replaceAll("FILTERED");
} else {
filtered = PasswordPattern.matcher(requestEntry).replaceAll("FILTERED");
}

super.write(filtered);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,6 @@ public void stop(final boolean force) {

// Log requests to org.eclipse.jetty.server.RequestLog
private RequestLog createRequestLog() {
return new CustomRequestLog(new Slf4jRequestLogWriter(), EXTENDED_RIPE_LOG_FORMAT);
return new CustomRequestLog(new FilteredSlf4jRequestLogWriter("password"), EXTENDED_RIPE_LOG_FORMAT);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.io.IOException;
import java.nio.file.Files;

import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;

Expand Down Expand Up @@ -92,6 +93,69 @@ public void log_request_x_forwarded_for() throws Exception {
}


@Test
public void password_filtered() throws Exception {
RestTest.target(getPort(), "whois/test/person/TP1-TEST?password=some-api_key-123")
.request()
.get(WhoisResources.class);


String actual = fileToString(getRequestLogFilename());
assertThat(actual, containsString("GET /whois/test/person/TP1-TEST?password=FILTERED"));
assertThat(actual, not(containsString("some-api_key-123")));
}

@Test
public void multiple_password_filtered() throws Exception {
RestTest.target(getPort(), "whois/test/person/TP1-TEST?password=pass1&password=pass2")
.request()
.get(WhoisResources.class);


String actual = fileToString(getRequestLogFilename());
assertThat(actual, containsString("GET /whois/test/person/TP1-TEST?password=FILTERED&password=FILTERED"));
assertThat(actual, not(containsString("pass1")));
assertThat(actual, not(containsString("pass2")));
}

@Test
public void multiple_query_password_filtered() throws Exception {
RestTest.target(getPort(), "whois/test/person/TP1-TEST?password=pass1&key=value")
.request()
.get(WhoisResources.class);


String actual = fileToString(getRequestLogFilename());
assertThat(actual, containsString("GET /whois/test/person/TP1-TEST?password=FILTERED&key=value"));
assertThat(actual, containsString("key=value"));
assertThat(actual, not(containsString("pass1")));
}

@Test
public void multiple_query_password_last_filtered() throws Exception {
RestTest.target(getPort(), "whois/test/person/TP1-TEST?key=value&password=pass1")
.request()
.get(WhoisResources.class);


String actual = fileToString(getRequestLogFilename());
assertThat(actual, containsString("GET /whois/test/person/TP1-TEST?key=value&password=FILTERED"));
assertThat(actual, containsString("key=value"));
assertThat(actual, not(containsString("pass1")));
}

@Test
public void password_filtered_case_insensitive() throws Exception {
RestTest.target(getPort(), "whois/test/person/TP1-TEST?PassWord=pass1")
.request()
.get(WhoisResources.class);


String actual = fileToString(getRequestLogFilename());
assertThat(actual.toLowerCase(), containsString("password=FILTERED".toLowerCase()));
assertThat(actual, not(containsString("pass1")));
}

// helper methods

private static void cleanupRequestLogDirectory() throws IOException {
Expand Down

0 comments on commit a298282

Please sign in to comment.