From f0b347e2f6f8fd53126c1a040b72a85a4defe4b1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?S=C3=A9bastien=20Lesaint?= Date: Mon, 28 Nov 2016 11:47:25 +0100 Subject: [PATCH] =?utf8?q?SONAR-8416=20prevent=20log=20flooding=20with=20?= =?utf8?q?=C3=BCber=20long=20login?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../event/AuthenticationEventImpl.java | 12 +++- .../event/AuthenticationEventImplTest.java | 56 +++++++++++++------ 2 files changed, 50 insertions(+), 18 deletions(-) diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/event/AuthenticationEventImpl.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/event/AuthenticationEventImpl.java index 413cbb99328..9cab0d0d95f 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/authentication/event/AuthenticationEventImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/server/authentication/event/AuthenticationEventImpl.java @@ -29,13 +29,14 @@ import org.sonar.core.util.stream.Collectors; public class AuthenticationEventImpl implements AuthenticationEvent { private static final Logger LOGGER = Loggers.get("auth.event"); + private static final int FLOOD_THRESHOLD = 128; @Override public void login(HttpServletRequest request, @Nullable String login, Source source) { LOGGER.info("login success [method|{}][provider|{}|{}][IP|{}|{}][login|{}]", source.getMethod(), source.getProvider(), source.getProviderName(), request.getRemoteAddr(), getAllIps(request), - emptyIfNull(login)); + preventLogFlood(emptyIfNull(login))); } private static String getAllIps(HttpServletRequest request) { @@ -49,11 +50,18 @@ public class AuthenticationEventImpl implements AuthenticationEvent { emptyIfNull(e.getMessage()), source.getMethod(), source.getProvider(), source.getProviderName(), request.getRemoteAddr(), getAllIps(request), - emptyIfNull(e.getLogin())); + preventLogFlood(emptyIfNull(e.getLogin()))); } private static String emptyIfNull(@Nullable String login) { return login == null ? "" : login; } + private static String preventLogFlood(String str) { + if (str.length() > FLOOD_THRESHOLD) { + return str.substring(0, FLOOD_THRESHOLD) + "...(" + str.length() + ")"; + } + return str; + } + } diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/event/AuthenticationEventImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/event/AuthenticationEventImplTest.java index f67c589c11e..b86235f2d08 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/authentication/event/AuthenticationEventImplTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/authentication/event/AuthenticationEventImplTest.java @@ -40,6 +40,9 @@ import static org.sonar.server.authentication.event.AuthenticationEvent.Source; import static org.sonar.server.authentication.event.AuthenticationException.newBuilder; public class AuthenticationEventImplTest { + private static final String LOGIN_129_CHARS = "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789012345678"; + @Rule public LogTester logTester = new LogTester(); @Rule @@ -75,6 +78,14 @@ public class AuthenticationEventImplTest { verifyLog("login success [method|BASIC][provider|REALM|some provider name][IP||][login|foo]"); } + @Test + public void login_prevents_log_flooding_on_login_starting_from_128_chars() { + underTest.login(mockRequest(), LOGIN_129_CHARS, Source.realm(Method.BASIC, "some provider name")); + + verifyLog("login success [method|BASIC][provider|REALM|some provider name][IP||][login|012345678901234567890123456789012345678901234567890123456789" + + "01234567890123456789012345678901234567890123456789012345678901234567...(129)]"); + } + @Test public void login_logs_remote_ip_from_request() { underTest.login(mockRequest("1.2.3.4"), "foo", Source.realm(Method.EXTERNAL, "bar")); @@ -131,22 +142,35 @@ public class AuthenticationEventImplTest { @Test public void failure_creates_INFO_log_with_method_provider_and_login() { AuthenticationException exception = newBuilder() - .setSource(Source.realm(Method.BASIC, "some provider name")) - .setMessage("something got terribly wrong") - .setLogin("BaR") - .build(); + .setSource(Source.realm(Method.BASIC, "some provider name")) + .setMessage("something got terribly wrong") + .setLogin("BaR") + .build(); underTest.failure(mockRequest(), exception); verifyLog("login failure [cause|something got terribly wrong][method|BASIC][provider|REALM|some provider name][IP||][login|BaR]"); } + @Test + public void failure_prevents_log_flooding_on_login_starting_from_128_chars() { + AuthenticationException exception = newBuilder() + .setSource(Source.realm(Method.BASIC, "some provider name")) + .setMessage("pop") + .setLogin(LOGIN_129_CHARS) + .build(); + underTest.failure(mockRequest(), exception); + + verifyLog("login failure [cause|pop][method|BASIC][provider|REALM|some provider name][IP||][login|012345678901234567890123456789012345678901234567890123456789" + + "01234567890123456789012345678901234567890123456789012345678901234567...(129)]"); + } + @Test public void failure_logs_remote_ip_from_request() { AuthenticationException exception = newBuilder() - .setSource(Source.realm(Method.EXTERNAL, "bar")) - .setMessage("Damn it!") - .setLogin("Baaad") - .build(); + .setSource(Source.realm(Method.EXTERNAL, "bar")) + .setMessage("Damn it!") + .setLogin("Baaad") + .build(); underTest.failure(mockRequest("1.2.3.4"), exception); verifyLog("login failure [cause|Damn it!][method|EXTERNAL][provider|REALM|bar][IP|1.2.3.4|][login|Baaad]"); @@ -155,10 +179,10 @@ public class AuthenticationEventImplTest { @Test public void failure_logs_X_Forwarded_For_header_from_request() { AuthenticationException exception = newBuilder() - .setSource(Source.realm(Method.EXTERNAL, "bar")) - .setMessage("Hop la!") - .setLogin("foo") - .build(); + .setSource(Source.realm(Method.EXTERNAL, "bar")) + .setMessage("Hop la!") + .setLogin("foo") + .build(); HttpServletRequest request = mockRequest("1.2.3.4", asList("2.3.4.5")); underTest.failure(request, exception); @@ -168,10 +192,10 @@ public class AuthenticationEventImplTest { @Test public void failure_logs_X_Forwarded_For_header_from_request_and_supports_multiple_headers() { AuthenticationException exception = newBuilder() - .setSource(Source.realm(Method.EXTERNAL, "bar")) - .setMessage("Boom!") - .setLogin("foo") - .build(); + .setSource(Source.realm(Method.EXTERNAL, "bar")) + .setMessage("Boom!") + .setLogin("foo") + .build(); HttpServletRequest request = mockRequest("1.2.3.4", asList("2.3.4.5", "6.5.4.3"), asList("9.5.6.7"), asList("6.3.2.4")); underTest.failure(request, exception); -- 2.39.5