Commit e7c7f84d authored by Sonia Zorba's avatar Sonia Zorba
Browse files

Audit logging improvements

parent d2408b1a
......@@ -3,6 +3,7 @@ package it.inaf.ia2.gms.authn;
import it.inaf.ia2.aa.UserManager;
import it.inaf.ia2.aa.data.User;
import it.inaf.ia2.gms.persistence.LoggingDAO;
import it.inaf.ia2.gms.persistence.model.ActionType;
import java.io.IOException;
import java.security.Principal;
import java.util.Map;
......@@ -55,13 +56,13 @@ public class JWTFilter implements Filter {
Map<String, Object> claims = userManager.parseIdTokenClaims(token);
if (claims.get("sub") == null) {
loggingDAO.logAction("Attempt to access WS with invalid token", request);
loggingDAO.logAction(ActionType.UNAUTHORIZED_ACCESS_ATTEMPT, "Attempt to access API with invalid token", request);
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid access token: missing sub claim");
return;
}
ServletRequestWithJWTPrincipal wrappedRequest = new ServletRequestWithJWTPrincipal(request, token, claims);
loggingDAO.logAction("WS access from " + wrappedRequest.getUserPrincipal().getName(), request);
loggingDAO.logAction(ActionType.UNAUTHORIZED_ACCESS_ATTEMPT, "API access from " + wrappedRequest.getUserPrincipal().getName(), request);
fc.doFilter(wrappedRequest, res);
}
......
......@@ -4,6 +4,7 @@ import it.inaf.ia2.gms.exception.BadRequestException;
import it.inaf.ia2.gms.exception.UnauthorizedException;
import it.inaf.ia2.gms.model.Permission;
import it.inaf.ia2.gms.persistence.LoggingDAO;
import it.inaf.ia2.gms.persistence.model.ActionType;
import it.inaf.ia2.gms.persistence.model.GroupEntity;
import it.inaf.ia2.gms.persistence.model.PermissionEntity;
import it.inaf.ia2.gms.service.GroupsService;
......@@ -84,14 +85,14 @@ public class GroupsManager extends UserAwareComponent {
public void verifyUserCanReadGroup(GroupEntity group) {
if (permissionsManager.getCurrentUserPermission(group) == null) {
loggingDAO.logAction("Unauthorized group management request, group_id=" + group.getId());
loggingDAO.logAction(ActionType.UNAUTHORIZED_ACCESS_ATTEMPT, "Unauthorized group management request, group_id=" + group.getId());
throw new UnauthorizedException("Missing permission to see this group");
}
}
private void verifyUserCanManageGroup(GroupEntity group) {
if (permissionsManager.getCurrentUserPermission(group) != Permission.ADMIN) {
loggingDAO.logAction("Unauthorized group management request, group_id=" + group.getId());
loggingDAO.logAction(ActionType.UNAUTHORIZED_ACCESS_ATTEMPT, "Unauthorized group management request, group_id=" + group.getId());
throw new UnauthorizedException("Missing admin permission");
}
}
......
......@@ -14,6 +14,7 @@ import it.inaf.ia2.gms.persistence.model.InvitedRegistration;
import it.inaf.ia2.gms.persistence.model.MembershipEntity;
import it.inaf.ia2.gms.service.PermissionsService;
import it.inaf.ia2.gms.authn.RapClient;
import static it.inaf.ia2.gms.persistence.model.ActionType.*;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
......@@ -68,6 +69,7 @@ public class InvitedRegistrationManager extends UserAwareComponent {
for (Map.Entry<GroupEntity, Permission> entry : groupsPermissions.entrySet()) {
GroupEntity group = entry.getKey();
if (permissionsManager.getCurrentUserPermission(group) != Permission.ADMIN) {
loggingDAO.logAction(UNAUTHORIZED_ACCESS_ATTEMPT, "Attempt to add invited registration for group " + group.getId());
throw new UnauthorizedException("You don't have the permission to perform invited registrations");
}
groupIdsPermissions.put(group.getId(), entry.getValue());
......@@ -80,6 +82,8 @@ public class InvitedRegistrationManager extends UserAwareComponent {
.setGroupsPermissions(groupIdsPermissions);
invitedRegistrationDAO.addInvitedRegistration(invitedRegistration);
loggingDAO.logAction(INVITED_REGISTRATION_ADDED, "Email=" + email);
}
public InvitedRegistration getInvitedRegistrationFromToken(String token) {
......@@ -94,7 +98,7 @@ public class InvitedRegistrationManager extends UserAwareComponent {
httpSession.setAttribute(INVITED_REGISTRATION, invitedRegistration);
loggingDAO.logAction("Started invited registration for email " + invitedRegistration.getEmail());
loggingDAO.logAction(INVITED_REGISTRATION_OPENED, "Started invited registration for email " + invitedRegistration.getEmail());
return invitedRegistration;
} catch (NoSuchAlgorithmException ex) {
......@@ -144,9 +148,11 @@ public class InvitedRegistrationManager extends UserAwareComponent {
}
private void completeInvitedRegistration(InvitedRegistration invitedRegistration) {
String userId = getCurrentUserId();
for (Map.Entry<String, Permission> entry : invitedRegistration.getGroupsPermissions().entrySet()) {
String groupId = entry.getKey();
String userId = getCurrentUserId();
GroupEntity groupEntity = groupsDAO.findGroupById(groupId).get();
......@@ -156,11 +162,14 @@ public class InvitedRegistrationManager extends UserAwareComponent {
membershipEntity.setCreatedBy(getCurrentUserId());
membershipsDAO.addMember(membershipEntity);
permissionsService.addPermission(groupEntity, userId, entry.getValue(), getCurrentUserId());
permissionsService.addPermission(groupEntity, userId, entry.getValue(), userId);
}
invitedRegistration.setUserId(getCurrentUserId());
invitedRegistration.setUserId(userId);
invitedRegistrationDAO.setRegistrationDone(invitedRegistration);
loggingDAO.logAction(INVITED_REGISTRATION_COMPLETED, "user_id=" + userId + " groups=["
+ String.join(",", invitedRegistration.getGroupsPermissions().keySet()) + "]");
}
public List<InvitedRegistrationItem> getInvitedRegistrationsForGroup(GroupEntity group) {
......@@ -201,7 +210,7 @@ public class InvitedRegistrationManager extends UserAwareComponent {
invitedRegistrationDAO.deleteInvitedRegistrationRequest(registrationId, groupId);
loggingDAO.logAction("Deleted invited registration request. "
loggingDAO.logAction(INVITED_REGISTRATION_DELETED, "Deleted invited registration request. "
+ "[request_id=" + registrationId + ", group_id=" + groupId
+ ", group_name=" + group.getName() + "]");
}
......
......@@ -10,6 +10,7 @@ import it.inaf.ia2.gms.persistence.model.MembershipEntity;
import it.inaf.ia2.gms.persistence.model.PermissionEntity;
import it.inaf.ia2.gms.service.PermissionUtils;
import it.inaf.ia2.gms.authn.RapClient;
import static it.inaf.ia2.gms.persistence.model.ActionType.*;
import it.inaf.ia2.rap.data.RapUser;
import java.util.HashSet;
import java.util.List;
......@@ -49,6 +50,7 @@ public class MembershipManager extends UserAwareComponent {
Permission groupPermission = permissionsManager.getCurrentUserPermission(group);
if (!Permission.includes(groupPermission, Permission.VIEW_MEMBERS)) {
loggingDAO.logAction(UNAUTHORIZED_ACCESS_ATTEMPT, "Attempted to view members of group " + group.getId());
throw new UnauthorizedException("You don't have the permission to view members");
}
......@@ -86,7 +88,7 @@ public class MembershipManager extends UserAwareComponent {
membership.setCreatedBy(getCurrentUserId());
membership = membershipsDAO.addMember(membership);
loggingDAO.logAction("Added member, group_id=" + group.getId() + ", user_id=" + userId);
loggingDAO.logAction(MEMBER_ADDED, "Added member, group_id=" + group.getId() + ", user_id=" + userId);
return membership;
}
......@@ -94,12 +96,13 @@ public class MembershipManager extends UserAwareComponent {
public void removeMember(GroupEntity group, String userId) {
verifyUserCanManageMembers(group);
membershipsDAO.removeMembership(group.getId(), userId);
loggingDAO.logAction("Member removed, group_id=" + group.getId() + ", user_id=" + userId);
loggingDAO.logAction(MEMBER_REMOVED, "Member removed, group_id=" + group.getId() + ", user_id=" + userId);
}
private Permission verifyUserCanManageMembers(GroupEntity group) {
Permission permission = permissionsManager.getCurrentUserPermission(group);
if (!Permission.includes(permission, Permission.MANAGE_MEMBERS)) {
loggingDAO.logAction(UNAUTHORIZED_ACCESS_ATTEMPT, "Attempted to manage members of group " + group.getId());
throw new UnauthorizedException("Missing manage members permissions");
}
return permission;
......
......@@ -9,6 +9,7 @@ import it.inaf.ia2.gms.persistence.model.PermissionEntity;
import it.inaf.ia2.gms.service.PermissionUtils;
import it.inaf.ia2.gms.service.PermissionsService;
import it.inaf.ia2.gms.authn.RapClient;
import it.inaf.ia2.gms.persistence.model.ActionType;
import it.inaf.ia2.rap.data.RapUser;
import java.util.ArrayList;
import java.util.List;
......@@ -144,7 +145,7 @@ public class PermissionsManager extends UserAwareComponent {
}
private Supplier<UnauthorizedException> unauthorizedExceptionSupplier(GroupEntity group) {
loggingDAO.logAction("Unauthorized attempt to manage permissions [group_id=" + group.getId() + "]");
loggingDAO.logAction(ActionType.UNAUTHORIZED_ACCESS_ATTEMPT, "Unauthorized attempt to manage permissions [group_id=" + group.getId() + "]");
return () -> new UnauthorizedException("You don't have the privileges for managing the requested permission");
}
......
package it.inaf.ia2.gms.persistence;
import it.inaf.ia2.gms.persistence.model.ActionType;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.sql.PreparedStatement;
......@@ -52,19 +53,20 @@ public class LoggingDAO {
return sw.toString();
}
public void logAction(String action) {
logAction(action, request);
public void logAction(ActionType type, String action) {
logAction(type, action, request);
}
public void logAction(String action, HttpServletRequest request) {
public void logAction(ActionType type, String description, HttpServletRequest request) {
try {
String sql = "INSERT INTO audit_log (\"user\", action, ip_address) VALUES (?, ?, ?)";
String sql = "INSERT INTO audit_log (\"user\", action_type, description, ip_address) VALUES (?, ?, ?, ?)";
jdbcTemplate.update(conn -> {
PreparedStatement ps = conn.prepareStatement(sql);
int i = 0;
ps.setString(++i, getUser(request));
ps.setString(++i, action);
ps.setString(++i, type.toString());
ps.setString(++i, description);
ps.setString(++i, getIPAddress(request));
return ps;
});
......
package it.inaf.ia2.gms.persistence.model;
public enum ActionType {
GROUP_CREATED,
GROUP_DELETED,
GROUP_UPDATED,
MEMBER_ADDED,
MEMBER_REMOVED,
PERMISSION_ADDED,
PERMISSION_UPDATED,
PERMISSION_REMOVED,
JOIN,
INVITED_REGISTRATION_ADDED,
INVITED_REGISTRATION_OPENED,
INVITED_REGISTRATION_DELETED,
INVITED_REGISTRATION_COMPLETED,
UNAUTHORIZED_ACCESS_ATTEMPT
}
......@@ -10,6 +10,7 @@ import it.inaf.ia2.gms.persistence.InvitedRegistrationDAO;
import it.inaf.ia2.gms.persistence.LoggingDAO;
import it.inaf.ia2.gms.persistence.MembershipsDAO;
import it.inaf.ia2.gms.persistence.PermissionsDAO;
import static it.inaf.ia2.gms.persistence.model.ActionType.*;
import it.inaf.ia2.gms.persistence.model.GroupEntity;
import java.util.Date;
import java.util.List;
......@@ -74,7 +75,7 @@ public class GroupsService {
group.setCreationTime(new Date());
groupsDAO.createGroup(group);
loggingDAO.logAction("Added group: parent_path=" + parent.getPath() + ", group_name=" + groupName);
loggingDAO.logAction(GROUP_CREATED, "Added group: parent_path=" + parent.getPath() + ", group_name=" + groupName);
return group;
}
......@@ -90,7 +91,7 @@ public class GroupsService {
group.setLeaf(leaf);
GroupEntity entity = groupsDAO.updateGroup(group);
loggingDAO.logAction("Group updated, group_id=" + group.getId()
loggingDAO.logAction(GROUP_UPDATED, "Group updated, group_id=" + group.getId()
+ ", new name: " + newGroupName + ", leaf: " + leaf);
return entity;
......@@ -124,7 +125,7 @@ public class GroupsService {
groupsDAO.deleteGroup(g);
}
loggingDAO.logAction("Group deleted [group_id=" + group.getId() + ", group_name=" + group.getName() + "]");
loggingDAO.logAction(GROUP_DELETED, "Group deleted [group_id=" + group.getId() + ", group_name=" + group.getName() + "]");
return parent;
}
......
......@@ -2,11 +2,14 @@ package it.inaf.ia2.gms.service;
import it.inaf.ia2.gms.model.Permission;
import it.inaf.ia2.gms.persistence.JoinDAO;
import it.inaf.ia2.gms.persistence.LoggingDAO;
import it.inaf.ia2.gms.persistence.MembershipsDAO;
import it.inaf.ia2.gms.persistence.PermissionsDAO;
import it.inaf.ia2.gms.persistence.model.ActionType;
import it.inaf.ia2.gms.persistence.model.GroupEntity;
import it.inaf.ia2.gms.persistence.model.MembershipEntity;
import it.inaf.ia2.gms.persistence.model.PermissionEntity;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
......@@ -25,6 +28,9 @@ public class JoinService {
@Autowired
private JoinDAO joinDAO;
@Autowired
private LoggingDAO loggingDAO;
public String join(String userId1, String userId2) {
List<GroupEntity> user1Groups = membershipsDAO.getUserMemberships(userId1);
......@@ -61,9 +67,22 @@ public class JoinService {
joinDAO.join(membershipsToAdd, permissionsToAdd, deletingUserId);
loggingDAO.logAction(ActionType.JOIN, "removed_user=" + deletingUserId
+ " added_memberships: " + String.join(", ", getAddedGroups(membershipsToAdd))
+ " added_permissions: " + String.join(", ", getAddedPermissions(permissionsToAdd))
);
return remainingUserId;
}
private List<String> getAddedGroups(Set<MembershipEntity> membershipsToAdd) {
return membershipsToAdd.stream().map(m -> m.getGroupId()).collect(Collectors.toList());
}
private List<String> getAddedPermissions(Set<PermissionEntity> permissionsToAdd) {
return permissionsToAdd.stream().map(m -> "(" + m.getGroupId() + "," + m.getPermission() + ")").collect(Collectors.toList());
}
private MembershipEntity getMembershipEntity(String groupId, String userId) {
MembershipEntity entity = new MembershipEntity();
entity.setGroupId(groupId);
......
......@@ -4,6 +4,7 @@ import it.inaf.ia2.gms.model.Permission;
import it.inaf.ia2.gms.persistence.LoggingDAO;
import it.inaf.ia2.gms.persistence.model.PermissionEntity;
import it.inaf.ia2.gms.persistence.PermissionsDAO;
import static it.inaf.ia2.gms.persistence.model.ActionType.*;
import it.inaf.ia2.gms.persistence.model.GroupEntity;
import java.util.List;
import java.util.Optional;
......@@ -36,7 +37,7 @@ public class PermissionsService {
public void removePermission(GroupEntity group, String userId) {
permissionsDAO.deletePermission(group.getId(), userId);
loggingDAO.logAction("Removed permission for " + userId + "in group " + group.getId());
loggingDAO.logAction(PERMISSION_REMOVED, "Removed permission for " + userId + " in group " + group.getId());
}
public PermissionEntity addPermission(GroupEntity group, String userId, Permission permission, String setBy) {
......@@ -62,7 +63,7 @@ public class PermissionsService {
}
permissionEntity = permissionsDAO.createOrUpdatePermission(permissionEntity);
loggingDAO.logAction("Added " + permission + " permission for " + userId + "in group " + group.getId());
loggingDAO.logAction(PERMISSION_ADDED, "Added " + permission + " permission for " + userId + " in group " + group.getId());
return permissionEntity;
}
......@@ -76,7 +77,10 @@ public class PermissionsService {
permissionEntity.setGroupPath(group.getPath());
permissionEntity.setSetBy(setBy);
return permissionsDAO.createOrUpdatePermission(permissionEntity);
permissionEntity = permissionsDAO.createOrUpdatePermission(permissionEntity);
loggingDAO.logAction(PERMISSION_ADDED, "Added " + permission + " permission for " + userId + " in group " + group.getId());
return permissionEntity;
}
public PermissionEntity updatePermission(GroupEntity group, String userId, Permission permission, String setBy) {
......@@ -87,6 +91,9 @@ public class PermissionsService {
permissionEntity.setSetBy(setBy);
permissionEntity.setPermission(permission);
return permissionsDAO.updatePermission(permissionEntity);
permissionEntity = permissionsDAO.updatePermission(permissionEntity);
loggingDAO.logAction(PERMISSION_UPDATED, "Updated permission for " + userId + " in group " + group.getId() + " to " + permission);
return permissionEntity;
}
}
......@@ -48,7 +48,8 @@ CREATE TABLE audit_log (
"date" timestamp DEFAULT NOW(),
"user" varchar,
"ip_address" varchar,
"action" TEXT
"action_type" varchar,
"description" TEXT
);
CREATE TABLE invited_registration_request (
......
......@@ -5,3 +5,7 @@ ALTER TABLE gms_membership ADD COLUMN creation_time timestamp DEFAULT NOW();
ALTER TABLE gms_membership ADD COLUMN created_by varchar;
ALTER TABLE gms_permission ADD COLUMN update_time timestamp DEFAULT NOW();
ALTER TABLE gms_permission ADD COLUMN set_by varchar;
--- 2021-03-19
ALTER TABLE audit_log ADD COLUMN action_type varchar;
ALTER TABLE audit_log RENAME COLUMN action TO description;
package it.inaf.ia2.gms.persistence;
import it.inaf.ia2.gms.DataSourceConfig;
import it.inaf.ia2.gms.persistence.model.ActionType;
import javax.servlet.http.HttpServletRequest;
import javax.sql.DataSource;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = DataSourceConfig.class)
public class LoggingDAOTest {
@MockBean
private HttpServletRequest request;
@Autowired
private DataSource dataSource;
private LoggingDAO dao;
@Before
public void setUp() {
dao = new LoggingDAO(dataSource);
}
@Test
public void testLogAction() {
dao.logAction(ActionType.GROUP_CREATED, "description");
}
@Test
public void testlogException() {
dao.logException(new RuntimeException("msg"));
}
}
......@@ -2,6 +2,7 @@ package it.inaf.ia2.gms.service;
import it.inaf.ia2.gms.model.Permission;
import it.inaf.ia2.gms.persistence.JoinDAO;
import it.inaf.ia2.gms.persistence.LoggingDAO;
import it.inaf.ia2.gms.persistence.MembershipsDAO;
import it.inaf.ia2.gms.persistence.PermissionsDAO;
import it.inaf.ia2.gms.persistence.model.GroupEntity;
......@@ -37,6 +38,9 @@ public class JoinServiceTest {
@Mock
private JoinDAO joinDAO;
@Mock
private LoggingDAO loggingDAO;
@InjectMocks
private JoinService joinService;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment