From fcd6b2ce08036ad0244e9551a8d980f9aa72c64a Mon Sep 17 00:00:00 2001 From: Nick Davis Date: Tue, 20 Jun 2017 15:09:55 -0400 Subject: [PATCH] postgresql settings UI is implemented. now to do cleanup/testing. --- .../actions/EamCaseEditDetailsDialog.java | 2 +- .../DataContentViewerOtherCases.java | 6 +- .../datamodel/AbstractSqlEamDb.java | 2 +- .../datamodel/EamDb.java | 11 +- .../datamodel/EamDbUtil.java | 48 +-- .../datamodel/PostgresEamDb.java | 173 --------- .../datamodel/PostgresEamDbSettings.java | 333 ++++++++++++++++-- .../datamodel/SqliteEamDb.java | 7 +- .../datamodel/SqliteEamDbSettings.java | 57 +-- .../eventlisteners/BadFileTagRunner.java | 2 +- .../eventlisteners/CaseEventListener.java | 8 +- .../eventlisteners/IngestEventsListener.java | 2 +- .../eventlisteners/NewArtifactsRunner.java | 2 +- .../ingestmodule/IngestModule.java | 6 +- .../optionspanel/EamDbSettingsDialog.form | 8 +- .../optionspanel/EamDbSettingsDialog.java | 62 +++- .../ImportHashDatabaseDialog.java | 4 +- 17 files changed, 404 insertions(+), 329 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/EamCaseEditDetailsDialog.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/EamCaseEditDetailsDialog.java index d2f147419d..d8c24d1a58 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/EamCaseEditDetailsDialog.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/EamCaseEditDetailsDialog.java @@ -524,7 +524,7 @@ public class EamCaseEditDetailsDialog extends JDialog { private void updateDb() { setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - if (!dbManager.isEnabled()) { + if (!EamDb.isEnabled()) { LOGGER.log(Level.SEVERE, "Enteprise artifacts manager database not enabled"); // NON-NLS return; } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/contentviewer/DataContentViewerOtherCases.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/contentviewer/DataContentViewerOtherCases.java index e0ad406386..f4679d52a6 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/contentviewer/DataContentViewerOtherCases.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/contentviewer/DataContentViewerOtherCases.java @@ -504,8 +504,7 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D @Override public boolean isSupported(Node node) { - EamDb dbManager = EamDb.getInstance(); - if (!dbManager.isEnabled()) { + if (!EamDb.isEnabled()) { return false; } @@ -516,8 +515,7 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D @Override @Messages({"DataContentViewerOtherCases.table.nodbconnection=Cannot connect to enterprise artifacts manager database."}) public void setNode(Node node) { - EamDb dbManager = EamDb.getInstance(); - if (!dbManager.isEnabled()) { + if (!EamDb.isEnabled()) { return; } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/AbstractSqlEamDb.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/AbstractSqlEamDb.java index 64c13420c1..5b0af7c6e6 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/AbstractSqlEamDb.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/AbstractSqlEamDb.java @@ -450,7 +450,7 @@ public abstract class AbstractSqlEamDb implements EamDb { PreparedStatement preparedStatement = null; ResultSet resultSet = null; - String sql = "SELECT * FROM data_sources WHERE device_id=?"; + String sql = "SELECT * FROM data_sources WHERE device_id=?"; // NON-NLS try { preparedStatement = conn.prepareStatement(sql); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDb.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDb.java index aaa688a783..0f7a1839cc 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDb.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDb.java @@ -27,9 +27,9 @@ public interface EamDb { public static final int SCHEMA_VERSION = 1; /** - * Get the instance; default to SQLITE. + * Get the instance * - * @return The EamDb instance + * @return The EamDb instance or null if one is not configured. * * @throws EamDbException */ @@ -41,8 +41,9 @@ public interface EamDb { return PostgresEamDb.getInstance(); case SQLITE: - default: return SqliteEamDb.getInstance(); + default: + return null; } } @@ -66,7 +67,9 @@ public interface EamDb { * * @return Is the database enabled */ - boolean isEnabled(); + static boolean isEnabled() { + return EamDbPlatformEnum.getSelectedPlatform() != EamDbPlatformEnum.DISABLED; + } /** * Get the list of tags recognized as "Bad" diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDbUtil.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDbUtil.java index 1a19b3e27d..3d5dbe3d5c 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDbUtil.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDbUtil.java @@ -7,18 +7,22 @@ package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel; import java.sql.Connection; +import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.List; import java.util.logging.Level; +import org.sleuthkit.autopsy.coreutils.Logger; import static org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb.SCHEMA_VERSION; /** * */ public class EamDbUtil { + private final static Logger LOGGER = Logger.getLogger(EamDbUtil.class.getName()); + /** * Close the prepared statement. * @@ -26,12 +30,12 @@ public class EamDbUtil { * * @throws EamDbException */ - public static void closePreparedStatement(PreparedStatement preparedStatement) throws EamDbException { + public static void closePreparedStatement(PreparedStatement preparedStatement) { if (null != preparedStatement) { try { preparedStatement.close(); } catch (SQLException ex) { - throw new EamDbException("Error closing PreparedStatement.", ex); + LOGGER.log(Level.SEVERE, "Error closing PreparedStatement.", ex); } } } @@ -43,12 +47,12 @@ public class EamDbUtil { * * @throws EamDbException */ - public static void closeResultSet(ResultSet resultSet) throws EamDbException { + public static void closeResultSet(ResultSet resultSet) { if (null != resultSet) { try { resultSet.close(); } catch (SQLException ex) { - throw new EamDbException("Error closing ResultSet.", ex); + LOGGER.log(Level.SEVERE, "Error closing ResultSet.", ex); } } } @@ -60,24 +64,23 @@ public class EamDbUtil { * * @throws EamDbException */ - public static void closeConnection(Connection conn) throws EamDbException { + public static void closeConnection(Connection conn) { if (null != conn) { try { conn.close(); } catch (SQLException ex) { - throw new EamDbException("Error closing Connection.", ex); + LOGGER.log(Level.SEVERE, "Error closing Connection.", ex); } } } - + /** * Insert the default artifact types into the database. * - * @param conn An open database connection. - * - * @throws EamDbException + * @param conn Open connection to use. + * @return true on success, else false */ - public static void insertDefaultArtifactTypes(Connection conn) throws EamDbException { + public static boolean insertDefaultArtifactTypes(Connection conn) { PreparedStatement preparedStatement = null; List DEFAULT_ARTIFACT_TYPES = EamArtifact.getDefaultArtifactTypes(); String sql = "INSERT INTO artifact_types(name, supported, enabled) VALUES (?, ?, ?)"; @@ -92,10 +95,12 @@ public class EamDbUtil { } preparedStatement.executeBatch(); } catch (SQLException ex) { - throw new EamDbException("Error inserting default correlation artifact types.", ex); // NON-NLS + LOGGER.log(Level.SEVERE, "Error inserting default correlation artifact types.", ex); // NON-NLS + return false; } finally { EamDbUtil.closePreparedStatement(preparedStatement); } + return true; } /** @@ -104,9 +109,10 @@ public class EamDbUtil { * This should be called immediately following the database schema being * loaded. * - * @throws EamDbException + * @param conn Open connection to use. + * @return true on success, else false */ - public static void insertSchemaVersion(Connection conn) throws EamDbException { + public static boolean insertSchemaVersion(Connection conn) { PreparedStatement preparedStatement = null; String sql = "INSERT INTO db_info (name, value) VALUES (?, ?)"; try { @@ -115,10 +121,12 @@ public class EamDbUtil { preparedStatement.setString(2, String.valueOf(SCHEMA_VERSION)); preparedStatement.executeUpdate(); } catch (SQLException ex) { - throw new EamDbException("Error adding schema version to db_info.", ex); + LOGGER.log(Level.SEVERE, "Error adding schema version to db_info.", ex); + return false; } finally { EamDbUtil.closePreparedStatement(preparedStatement); } + return true; } /** @@ -142,10 +150,7 @@ public class EamDbUtil { } catch (SQLException ex) { return false; } finally { - try { - EamDbUtil.closeResultSet(resultSet); - } catch (EamDbException ex) { - } + EamDbUtil.closeResultSet(resultSet); } return true; } @@ -171,10 +176,7 @@ public class EamDbUtil { } catch (SQLException ex) { return false; } finally { - try { - EamDbUtil.closeResultSet(resultSet); - } catch (EamDbException ex) { - } + EamDbUtil.closeResultSet(resultSet); } return false; diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/PostgresEamDb.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/PostgresEamDb.java index 1c889cd3c3..83fafdf7db 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/PostgresEamDb.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/PostgresEamDb.java @@ -126,174 +126,6 @@ public class PostgresEamDb extends AbstractSqlEamDb { connectionPool.setValidationQuery(dbSettings.getValidationQuery()); } - /** - * Initialize the database schema. - * - * Requires valid connectionPool. - * - * This method is called from within connect(), so we cannot call connect() - * to get a connection. This method is called after setupConnectionPool(), - * so it is safe to assume that a valid connectionPool exists. The - * implementation of connect() is synchronized, so we can safely use the - * connectionPool object directly. - */ - private void initializeDatabaseSchema() throws EamDbException { - // The "id" column is an alias for the built-in 64-bit int "rowid" column. - // It is autoincrementing by default and must be of type "integer primary key". - // We've omitted the autoincrement argument because we are not currently - // using the id value to search for specific rows, so we do not care - // if a rowid is re-used after an existing rows was previously deleted. - StringBuilder createOrganizationsTable = new StringBuilder(); - createOrganizationsTable.append("CREATE TABLE IF NOT EXISTS organizations ("); - createOrganizationsTable.append("id SERIAL PRIMARY KEY,"); - createOrganizationsTable.append("org_name text NOT NULL,"); - createOrganizationsTable.append("poc_name text NOT NULL,"); - createOrganizationsTable.append("poc_email text NOT NULL,"); - createOrganizationsTable.append("poc_phone text NOT NULL"); - createOrganizationsTable.append(")"); - - // NOTE: The organizations will only have a small number of rows, so - // an index is probably not worthwhile. - - StringBuilder createCasesTable = new StringBuilder(); - createCasesTable.append("CREATE TABLE IF NOT EXISTS cases ("); - createCasesTable.append("id SERIAL PRIMARY KEY,"); - createCasesTable.append("case_uid text NOT NULL,"); - createCasesTable.append("org_id integer,"); - createCasesTable.append("case_name text NOT NULL,"); - createCasesTable.append("creation_date text NOT NULL,"); - createCasesTable.append("case_number text NOT NULL,"); - createCasesTable.append("examiner_name text NOT NULL,"); - createCasesTable.append("examiner_email text NOT NULL,"); - createCasesTable.append("examiner_phone text NOT NULL,"); - createCasesTable.append("notes text NOT NULL,"); - createCasesTable.append("foreign key (org_id) references organizations(id) on update set null on delete set null"); - createCasesTable.append(")"); - - // NOTE: when there are few cases in the cases table, these indices may not be worthwhile - String casesIdx1 = "CREATE INDEX IF NOT EXISTS cases_org_id ON cases (org_id)"; - String casesIdx2 = "CREATE INDEX IF NOT EXISTS cases_case_uid ON cases (case_uid)"; - - StringBuilder createDataSourcesTable = new StringBuilder(); - createDataSourcesTable.append("CREATE TABLE IF NOT EXISTS data_sources ("); - createDataSourcesTable.append("id SERIAL PRIMARY KEY,"); - createDataSourcesTable.append("device_id text NOT NULL,"); - createDataSourcesTable.append("name text NOT NULL,"); - createDataSourcesTable.append("CONSTRAINT device_id_unique UNIQUE (device_id)"); - createDataSourcesTable.append(")"); - - String dataSourceIdx1 = "CREATE INDEX IF NOT EXISTS data_sources_name ON data_sources (name)"; - - StringBuilder createGlobalReferenceSetsTable = new StringBuilder(); - createGlobalReferenceSetsTable.append("CREATE TABLE IF NOT EXISTS global_reference_sets ("); - createGlobalReferenceSetsTable.append("id SERIAL PRIMARY KEY,"); - createGlobalReferenceSetsTable.append("org_id integer,"); - createGlobalReferenceSetsTable.append("set_name text NOT NULL,"); - createGlobalReferenceSetsTable.append("version text NOT NULL,"); - createGlobalReferenceSetsTable.append("import_date text NOT NULL,"); - createGlobalReferenceSetsTable.append("foreign key (org_id) references organizations(id) on update set null on delete set null"); - createGlobalReferenceSetsTable.append(")"); - - String globalReferenceSetsIdx1 = "CREATE INDEX IF NOT EXISTS global_reference_sets_org_id ON global_reference_sets (org_id)"; - - StringBuilder createGlobalFilesTable = new StringBuilder(); - createGlobalFilesTable.append("CREATE TABLE IF NOT EXISTS global_files ("); - createGlobalFilesTable.append("id SERIAL PRIMARY KEY,"); - createGlobalFilesTable.append("global_reference_set_id integer,"); - createGlobalFilesTable.append("value text NOT NULL,"); - createGlobalFilesTable.append("known_status text NOT NULL,"); - createGlobalFilesTable.append("comment text NOT NULL,"); - createGlobalFilesTable.append("CONSTRAINT global_files_multi_unique UNIQUE (global_reference_set_id,value),"); - createGlobalFilesTable.append("foreign key (global_reference_set_id) references global_reference_sets(id) on update set null on delete set null"); - createGlobalFilesTable.append(")"); - - String globalFilesIdx1 = "CREATE INDEX IF NOT EXISTS global_files_value ON global_files (value)"; - String globalFilesIdx2 = "CREATE INDEX IF NOT EXISTS global_files_value_known_status ON global_files (value, known_status)"; - - StringBuilder createArtifactTypesTable = new StringBuilder(); - createArtifactTypesTable.append("CREATE TABLE IF NOT EXISTS artifact_types ("); - createArtifactTypesTable.append("id SERIAL PRIMARY KEY,"); - createArtifactTypesTable.append("name text NOT NULL,"); - createArtifactTypesTable.append("supported integer NOT NULL,"); - createArtifactTypesTable.append("enabled integer NOT NULL,"); - createArtifactTypesTable.append("CONSTRAINT artifact_type_name_unique UNIQUE (name)"); - createArtifactTypesTable.append(")"); - - // NOTE: there are API methods that query by one of: name, supported, or enabled. - // Only name is currently implemented, but, there will only be a small number - // of artifact_types, so there is no benefit to having any indices. - StringBuilder createArtifactInstancesTableTemplate = new StringBuilder(); - createArtifactInstancesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s_instances ("); - createArtifactInstancesTableTemplate.append("id SERIAL PRIMARY KEY,"); - createArtifactInstancesTableTemplate.append("case_id integer,"); - createArtifactInstancesTableTemplate.append("data_source_id integer,"); - createArtifactInstancesTableTemplate.append("value text NOT NULL,"); - createArtifactInstancesTableTemplate.append("file_path text NOT NULL,"); - createArtifactInstancesTableTemplate.append("known_status text NOT NULL,"); - createArtifactInstancesTableTemplate.append("comment text NOT NULL,"); - createArtifactInstancesTableTemplate.append("CONSTRAINT %s_instances_multi_unique_ UNIQUE (case_id, data_source_id, value, file_path),"); - createArtifactInstancesTableTemplate.append("foreign key (case_id) references cases(id) on update set null on delete set null,"); - createArtifactInstancesTableTemplate.append("foreign key (data_source_id) references data_sources(id) on update set null on delete set null"); - createArtifactInstancesTableTemplate.append(")"); - - // TODO: do we need any more indices? - String instancesIdx1 = "CREATE INDEX IF NOT EXISTS %s_instances_case_id ON %s_instances (case_id)"; - String instancesIdx2 = "CREATE INDEX IF NOT EXISTS %s_instances_data_source_id ON %s_instances (data_source_id)"; - String instancesIdx3 = "CREATE INDEX IF NOT EXISTS %s_instances_value ON %s_instances (value)"; - String instancesIdx4 = "CREATE INDEX IF NOT EXISTS %s_instances_value_known_status ON %s_instances (value, known_status)"; - - StringBuilder createDbInfoTable = new StringBuilder(); - createDbInfoTable.append("CREATE TABLE IF NOT EXISTS db_info ("); - createDbInfoTable.append("id SERIAL PRIMARY KEY NOT NULL,"); - createDbInfoTable.append("name text NOT NULL,"); - createDbInfoTable.append("value text NOT NULL"); - createDbInfoTable.append(")"); - - // NOTE: the db_info table currenly only has 1 row, so having an index - // provides no benefit. - - Connection conn = null; - try { - conn = connectionPool.getConnection(); - Statement stmt = conn.createStatement(); - - stmt.execute(createOrganizationsTable.toString()); - - stmt.execute(createCasesTable.toString()); - stmt.execute(casesIdx1); - stmt.execute(casesIdx2); - - stmt.execute(createDataSourcesTable.toString()); - stmt.execute(dataSourceIdx1); - - stmt.execute(createGlobalReferenceSetsTable.toString()); - stmt.execute(globalReferenceSetsIdx1); - - stmt.execute(createGlobalFilesTable.toString()); - stmt.execute(globalFilesIdx1); - stmt.execute(globalFilesIdx2); - - stmt.execute(createArtifactTypesTable.toString()); - - stmt.execute(createDbInfoTable.toString()); - - // Create a separate table for each artifact type - String type_name; - for (EamArtifact.Type type : DEFAULT_ARTIFACT_TYPES) { - type_name = type.getName(); - stmt.execute(String.format(createArtifactInstancesTableTemplate.toString(), type_name, type_name)); - stmt.execute(String.format(instancesIdx1, type_name, type_name)); - stmt.execute(String.format(instancesIdx2, type_name, type_name)); - stmt.execute(String.format(instancesIdx3, type_name, type_name)); - stmt.execute(String.format(instancesIdx4, type_name, type_name)); - } - } catch (SQLException ex) { - throw new EamDbException("Error initializing db schema.", ex); // NON-NLS - } finally { - EamDbUtil.closeConnection(conn); - } - } - /** * Lazily setup Singleton connection on first request. * @@ -321,11 +153,6 @@ public class PostgresEamDb extends AbstractSqlEamDb { } } - @Override - public boolean isEnabled() { - return dbSettings.isEnabled(); - } - @Override public List getBadTags() { return dbSettings.getBadTags(); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/PostgresEamDbSettings.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/PostgresEamDbSettings.java index 3c0a64ae46..e59af50013 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/PostgresEamDbSettings.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/PostgresEamDbSettings.java @@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel; import java.sql.Connection; import java.sql.DriverManager; +import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; @@ -27,6 +28,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.logging.Level; +import org.openide.util.Exceptions; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ModuleSettings; @@ -39,7 +41,7 @@ public final class PostgresEamDbSettings { private final static Logger LOGGER = Logger.getLogger(PostgresEamDbSettings.class.getName()); private final String DEFAULT_HOST = "localhost"; // NON-NLS private final int DEFAULT_PORT = 5432; - private final String DEFAULT_DBNAME = "enterpriseartifactmanagerdb"; // NON-NLS + private final String DEFAULT_DBNAME = "EnterpriseArtifacts"; // NON-NLS private final int DEFAULT_BULK_THRESHHOLD = 1000; private final String DEFAULT_USERNAME = ""; private final String DEFAULT_PASSWORD = ""; @@ -120,7 +122,6 @@ public final class PostgresEamDbSettings { } public void saveSettings() { - ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.enabled", Boolean.toString(isEnabled())); // NON-NLS ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.postgresql.host", getHost()); // NON-NLS ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.postgresql.port", Integer.toString(port)); // NON-NLS ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.postgresql.dbName", getDbName()); // NON-NLS @@ -133,14 +134,21 @@ public final class PostgresEamDbSettings { /** * Get the full connection URL as a String * + * @param usePostgresDb Connect to the 'postgres' database when testing + * connectivity and creating the main database. + * * @return */ - public String getConnectionURL() { + public String getConnectionURL(boolean usePostgresDb) { StringBuilder url = new StringBuilder(); url.append(getJDBCBaseURI()); url.append(getHost()); url.append("/"); // NON-NLS - url.append(getDbName()); + if (usePostgresDb) { + url.append("postgres"); // NON-NLS + } else { + url.append(getDbName()); + } url.append("?user="); // NON-NLS url.append(getUserName()); url.append("&password="); // NON-NLS @@ -150,50 +158,299 @@ public final class PostgresEamDbSettings { } /** - * Using the current settings, test the connection to the database. + * Use the current settings to get an ephemeral client connection for testing. + * + * @return Connection or null. + */ + private Connection getEphemeralConnection(boolean usePostgresDb) { + Connection conn; + try { + String url = getConnectionURL(usePostgresDb); + Class.forName(getDriver()); + conn = DriverManager.getConnection(url); + } catch (ClassNotFoundException | SQLException ex) { + // TODO: Determine why a connection failure (ConnectionException) re-throws + // the SQLException and does not print this log message? + LOGGER.log(Level.SEVERE, "Failed to acquire ephemeral connection to postgresql."); // NON-NLS + conn = null; + } + return conn; + } + + /** + * Use the current settings and the validation query + * to test the connection to the database. * * @return true if successfull connection, else false. */ - public boolean testConnectionSettings() { - // Open a new ephemeral client here to test that we can connect - ResultSet resultSet = null; - Connection conn = null; - try { - String url = getConnectionURL(); - Class.forName(getDriver()); - conn = DriverManager.getConnection(url); - Statement tester = conn.createStatement(); - resultSet = tester.executeQuery(getValidationQuery()); - if (resultSet.next()) { - LOGGER.log(Level.INFO, "Testing connection to postgresql success."); // NON-NLS - } - } catch (ClassNotFoundException | SQLException ex) { - LOGGER.log(Level.INFO, "Testing connection to postgresql failed.", ex); // NON-NLS + public boolean verifyConnection() { + Connection conn = getEphemeralConnection(true); + if (null == conn) { + return false; + } + + boolean result = EamDbUtil.executeValidationQuery(conn, VALIDATION_QUERY); + EamDbUtil.closeConnection(conn); + return result; + } + + /** + * Check to see if the database exists. + * + * @return true if exists, else false + */ + public boolean verifyDatabaseExists() { + Connection conn = getEphemeralConnection(true); + if (null == conn) { return false; - } finally { - if (null != resultSet) { - try { - resultSet.close(); - } catch (SQLException ex) { - LOGGER.log(Level.SEVERE, "Error closing ResultSet.", ex); // NON-NLS - } - } - if (null != conn) { - try { - conn.close(); - } catch (SQLException ex) { - LOGGER.log(Level.SEVERE, "Error closing test connection.", ex); // NON-NLS - } - } } - return true; + String sql = "SELECT datname FROM pg_catalog.pg_database WHERE lower(datname) = lower(?) LIMIT 1"; // NON-NLS + PreparedStatement ps = null; + ResultSet rs = null; + try { + ps = conn.prepareStatement(sql); + ps.setString(1, getDbName()); + rs = ps.executeQuery(); + if (rs.next()) { + return true; + } + } catch (SQLException ex) { + LOGGER.log(Level.SEVERE, "Failed to execute database existance query.", ex); // NON-NLS + return false; + } finally { + EamDbUtil.closePreparedStatement(ps); + EamDbUtil.closeResultSet(rs); + EamDbUtil.closeConnection(conn); + } + return false; } + /** + * Use the current settings and the schema version query + * to test the database schema. + * + * @return true if successfull connection, else false. + */ + public boolean verifyDatabaseSchema() { + Connection conn = getEphemeralConnection(false); + if (null == conn) { + return false; + } + + boolean result = EamDbUtil.schemaVersionIsSet(conn); + + EamDbUtil.closeConnection(conn); + return result; + } + + public boolean createDatabase() { + Connection conn = getEphemeralConnection(true); + if (null == conn) { + return false; + } + + String sql = "CREATE DATABASE %s OWNER %s"; // NON-NLS + try { + Statement stmt; + stmt = conn.createStatement(); + stmt.execute(String.format(sql, getDbName(), getUserName())); + } catch (SQLException ex) { + LOGGER.log(Level.SEVERE, "Failed to execute create database statement.", ex); // NON-NLS + return false; + } finally { + EamDbUtil.closeConnection(conn); + } + return true; + + } + /** + * Initialize the database schema. + * + * Requires valid connectionPool. + * + * This method is called from within connect(), so we cannot call connect() + * to get a connection. This method is called after setupConnectionPool(), + * so it is safe to assume that a valid connectionPool exists. The + * implementation of connect() is synchronized, so we can safely use the + * connectionPool object directly. + */ + public boolean initializeDatabaseSchema() { + // The "id" column is an alias for the built-in 64-bit int "rowid" column. + // It is autoincrementing by default and must be of type "integer primary key". + // We've omitted the autoincrement argument because we are not currently + // using the id value to search for specific rows, so we do not care + // if a rowid is re-used after an existing rows was previously deleted. + StringBuilder createOrganizationsTable = new StringBuilder(); + createOrganizationsTable.append("CREATE TABLE IF NOT EXISTS organizations ("); + createOrganizationsTable.append("id SERIAL PRIMARY KEY,"); + createOrganizationsTable.append("org_name text NOT NULL,"); + createOrganizationsTable.append("poc_name text NOT NULL,"); + createOrganizationsTable.append("poc_email text NOT NULL,"); + createOrganizationsTable.append("poc_phone text NOT NULL"); + createOrganizationsTable.append(")"); + + // NOTE: The organizations will only have a small number of rows, so + // an index is probably not worthwhile. + + StringBuilder createCasesTable = new StringBuilder(); + createCasesTable.append("CREATE TABLE IF NOT EXISTS cases ("); + createCasesTable.append("id SERIAL PRIMARY KEY,"); + createCasesTable.append("case_uid text NOT NULL,"); + createCasesTable.append("org_id integer,"); + createCasesTable.append("case_name text NOT NULL,"); + createCasesTable.append("creation_date text NOT NULL,"); + createCasesTable.append("case_number text NOT NULL,"); + createCasesTable.append("examiner_name text NOT NULL,"); + createCasesTable.append("examiner_email text NOT NULL,"); + createCasesTable.append("examiner_phone text NOT NULL,"); + createCasesTable.append("notes text NOT NULL,"); + createCasesTable.append("foreign key (org_id) references organizations(id) on update set null on delete set null"); + createCasesTable.append(")"); + + // NOTE: when there are few cases in the cases table, these indices may not be worthwhile + String casesIdx1 = "CREATE INDEX IF NOT EXISTS cases_org_id ON cases (org_id)"; + String casesIdx2 = "CREATE INDEX IF NOT EXISTS cases_case_uid ON cases (case_uid)"; + + StringBuilder createDataSourcesTable = new StringBuilder(); + createDataSourcesTable.append("CREATE TABLE IF NOT EXISTS data_sources ("); + createDataSourcesTable.append("id SERIAL PRIMARY KEY,"); + createDataSourcesTable.append("device_id text NOT NULL,"); + createDataSourcesTable.append("name text NOT NULL,"); + createDataSourcesTable.append("CONSTRAINT device_id_unique UNIQUE (device_id)"); + createDataSourcesTable.append(")"); + + String dataSourceIdx1 = "CREATE INDEX IF NOT EXISTS data_sources_name ON data_sources (name)"; + + StringBuilder createGlobalReferenceSetsTable = new StringBuilder(); + createGlobalReferenceSetsTable.append("CREATE TABLE IF NOT EXISTS global_reference_sets ("); + createGlobalReferenceSetsTable.append("id SERIAL PRIMARY KEY,"); + createGlobalReferenceSetsTable.append("org_id integer,"); + createGlobalReferenceSetsTable.append("set_name text NOT NULL,"); + createGlobalReferenceSetsTable.append("version text NOT NULL,"); + createGlobalReferenceSetsTable.append("import_date text NOT NULL,"); + createGlobalReferenceSetsTable.append("foreign key (org_id) references organizations(id) on update set null on delete set null"); + createGlobalReferenceSetsTable.append(")"); + + String globalReferenceSetsIdx1 = "CREATE INDEX IF NOT EXISTS global_reference_sets_org_id ON global_reference_sets (org_id)"; + + StringBuilder createGlobalFilesTable = new StringBuilder(); + createGlobalFilesTable.append("CREATE TABLE IF NOT EXISTS global_files ("); + createGlobalFilesTable.append("id SERIAL PRIMARY KEY,"); + createGlobalFilesTable.append("global_reference_set_id integer,"); + createGlobalFilesTable.append("value text NOT NULL,"); + createGlobalFilesTable.append("known_status text NOT NULL,"); + createGlobalFilesTable.append("comment text NOT NULL,"); + createGlobalFilesTable.append("CONSTRAINT global_files_multi_unique UNIQUE (global_reference_set_id,value),"); + createGlobalFilesTable.append("foreign key (global_reference_set_id) references global_reference_sets(id) on update set null on delete set null"); + createGlobalFilesTable.append(")"); + + String globalFilesIdx1 = "CREATE INDEX IF NOT EXISTS global_files_value ON global_files (value)"; + String globalFilesIdx2 = "CREATE INDEX IF NOT EXISTS global_files_value_known_status ON global_files (value, known_status)"; + + StringBuilder createArtifactTypesTable = new StringBuilder(); + createArtifactTypesTable.append("CREATE TABLE IF NOT EXISTS artifact_types ("); + createArtifactTypesTable.append("id SERIAL PRIMARY KEY,"); + createArtifactTypesTable.append("name text NOT NULL,"); + createArtifactTypesTable.append("supported integer NOT NULL,"); + createArtifactTypesTable.append("enabled integer NOT NULL,"); + createArtifactTypesTable.append("CONSTRAINT artifact_type_name_unique UNIQUE (name)"); + createArtifactTypesTable.append(")"); + + // NOTE: there are API methods that query by one of: name, supported, or enabled. + // Only name is currently implemented, but, there will only be a small number + // of artifact_types, so there is no benefit to having any indices. + StringBuilder createArtifactInstancesTableTemplate = new StringBuilder(); + createArtifactInstancesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s_instances ("); + createArtifactInstancesTableTemplate.append("id SERIAL PRIMARY KEY,"); + createArtifactInstancesTableTemplate.append("case_id integer,"); + createArtifactInstancesTableTemplate.append("data_source_id integer,"); + createArtifactInstancesTableTemplate.append("value text NOT NULL,"); + createArtifactInstancesTableTemplate.append("file_path text NOT NULL,"); + createArtifactInstancesTableTemplate.append("known_status text NOT NULL,"); + createArtifactInstancesTableTemplate.append("comment text NOT NULL,"); + createArtifactInstancesTableTemplate.append("CONSTRAINT %s_instances_multi_unique_ UNIQUE (case_id, data_source_id, value, file_path),"); + createArtifactInstancesTableTemplate.append("foreign key (case_id) references cases(id) on update set null on delete set null,"); + createArtifactInstancesTableTemplate.append("foreign key (data_source_id) references data_sources(id) on update set null on delete set null"); + createArtifactInstancesTableTemplate.append(")"); + + // TODO: do we need any more indices? + String instancesIdx1 = "CREATE INDEX IF NOT EXISTS %s_instances_case_id ON %s_instances (case_id)"; + String instancesIdx2 = "CREATE INDEX IF NOT EXISTS %s_instances_data_source_id ON %s_instances (data_source_id)"; + String instancesIdx3 = "CREATE INDEX IF NOT EXISTS %s_instances_value ON %s_instances (value)"; + String instancesIdx4 = "CREATE INDEX IF NOT EXISTS %s_instances_value_known_status ON %s_instances (value, known_status)"; + + StringBuilder createDbInfoTable = new StringBuilder(); + createDbInfoTable.append("CREATE TABLE IF NOT EXISTS db_info ("); + createDbInfoTable.append("id SERIAL PRIMARY KEY NOT NULL,"); + createDbInfoTable.append("name text NOT NULL,"); + createDbInfoTable.append("value text NOT NULL"); + createDbInfoTable.append(")"); + + // NOTE: the db_info table currenly only has 1 row, so having an index + // provides no benefit. + + Connection conn = null; + try { + conn = getEphemeralConnection(false); + if (null == conn) { + return false; + } + Statement stmt = conn.createStatement(); + + stmt.execute(createOrganizationsTable.toString()); + + stmt.execute(createCasesTable.toString()); + stmt.execute(casesIdx1); + stmt.execute(casesIdx2); + + stmt.execute(createDataSourcesTable.toString()); + stmt.execute(dataSourceIdx1); + + stmt.execute(createGlobalReferenceSetsTable.toString()); + stmt.execute(globalReferenceSetsIdx1); + + stmt.execute(createGlobalFilesTable.toString()); + stmt.execute(globalFilesIdx1); + stmt.execute(globalFilesIdx2); + + stmt.execute(createArtifactTypesTable.toString()); + + stmt.execute(createDbInfoTable.toString()); + + // Create a separate table for each artifact type + List DEFAULT_ARTIFACT_TYPES = EamArtifact.getDefaultArtifactTypes(); + String type_name; + for (EamArtifact.Type type : DEFAULT_ARTIFACT_TYPES) { + type_name = type.getName(); + stmt.execute(String.format(createArtifactInstancesTableTemplate.toString(), type_name, type_name)); + stmt.execute(String.format(instancesIdx1, type_name, type_name)); + stmt.execute(String.format(instancesIdx2, type_name, type_name)); + stmt.execute(String.format(instancesIdx3, type_name, type_name)); + stmt.execute(String.format(instancesIdx4, type_name, type_name)); + } + } catch (SQLException ex) { + LOGGER.log(Level.SEVERE, "Error initializing db schema.", ex); // NON-NLS + return false; + } finally { + EamDbUtil.closeConnection(conn); + } + return true; + } + public boolean insertDefaultDatabaseContent() { - return true; + Connection conn = getEphemeralConnection(false); + if (null == conn) { + return false; + } + + boolean result = EamDbUtil.insertDefaultArtifactTypes(conn) + && EamDbUtil.insertSchemaVersion(conn); + EamDbUtil.closeConnection(conn); + + return result; } - + public boolean isChanged() { String hostString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.postgresql.host"); // NON-NLS String portString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.postgresql.port"); // NON-NLS diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/SqliteEamDb.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/SqliteEamDb.java index a5d4111b3c..0b41f2d7d9 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/SqliteEamDb.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/SqliteEamDb.java @@ -133,7 +133,7 @@ public class SqliteEamDb extends AbstractSqlEamDb { @Override protected Connection connect() throws EamDbException { synchronized (this) { - if (!dbSettings.isEnabled()) { + if (!EamDb.isEnabled()) { throw new EamDbException("Enterprise artifacts manager is not enabled"); // NON-NLS } @@ -151,11 +151,6 @@ public class SqliteEamDb extends AbstractSqlEamDb { } } - @Override - public boolean isEnabled() { - return dbSettings.isEnabled(); - } - @Override public List getBadTags() { return dbSettings.getBadTags(); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/SqliteEamDbSettings.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/SqliteEamDbSettings.java index 5ac7da6834..b4a891a57b 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/SqliteEamDbSettings.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/SqliteEamDbSettings.java @@ -104,7 +104,6 @@ public final class SqliteEamDbSettings { public void saveSettings() { createDbDirectory(); - ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.enabled", Boolean.toString(isEnabled())); // NON-NLS ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.sqlite.dbName", getDbName()); // NON-NLS ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.sqlite.dbDirectory", getDbDirectory()); // NON-NLS ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.sqlite.bulkThreshold", Integer.toString(getBulkThreshold())); // NON-NLS @@ -175,14 +174,14 @@ public final class SqliteEamDbSettings { return null; } - Connection conn = null; + Connection conn; try { String url = getConnectionURL(); Class.forName(getDriver()); conn = DriverManager.getConnection(url); } catch (ClassNotFoundException | SQLException ex) { LOGGER.log(Level.SEVERE, "Failed to acquire ephemeral connection to sqlite.", ex); // NON-NLS - return null; + conn = null; } return conn; } @@ -200,11 +199,7 @@ public final class SqliteEamDbSettings { } boolean result = EamDbUtil.executeValidationQuery(conn, VALIDATION_QUERY); - try { - EamDbUtil.closeConnection(conn); - } catch (EamDbException ex) { - LOGGER.log(Level.SEVERE, "verifyConnection failed to close resources.", ex); - } + EamDbUtil.closeConnection(conn); return result; } @@ -221,11 +216,7 @@ public final class SqliteEamDbSettings { } boolean result = EamDbUtil.schemaVersionIsSet(conn); - try { - EamDbUtil.closeConnection(conn); - } catch (EamDbException ex) { - LOGGER.log(Level.SEVERE, "verifyDatabaseSchema failed to close resources.", ex); - } + EamDbUtil.closeConnection(conn); return result; } @@ -359,6 +350,9 @@ public final class SqliteEamDbSettings { Connection conn = null; try { conn = getEphemeralConnection(); + if (null == conn) { + return false; + } Statement stmt = conn.createStatement(); stmt.execute(PRAGMA_JOURNAL_WAL); stmt.execute(PRAGMA_SYNC_OFF); @@ -403,11 +397,7 @@ public final class SqliteEamDbSettings { LOGGER.log(Level.SEVERE, "Error initializing db schema.", ex); // NON-NLS return false; } finally { - try { - EamDbUtil.closeConnection(conn); - } catch (EamDbException ex) { - LOGGER.log(Level.SEVERE, "initializeDatabaseSchema failed to close resources.", ex); - } + EamDbUtil.closeConnection(conn); } return true; } @@ -418,19 +408,10 @@ public final class SqliteEamDbSettings { return false; } - try { - EamDbUtil.insertDefaultArtifactTypes(conn); - EamDbUtil.insertSchemaVersion(conn); - } catch (EamDbException ex) { - return false; - } finally { - try { - EamDbUtil.closeConnection(conn); - } catch (EamDbException ex) { - LOGGER.log(Level.SEVERE, "insertDefaultDatabaseContent failed to close resources.", ex); - } - } - return true; + boolean result = EamDbUtil.insertDefaultArtifactTypes(conn) + && EamDbUtil.insertSchemaVersion(conn); + EamDbUtil.closeConnection(conn); + return result; } public boolean isChanged() { @@ -443,20 +424,6 @@ public final class SqliteEamDbSettings { || !Integer.toString(bulkThreshold).equals(bulkThresholdString); } - /** - * @return the enabled - */ - public boolean isEnabled() { - return enabled; - } - - /** - * @param enabled the enabled to set - */ - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - /** * @return the dbName */ diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/BadFileTagRunner.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/BadFileTagRunner.java index 3bbbb1aebf..1355bbef7e 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/BadFileTagRunner.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/BadFileTagRunner.java @@ -42,7 +42,7 @@ public class BadFileTagRunner implements Runnable { @Override public void run() { - if (!dbManager.isEnabled()) { + if (!EamDb.isEnabled()) { LOGGER.log(Level.WARNING, "Enterprise artifacts manager database not configured"); // NON-NLS return; } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/CaseEventListener.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/CaseEventListener.java index 053eeebbc3..039e9a8867 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/CaseEventListener.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/CaseEventListener.java @@ -61,7 +61,7 @@ public class CaseEventListener implements PropertyChangeListener { EamDb dbManager = EamDb.getInstance(); switch (Case.Events.valueOf(evt.getPropertyName())) { case CONTENT_TAG_ADDED: { - if (!dbManager.isEnabled()) { + if (!EamDb.isEnabled()) { return; } @@ -125,7 +125,7 @@ public class CaseEventListener implements PropertyChangeListener { break; case BLACKBOARD_ARTIFACT_TAG_ADDED: { - if (!dbManager.isEnabled()) { + if (!EamDb.isEnabled()) { return; } @@ -157,7 +157,7 @@ public class CaseEventListener implements PropertyChangeListener { break; case DATA_SOURCE_ADDED: { - if (!dbManager.isEnabled()) { + if (!EamDb.isEnabled()) { break; } @@ -214,7 +214,7 @@ public class CaseEventListener implements PropertyChangeListener { "", ""); - if (!dbManager.isEnabled()) { + if (!EamDb.isEnabled()) { break; } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/IngestEventsListener.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/IngestEventsListener.java index bcd1f3abeb..9066d960d5 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/IngestEventsListener.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/IngestEventsListener.java @@ -78,7 +78,7 @@ public class IngestEventsListener { EamDb dbManager = EamDb.getInstance(); switch (IngestManager.IngestModuleEvent.valueOf(evt.getPropertyName())) { case DATA_ADDED: { - if (!dbManager.isEnabled()) { + if (!EamDb.isEnabled()) { return; } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/NewArtifactsRunner.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/NewArtifactsRunner.java index 79762b75a6..a8eaa8fd3d 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/NewArtifactsRunner.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/NewArtifactsRunner.java @@ -45,7 +45,7 @@ public class NewArtifactsRunner implements Runnable { @Override public void run() { - if (!dbManager.isEnabled()) { + if (!EamDb.isEnabled()) { LOGGER.log(Level.WARNING, "Enterprise artifacts manager database not configured"); // NON-NLS return; } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/ingestmodule/IngestModule.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/ingestmodule/IngestModule.java index 72fdf1762b..3742ba564d 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/ingestmodule/IngestModule.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/ingestmodule/IngestModule.java @@ -70,7 +70,7 @@ class IngestModule implements FileIngestModule { @Override public ProcessResult process(AbstractFile af) { if (Boolean.parseBoolean(ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.enabled")) == false - || EamDb.getInstance().isEnabled() == false) { + || EamDb.isEnabled() == false) { /* * Not signaling an error for now. This is a workaround for the way * all newly didscovered ingest modules are automatically anabled. @@ -153,7 +153,7 @@ class IngestModule implements FileIngestModule { @Override public void shutDown() { if (Boolean.parseBoolean(ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.enabled")) == false - || EamDb.getInstance().isEnabled() == false) { + || EamDb.isEnabled() == false) { /* * Not signaling an error for now. This is a workaround for the way * all newly didscovered ingest modules are automatically anabled. @@ -188,7 +188,7 @@ class IngestModule implements FileIngestModule { @Override public void startUp(IngestJobContext context) throws IngestModuleException { if (Boolean.parseBoolean(ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.enabled")) == false - || EamDb.getInstance().isEnabled() == false) { + || EamDb.isEnabled() == false) { /* * Not throwing the customary exception for now. This is a * workaround for the way all newly didscovered ingest modules are diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamDbSettingsDialog.form b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamDbSettingsDialog.form index 881f93eac4..e9e3f2aaab 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamDbSettingsDialog.form +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamDbSettingsDialog.form @@ -200,11 +200,11 @@ - - + + @@ -236,7 +236,7 @@ - + @@ -287,7 +287,7 @@ - + diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamDbSettingsDialog.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamDbSettingsDialog.java index 9d11ff16c7..3fcfda51c0 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamDbSettingsDialog.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamDbSettingsDialog.java @@ -28,6 +28,7 @@ import org.openide.util.NbBundle.Messages; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.corecomponents.TextPrompt; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb; import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbException; import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbPlatformEnum; import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.PostgresEamDbSettings; @@ -98,7 +99,7 @@ public class EamDbSettingsDialog extends JDialog { tbDbPort = new javax.swing.JTextField(); tbDbName = new javax.swing.JTextField(); tbDbUsername = new javax.swing.JTextField(); - tbDbPassword = new javax.swing.JTextField(); + jpDbPassword = new javax.swing.JPasswordField(); rdioBnSQLite = new javax.swing.JRadioButton(); rdioBnPostgreSQL = new javax.swing.JRadioButton(); rdioBnDisabled = new javax.swing.JRadioButton(); @@ -179,11 +180,11 @@ public class EamDbSettingsDialog extends JDialog { .addComponent(lbUserPassword)) .addGap(18, 18, 18) .addGroup(pnPostgreSQLSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(tbDbPassword, javax.swing.GroupLayout.DEFAULT_SIZE, 439, Short.MAX_VALUE) - .addComponent(tbDbUsername) + .addComponent(tbDbUsername, javax.swing.GroupLayout.DEFAULT_SIZE, 439, Short.MAX_VALUE) .addComponent(tbDbName) .addComponent(tbDbPort) - .addComponent(tbDbHostname)) + .addComponent(tbDbHostname) + .addComponent(jpDbPassword)) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); pnPostgreSQLSettingsLayout.setVerticalGroup( @@ -208,7 +209,7 @@ public class EamDbSettingsDialog extends JDialog { .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(pnPostgreSQLSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(lbUserPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(tbDbPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(jpDbPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addContainerGap(19, Short.MAX_VALUE)) ); @@ -439,14 +440,21 @@ public class EamDbSettingsDialog extends JDialog { private void bnTestActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnTestActionPerformed // lbTestDatabase.setIcon(null); // lbTestDatabase.setText(""); - boolean connectionOk; - boolean schemaOk; setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); EamDbPlatformEnum selectedPlatform = EamDbPlatformEnum.getSelectedPlatform(); switch (selectedPlatform) { case POSTGRESQL: - connectionOk = dbSettingsPostgres.testConnectionSettings(); + if (dbSettingsPostgres.verifyConnection()) { + if (dbSettingsPostgres.verifyDatabaseExists() + && dbSettingsPostgres.verifyDatabaseSchema()) { + testingStatus = DatabaseTestResult.TESTEDOK; + } else { + testingStatus = DatabaseTestResult.SCHEMA_INVALID; + } + } else { + testingStatus = DatabaseTestResult.CONNECTION_FAILED; + } break; case SQLITE: if (dbSettingsSqlite.dbDirectoryExists() @@ -474,6 +482,12 @@ public class EamDbSettingsDialog extends JDialog { boolean result = false; switch (selectedPlatform) { case POSTGRESQL: + if (!dbSettingsPostgres.verifyDatabaseExists()) { + dbSettingsPostgres.createDatabase(); + } + result = dbSettingsPostgres.initializeDatabaseSchema() + && dbSettingsPostgres.insertDefaultDatabaseContent(); + break; case SQLITE: if (!dbSettingsSqlite.dbDirectoryExists()) { @@ -487,14 +501,27 @@ public class EamDbSettingsDialog extends JDialog { if (false == result) { taSetupGuidance.setText(Bundle.EamDbSettingsDialog_creation_failed()); } else { + testingStatus = DatabaseTestResult.TESTEDOK; valid(); } }//GEN-LAST:event_bnCreateDbActionPerformed private void bnOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOkActionPerformed -// hasChanged = true; -// dbSettings.setEnabled(true); -// dbSettings.saveSettings(); + EamDbPlatformEnum selectedPlatform = EamDbPlatformEnum.getSelectedPlatform(); + EamDbPlatformEnum.saveSelectedPlatform(); + switch (selectedPlatform) { + case POSTGRESQL: + dbSettingsPostgres.saveSettings(); + EamDb.getInstance().updateSettings(); + break; + case SQLITE: + dbSettingsSqlite.saveSettings(); + EamDb.getInstance().updateSettings(); + break; + case DISABLED: + break; + } + dispose(); }//GEN-LAST:event_bnOkActionPerformed @@ -543,8 +570,8 @@ public class EamDbSettingsDialog extends JDialog { tbDbName.setEnabled(enabled); tbDbUsername.setText(enabled ? dbSettingsPostgres.getUserName() : ""); tbDbUsername.setEnabled(enabled); - tbDbPassword.setText(enabled ? dbSettingsPostgres.getPassword() : ""); - tbDbPassword.setEnabled(enabled); + jpDbPassword.setText(enabled ? dbSettingsPostgres.getPassword() : ""); + jpDbPassword.setEnabled(enabled); } /** @@ -573,7 +600,6 @@ public class EamDbSettingsDialog extends JDialog { textPrompts.add(new TextPrompt(Bundle.EamDbSettingsDialog_textPrompt_port(), tbDbPort)); textPrompts.add(new TextPrompt(Bundle.EamDbSettingsDialog_textPrompt_dbName(), tbDbName)); textPrompts.add(new TextPrompt(Bundle.EamDbSettingsDialog_textPrompt_user(), tbDbUsername)); - textPrompts.add(new TextPrompt(Bundle.EamDbSettingsDialog_textPrompt_password(), tbDbPassword)); configureTextPrompts(textPrompts); } @@ -598,7 +624,7 @@ public class EamDbSettingsDialog extends JDialog { textBoxes.add(tbDbPort); textBoxes.add(tbDbName); textBoxes.add(tbDbUsername); - textBoxes.add(tbDbPassword); + textBoxes.add(jpDbPassword); addDocumentListeners(textBoxes, textBoxChangedListener); } @@ -643,7 +669,7 @@ public class EamDbSettingsDialog extends JDialog { && !tbDbPort.getText().trim().isEmpty() && !tbDbName.getText().trim().isEmpty() && !tbDbUsername.getText().trim().isEmpty() - && !tbDbPassword.getText().trim().isEmpty(); + && 0 < jpDbPassword.getPassword().length; break; @@ -727,7 +753,7 @@ public class EamDbSettingsDialog extends JDialog { } try { - dbSettingsPostgres.setPassword(tbDbPassword.getText().trim()); + dbSettingsPostgres.setPassword(jpDbPassword.getPassword().toString()); } catch (EamDbException ex) { if (!guidanceText.toString().isEmpty()) { guidanceText.append(", "); @@ -874,6 +900,7 @@ public class EamDbSettingsDialog extends JDialog { private javax.swing.JButton bnOk; private javax.swing.JButton bnTest; private javax.swing.JFileChooser fcDatabasePath; + private javax.swing.JPasswordField jpDbPassword; private javax.swing.JLabel lbDatabaseName; private javax.swing.JLabel lbDatabasePath; private javax.swing.JLabel lbHostName; @@ -891,7 +918,6 @@ public class EamDbSettingsDialog extends JDialog { private javax.swing.JTextArea taSetupGuidance; private javax.swing.JTextField tbDbHostname; private javax.swing.JTextField tbDbName; - private javax.swing.JTextField tbDbPassword; private javax.swing.JTextField tbDbPort; private javax.swing.JTextField tbDbUsername; private javax.swing.JTextField tfDatabasePath; diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/ImportHashDatabaseDialog.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/ImportHashDatabaseDialog.java index e1927401cd..3b1d392943 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/ImportHashDatabaseDialog.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/ImportHashDatabaseDialog.java @@ -178,7 +178,7 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog { public boolean valid() { lbWarningMsg.setText(""); EamDb dbManager = EamDb.getInstance(); - if (!dbManager.isEnabled()) { + if (!EamDb.isEnabled()) { lbWarningMsg.setText(Bundle.ImportHashDatabaseDialog_validation_notEnabled()); return false; } @@ -561,7 +561,7 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog { this.knownStatus = knownStatus; this.globalSetID = globalSetID; - if (!dbManager.isEnabled()) { + if (!EamDb.isEnabled()) { throw new EamDbException("Enterprise artifacts manager database settings were not properly initialized"); // NON-NLS } }