From 36b5842d426d907482c7db27c3bbb91a5daa9de5 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 5 Oct 2022 09:41:54 -0700 Subject: [PATCH] GUACAMOLE-1224: Log user password updates. --- .../guacamole/event/AffectedObject.java | 4 +++ .../guacamole/event/EventLoggingListener.java | 33 +++++++++++++++++-- .../guacamole/rest/user/UserResource.java | 32 +++++++++++++----- 3 files changed, 58 insertions(+), 11 deletions(-) diff --git a/guacamole/src/main/java/org/apache/guacamole/event/AffectedObject.java b/guacamole/src/main/java/org/apache/guacamole/event/AffectedObject.java index b95122bae..c610bf177 100644 --- a/guacamole/src/main/java/org/apache/guacamole/event/AffectedObject.java +++ b/guacamole/src/main/java/org/apache/guacamole/event/AffectedObject.java @@ -94,6 +94,10 @@ public class AffectedObject implements LoggableDetail { // Users case USER: + + if (identifier.equals(event.getAuthenticatedUser().getIdentifier())) + return "their own user account"; + objectType = "user"; break; diff --git a/guacamole/src/main/java/org/apache/guacamole/event/EventLoggingListener.java b/guacamole/src/main/java/org/apache/guacamole/event/EventLoggingListener.java index 90a929765..b21b8b230 100644 --- a/guacamole/src/main/java/org/apache/guacamole/event/EventLoggingListener.java +++ b/guacamole/src/main/java/org/apache/guacamole/event/EventLoggingListener.java @@ -24,6 +24,8 @@ import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleResourceNotFoundException; import org.apache.guacamole.net.auth.AuthenticationProvider; import org.apache.guacamole.net.auth.Credentials; +import org.apache.guacamole.net.auth.Identifiable; +import org.apache.guacamole.net.auth.User; import org.apache.guacamole.net.auth.credentials.GuacamoleInsufficientCredentialsException; import org.apache.guacamole.net.event.ApplicationShutdownEvent; import org.apache.guacamole.net.event.ApplicationStartedEvent; @@ -32,6 +34,7 @@ import org.apache.guacamole.net.event.AuthenticationSuccessEvent; import org.apache.guacamole.net.event.DirectoryEvent; import org.apache.guacamole.net.event.DirectoryFailureEvent; import org.apache.guacamole.net.event.DirectorySuccessEvent; +import org.apache.guacamole.net.event.IdentifiableObjectEvent; import org.apache.guacamole.net.event.UserSessionInvalidatedEvent; import org.apache.guacamole.net.event.listener.Listener; import org.slf4j.Logger; @@ -48,6 +51,26 @@ public class EventLoggingListener implements Listener { */ private final Logger logger = LoggerFactory.getLogger(EventLoggingListener.class); + /** + * Returns whether the given event affects the password of a User object. + * + * @param event + * The event to check. + * + * @return + * true if a user's password is specifically set or modified by the + * given event, false otherwise. + */ + private boolean isPasswordAffected(IdentifiableObjectEvent event) { + + Identifiable object = event.getObject(); + if (!(object instanceof User)) + return false; + + return ((User) object).getPassword() != null; + + } + /** * Logs that an operation was performed on an object within a Directory * successfully. @@ -65,11 +88,17 @@ public class EventLoggingListener implements Listener { break; case ADD: - logger.info("{} successfully created {}", new RequestingUser(event), new AffectedObject(event)); + if (isPasswordAffected(event)) + logger.info("{} successfully created {}, setting their password", new RequestingUser(event), new AffectedObject(event)); + else + logger.info("{} successfully created {}", new RequestingUser(event), new AffectedObject(event)); break; case UPDATE: - logger.info("{} successfully updated {}", new RequestingUser(event), new AffectedObject(event)); + if (isPasswordAffected(event)) + logger.info("{} successfully updated {}, changing their password", new RequestingUser(event), new AffectedObject(event)); + else + logger.info("{} successfully updated {}", new RequestingUser(event), new AffectedObject(event)); break; case REMOVE: diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/user/UserResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/user/UserResource.java index 9b79fbb48..91600f736 100644 --- a/guacamole/src/main/java/org/apache/guacamole/rest/user/UserResource.java +++ b/guacamole/src/main/java/org/apache/guacamole/rest/user/UserResource.java @@ -41,6 +41,7 @@ import org.apache.guacamole.net.auth.Directory; import org.apache.guacamole.net.auth.UserContext; import org.apache.guacamole.net.auth.credentials.GuacamoleCredentialsException; import org.apache.guacamole.net.auth.simple.SimpleActivityRecordSet; +import org.apache.guacamole.net.event.DirectoryEvent; import org.apache.guacamole.rest.directory.DirectoryObjectResource; import org.apache.guacamole.rest.directory.DirectoryObjectTranslator; import org.apache.guacamole.rest.history.UserHistoryResource; @@ -134,13 +135,19 @@ public class UserResource public void updateObject(APIUser modifiedObject) throws GuacamoleException { // A user may not use this endpoint to update their password - User currentUser = getUserContext().self(); - if ( - currentUser.getIdentifier().equals(modifiedObject.getUsername()) - && modifiedObject.getPassword() != null) { - throw new GuacamoleSecurityException( - "Permission denied. The password update endpoint must" - + " be used to change the current user's password."); + try { + User currentUser = getUserContext().self(); + if ( + currentUser.getIdentifier().equals(modifiedObject.getUsername()) + && modifiedObject.getPassword() != null) { + throw new GuacamoleSecurityException( + "Permission denied. The password update endpoint must" + + " be used to change the current user's password."); + } + } + catch (GuacamoleException | RuntimeException | Error e) { + fireDirectoryFailureEvent(DirectoryEvent.Operation.UPDATE, e); + throw e; } super.updateObject(modifiedObject); @@ -184,8 +191,15 @@ public class UserResource } // Set password to the newly provided one - user.setPassword(userPasswordUpdate.getNewPassword()); - getDirectory().update(user); + try { + user.setPassword(userPasswordUpdate.getNewPassword()); + getDirectory().update(user); + fireDirectorySuccessEvent(DirectoryEvent.Operation.UPDATE); + } + catch (GuacamoleException | RuntimeException | Error e) { + fireDirectoryFailureEvent(DirectoryEvent.Operation.UPDATE, e); + throw e; + } }