Autopsy  4.19.3
Graphical digital forensics platform for The Sleuth Kit and other tools.
IngestJobSettings.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2014-2021 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.ingest;
20 
21 import java.io.File;
22 import java.io.FileInputStream;
23 import java.io.FileOutputStream;
24 import java.io.IOException;
25 import java.nio.file.Files;
26 import java.nio.file.Path;
27 import java.nio.file.Paths;
28 import java.text.MessageFormat;
29 import java.util.ArrayList;
30 import java.util.Collection;
31 import java.util.Collections;
32 import java.util.HashSet;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Objects;
36 import java.util.logging.Level;
37 import org.openide.util.NbBundle;
38 import org.openide.util.io.NbObjectInputStream;
39 import org.openide.util.io.NbObjectOutputStream;
46 
50 public final class IngestJobSettings {
51 
52  private static final String ENABLED_MODULES_PROPERTY = "Enabled_Ingest_Modules"; //NON-NLS
53  private static final String DISABLED_MODULES_PROPERTY = "Disabled_Ingest_Modules"; //NON-NLS
54  private static final String LAST_FILE_INGEST_FILTER_PROPERTY = "Last_File_Ingest_Filter"; //NON-NLS
55  private static final String MODULE_SETTINGS_FOLDER_NAME = "IngestSettings"; //NON-NLS
56 
57  private static final String MODULE_SETTINGS_FOLDER = Paths.get(
58  Paths.get(PlatformUtil.getUserConfigDirectory()).relativize(Paths.get(PlatformUtil.getModuleConfigDirectory())).toString(),
60  ).toString();
61 
62  private static final String MODULE_SETTINGS_FOLDER_PATH = Paths.get(
65  ).toAbsolutePath().toString();
66 
67  private static final String MODULE_SETTINGS_FILE_EXT = ".settings"; //NON-NLS
68  private static final CharSequence PYTHON_CLASS_PROXY_PREFIX = "org.python.proxies.".subSequence(0, "org.python.proxies.".length() - 1); //NON-NLS
69  private static final Logger logger = Logger.getLogger(IngestJobSettings.class.getName());
70  private final IngestType ingestType;
71  private final List<IngestModuleTemplate> moduleTemplates = new ArrayList<>();
72  private final List<String> warnings = new ArrayList<>();
73  private String executionContext;
75  private String moduleSettingsFolderPath;
76 
80  static String getBaseSettingsPath() {
82  }
83 
92  static String getModuleSettingsResource(String executionContext) {
93  return Paths.get(MODULE_SETTINGS_FOLDER, executionContext).toString();
94  }
95 
108  static Path getSavedModuleSettingsFolder(String executionContext) {
109  return Paths.get(getBaseSettingsPath(), executionContext);
110  }
111 
123  public IngestJobSettings(final String executionContext) {
125  }
126 
141  public IngestJobSettings(String executionContext, IngestType ingestType) {
142  this.ingestType = ingestType;
143  if (this.ingestType.equals(IngestType.ALL_MODULES)) {
144  this.executionContext = executionContext;
145  } else {
146  this.executionContext = executionContext + "." + this.ingestType.name();
147  }
149  this.load();
150  }
151 
165  public IngestJobSettings(String executionContext, IngestType ingestType, Collection<IngestModuleTemplate> moduleTemplates) {
166  this.ingestType = ingestType;
167  if (this.ingestType.equals(IngestType.ALL_MODULES)) {
168  this.executionContext = executionContext;
169  } else {
170  this.executionContext = executionContext + "." + this.ingestType.name();
171  }
172  this.moduleTemplates.addAll(moduleTemplates);
173  }
174 
189  public IngestJobSettings(String executionContext, IngestType ingestType, Collection<IngestModuleTemplate> moduleTemplates, FilesSet fileFilter) {
191  this.setFileFilter(fileFilter);
192  }
193 
201  return getSavedModuleSettingsFolder(executionContext);
202  }
203 
207  public void save() {
209  this.store();
210  }
211 
221  public void saveAs(String executionContext) {
222  this.executionContext = executionContext;
224  this.store();
225  }
226 
233  public List<String> getWarnings() {
234  List<String> warningMessages = new ArrayList<>(this.warnings);
235  this.warnings.clear();
236  return warningMessages;
237  }
238 
248  public String getExecutionContext() {
249  return this.executionContext;
250  }
251 
258  if (fileFilter == null) {
259  fileFilter = FilesSetsManager.getDefaultFilter();
260  }
261  return fileFilter;
262  }
263 
269  public void setFileFilter(FilesSet fileIngestFilter) {
270  this.fileFilter = fileIngestFilter;
271  }
272 
278  public List<IngestModuleTemplate> getIngestModuleTemplates() {
279  return Collections.unmodifiableList(this.moduleTemplates);
280  }
281 
287  public void setIngestModuleTemplates(List<IngestModuleTemplate> moduleTemplates) {
288  this.moduleTemplates.clear();
289  this.moduleTemplates.addAll(moduleTemplates);
290  }
291 
297  public List<IngestModuleTemplate> getEnabledIngestModuleTemplates() {
298  List<IngestModuleTemplate> enabledModuleTemplates = new ArrayList<>();
299  for (IngestModuleTemplate moduleTemplate : this.moduleTemplates) {
300  if (moduleTemplate.isEnabled()) {
301  enabledModuleTemplates.add(moduleTemplate);
302  }
303  }
304  return enabledModuleTemplates;
305  }
306 
313  public boolean getProcessUnallocatedSpace() {
314  boolean processUnallocated = true;
315  if (!Objects.isNull(this.fileFilter)) {
316  processUnallocated = (this.fileFilter.ingoresUnallocatedSpace() == false);
317  }
318  return processUnallocated;
319  }
320 
326  try {
327  Path folder = getSavedModuleSettingsFolder();
328  Files.createDirectories(folder);
329  this.moduleSettingsFolderPath = folder.toAbsolutePath().toString();
330  } catch (IOException | SecurityException ex) {
331  logger.log(Level.SEVERE, "Failed to create ingest module settings directory " + this.moduleSettingsFolderPath, ex); //NON-NLS
332  this.warnings.add(NbBundle.getMessage(IngestJobSettings.class, "IngestJobSettings.createModuleSettingsFolder.warning")); //NON-NLS
333  }
334  }
335 
340  private void load() {
345  List<IngestModuleFactory> moduleFactories = new ArrayList<>();
346  List<IngestModuleFactory> allModuleFactories = IngestModuleFactoryLoader.getIngestModuleFactories();
347  HashSet<String> loadedModuleNames = new HashSet<>();
348 
349  // Add modules that are going to be used for this ingest depending on type.
350  for (IngestModuleFactory moduleFactory : allModuleFactories) {
351  if (moduleFactory.isDataArtifactIngestModuleFactory() || ingestType.equals(IngestType.ALL_MODULES)) {
352  moduleFactories.add(moduleFactory);
353  } else if (this.ingestType.equals(IngestType.DATA_SOURCE_ONLY) && moduleFactory.isDataSourceIngestModuleFactory()) {
354  moduleFactories.add(moduleFactory);
355  } else if (this.ingestType.equals(IngestType.FILES_ONLY) && moduleFactory.isFileIngestModuleFactory()) {
356  moduleFactories.add(moduleFactory);
357  }
358  }
359 
360  for (IngestModuleFactory moduleFactory : moduleFactories) {
361  loadedModuleNames.add(moduleFactory.getModuleDisplayName());
362  }
363 
371  final String plasoModuleName = "Plaso";
372  boolean plasoLoaded = loadedModuleNames.contains(plasoModuleName);
373  if (plasoLoaded) {
374  loadedModuleNames.remove(plasoModuleName);
375  }
376 
381  HashSet<String> enabledModuleNames = getModulesNames(this.executionContext, IngestJobSettings.ENABLED_MODULES_PROPERTY, makeCsvList(loadedModuleNames));
382  HashSet<String> disabledModuleNames = getModulesNames(this.executionContext, IngestJobSettings.DISABLED_MODULES_PROPERTY, plasoModuleName); //NON-NLS
383 
384  // If plaso was loaded, but appears in neither the enabled nor the
385  // disabled list, add it to the disabled list.
386  if (!enabledModuleNames.contains(plasoModuleName) && !disabledModuleNames.contains(plasoModuleName)) {
387  disabledModuleNames.add(plasoModuleName);
388  }
389 
390  //Put plaso back into loadedModuleNames
391  if (plasoLoaded) {
392  loadedModuleNames.add(plasoModuleName);
393  }
394 
398  List<String> missingModuleNames = new ArrayList<>();
399  for (String moduleName : enabledModuleNames) {
400  if (!loadedModuleNames.contains(moduleName)) {
401  missingModuleNames.add(moduleName);
402  }
403  }
404  for (String moduleName : disabledModuleNames) {
405  if (!loadedModuleNames.contains(moduleName)) {
406  logger.log(Level.WARNING, MessageFormat.format("A module marked as disabled in the ingest job settings, ''{0}'', could not be found.", moduleName));
407  }
408  }
409  for (String moduleName : missingModuleNames) {
410  enabledModuleNames.remove(moduleName);
411  disabledModuleNames.remove(moduleName);
412  String warning = NbBundle.getMessage(IngestJobSettings.class, "IngestJobSettings.missingModule.warning", moduleName); //NON-NLS
413  logger.log(Level.WARNING, warning);
414  this.warnings.add(warning);
415  }
416 
421  for (IngestModuleFactory moduleFactory : moduleFactories) {
422  IngestModuleTemplate moduleTemplate = new IngestModuleTemplate(moduleFactory, loadModuleSettings(moduleFactory));
423  String moduleName = moduleTemplate.getModuleName();
424  if (enabledModuleNames.contains(moduleName)) {
425  moduleTemplate.setEnabled(true);
426  } else if (disabledModuleNames.contains(moduleName)) {
427  moduleTemplate.setEnabled(false);
428  } else {
429  // The module factory was loaded, but the module name does not
430  // appear in the enabled/disabled module settings. Treat the
431  // module as a new module and enable it by default.
432  moduleTemplate.setEnabled(true);
433  enabledModuleNames.add(moduleName);
434  }
435  this.moduleTemplates.add(moduleTemplate);
436  }
437 
442  String ingestModuleResource = getModuleSettingsResource(this.executionContext);
443  ModuleSettings.setConfigSetting(ingestModuleResource, IngestJobSettings.ENABLED_MODULES_PROPERTY, makeCsvList(enabledModuleNames));
444  ModuleSettings.setConfigSetting(ingestModuleResource, IngestJobSettings.DISABLED_MODULES_PROPERTY, makeCsvList(disabledModuleNames));
445 
451  }
452  try {
453  Map<String, FilesSet> fileIngestFilters = FilesSetsManager.getInstance()
456  fileIngestFilters.put(fSet.getName(), fSet);
457  }
458  this.fileFilter = fileIngestFilters.get(ModuleSettings.getConfigSetting(ingestModuleResource, IngestJobSettings.LAST_FILE_INGEST_FILTER_PROPERTY));
460  this.fileFilter = FilesSetsManager.getDefaultFilter();
461  logger.log(Level.SEVERE, "Failed to get file filter from .properties file, default filter being used", ex); //NON-NLS
462  }
463  }
464 
476  private static HashSet<String> getModulesNames(String executionContext, String propertyName, String defaultSetting) {
477  String ingestModuleResource = getModuleSettingsResource(executionContext);
478  if (ModuleSettings.settingExists(ingestModuleResource, propertyName) == false) {
479  ModuleSettings.setConfigSetting(ingestModuleResource, propertyName, defaultSetting);
480  }
481  HashSet<String> moduleNames = new HashSet<>();
482  String modulesSetting = ModuleSettings.getConfigSetting(ingestModuleResource, propertyName);
483  if (!modulesSetting.isEmpty()) {
484  String[] settingNames = modulesSetting.split(", ");
485  for (String name : settingNames) {
486  /*
487  * Map some obsolete core ingest module names to the current
488  * core ingest module names.
489  */
490  switch (name) {
491  case "Thunderbird Parser": //NON-NLS
492  case "MBox Parser": //NON-NLS
493  moduleNames.add("Email Parser"); //NON-NLS
494  break;
495  case "File Extension Mismatch Detection": //NON-NLS
496  moduleNames.add("Extension Mismatch Detector"); //NON-NLS
497  break;
498  case "EWF Verify": //NON-NLS
499  case "E01 Verify": //NON-NLS
500  case "E01 Verifier": // NON-NLS
501  moduleNames.add("Data Source Integrity"); //NON-NLS
502  break;
503  case "Archive Extractor": //NON-NLS
504  moduleNames.add("Embedded File Extractor"); //NON-NLS
505  break;
506  case "Correlation Engine": //NON-NLS
507  moduleNames.add("Central Repository"); //NON-NLS
508  break;
509  case "Exif Parser": //NON-NLS
510  moduleNames.add("Picture Analyzer"); //NON-NLS
511  break;
512  case "Drone Analyzer":
513  moduleNames.add("DJI Drone Analyzer");
514  break;
515  default:
516  moduleNames.add(name);
517  }
518  }
519  }
520  return moduleNames;
521  }
522 
531  static List<String> getEnabledModules(String context) {
532  return new ArrayList<>(getModulesNames(context, ENABLED_MODULES_PROPERTY, ""));
533  }
534 
545  private boolean isPythonModuleSettingsFile(String moduleSettingsFilePath) {
546  return moduleSettingsFilePath.contains(PYTHON_CLASS_PROXY_PREFIX);
547  }
548 
557  IngestModuleIngestJobSettings settings = null;
558  String moduleSettingsFilePath = getModuleSettingsFilePath(factory);
559  File settingsFile = new File(moduleSettingsFilePath);
560  if (settingsFile.exists()) {
561  try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(settingsFile.getAbsolutePath()))) {
562  settings = (IngestModuleIngestJobSettings) in.readObject();
563  } catch (IOException | ClassNotFoundException ex) {
564  String warning = NbBundle.getMessage(IngestJobSettings.class, "IngestJobSettings.moduleSettingsLoad.warning", factory.getModuleDisplayName(), this.executionContext); //NON-NLS
565  logger.log(Level.WARNING, warning, ex);
566  this.warnings.add(warning);
567  }
568  }
569  if (settings == null) {
570  settings = factory.getDefaultIngestJobSettings();
571  }
572  return settings;
573  }
574 
584  String fileName = FactoryClassNameNormalizer.normalize(factory.getClass().getCanonicalName()) + IngestJobSettings.MODULE_SETTINGS_FILE_EXT;
585  Path path = Paths.get(this.moduleSettingsFolderPath, fileName);
586  return path.toAbsolutePath().toString();
587  }
588 
592  private void store() {
596  HashSet<String> enabledModuleNames = new HashSet<>();
597  HashSet<String> disabledModuleNames = new HashSet<>();
598  for (IngestModuleTemplate moduleTemplate : moduleTemplates) {
599  saveModuleSettings(moduleTemplate.getModuleFactory(), moduleTemplate.getModuleSettings());
600  String moduleName = moduleTemplate.getModuleName();
601  if (moduleTemplate.isEnabled()) {
602  enabledModuleNames.add(moduleName);
603  } else {
604  disabledModuleNames.add(moduleName);
605  }
606  }
607 
608  String ingestModuleResource = getModuleSettingsResource(this.executionContext);
609  ModuleSettings.setConfigSetting(ingestModuleResource, IngestJobSettings.ENABLED_MODULES_PROPERTY, makeCsvList(enabledModuleNames));
610  ModuleSettings.setConfigSetting(ingestModuleResource, IngestJobSettings.DISABLED_MODULES_PROPERTY, makeCsvList(disabledModuleNames));
611 
615  ModuleSettings.setConfigSetting(ingestModuleResource, LAST_FILE_INGEST_FILTER_PROPERTY, fileFilter.getName());
616  }
617 
625  String moduleSettingsFilePath = getModuleSettingsFilePath(factory);
626  try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(moduleSettingsFilePath))) {
627  out.writeObject(settings);
628  } catch (IOException ex) {
629  String warning = NbBundle.getMessage(IngestJobSettings.class, "IngestJobSettings.moduleSettingsSave.warning", factory.getModuleDisplayName(), this.executionContext); //NON-NLS
630  logger.log(Level.SEVERE, warning, ex);
631  this.warnings.add(warning);
632  }
633  }
634 
643  private static String makeCsvList(Collection<String> collection) {
644  if (collection == null || collection.isEmpty()) {
645  return "";
646  }
647 
648  ArrayList<String> list = new ArrayList<>();
649  list.addAll(collection);
650  StringBuilder csvList = new StringBuilder();
651  for (int i = 0; i < list.size() - 1; ++i) {
652  csvList.append(list.get(i)).append(", ");
653  }
654  csvList.append(list.get(list.size() - 1));
655  return csvList.toString();
656  }
657 
661  public enum IngestType {
662 
674  FILES_ONLY
675  }
676 
677 }
static synchronized String getConfigSetting(String moduleName, String settingName)
IngestJobSettings(final String executionContext)
void saveModuleSettings(IngestModuleFactory factory, IngestModuleIngestJobSettings settings)
List< IngestModuleTemplate > getEnabledIngestModuleTemplates()
static HashSet< String > getModulesNames(String executionContext, String propertyName, String defaultSetting)
static String makeCsvList(Collection< String > collection)
void setIngestModuleTemplates(List< IngestModuleTemplate > moduleTemplates)
static synchronized boolean settingExists(String moduleName, String settingName)
final List< IngestModuleTemplate > moduleTemplates
IngestJobSettings(String executionContext, IngestType ingestType, Collection< IngestModuleTemplate > moduleTemplates, FilesSet fileFilter)
static synchronized void setConfigSetting(String moduleName, String settingName, String settingVal)
IngestModuleIngestJobSettings loadModuleSettings(IngestModuleFactory factory)
String getModuleSettingsFilePath(IngestModuleFactory factory)
default IngestModuleIngestJobSettings getDefaultIngestJobSettings()
List< IngestModuleTemplate > getIngestModuleTemplates()
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
IngestJobSettings(String executionContext, IngestType ingestType, Collection< IngestModuleTemplate > moduleTemplates)
boolean isPythonModuleSettingsFile(String moduleSettingsFilePath)
IngestJobSettings(String executionContext, IngestType ingestType)

Copyright © 2012-2022 Basis Technology. Generated on: Tue Jun 27 2023
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.