/*******************************************************************************
* Copyright (c) 2013, 2014 Lectorius, Inc.
* Authors:
* Vijay Pandurangan (vijayp@mitro.co)
* Evan Jones (ej@mitro.co)
* Adam Hilss (ahilss@mitro.co)
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* You can contact the authors at inbound@mitro.co.
*******************************************************************************/
package co.mitro.core.servlets;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.sql.SQLException;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import co.mitro.analysis.AuditLogProcessor.ActionType;
import co.mitro.core.exceptions.MitroServletException;
import co.mitro.core.server.data.DBAcl;
import co.mitro.core.server.data.DBGroup;
import co.mitro.core.server.data.DBIdentity;
import co.mitro.core.server.data.RPC;
import co.mitro.core.server.data.RPC.MitroRPC;
import co.mitro.core.servlets.MitroServlet.MitroRequestContext;
public class GetAuditLogTest extends OrganizationsFixture {
private GetAuditLog servlet;
private RPC.GetAuditLogRequest request;
protected int addSecret(DBIdentity requestor, int groupId)
throws IOException, SQLException, MitroServletException {
RPC.AddSecretRequest request = new RPC.AddSecretRequest();
request.ownerGroupId = groupId;
request.encryptedClientData = "client";
request.encryptedCriticalData = "critical";
manager.setRequestor(requestor, null);
AddSecret servlet = new AddSecret();
MitroRPC output = servlet.processCommand(new MitroRequestContext(requestor, gson.toJson(request), manager, null));
RPC.AddSecretResponse response = (RPC.AddSecretResponse) output;
return response.secretId;
}
// don't use the enum value to ensure the enum stuff works
private static final String INCLUDE_CRITICAL_DATA_STRING = "true";
protected void accessSecret(DBIdentity requestor, DBGroup group, int secretId)
throws MitroServletException, IOException, SQLException {
RPC.GetSecretRequest request = new RPC.GetSecretRequest();
request.groupId = group.getId();
request.secretId = secretId;
request.includeCriticalData = INCLUDE_CRITICAL_DATA_STRING;
manager.setRequestor(requestor, null);
GetSecret servlet = new GetSecret();
servlet.processCommand(new MitroRequestContext(requestor, gson.toJson(request), manager, null));
}
protected RPC.GetAuditLogResponse getAuditLog(DBIdentity identity) throws IOException, SQLException, MitroServletException {
MitroRPC output = servlet.processCommand(new MitroRequestContext(identity, gson.toJson(request), manager, null));
return (RPC.GetAuditLogResponse) output;
}
private void expectException(DBIdentity identity) throws IOException, SQLException {
try {
getAuditLog(identity);
fail("expected exception");
} catch (MitroServletException expected) {
assertThat(expected.getMessage(), containsString("no access"));
}
}
@Before
public void setUp() throws Exception {
servlet = new GetAuditLog();
request = new RPC.GetAuditLogRequest();
request.limit = 100L;
request.offset = 0L;
}
@Ignore @Test
public void testSingleUserAuditLog() throws MitroServletException, IOException, SQLException, InterruptedException {
Integer secretId = addSecret(testIdentity, testIdentity.getId());
RPC.GetAuditLogResponse response = getAuditLog(testIdentity);
assertEquals(1, response.events.size());
assertEquals(testIdentity.getId(), response.events.get(0).userId);
assertEquals(ActionType.CREATE_SECRET, response.events.get(0).action);
assertEquals(secretId, response.events.get(0).secretId);
accessSecret(testIdentity, testGroup, secretId);
response = getAuditLog(testIdentity);
assertEquals(2, response.events.size());
assertEquals(testIdentity.getId(), response.events.get(1).userId);
assertEquals(ActionType.CREATE_SECRET, response.events.get(1).action);
assertEquals(secretId, response.events.get(1).secretId);
assertEquals(testIdentity.getId(), response.events.get(0).userId);
assertEquals(ActionType.GET_SECRET_CRITICAL_DATA_FOR_EDIT, response.events.get(0).action);
assertEquals(secretId, response.events.get(0).secretId);
}
@Ignore @Test
public void testMultipleUserAuditLog() throws Exception {
addToGroup(testIdentity2, testGroup, DBAcl.AccessLevelType.ADMIN);
Integer secretId = addSecret(testIdentity, testIdentity.getId());
accessSecret(testIdentity, testGroup, secretId);
RPC.GetAuditLogResponse response = getAuditLog(testIdentity);
assertEquals(2, response.events.size());
assertEquals(testIdentity.getId(), response.events.get(1).userId);
assertEquals(ActionType.CREATE_SECRET, response.events.get(1).action);
assertEquals(secretId, response.events.get(1).secretId);
assertEquals(testIdentity.getId(), response.events.get(0).userId);
assertEquals(ActionType.GET_SECRET_CRITICAL_DATA_FOR_EDIT, response.events.get(0).action);
assertEquals(secretId, response.events.get(0).secretId);
// Check that actions are visible to a second user that has access to the secret.
response = getAuditLog(testIdentity2);
assertEquals(2, response.events.size());
assertEquals(testIdentity.getId(), response.events.get(1).userId);
assertEquals(ActionType.CREATE_SECRET, response.events.get(1).action);
assertEquals(secretId, response.events.get(1).secretId);
assertEquals(testIdentity.getId(), response.events.get(0).userId);
assertEquals(ActionType.GET_SECRET_CRITICAL_DATA_FOR_EDIT, response.events.get(0).action);
assertEquals(secretId, response.events.get(0).secretId);
}
@Ignore @Test
public void testOrgAuditLog() throws Exception {
DBIdentity orgMember = members.iterator().next();
DBIdentity orgAdmin = admins.iterator().next();
Integer secretId = addSecret(orgAdmin, org.getId());
// Verify that org admin doesn't see events in personal audit log.
RPC.GetAuditLogResponse response = getAuditLog(orgAdmin);
assertEquals(0, response.events.size());
// Check that regular org member cannot access audit log for org.
request.orgId = org.getId();
expectException(orgMember);
// Check that org admin sees events in org audit log.
response = getAuditLog(orgAdmin);
assertEquals(1, response.events.size());
assertEquals(orgAdmin.getId(), response.events.get(0).userId);
assertEquals(ActionType.CREATE_SECRET, response.events.get(0).action);
assertEquals(secretId, response.events.get(0).secretId);
}
@Ignore @Test
public void testTimestampQuery() throws Exception {
int secretId = addSecret(testIdentity, testIdentity.getId());
Thread.sleep(10);
Long t1 = System.currentTimeMillis();
accessSecret(testIdentity, testGroup, secretId);
Thread.sleep(10);
Long t2 = System.currentTimeMillis();
accessSecret(testIdentity, testGroup, secretId);
request.startTimeMs = null;
request.endTimeMs = null;
RPC.GetAuditLogResponse response = getAuditLog(testIdentity);
assertEquals(3, response.events.size());
request.endTimeMs = t1;
response = getAuditLog(testIdentity);
assertEquals(1, response.events.size());
request.startTimeMs = t1;
request.endTimeMs = t2 - 1;
response = getAuditLog(testIdentity);
assertEquals(1, response.events.size());
request.startTimeMs = t2;
request.endTimeMs = null;
response = getAuditLog(testIdentity);
assertEquals(1, response.events.size());
}
}