diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/audit/event/AbstractUaaEvent.java b/server/src/main/java/org/cloudfoundry/identity/uaa/audit/event/AbstractUaaEvent.java index a8b0d4fcbda..576112f2835 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/audit/event/AbstractUaaEvent.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/audit/event/AbstractUaaEvent.java @@ -13,10 +13,10 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.audit.event; -import tools.jackson.core.type.TypeReference; import org.cloudfoundry.identity.uaa.audit.AuditEvent; import org.cloudfoundry.identity.uaa.audit.AuditEventType; import org.cloudfoundry.identity.uaa.audit.UaaAuditService; +import org.cloudfoundry.identity.uaa.authentication.UaaAuthenticationDetails; import org.cloudfoundry.identity.uaa.oauth.UaaOauth2Authentication; import org.cloudfoundry.identity.uaa.oauth.jwt.Jwt; import org.cloudfoundry.identity.uaa.oauth.jwt.JwtHelper; @@ -24,19 +24,24 @@ import org.cloudfoundry.identity.uaa.oauth.provider.authentication.OAuth2AuthenticationDetails; import org.cloudfoundry.identity.uaa.oauth.token.ClaimConstants; import org.cloudfoundry.identity.uaa.util.JsonUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationEvent; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.authentication.WebAuthenticationDetails; +import org.springframework.util.StringUtils; +import tools.jackson.core.type.TypeReference; import java.io.Serial; import java.security.Principal; import java.util.ArrayList; import java.util.Collection; import java.util.Map; +import java.util.Optional; import static org.cloudfoundry.identity.uaa.util.UaaTokenUtils.isJwtToken; -import static org.springframework.util.StringUtils.hasText; /** * Base class for UAA events that want to publish audit records. @@ -49,6 +54,9 @@ public abstract class AbstractUaaEvent extends ApplicationEvent { @Serial private static final long serialVersionUID = -7639844193401892160L; + + private static final Logger logger = LoggerFactory.getLogger(AbstractUaaEvent.class); + private final transient String zoneId; private Authentication authentication; @@ -115,35 +123,50 @@ private String getAuthenticationString(Authentication caller) { builder.append("caller=").append(caller.getName()); } - if (caller.getDetails() != null) { + Object details = caller.getDetails(); + if (details != null) { builder.append(", details=("); - try { - @SuppressWarnings("unchecked") - Map map = - JsonUtils.readValue((String) caller.getDetails(), new TypeReference>(){ - }); - if (map.containsKey("remoteAddress")) { - builder.append("remoteAddress=").append(map.get("remoteAddress")).append(", "); - } - builder.append("type=").append(caller.getDetails().getClass().getSimpleName()); - } catch (Exception _) { - // ignore - builder.append(caller.getDetails()); - } + extractRemoteAddress(details).ifPresent(address -> builder.append("remoteAddress=").append(address).append(", ")); + builder.append("type=").append(details.getClass().getSimpleName()); appendTokenDetails(caller, builder); builder.append(")"); } + return builder.toString(); } - protected void appendTokenDetails(Authentication caller, StringBuilder builder) { + private Optional extractRemoteAddress(Object details) { + return switch (details) { + case UaaAuthenticationDetails d -> Optional.ofNullable(d.getOrigin()).filter(StringUtils::hasText); + case OAuth2AuthenticationDetails d -> Optional.ofNullable(d.getRemoteAddress()).filter(StringUtils::hasText); + case WebAuthenticationDetails d -> Optional.ofNullable(d.getRemoteAddress()).filter(StringUtils::hasText); + case Map map -> Optional.ofNullable(map.get("remoteAddress")).map(Object::toString).filter(StringUtils::hasText); + case String jsonBlob -> extractRemoteAddressFromJson(jsonBlob); + default -> { + logger.warn("Unhandled Authentication.details type in audit origin: {}", details.getClass().getName()); + yield Optional.empty(); + } + }; + } + + private Optional extractRemoteAddressFromJson(String jsonBlob) { + try { + Map map = JsonUtils.readValue(jsonBlob, new TypeReference<>() { + }); + return map == null ? Optional.empty() : extractRemoteAddress(map); + } catch (JsonUtils.JsonUtilException _) { + return Optional.empty(); + } + } + + private void appendTokenDetails(Authentication caller, StringBuilder builder) { String tokenValue = null; if (caller instanceof UaaOauth2Authentication uaaOauth2Authentication) { tokenValue = uaaOauth2Authentication.getTokenValue(); } else if (caller.getDetails() instanceof OAuth2AuthenticationDetails oAuth2AuthenticationDetails) { tokenValue = oAuth2AuthenticationDetails.getTokenValue(); } - if (hasText(tokenValue)) { + if (StringUtils.hasText(tokenValue)) { if (isJwtToken(tokenValue)) { try { Jwt token = JwtHelper.decode(tokenValue); diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/event/AbstractUaaAuthenticationEvent.java b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/event/AbstractUaaAuthenticationEvent.java index 66322930102..e8590120d10 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/event/AbstractUaaAuthenticationEvent.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/event/AbstractUaaAuthenticationEvent.java @@ -17,6 +17,10 @@ import org.cloudfoundry.identity.uaa.authentication.UaaAuthenticationDetails; import org.springframework.security.core.Authentication; +import java.util.StringJoiner; + +import static org.springframework.util.StringUtils.hasText; + /** * @author Luke Taylor */ @@ -27,7 +31,21 @@ public abstract class AbstractUaaAuthenticationEvent extends AbstractUaaEvent { } protected String getOrigin(UaaAuthenticationDetails details) { - return details == null ? "unknown" : details.toString(); + if (details == null) { + return "unknown"; + } + + StringJoiner joiner = new StringJoiner(", "); + + if (hasText(details.getOrigin())) { + joiner.add("remoteAddress=" + details.getOrigin()); + } + + if (hasText(details.getClientId())) { + joiner.add("clientId=" + details.getClientId()); + } + + return joiner.length() == 0 ? "unknown" : joiner.toString(); } UaaAuthenticationDetails getAuthenticationDetails() { diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/audit/event/AbstractUaaEventTest.java b/server/src/test/java/org/cloudfoundry/identity/uaa/audit/event/AbstractUaaEventTest.java index c96444eee24..1af4eb57329 100644 --- a/server/src/test/java/org/cloudfoundry/identity/uaa/audit/event/AbstractUaaEventTest.java +++ b/server/src/test/java/org/cloudfoundry/identity/uaa/audit/event/AbstractUaaEventTest.java @@ -4,6 +4,7 @@ import org.cloudfoundry.identity.uaa.audit.AuditEventType; import org.cloudfoundry.identity.uaa.audit.JdbcAuditService; import org.cloudfoundry.identity.uaa.audit.UaaAuditService; +import org.cloudfoundry.identity.uaa.authentication.UaaAuthenticationDetails; import org.cloudfoundry.identity.uaa.oauth.UaaOauth2Authentication; import org.cloudfoundry.identity.uaa.oauth.provider.OAuth2Authentication; import org.cloudfoundry.identity.uaa.oauth.provider.OAuth2Request; @@ -16,6 +17,7 @@ import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.authentication.WebAuthenticationDetails; import java.util.Map; @@ -69,19 +71,34 @@ void getContextAuthentication() { } @Test - void getOrigin() { + void getOrigin_whenMapDetailsHasNoKnownKeys_doesNotLeakMapContents() { UaaOauth2Authentication authentication = mock(UaaOauth2Authentication.class); OAuth2Request oAuth2Request = mock(OAuth2Request.class); when(authentication.getOAuth2Request()).thenReturn(oAuth2Request); when(authentication.getName()).thenReturn("marissa"); - when(authentication.getDetails()).thenReturn(Map.of("misc", "somedetails", "remoteAddress", "external")); + when(authentication.getDetails()).thenReturn(Map.of("grant_type", "password", "username", "marissa", "client_id", "clientid")); SecurityContextHolder.getContext().setAuthentication(authentication); String originString = event.getOrigin(authentication); assertThat(originString).contains("marissa") .contains("client=null") - .contains("misc=somedetails") - .contains("remoteAddress=external") - .contains("details=({"); + .doesNotContain("remoteAddress=") + .doesNotContain("grant_type=") + .doesNotContain("username=") + .doesNotContain("client_id="); + } + + @Test + void getOrigin_whenMapDetailsContainsRemoteAddress_extractsRemoteAddress() { + UaaOauth2Authentication authentication = mock(UaaOauth2Authentication.class); + OAuth2Request oAuth2Request = mock(OAuth2Request.class); + when(authentication.getOAuth2Request()).thenReturn(oAuth2Request); + when(authentication.getName()).thenReturn("marissa"); + when(authentication.getDetails()).thenReturn(Map.of("grant_type", "password", "remoteAddress", "10.0.0.1")); + SecurityContextHolder.getContext().setAuthentication(authentication); + String originString = event.getOrigin(authentication); + assertThat(originString).contains("marissa") + .contains("remoteAddress=10.0.0.1") + .doesNotContain("grant_type="); } @Test @@ -102,9 +119,97 @@ void getOriginDetailsParsed() { .contains("client=null") .doesNotContain("misc=somedetails") .contains("remoteAddress=external") + .contains("type=String") .doesNotContain("{"); } + @Test + void getOrigin_whenOAuth2AuthenticationWithUser_emitsClientAndUser() { + OAuth2Authentication authentication = mock(OAuth2Authentication.class); + OAuth2Request oAuth2Request = mock(OAuth2Request.class); + when(authentication.getOAuth2Request()).thenReturn(oAuth2Request); + when(oAuth2Request.getClientId()).thenReturn("clientid"); + when(authentication.isClientOnly()).thenReturn(false); + when(authentication.getName()).thenReturn("marissa"); + SecurityContextHolder.getContext().setAuthentication(authentication); + String originString = event.getOrigin(authentication); + assertThat(originString).contains("client=clientid") + .contains("user=marissa"); + } + + @Test + void getOrigin_whenStringDetailsIsNotJson_omitsRemoteAddress() { + UaaOauth2Authentication authentication = mock(UaaOauth2Authentication.class); + OAuth2Request oAuth2Request = mock(OAuth2Request.class); + when(authentication.getOAuth2Request()).thenReturn(oAuth2Request); + when(authentication.getName()).thenReturn("marissa"); + when(authentication.getDetails()).thenReturn("session-id-abc"); + SecurityContextHolder.getContext().setAuthentication(authentication); + String originString = event.getOrigin(authentication); + assertThat(originString).contains("marissa") + .contains("type=String") + .doesNotContain("remoteAddress="); + } + + @Test + void getOrigin_whenJsonDetailsMissingRemoteAddress_omitsRemoteAddress() { + UaaOauth2Authentication authentication = mock(UaaOauth2Authentication.class); + OAuth2Request oAuth2Request = mock(OAuth2Request.class); + when(authentication.getOAuth2Request()).thenReturn(oAuth2Request); + when(authentication.getName()).thenReturn("marissa"); + when(authentication.getDetails()).thenReturn("{\"remoteAddress\":null,\"sessionId\":\"abc\"}"); + SecurityContextHolder.getContext().setAuthentication(authentication); + String originString = event.getOrigin(authentication); + assertThat(originString).contains("marissa") + .contains("type=String") + .doesNotContain("remoteAddress="); + } + + @Test + void getOrigin_whenUaaAuthenticationDetails_extractsRemoteAddressFromAccessor() { + UaaOauth2Authentication authentication = mock(UaaOauth2Authentication.class); + OAuth2Request oAuth2Request = mock(OAuth2Request.class); + when(authentication.getOAuth2Request()).thenReturn(oAuth2Request); + when(authentication.getName()).thenReturn("marissa"); + UaaAuthenticationDetails uaaDetails = mock(UaaAuthenticationDetails.class); + when(uaaDetails.getOrigin()).thenReturn("10.0.0.1"); + when(authentication.getDetails()).thenReturn(uaaDetails); + SecurityContextHolder.getContext().setAuthentication(authentication); + String originString = event.getOrigin(authentication); + assertThat(originString).contains("details=(remoteAddress=10.0.0.1, type=UaaAuthenticationDetails"); + } + + @Test + void getOrigin_whenOAuth2AuthenticationDetails_extractsRemoteAddressFromAccessor() { + OAuth2Authentication authentication = mock(OAuth2Authentication.class); + OAuth2Request oAuth2Request = mock(OAuth2Request.class); + when(authentication.getOAuth2Request()).thenReturn(oAuth2Request); + when(oAuth2Request.getClientId()).thenReturn("clientid"); + when(authentication.isClientOnly()).thenReturn(true); + OAuth2AuthenticationDetails oauthDetails = mock(OAuth2AuthenticationDetails.class); + when(oauthDetails.getRemoteAddress()).thenReturn("172.18.0.1"); + when(authentication.getDetails()).thenReturn(oauthDetails); + SecurityContextHolder.getContext().setAuthentication(authentication); + String originString = event.getOrigin(authentication); + assertThat(originString).contains("client=clientid") + .contains("details=(remoteAddress=172.18.0.1, type=OAuth2AuthenticationDetails"); + } + + @Test + void getOrigin_whenWebAuthenticationDetails_extractsRemoteAddressFromAccessor() { + UaaOauth2Authentication authentication = mock(UaaOauth2Authentication.class); + OAuth2Request oAuth2Request = mock(OAuth2Request.class); + when(authentication.getOAuth2Request()).thenReturn(oAuth2Request); + when(authentication.getName()).thenReturn("marissa"); + WebAuthenticationDetails webDetails = mock(WebAuthenticationDetails.class); + when(webDetails.getRemoteAddress()).thenReturn("192.168.1.5"); + when(authentication.getDetails()).thenReturn(webDetails); + SecurityContextHolder.getContext().setAuthentication(authentication); + String originString = event.getOrigin(authentication); + assertThat(originString).contains("marissa") + .contains("details=(remoteAddress=192.168.1.5, type=WebAuthenticationDetails"); + } + @Test void getAuthenticationJsonWebTokenValue() { String originTokenString = event.getOrigin(mockAuthenticationWithToken("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXJpc3NhIiwiaXNzIjoidWFhIn0.omitted")); diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/event/UserAuthenticationSuccessEventTests.java b/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/event/UserAuthenticationSuccessEventTests.java index 5dd171d6412..8373c412f98 100644 --- a/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/event/UserAuthenticationSuccessEventTests.java +++ b/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/event/UserAuthenticationSuccessEventTests.java @@ -27,6 +27,6 @@ void getOriginFromRequest() { assertThat(origin).contains("remoteAddress=127.10.10.10") .contains("clientId=client-id") - .contains("sessionId="); + .doesNotContain("sessionId"); } } diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/audit/AuditCheckMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/audit/AuditCheckMockMvcTests.java index 5b25e070970..c494a73408b 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/audit/AuditCheckMockMvcTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/audit/AuditCheckMockMvcTests.java @@ -252,19 +252,17 @@ void userLoginTest() throws Exception { IdentityProviderAuthenticationSuccessEvent passwordEvent = testListener.getLatestEventOfType(IdentityProviderAuthenticationSuccessEvent.class); assertThat(passwordEvent.getUser().getUsername()).isEqualTo(testUser.getUserName()); - assertThat(passwordEvent.getAuditEvent().getOrigin()).contains("sessionId="); UserAuthenticationSuccessEvent userEvent = testListener.getLatestEventOfType(UserAuthenticationSuccessEvent.class); assertThat(userEvent.getUser().getId()).isEqualTo(passwordEvent.getUser().getId()); assertThat(userEvent.getUser().getUsername()).isEqualTo(testUser.getUserName()); - assertThat(userEvent.getAuditEvent().getOrigin()).contains("sessionId="); assertThat(passwordEvent.getAuthenticationType()).isEqualTo(OriginKeys.UAA); String passwordLogMsg = testLogger.getFirstLogMessageOfType(IdentityProviderAuthenticationSuccess); - assertLogMessageWithSession(passwordLogMsg, IdentityProviderAuthenticationSuccess, testUser.getId(), testUser.getUserName()); + assertLogMessage(passwordLogMsg, IdentityProviderAuthenticationSuccess, testUser.getId(), testUser.getUserName()); String userEventLogMsg = testLogger.getFirstLogMessageOfType(UserAuthenticationSuccess); - assertLogMessageWithSession(userEventLogMsg, UserAuthenticationSuccess, testUser.getId(), testUser.getUserName()); + assertLogMessage(userEventLogMsg, UserAuthenticationSuccess, testUser.getId(), testUser.getUserName()); } @ParameterizedTest @@ -288,19 +286,17 @@ void userLoginAuthenticateEndpointTest(String url) throws Exception { IdentityProviderAuthenticationSuccessEvent passwordEvent = testListener.getLatestEventOfType(IdentityProviderAuthenticationSuccessEvent.class); assertThat(passwordEvent.getUser().getUsername()).isEqualTo(testUser.getUserName()); - assertThat(passwordEvent.getAuditEvent().getOrigin()).contains("sessionId="); UserAuthenticationSuccessEvent userEvent = testListener.getLatestEventOfType(UserAuthenticationSuccessEvent.class); assertThat(userEvent.getUser().getId()).isEqualTo(passwordEvent.getUser().getId()); assertThat(userEvent.getUser().getUsername()).isEqualTo(testUser.getUserName()); - assertThat(userEvent.getAuditEvent().getOrigin()).contains("sessionId="); assertThat(passwordEvent.getAuthenticationType()).isEqualTo(OriginKeys.UAA); String passwordLogMsg = testLogger.getFirstLogMessageOfType(IdentityProviderAuthenticationSuccess); - assertLogMessageWithSession(passwordLogMsg, IdentityProviderAuthenticationSuccess, testUser.getId(), testUser.getUserName()); + assertLogMessage(passwordLogMsg, IdentityProviderAuthenticationSuccess, testUser.getId(), testUser.getUserName()); String userEventLogMsg = testLogger.getFirstLogMessageOfType(UserAuthenticationSuccess); - assertLogMessageWithSession(userEventLogMsg, UserAuthenticationSuccess, testUser.getId(), testUser.getUserName()); + assertLogMessage(userEventLogMsg, UserAuthenticationSuccess, testUser.getId(), testUser.getUserName()); } @Test @@ -321,24 +317,21 @@ void invalidPasswordLoginUnsuccessfulTest() throws Exception { IdentityProviderAuthenticationFailureEvent idpAuthFailEvent = (IdentityProviderAuthenticationFailureEvent) testListener.getEvents().getFirst(); assertThat(idpAuthFailEvent.getUsername()).isEqualTo(testUser.getUserName()); - assertThat(idpAuthFailEvent.getAuditEvent().getOrigin()).contains("sessionId="); UserAuthenticationFailureEvent userAuthFailEvent = (UserAuthenticationFailureEvent) testListener.getEvents().get(1); assertThat(userAuthFailEvent.getUser().getUsername()).isEqualTo(testUser.getUserName()); - assertThat(userAuthFailEvent.getAuditEvent().getOrigin()).contains("sessionId="); PrincipalAuthenticationFailureEvent principalAuthFailEvent = (PrincipalAuthenticationFailureEvent) testListener.getEvents().get(2); assertThat(principalAuthFailEvent.getName()).isEqualTo(testUser.getUserName()); - assertThat(principalAuthFailEvent.getAuditEvent().getOrigin()).doesNotContain("sessionId"); // PrincipalAuthenticationFailureEvent should not contain sessionId at all String idpAuthFailMsg = testLogger.getMessageAtIndex(0); - assertLogMessageWithSession(idpAuthFailMsg, IdentityProviderAuthenticationFailure, "null", testUser.getUserName()); + assertLogMessage(idpAuthFailMsg, IdentityProviderAuthenticationFailure, "null", testUser.getUserName()); String userAuthFailMsg = testLogger.getMessageAtIndex(1); - assertLogMessageWithSession(userAuthFailMsg, UserAuthenticationFailure, testUser.getId(), testUser.getUserName()); + assertLogMessage(userAuthFailMsg, UserAuthenticationFailure, testUser.getId(), testUser.getUserName()); String principalAuthFailMsg = testLogger.getMessageAtIndex(2); - assertLogMessageWithoutSession(principalAuthFailMsg, PrincipalAuthenticationFailure, testUser.getUserName(), "null"); + assertLogMessage(principalAuthFailMsg, PrincipalAuthenticationFailure, testUser.getUserName(), "null"); } @Test @@ -371,10 +364,9 @@ void unverifiedLegacyUserAuthenticationWhenAllowedTest( verify(authSuccessListener, times(1)).onApplicationEvent(captor.capture()); UserAuthenticationSuccessEvent event = captor.getValue(); assertThat(event.getUser().getUsername()).isEqualTo(molly.getUserName()); - assertThat(event.getAuditEvent().getOrigin()).contains("sessionId="); String userAuthLogMsg = testLogger.getFirstLogMessageOfType(UserAuthenticationSuccess); - assertLogMessageWithSession(userAuthLogMsg, UserAuthenticationSuccess, molly.getId(), molly.getUserName()); + assertLogMessage(userAuthLogMsg, UserAuthenticationSuccess, molly.getId(), molly.getUserName()); } @Test @@ -400,10 +392,9 @@ void unverifiedPostLegacyUserAuthenticationWhenAllowedTest() throws Exception { UnverifiedUserAuthenticationEvent unverifiedUserAuthEvent = testListener.getLatestEventOfType(UnverifiedUserAuthenticationEvent.class); assertThat(unverifiedUserAuthEvent.getUser().getUsername()).isEqualTo(molly.getUserName()); - assertThat(unverifiedUserAuthEvent.getAuditEvent().getOrigin()).contains("sessionId="); String userAuthLogMsg = testLogger.getFirstLogMessageOfType(UnverifiedUserAuthentication); - assertLogMessageWithSession(userAuthLogMsg, UnverifiedUserAuthentication, molly.getId(), molly.getUserName()); + assertLogMessage(userAuthLogMsg, UnverifiedUserAuthentication, molly.getId(), molly.getUserName()); } @Test @@ -427,10 +418,9 @@ void unverifiedUserAuthenticationWhenNotAllowedTest() throws Exception { UnverifiedUserAuthenticationEvent event = (UnverifiedUserAuthenticationEvent) testListener.getLatestEvent(); assertThat(event.getUser().getUsername()).isEqualTo(molly.getUserName()); - assertThat(event.getAuditEvent().getOrigin()).contains("sessionId="); String userAuthLogMsg = testLogger.getFirstLogMessageOfType(UnverifiedUserAuthentication); - assertLogMessageWithSession(userAuthLogMsg, UnverifiedUserAuthentication, molly.getId(), molly.getUserName()); + assertLogMessage(userAuthLogMsg, UnverifiedUserAuthentication, molly.getId(), molly.getUserName()); } @Test @@ -453,19 +443,15 @@ void invalidPasswordLoginAuthenticateEndpointTest() throws Exception { assertThat(event1.getUsername()).isEqualTo(testUser.getUserName()); assertThat(event2.getUser().getUsername()).isEqualTo(testUser.getUserName()); assertThat(event3.getName()).isEqualTo(testUser.getUserName()); - assertThat(event1.getAuditEvent().getOrigin()).contains("sessionId="); - assertThat(event2.getAuditEvent().getOrigin()).contains("sessionId="); - // PrincipalAuthenticationFailureEvent does not contain sessionId at all - assertThat(event3.getAuditEvent().getOrigin()).doesNotContain("sessionId="); String idpAuthLogMsg = testLogger.getMessageAtIndex(0); - assertLogMessageWithSession(idpAuthLogMsg, IdentityProviderAuthenticationFailure, "null", testUser.getUserName()); + assertLogMessage(idpAuthLogMsg, IdentityProviderAuthenticationFailure, "null", testUser.getUserName()); String userAuthLogMsg = testLogger.getMessageAtIndex(1); - assertLogMessageWithSession(userAuthLogMsg, UserAuthenticationFailure, testUser.getId(), testUser.getUserName()); + assertLogMessage(userAuthLogMsg, UserAuthenticationFailure, testUser.getId(), testUser.getUserName()); String principalAuthLogMsg = testLogger.getMessageAtIndex(2); - assertLogMessageWithoutSession(principalAuthLogMsg, PrincipalAuthenticationFailure, testUser.getUserName(), "null"); + assertLogMessage(principalAuthLogMsg, PrincipalAuthenticationFailure, testUser.getUserName(), "null"); } @Test @@ -493,9 +479,6 @@ void findAuditHistory(@Autowired JdbcAuditService auditService) throws Exception //after we reach our max attempts, 5, the system stops logging them until the period is over List events = auditService.find(jacobId, System.currentTimeMillis() - 10000, identityZoneManager.getCurrentIdentityZoneId()); assertThat(events).hasSize(5); - for (AuditEvent event : events) { - assertThat(event.getOrigin()).contains("sessionId="); - } } @Test @@ -517,16 +500,13 @@ void userNotFoundLoginUnsuccessfulTest() throws Exception { assertThatNumberOfAuditEventsReceivedIsGreaterThanOrEqualTo(2); UserNotFoundEvent event1 = (UserNotFoundEvent) testListener.getEvents().getFirst(); - assertThat(event1.getAuditEvent().getOrigin()).contains("sessionId="); PrincipalAuthenticationFailureEvent event2 = (PrincipalAuthenticationFailureEvent) testListener.getEvents().get(1); assertThat(((Authentication) event1.getSource()).getName()).isEqualTo(username); assertThat(event2.getName()).isEqualTo(username); - // PrincipalAuthenticationFailureEvent does not contain sessionId at all - assertThat(event2.getAuditEvent().getOrigin()).doesNotContain("sessionId="); String encodedUsername = Utf8.decode(Base64.encodeBase64(MessageDigest.getInstance("SHA-1").digest(Utf8.encode(username)))); - assertLogMessageWithSession(testLogger.getMessageAtIndex(0), UserNotFound, encodedUsername, ""); - assertLogMessageWithoutSession(testLogger.getMessageAtIndex(1), PrincipalAuthenticationFailure, username, "null"); + assertLogMessage(testLogger.getMessageAtIndex(0), UserNotFound, encodedUsername, ""); + assertLogMessage(testLogger.getMessageAtIndex(1), PrincipalAuthenticationFailure, username, "null"); } @Test @@ -547,17 +527,15 @@ void userChangePasswordTest() throws Exception { IdentityProviderAuthenticationSuccessEvent passwordevent = testListener.getLatestEventOfType(IdentityProviderAuthenticationSuccessEvent.class); String userid = passwordevent.getUser().getId(); - assertThat(passwordevent.getAuditEvent().getOrigin()).contains("sessionId="); UserAuthenticationSuccessEvent userevent = testListener.getLatestEventOfType(UserAuthenticationSuccessEvent.class); assertThat(userevent.getUser().getId()).isEqualTo(passwordevent.getUser().getId()); - assertThat(userevent.getAuditEvent().getOrigin()).contains("sessionId="); assertThat(passwordevent.getAuthenticationType()).isEqualTo(OriginKeys.UAA); String passwordLogMsg = testLogger.getFirstLogMessageOfType(IdentityProviderAuthenticationSuccess); - assertLogMessageWithSession(passwordLogMsg, IdentityProviderAuthenticationSuccess, testUser.getId(), testUser.getUserName()); + assertLogMessage(passwordLogMsg, IdentityProviderAuthenticationSuccess, testUser.getId(), testUser.getUserName()); String userEventLogMsg = testLogger.getFirstLogMessageOfType(UserAuthenticationSuccess); - assertLogMessageWithSession(userEventLogMsg, UserAuthenticationSuccess, testUser.getId(), testUser.getUserName()); + assertLogMessage(userEventLogMsg, UserAuthenticationSuccess, testUser.getId(), testUser.getUserName()); resetAuditTestReceivers(); String marissaToken = testClient.getUserOAuthAccessToken("app", "appclientsecret", testUser.getUserName(), testPassword, "password.write"); @@ -583,11 +561,10 @@ void userChangePasswordTest() throws Exception { PasswordChangeEvent pw = (PasswordChangeEvent) testListener.getLatestEvent(); assertThat(pw.getUser().getUsername()).isEqualTo(testUser.getUserName()); assertThat(pw.getMessage()).isEqualTo("Password changed"); - assertThat(pw.getAuditEvent().getOrigin()).contains("sessionId="); assertThat(pw.getAuditEvent().getPrincipalName()).isEqualTo(testUser.getUserName()); String pwLogMsg = testLogger.getLatestMessage(); - assertLogMessageWithSession(pwLogMsg, PasswordChangeSuccess, testUser.getId(), "Password changed"); + assertLogMessage(pwLogMsg, PasswordChangeSuccess, testUser.getId(), "Password changed"); assertThat(pwLogMsg).contains("principalName=[%s]".formatted(testUser.getUserName())); } @@ -610,17 +587,15 @@ void userChangeInvalidPasswordTest() throws Exception { IdentityProviderAuthenticationSuccessEvent passwordevent = testListener.getLatestEventOfType(IdentityProviderAuthenticationSuccessEvent.class); String userid = passwordevent.getUser().getId(); - assertThat(passwordevent.getAuditEvent().getOrigin()).contains("sessionId="); UserAuthenticationSuccessEvent userevent = testListener.getLatestEventOfType(UserAuthenticationSuccessEvent.class); assertThat(userevent.getUser().getId()).isEqualTo(passwordevent.getUser().getId()); - assertThat(userevent.getAuditEvent().getOrigin()).contains("sessionId="); assertThat(passwordevent.getAuthenticationType()).isEqualTo(OriginKeys.UAA); String passwordLogMsg = testLogger.getFirstLogMessageOfType(IdentityProviderAuthenticationSuccess); - assertLogMessageWithSession(passwordLogMsg, IdentityProviderAuthenticationSuccess, testUser.getId(), testUser.getUserName()); + assertLogMessage(passwordLogMsg, IdentityProviderAuthenticationSuccess, testUser.getId(), testUser.getUserName()); String userEventLogMsg = testLogger.getFirstLogMessageOfType(UserAuthenticationSuccess); - assertLogMessageWithSession(userEventLogMsg, UserAuthenticationSuccess, testUser.getId(), testUser.getUserName()); + assertLogMessage(userEventLogMsg, UserAuthenticationSuccess, testUser.getId(), testUser.getUserName()); resetAuditTestReceivers(); String marissaToken = testClient.getUserOAuthAccessToken("app", "appclientsecret", testUser.getUserName(), testPassword, "password.write"); @@ -648,11 +623,10 @@ void userChangeInvalidPasswordTest() throws Exception { PasswordChangeFailureEvent pwfe = (PasswordChangeFailureEvent) testListener.getLatestEvent(); assertThat(pwfe.getUser().getUsername()).isEqualTo(testUser.getUserName()); assertThat(pwfe.getMessage()).isEqualTo("Old password is incorrect"); - assertThat(pwfe.getAuditEvent().getOrigin()).contains("sessionId="); assertThat(pwfe.getAuditEvent().getPrincipalName()).isEqualTo(testUser.getUserName()); String pwfeLogMsg = testLogger.getLatestMessage(); - assertLogMessageWithSession(pwfeLogMsg, PasswordChangeFailure, testUser.getId(), "Old password is incorrect"); + assertLogMessage(pwfeLogMsg, PasswordChangeFailure, testUser.getId(), "Old password is incorrect"); assertThat(pwfeLogMsg).contains("principalName=[%s]".formatted(testUser.getUserName())); } @@ -672,7 +646,7 @@ void password_change_recorded_at_dao(@Autowired ScimUserProvisioning provisionin assertThat(pw.getAuditEvent().getPrincipalName()).isEqualTo(user.getUserName()); String pwLogMsg = testLogger.getLatestMessage(); - assertLogMessageWithoutSession(pwLogMsg, PasswordChangeSuccess, user.getId(), "Password changed"); + assertLogMessage(pwLogMsg, PasswordChangeSuccess, user.getId(), "Password changed"); assertThat(pwLogMsg).contains("principalName=[%s]".formatted(user.getUserName())); } @@ -701,11 +675,10 @@ void changePassword_ReturnsSuccess_WithValidExpiringCode() throws Exception { assertThat(pce.getUser().getUsername()).isEqualTo(testUser.getUserName()); assertThat(pce.getMessage()).isEqualTo("Password changed"); //PasswordChangeEvent does not contain session in this case - assertThat(pce.getAuditEvent().getOrigin()).doesNotContain("sessionId="); assertThat(pce.getAuditEvent().getPrincipalName()).isEqualTo(testUser.getUserName()); String pceLogMsg = testLogger.getLatestMessage(); - assertLogMessageWithoutSession(pceLogMsg, PasswordChangeSuccess, testUser.getId(), "Password changed"); + assertLogMessage(pceLogMsg, PasswordChangeSuccess, testUser.getId(), "Password changed"); assertThat(pceLogMsg).contains("principalName=[%s]".formatted(testUser.getUserName())); } @@ -726,7 +699,7 @@ void clientAuthenticationSuccess() throws Exception { AuditEvent auditEvent = event.getAuditEvent(); assertThat(auditEvent.getPrincipalId()).isEqualTo("login"); - assertLogMessageWithoutSession(testLogger.getMessageAtIndex(0), ClientAuthenticationSuccess, "login", "Client authentication success"); + assertLogMessage(testLogger.getMessageAtIndex(0), ClientAuthenticationSuccess, "login", "Client authentication success"); } @Test @@ -746,7 +719,7 @@ void clientAuthenticationFailure() throws Exception { AuditEvent auditEvent = event.getAuditEvent(); assertThat(auditEvent.getPrincipalId()).isEqualTo("login"); - assertLogMessageWithoutSession(testLogger.getLatestMessage(), ClientAuthenticationFailure, "login", "Bad credentials"); + assertLogMessage(testLogger.getLatestMessage(), ClientAuthenticationFailure, "login", "Bad credentials"); } @Test @@ -767,8 +740,8 @@ void clientAuthenticationFailureClientNotFound() throws Exception { ClientAuthenticationFailureEvent event1 = (ClientAuthenticationFailureEvent) testListener.getEvents().get(1); assertThat(event1.getClientId()).isEqualTo("login"); - assertLogMessageWithoutSession(testLogger.getMessageAtIndex(0), PrincipalAuthenticationFailure, "login2", "null"); - assertLogMessageWithoutSession(testLogger.getMessageAtIndex(1), ClientAuthenticationFailure, "login", "Bad credentials"); + assertLogMessage(testLogger.getMessageAtIndex(0), PrincipalAuthenticationFailure, "login2", "null"); + assertLogMessage(testLogger.getMessageAtIndex(1), ClientAuthenticationFailure, "login", "Bad credentials"); } @Test @@ -799,11 +772,10 @@ void userApprovalAdded() throws Exception { ApprovalModifiedEvent approvalModifiedEvent = (ApprovalModifiedEvent) testListener.getLatestEvent(); assertThat(approvalModifiedEvent.getAuthentication().getName()).isEqualTo(testUser.getUserName()); - assertThat(approvalModifiedEvent.getAuditEvent().getOrigin()).contains("sessionId="); String latestMessage = testLogger.getLatestMessage(); assertThat(latestMessage).contains(" user=" + testUser.getUserName()); - assertLogMessageWithSession(latestMessage, ApprovalModifiedEvent, testUser.getId(), "{\"scope\":\"cloud_controller.read\",\"status\":\"APPROVED\"}"); + assertLogMessage(latestMessage, ApprovalModifiedEvent, testUser.getId(), "{\"scope\":\"cloud_controller.read\",\"status\":\"APPROVED\"}"); } @Test @@ -833,14 +805,13 @@ void generateUserModifiedEvent_whenUserCreatedByClient() throws Exception { assertThat(userModifiedEvent.getAuthentication().getName()).isEqualTo(testAccounts.getAdminClientId()); assertThat(userModifiedEvent.getUsername()).isEqualTo(scimUser.getUserName()); assertThat(userModifiedEvent.getAuditEvent().getType()).isEqualTo(UserCreatedEvent); - assertThat(userModifiedEvent.getAuditEvent().getOrigin()).contains("sessionId="); ScimUser createdUser = jdbcScimUserProvisioning.retrieveAll(identityZoneManager.getCurrentIdentityZoneId()) .stream().filter(dbUser -> dbUser.getUserName().equals(scimUser.getUserName())).findFirst().get(); String logMessage = "[\"user_id=%s\",\"username=%s\"]".formatted( createdUser.getId(), scimUser.getUserName()); - assertLogMessageWithSession(testLogger.getLatestMessage(), + assertLogMessage(testLogger.getLatestMessage(), UserCreatedEvent, createdUser.getId(), logMessage); } @@ -905,8 +876,7 @@ void generateUserModifiedEvent_whenCreatingUser( assertThat(actualLogMessage).startsWith(UserCreatedEvent.toString()) .contains("principal=%s,".formatted(createdUser.getId())) .contains(logMessage) - .contains(", identityZoneId=[%s]".formatted(zoneSeeder.getIdentityZoneId())) - .matches(".*origin=\\[.*sessionId=.*\\].*"); + .contains(", identityZoneId=[%s]".formatted(zoneSeeder.getIdentityZoneId())); } @Test @@ -947,8 +917,7 @@ void generateUserDeletedEvent_whenDeletingUser( assertThat(actualLogMessage).startsWith(UserDeletedEvent.toString()) .contains("principal=%s,".formatted(scimUser.getId())) .contains(" ('%s'): ".formatted(logMessage)) - .contains(", identityZoneId=[%s]".formatted(zoneSeeder.getIdentityZoneId())) - .matches(".*origin=\\[.*sessionId=.*\\].*"); + .contains(", identityZoneId=[%s]".formatted(zoneSeeder.getIdentityZoneId())); } } @@ -990,7 +959,6 @@ void generateUserCreatedEvent_DuringLoginServerAuthorize() throws Exception { assertThat(userModifiedEvent.getAuthentication().getName()).isEqualTo("login"); assertThat(userModifiedEvent.getUsername()).isEqualTo(username); assertThat(userModifiedEvent.getAuditEvent().getType()).isEqualTo(UserCreatedEvent); - assertThat(userModifiedEvent.getAuditEvent().getOrigin()).contains("sessionId="); ScimUser createdUser = jdbcScimUserProvisioning.retrieveAll(identityZoneManager.getCurrentIdentityZoneId()) .stream().filter(dbUser -> dbUser.getUserName().equals(username)).findFirst().get(); @@ -999,7 +967,7 @@ void generateUserCreatedEvent_DuringLoginServerAuthorize() throws Exception { createdUser.getId(), username); - assertLogMessageWithSession(testLogger.getMessageAtIndex(0), + assertLogMessage(testLogger.getMessageAtIndex(0), UserCreatedEvent, createdUser.getId(), logMessage); } @@ -1060,10 +1028,9 @@ void generateUserModifiedEvent_whenModifyingUser( assertThat(userModifiedEvent.getAuthentication().getName()).isEqualTo(testAccounts.getAdminClientId()); assertThat(userModifiedEvent.getUsername()).isEqualTo(scimUser.getUserName()); assertThat(userModifiedEvent.getAuditEvent().getType()).isEqualTo(UserModifiedEvent); - assertThat(userModifiedEvent.getAuditEvent().getOrigin()).contains("sessionId="); String logMessage = "[\"user_id=%s\",\"username=%s\"]".formatted(scimUser.getId(), scimUser.getUserName()); - assertLogMessageWithSession(testLogger.getLatestMessage(), + assertLogMessage(testLogger.getLatestMessage(), UserModifiedEvent, scimUser.getId(), logMessage); @@ -1089,12 +1056,11 @@ void generateUserDeletedEvent_whenDeletingUser( assertThat(userDeletedEvent.getAuthentication().getName()).isEqualTo(testAccounts.getAdminClientId()); assertThat(userDeletedEvent.getUsername()).isEqualTo(scimUser.getUserName()); assertThat(userDeletedEvent.getAuditEvent().getType()).isEqualTo(UserDeletedEvent); - assertThat(userDeletedEvent.getAuditEvent().getOrigin()).contains("sessionId="); String logMessage = "[\"user_id=%s\",\"username=%s\"]".formatted( scimUser.getId(), scimUser.getUserName()); - assertLogMessageWithSession(testLogger.getLatestMessage(), + assertLogMessage(testLogger.getLatestMessage(), UserDeletedEvent, scimUser.getId(), logMessage); } } @@ -1143,9 +1109,8 @@ void userVerifiedEvent() throws Exception { assertThat(userModifiedEvent.getAuthentication().getName()).isEqualTo(testAccounts.getAdminClientId()); assertThat(userModifiedEvent.getUsername()).isEqualTo(username); assertThat(userModifiedEvent.getAuditEvent().getType()).isEqualTo(UserVerifiedEvent); - assertThat(userModifiedEvent.getAuditEvent().getOrigin()).contains("sessionId="); - assertLogMessageWithSession(testLogger.getLatestMessage(), + assertLogMessage(testLogger.getLatestMessage(), UserVerifiedEvent, user.getId(), "[\"user_id=%s\",\"username=%s\"]".formatted(user.getId(), username)); } @@ -1170,9 +1135,8 @@ void passwordResetRequestEvent() throws Exception { ResetPasswordRequestEvent event = (ResetPasswordRequestEvent) testListener.getLatestEvent(); assertThat(event.getAuditEvent().getPrincipalId()).isEqualTo(testUser.getUserName()); assertThat(event.getAuditEvent().getData()).isEqualTo(testUser.getPrimaryEmail()); - assertThat(event.getAuditEvent().getOrigin()).contains("sessionId="); - assertLogMessageWithSession(testLogger.getLatestMessage(), + assertLogMessage(testLogger.getLatestMessage(), PasswordResetRequest, testUser.getUserName(), testUser.getPrimaryEmail()); } @@ -1341,7 +1305,6 @@ private ScimUser createUser(String adminToken, String username, String firstname assertThat(userModifiedEvent.getAuthentication().getName()).isEqualTo(testAccounts.getAdminClientId()); assertThat(userModifiedEvent.getUsername()).isEqualTo(username); assertThat(userModifiedEvent.getAuditEvent().getType()).isEqualTo(UserCreatedEvent); - assertThat(userModifiedEvent.getAuditEvent().getOrigin()).contains("sessionId="); return JsonUtils.readValue(result.andReturn().getResponse().getContentAsString(), ScimUser.class); } @@ -1425,15 +1388,7 @@ private void assertSingleAuditEventLogMessage(AuditEventType expectedEventType, assertThat(message).contains("\"authorities\":[%s]".formatted(commaSeparatedQuotedAuthorities)); } - private void assertLogMessageWithSession(String actualLogMessage, AuditEventType expectedAuditEventType, String expectedPrincipal, String expectedUserName) { - assertThat(actualLogMessage).startsWith(expectedAuditEventType.toString() + " ") - .contains("principal=%s,".formatted(expectedPrincipal)) - .contains(" ('%s'): ".formatted(expectedUserName)) - .contains(", identityZoneId=[uaa]") - .matches(".*origin=\\[.*sessionId=.*\\].*"); - } - - private static void assertLogMessageWithoutSession(String actualLogMessage, AuditEventType expectedAuditEventType, String expectedPrincipal, String expectedUserName) { + private void assertLogMessage(String actualLogMessage, AuditEventType expectedAuditEventType, String expectedPrincipal, String expectedUserName) { assertThat(actualLogMessage).startsWith(expectedAuditEventType.toString() + " ") .contains("principal=%s,".formatted(expectedPrincipal)) .contains(" ('%s'): ".formatted(expectedUserName))