From cb08eac551ec00a02c13e123639a40c97d106d93 Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Thu, 23 Apr 2020 19:51:32 -0400 Subject: [PATCH] - Added more tests to the functional test - creating cases and datasources, and account_instance attributes so that Persona could be traced back to a case/data source. - Fixed an issue with tests failing because Central Repo cache was not being cleared between tests, even though the underlying database itself was being recreated. - Fixed a bug in the Persona query. --- .../datamodel/CentralRepository.java | 4 + .../CorrelationAttributeInstance.java | 2 +- .../datamodel/PersonaHelper.java | 2 +- .../datamodel/RdbmsCentralRepo.java | 5 +- .../datamodel/CentralRepoPersonasTest.java | 240 +++++++++++++++--- 5 files changed, 218 insertions(+), 35 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java index d8b7b285c6..6faa957cd3 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java @@ -864,4 +864,8 @@ public interface CentralRepository { CentralRepoAccount getOrCreateAccount(CentralRepoAccount.CentralRepoAccountType crAccountType, String accountUniqueID) throws CentralRepoException; + /** + * Clears all caches. + */ + void clearCaches(); } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java index 4d5e2857a1..32121989e0 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java @@ -77,7 +77,7 @@ public class CorrelationAttributeInstance implements Serializable { ) throws CentralRepoException, CorrelationAttributeNormalizationException { this(type, value, -1, eamCase, eamDataSource, filePath, comment, knownStatus, fileObjectId, (long)-1); } - CorrelationAttributeInstance( + public CorrelationAttributeInstance( Type type, String value, int instanceId, diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PersonaHelper.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PersonaHelper.java index 3ad53b5c91..b3e6522e12 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PersonaHelper.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PersonaHelper.java @@ -122,7 +122,7 @@ public class PersonaHelper { PersonaStatus status = PersonaStatus.fromId(rs.getInt("status_id")); persona = new Persona( - rs.getInt("examiner_id"), + rs.getInt("id"), rs.getString("uuid"), rs.getString("name"), rs.getString("comment"), diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java index 14d11f480b..3f5fd61da0 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java @@ -222,7 +222,8 @@ abstract class RdbmsCentralRepo implements CentralRepository { /** * Reset the contents of the caches associated with EamDb results. */ - protected final void clearCaches() { + @Override + public final void clearCaches() { synchronized(typeCache) { typeCache.invalidateAll(); isCRTypeCacheInitialized = false; @@ -231,6 +232,8 @@ abstract class RdbmsCentralRepo implements CentralRepository { caseCacheById.invalidateAll(); dataSourceCacheByDsObjectId.invalidateAll(); dataSourceCacheById.invalidateAll(); + accountsCache.invalidateAll(); + cachedCurrentExaminer = null; } /** diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoPersonasTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoPersonasTest.java index f7bb5ac605..75c5fa4f83 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoPersonasTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoPersonasTest.java @@ -25,13 +25,16 @@ import java.nio.file.Paths; import java.time.Instant; import java.util.Collection; import junit.framework.Assert; +import static junit.framework.Assert.assertTrue; import junit.framework.TestCase; import junit.framework.Test; import org.apache.commons.io.FileUtils; import org.netbeans.junit.NbModuleSuite; +import org.openide.util.Exceptions; import static org.sleuthkit.autopsy.centralrepository.datamodel.PersonaHelper.addAccountToPersona; import org.sleuthkit.datamodel.Account; +import org.sleuthkit.datamodel.TskData; /** @@ -42,6 +45,45 @@ public class CentralRepoPersonasTest extends TestCase { private final Path testDirectory = Paths.get(System.getProperty("java.io.tmpdir"), "CentralRepoDatamodelTest"); + + private static final long CASE_1_DATA_SOURCE_1_ID = 11; + private static final long CASE_1_DATA_SOURCE_2_ID = 12; + private static final long CASE_2_DATA_SOURCE_1_ID = 21; + + private static final String PHONE_NUM_1 = "+1 441-231-2552"; + + + private static final String FACEBOOK_ID_CATDOG = "BalooSherkhan"; + private static final String EMAIL_ID_1 = "rkipling@junglebook.com"; + + + private static final String DOG_PERSONA_NAME = "Baloo McDog"; + private static final String CAT_PERSONA_NAME = "SherKhan"; + + private CorrelationCase case1; + private CorrelationCase case2; + private CorrelationDataSource dataSource1fromCase1; + private CorrelationDataSource dataSource2fromCase1; + private CorrelationDataSource dataSource1fromCase2; + private CentralRepoOrganization org1; + private CentralRepoOrganization org2; + + private CentralRepoAccount.CentralRepoAccountType phoneAccountType; + private CentralRepoAccount.CentralRepoAccountType emailAccountType; + private CentralRepoAccount.CentralRepoAccountType facebookAccountType; + private CentralRepoAccount.CentralRepoAccountType textnowAccountType; + private CentralRepoAccount.CentralRepoAccountType whatsAppAccountType; + private CentralRepoAccount.CentralRepoAccountType skypeAccountType; + + + private CorrelationAttributeInstance.Type phoneInstanceType; + private CorrelationAttributeInstance.Type emailInstanceType; + private CorrelationAttributeInstance.Type facebookInstanceType; + private CorrelationAttributeInstance.Type textnowInstanceType; + private CorrelationAttributeInstance.Type whatsAppInstanceType; + private CorrelationAttributeInstance.Type skypeInstanceType; + + // NbModuleSuite requires these tests use Junit 3.8 // Extension of the TestCase class is how tests were defined and used // in Junit 3.8 @@ -66,6 +108,8 @@ public class CentralRepoPersonasTest extends TestCase { final String CR_DB_NAME = "testcentralrepo.db"; + + SqliteCentralRepoSettings sqliteSettings = new SqliteCentralRepoSettings(); sqliteSettings.setDbName(CR_DB_NAME); sqliteSettings.setDbDirectory(testDirectory.toString()); @@ -88,8 +132,74 @@ public class CentralRepoPersonasTest extends TestCase { Assert.fail("Failed to create central repo database, should be located at + " + crDbFilePath); } + // clear caches to match the clean slate database. + CentralRepository.getInstance().clearCaches(); + // Add current logged in user to examiners table - since we delete the DB after every test. CentralRepository.getInstance().updateExaminers(); + + // Set up some default objects to be used by the tests + try { + case1 = new CorrelationCase("case1_uuid", "case1"); + case1 = CentralRepository.getInstance().newCase(case1); + assertTrue("Failed to create test object case1", case1 != null); + + case2 = new CorrelationCase("case2_uuid", "case2"); + case2 = CentralRepository.getInstance().newCase(case2); + assertTrue("Failed to create test object case2", case2 != null); + + dataSource1fromCase1 = new CorrelationDataSource(case1, "dataSource1_deviceID", "dataSource1", CASE_1_DATA_SOURCE_1_ID, null, null, null); + CentralRepository.getInstance().newDataSource(dataSource1fromCase1); + dataSource1fromCase1 = CentralRepository.getInstance().getDataSource(case1, dataSource1fromCase1.getDataSourceObjectID()); + assertTrue("Failed to create test object dataSource1fromCase1", dataSource1fromCase1 != null); + + dataSource2fromCase1 = new CorrelationDataSource(case1, "dataSource2_deviceID", "dataSource2", CASE_1_DATA_SOURCE_2_ID, null, null, null); + CentralRepository.getInstance().newDataSource(dataSource2fromCase1); + dataSource2fromCase1 = CentralRepository.getInstance().getDataSource(case1, dataSource2fromCase1.getDataSourceObjectID()); + assertTrue("Failed to create test object dataSource2fromCase1", dataSource2fromCase1 != null); + + dataSource1fromCase2 = new CorrelationDataSource(case2, "dataSource3_deviceID", "dataSource3", CASE_2_DATA_SOURCE_1_ID, null, null, null); + CentralRepository.getInstance().newDataSource(dataSource1fromCase2); + dataSource1fromCase2 = CentralRepository.getInstance().getDataSource(case2, dataSource1fromCase2.getDataSourceObjectID()); + assertTrue("Failed to create test object dataSource1fromCase2", dataSource1fromCase2 != null); + + org1 = new CentralRepoOrganization("org1"); + org1 = CentralRepository.getInstance().newOrganization(org1); + + org2 = new CentralRepoOrganization("org2"); + org2 = CentralRepository.getInstance().newOrganization(org2); + + // get some correltion types for different account types, for later use + phoneAccountType = CentralRepository.getInstance().getAccountTypeByName( Account.Type.PHONE.getTypeName()); + phoneInstanceType = CentralRepository.getInstance().getCorrelationTypeById(phoneAccountType.getCorrelationTypeId()); + assertTrue("getCorrelationTypeById(PHONE) returned null", phoneInstanceType != null); + + emailAccountType = CentralRepository.getInstance().getAccountTypeByName( Account.Type.EMAIL.getTypeName()); + emailInstanceType = CentralRepository.getInstance().getCorrelationTypeById(emailAccountType.getCorrelationTypeId()); + assertTrue("getCorrelationTypeById(EMAIL) returned null", emailInstanceType != null); + + facebookAccountType = CentralRepository.getInstance().getAccountTypeByName( Account.Type.FACEBOOK.getTypeName()); + facebookInstanceType = CentralRepository.getInstance().getCorrelationTypeById(facebookAccountType.getCorrelationTypeId()); + assertTrue("getCorrelationTypeById(FACEBOOK) returned null", facebookInstanceType != null); + + textnowAccountType = CentralRepository.getInstance().getAccountTypeByName( Account.Type.TEXTNOW.getTypeName()); + textnowInstanceType = CentralRepository.getInstance().getCorrelationTypeById(textnowAccountType.getCorrelationTypeId()); + assertTrue("getCorrelationTypeById(TEXTNOW) returned null", textnowInstanceType != null); + + whatsAppAccountType = CentralRepository.getInstance().getAccountTypeByName( Account.Type.WHATSAPP.getTypeName()); + whatsAppInstanceType = CentralRepository.getInstance().getCorrelationTypeById(whatsAppAccountType.getCorrelationTypeId()); + assertTrue("getCorrelationTypeById(WHATSAPP) returned null", whatsAppInstanceType != null); + + skypeAccountType = CentralRepository.getInstance().getAccountTypeByName( Account.Type.SKYPE.getTypeName()); + skypeInstanceType = CentralRepository.getInstance().getCorrelationTypeById(skypeAccountType.getCorrelationTypeId()); + assertTrue("getCorrelationTypeById(SKYPE) returned null", skypeInstanceType != null); + + + } catch (CentralRepoException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex.getMessage()); + } + } // This function is run after every test, NOT after the entire collection of @@ -121,25 +231,21 @@ public class CentralRepoPersonasTest extends TestCase { try { // Step 1: Create an account - CentralRepoAccount.CentralRepoAccountType phoneAccountType = CentralRepository - .getInstance() - .getAccountTypeByName( Account.Type.PHONE.getTypeName()); - CentralRepoAccount phoneAccount1 = CentralRepository.getInstance() - .getOrCreateAccount(phoneAccountType, "+1 441-231-2552"); + .getOrCreateAccount(phoneAccountType, PHONE_NUM_1); // Step 2: Create a Persona for the Account - String personaName = "Baloo McDog"; + String comment = "The best dog ever"; Persona.PersonaStatus status = Persona.PersonaStatus.ACTIVE; - PersonaAccount pa1 = PersonaHelper.createPersonaForAccount(personaName, comment , status, phoneAccount1, "Because I said so", Persona.Confidence.LOW ); + PersonaAccount pa1 = PersonaHelper.createPersonaForAccount(DOG_PERSONA_NAME, comment , status, phoneAccount1, "Because I said so", Persona.Confidence.LOW ); Persona dogPersona = pa1.getPersona(); // Verify Persona name, status etc. - Assert.assertEquals(personaName, pa1.getPersona().getName()); + Assert.assertEquals(DOG_PERSONA_NAME, pa1.getPersona().getName()); Assert.assertEquals(status.name(), dogPersona.getStatus().name()); Assert.assertTrue(dogPersona.getExaminer().getLoginName().equalsIgnoreCase(pa1.getExaminer().getLoginName())); @@ -154,14 +260,6 @@ public class CentralRepoPersonasTest extends TestCase { Assert.assertNotNull(alias1); Assert.assertNotNull(alias2); - - //Step 4: Add Persona metadata - PersonaMetadata metadata1 = PersonaHelper.addPersonaMetadata(dogPersona, "Color", "Black", "He's got thick black hair.", Persona.Confidence.MEDIUM); - PersonaMetadata metadata2 = PersonaHelper.addPersonaMetadata(dogPersona, "Gender", "Male", "Because...", Persona.Confidence.LOW); - - Assert.assertNotNull(metadata1); - Assert.assertNotNull(metadata2); - // get all aliases for persona Collection aliases = PersonaHelper.getPersonaAliases(dogPersona.getId()); Assert.assertEquals(2, aliases.size()); @@ -170,6 +268,14 @@ public class CentralRepoPersonasTest extends TestCase { Assert.assertFalse(alias.getAlias().isEmpty()); } + + //Step 4: Add Persona metadata + PersonaMetadata metadata1 = PersonaHelper.addPersonaMetadata(dogPersona, "Color", "Black", "He's got thick black hair.", Persona.Confidence.MEDIUM); + PersonaMetadata metadata2 = PersonaHelper.addPersonaMetadata(dogPersona, "Gender", "Male", "Because...", Persona.Confidence.LOW); + + Assert.assertNotNull(metadata1); + Assert.assertNotNull(metadata2); + // get all metadata for persona Collection metadataList = PersonaHelper.getPersonaMetadata(dogPersona.getId()); Assert.assertEquals(2, metadataList.size()); @@ -181,12 +287,8 @@ public class CentralRepoPersonasTest extends TestCase { // Step 5: associate another account with same persona - CentralRepoAccount.CentralRepoAccountType facebookAccountType = CentralRepository - .getInstance() - .getAccountTypeByName(Account.Type.FACEBOOK.getTypeName()); - CentralRepoAccount catdogFBAccount = CentralRepository.getInstance() - .getOrCreateAccount(facebookAccountType, "BalooSherkhan"); + .getOrCreateAccount(facebookAccountType, FACEBOOK_ID_CATDOG); // Add account to persona addAccountToPersona( dogPersona, catdogFBAccount, "Looks like dog, barks like a dog...", Persona.Confidence.MEDIUM); @@ -204,11 +306,13 @@ public class CentralRepoPersonasTest extends TestCase { Assert.assertTrue(pa.getPersona().getCreatedDate()> 0); } - // Create a Second Persona associated with same account - String catPersonaName = "SherKhan"; - String comment2 = "The fiercest cat alive."; + // Step 6: Create a Second Persona, that shares a common account with another persona - PersonaHelper.createPersonaForAccount(catPersonaName, comment2 , Persona.PersonaStatus.ACTIVE, catdogFBAccount, "Smells like a cat.", Persona.Confidence.LOW ); + String comment2 = "The fiercest cat alive."; + PersonaAccount pa2 = PersonaHelper.createPersonaForAccount(CAT_PERSONA_NAME, comment2 , Persona.PersonaStatus.ACTIVE, catdogFBAccount, "Smells like a cat.", Persona.Confidence.LOW ); + Assert.assertNotNull(pa2); + Assert.assertTrue(pa2.getPersona().getName().equalsIgnoreCase(CAT_PERSONA_NAME)); + // Get ALL personas for an account Collection personaAccounts2 = PersonaHelper.getPersonaAccountsForAccount(catdogFBAccount.getAccountId()); @@ -229,25 +333,97 @@ public class CentralRepoPersonasTest extends TestCase { } } + /** + * Tests Personas & X_Accounts and X_instances in the context of Case/data source. + */ + public void testPersonaWithCases() { + + try { + // Create an account + CentralRepoAccount catdogFBAccount = CentralRepository.getInstance() + .getOrCreateAccount(facebookAccountType, FACEBOOK_ID_CATDOG); + + + // Create account instance attribute for that account, on Case 1, DS 1 + CorrelationAttributeInstance fbAcctInstance1 = new CorrelationAttributeInstance(facebookInstanceType, FACEBOOK_ID_CATDOG, + -1, + case1, + dataSource1fromCase1, + "path1", + "", + TskData.FileKnown.UNKNOWN, + 1001L, + catdogFBAccount.getAccountId()); + CentralRepository.getInstance().addArtifactInstance(fbAcctInstance1); + + + + + // Create account instance attribute for that account, on Case 1, DS 2 + CorrelationAttributeInstance fbAcctInstance2 = new CorrelationAttributeInstance(facebookInstanceType, FACEBOOK_ID_CATDOG, + -1, + case1, + dataSource2fromCase1, + "path2", + "", + TskData.FileKnown.UNKNOWN, + 1002L, catdogFBAccount.getAccountId()); + + CentralRepository.getInstance().addArtifactInstance(fbAcctInstance2); + + + // Create account instance attribute for that account, on Case 1, DS 2 + CorrelationAttributeInstance fbAcctInstance3 = new CorrelationAttributeInstance(facebookInstanceType, FACEBOOK_ID_CATDOG, + -1, + case2, + dataSource1fromCase2, + "path3", + "", + TskData.FileKnown.UNKNOWN, + 1003L, catdogFBAccount.getAccountId()); + CentralRepository.getInstance().addArtifactInstance(fbAcctInstance3); + + + // Create Persona for that account + + String comment = "The best dog ever"; + Persona.PersonaStatus status = Persona.PersonaStatus.ACTIVE; + PersonaAccount pa1 = PersonaHelper.createPersonaForAccount(DOG_PERSONA_NAME, + comment , + status, catdogFBAccount, "Because I said so", Persona.Confidence.LOW ); + + + // Test that getting all Personas for Case 1 includes the persona above + // Test that getting all Personas for Case 2 includes the persona above + // Test that getting all Personas for DS 1 includes the persona above + // Test that getting all Personas for DS 2 includes the persona above + + + // Test that getting cases for the Persona returns Case 1 & 2 + // Test that getting data sources for the Persona returns Case1_DS1 & Case1_DS2 & Case2_DS1 + + } + catch (CentralRepoException | CorrelationAttributeNormalizationException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex.getMessage()); + } + + } /** * Tests edge cases, error cases */ public void testPersonaCreationEdgeCases() { - // Test1: Persona with no name + // Test1: create Persona without specifying a name { try { // Create an email account - CentralRepoAccount.CentralRepoAccountType emailAccountType = CentralRepository - .getInstance() - .getAccountTypeByName(Account.Type.EMAIL.getTypeName()); - CentralRepoAccount emailAccount1 = CentralRepository.getInstance() - .getOrCreateAccount(emailAccountType, "tbigbos@ringobaby344.cf"); + .getOrCreateAccount(emailAccountType, EMAIL_ID_1); // Create a Persona with no name PersonaAccount pa1 = PersonaHelper.createPersonaForAccount(null, "A persona with no name", - Persona.PersonaStatus.ACTIVE, emailAccount1, "Becuase that's a curious looking email address", Persona.Confidence.LOW); + Persona.PersonaStatus.ACTIVE, emailAccount1, "The person lost his name", Persona.Confidence.LOW); // Verify Persona has a default name Assert.assertEquals("NoName", pa1.getPersona().getName());