GUACAMOLE-1224: Log user password updates.

This commit is contained in:
Michael Jumper
2022-10-05 09:41:54 -07:00
parent 606c7bd55c
commit 36b5842d42
3 changed files with 58 additions and 11 deletions

View File

@@ -94,6 +94,10 @@ public class AffectedObject implements LoggableDetail {
// Users // Users
case USER: case USER:
if (identifier.equals(event.getAuthenticatedUser().getIdentifier()))
return "their own user account";
objectType = "user"; objectType = "user";
break; break;

View File

@@ -24,6 +24,8 @@ import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleResourceNotFoundException; import org.apache.guacamole.GuacamoleResourceNotFoundException;
import org.apache.guacamole.net.auth.AuthenticationProvider; import org.apache.guacamole.net.auth.AuthenticationProvider;
import org.apache.guacamole.net.auth.Credentials; 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.auth.credentials.GuacamoleInsufficientCredentialsException;
import org.apache.guacamole.net.event.ApplicationShutdownEvent; import org.apache.guacamole.net.event.ApplicationShutdownEvent;
import org.apache.guacamole.net.event.ApplicationStartedEvent; 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.DirectoryEvent;
import org.apache.guacamole.net.event.DirectoryFailureEvent; import org.apache.guacamole.net.event.DirectoryFailureEvent;
import org.apache.guacamole.net.event.DirectorySuccessEvent; 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.UserSessionInvalidatedEvent;
import org.apache.guacamole.net.event.listener.Listener; import org.apache.guacamole.net.event.listener.Listener;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -48,6 +51,26 @@ public class EventLoggingListener implements Listener {
*/ */
private final Logger logger = LoggerFactory.getLogger(EventLoggingListener.class); 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 * Logs that an operation was performed on an object within a Directory
* successfully. * successfully.
@@ -65,11 +88,17 @@ public class EventLoggingListener implements Listener {
break; break;
case ADD: 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; break;
case UPDATE: 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; break;
case REMOVE: case REMOVE:

View File

@@ -41,6 +41,7 @@ import org.apache.guacamole.net.auth.Directory;
import org.apache.guacamole.net.auth.UserContext; import org.apache.guacamole.net.auth.UserContext;
import org.apache.guacamole.net.auth.credentials.GuacamoleCredentialsException; import org.apache.guacamole.net.auth.credentials.GuacamoleCredentialsException;
import org.apache.guacamole.net.auth.simple.SimpleActivityRecordSet; 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.DirectoryObjectResource;
import org.apache.guacamole.rest.directory.DirectoryObjectTranslator; import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
import org.apache.guacamole.rest.history.UserHistoryResource; import org.apache.guacamole.rest.history.UserHistoryResource;
@@ -134,13 +135,19 @@ public class UserResource
public void updateObject(APIUser modifiedObject) throws GuacamoleException { public void updateObject(APIUser modifiedObject) throws GuacamoleException {
// A user may not use this endpoint to update their password // A user may not use this endpoint to update their password
User currentUser = getUserContext().self(); try {
if ( User currentUser = getUserContext().self();
currentUser.getIdentifier().equals(modifiedObject.getUsername()) if (
&& modifiedObject.getPassword() != null) { currentUser.getIdentifier().equals(modifiedObject.getUsername())
throw new GuacamoleSecurityException( && modifiedObject.getPassword() != null) {
"Permission denied. The password update endpoint must" throw new GuacamoleSecurityException(
+ " be used to change the current user's password."); "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); super.updateObject(modifiedObject);
@@ -184,8 +191,15 @@ public class UserResource
} }
// Set password to the newly provided one // Set password to the newly provided one
user.setPassword(userPasswordUpdate.getNewPassword()); try {
getDirectory().update(user); user.setPassword(userPasswordUpdate.getNewPassword());
getDirectory().update(user);
fireDirectorySuccessEvent(DirectoryEvent.Operation.UPDATE);
}
catch (GuacamoleException | RuntimeException | Error e) {
fireDirectoryFailureEvent(DirectoryEvent.Operation.UPDATE, e);
throw e;
}
} }