Autopsy 4.23.0
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 */
19package org.sleuthkit.autopsy.ingest;
20
21import com.basistech.df.cybertriage.autopsy.malwarescan.MalwareScanIngestModuleFactory;
22import java.io.File;
23import java.io.FileInputStream;
24import java.io.FileOutputStream;
25import java.io.IOException;
26import java.nio.file.Files;
27import java.nio.file.Path;
28import java.nio.file.Paths;
29import java.text.MessageFormat;
30import java.util.ArrayList;
31import java.util.Collection;
32import java.util.Collections;
33import java.util.HashSet;
34import java.util.List;
35import java.util.Map;
36import java.util.Objects;
37import java.util.Set;
38import java.util.logging.Level;
39import java.util.stream.Collectors;
40import java.util.stream.Stream;
41import org.openide.util.NbBundle;
42import org.openide.util.io.NbObjectInputStream;
43import org.openide.util.io.NbObjectOutputStream;
44import org.sleuthkit.autopsy.coreutils.Logger;
45import org.sleuthkit.autopsy.coreutils.ModuleSettings;
46import org.sleuthkit.autopsy.coreutils.PlatformUtil;
47import org.sleuthkit.autopsy.modules.interestingitems.FilesSet;
48import org.sleuthkit.autopsy.modules.interestingitems.FilesSetsManager;
49import org.sleuthkit.autopsy.python.FactoryClassNameNormalizer;
50
54public final class IngestJobSettings {
55
56 private static final String ENABLED_MODULES_PROPERTY = "Enabled_Ingest_Modules"; //NON-NLS
57 private static final String DISABLED_MODULES_PROPERTY = "Disabled_Ingest_Modules"; //NON-NLS
58 private static final String LAST_FILE_INGEST_FILTER_PROPERTY = "Last_File_Ingest_Filter"; //NON-NLS
59 private static final String MODULE_SETTINGS_FOLDER_NAME = "IngestSettings"; //NON-NLS
60
61 private static final Set<String> DEFAULT_DISABLED_MODULES = Stream.of(
62 "Plaso",
63 "Keyword Search",
65 ).collect(Collectors.toSet());
66
67 private static final String MODULE_SETTINGS_FOLDER = Paths.get(
68 Paths.get(PlatformUtil.getUserConfigDirectory()).relativize(Paths.get(PlatformUtil.getModuleConfigDirectory())).toString(),
70 ).toString();
71
72 private static final String MODULE_SETTINGS_FOLDER_PATH = Paths.get(
74 IngestJobSettings.MODULE_SETTINGS_FOLDER_NAME
75 ).toAbsolutePath().toString();
76
77 private static final String MODULE_SETTINGS_FILE_EXT = ".settings"; //NON-NLS
78 private static final CharSequence PYTHON_CLASS_PROXY_PREFIX = "org.python.proxies.".subSequence(0, "org.python.proxies.".length() - 1); //NON-NLS
79 private static final Logger logger = Logger.getLogger(IngestJobSettings.class.getName());
80 private final IngestType ingestType;
81 private final List<IngestModuleTemplate> moduleTemplates = new ArrayList<>();
82 private final List<String> warnings = new ArrayList<>();
83 private String executionContext;
86
90 static String getBaseSettingsPath() {
92 }
93
102 static String getModuleSettingsResource(String executionContext) {
103 return Paths.get(MODULE_SETTINGS_FOLDER, executionContext).toString();
104 }
105
119 return Paths.get(getBaseSettingsPath(), executionContext);
120 }
121
136
152 this.ingestType = ingestType;
153 if (this.ingestType.equals(IngestType.ALL_MODULES)) {
154 this.executionContext = executionContext;
155 } else {
156 this.executionContext = executionContext + "." + this.ingestType.name();
157 }
159 this.load();
160 }
161
175 public IngestJobSettings(String executionContext, IngestType ingestType, Collection<IngestModuleTemplate> moduleTemplates) {
176 this.ingestType = ingestType;
177 if (this.ingestType.equals(IngestType.ALL_MODULES)) {
178 this.executionContext = executionContext;
179 } else {
180 this.executionContext = executionContext + "." + this.ingestType.name();
181 }
182 this.moduleTemplates.addAll(moduleTemplates);
183 }
184
199 public IngestJobSettings(String executionContext, IngestType ingestType, Collection<IngestModuleTemplate> moduleTemplates, FilesSet fileFilter) {
201 this.setFileFilter(fileFilter);
202 }
203
213
217 public void save() {
219 this.store();
220 }
221
231 public void saveAs(String executionContext) {
232 this.executionContext = executionContext;
234 this.store();
235 }
236
243 public List<String> getWarnings() {
244 List<String> warningMessages = new ArrayList<>(this.warnings);
245 this.warnings.clear();
246 return warningMessages;
247 }
248
258 public String getExecutionContext() {
259 return this.executionContext;
260 }
261
268 if (fileFilter == null) {
270 }
271 return fileFilter;
272 }
273
279 public void setFileFilter(FilesSet fileIngestFilter) {
280 this.fileFilter = fileIngestFilter;
281 }
282
288 public List<IngestModuleTemplate> getIngestModuleTemplates() {
289 return Collections.unmodifiableList(this.moduleTemplates);
290 }
291
297 public void setIngestModuleTemplates(List<IngestModuleTemplate> moduleTemplates) {
298 this.moduleTemplates.clear();
299 this.moduleTemplates.addAll(moduleTemplates);
300 }
301
307 public List<IngestModuleTemplate> getEnabledIngestModuleTemplates() {
308 List<IngestModuleTemplate> enabledModuleTemplates = new ArrayList<>();
309 for (IngestModuleTemplate moduleTemplate : this.moduleTemplates) {
310 if (moduleTemplate.isEnabled()) {
311 enabledModuleTemplates.add(moduleTemplate);
312 }
313 }
314 return enabledModuleTemplates;
315 }
316
323 public boolean getProcessUnallocatedSpace() {
324 boolean processUnallocated = true;
325 if (!Objects.isNull(this.fileFilter)) {
326 processUnallocated = (this.fileFilter.ingoresUnallocatedSpace() == false);
327 }
328 return processUnallocated;
329 }
330
336 try {
337 Path folder = getSavedModuleSettingsFolder();
338 Files.createDirectories(folder);
339 this.moduleSettingsFolderPath = folder.toAbsolutePath().toString();
340 } catch (IOException | SecurityException ex) {
341 logger.log(Level.SEVERE, "Failed to create ingest module settings directory " + this.moduleSettingsFolderPath, ex); //NON-NLS
342 this.warnings.add(NbBundle.getMessage(IngestJobSettings.class, "IngestJobSettings.createModuleSettingsFolder.warning")); //NON-NLS
343 }
344 }
345
350 private void load() {
355 List<IngestModuleFactory> moduleFactories = new ArrayList<>();
356 List<IngestModuleFactory> allModuleFactories = IngestModuleFactoryLoader.getIngestModuleFactories();
357 HashSet<String> loadedModuleNames = new HashSet<>();
358
359 // Add modules that are going to be used for this ingest depending on type.
360 for (IngestModuleFactory moduleFactory : allModuleFactories) {
361 if (moduleFactory.isDataArtifactIngestModuleFactory() || ingestType.equals(IngestType.ALL_MODULES)) {
362 moduleFactories.add(moduleFactory);
363 } else if (this.ingestType.equals(IngestType.DATA_SOURCE_ONLY) && moduleFactory.isDataSourceIngestModuleFactory()) {
364 moduleFactories.add(moduleFactory);
365 } else if (this.ingestType.equals(IngestType.FILES_ONLY) && moduleFactory.isFileIngestModuleFactory()) {
366 moduleFactories.add(moduleFactory);
367 }
368 }
369
370 for (IngestModuleFactory moduleFactory : moduleFactories) {
371 loadedModuleNames.add(moduleFactory.getModuleDisplayName());
372 }
373
374
375 Set<String> defaultEnabledAndLoaded = new HashSet<>();
376 Set<String> defaultDisabledAndLoaded = new HashSet<>();
377 for (String loadedModule: loadedModuleNames) {
378 if (DEFAULT_DISABLED_MODULES.contains(loadedModule)) {
379 defaultDisabledAndLoaded.add(loadedModule);
380 } else {
381 defaultEnabledAndLoaded.add(loadedModule);
382 }
383 }
384
389 HashSet<String> enabledModuleNames = getModulesNames(this.executionContext, IngestJobSettings.ENABLED_MODULES_PROPERTY, makeCsvList(defaultEnabledAndLoaded));
390 HashSet<String> disabledModuleNames = getModulesNames(this.executionContext, IngestJobSettings.DISABLED_MODULES_PROPERTY, makeCsvList(defaultDisabledAndLoaded)); //NON-NLS
391
392 // double check to ensure all loaded modules are present in one of the lists in case more modules (in case settings didn't have a module)
393 for (String loadedModule : loadedModuleNames) {
394 // if neither enabled modules or disabled modules contains the loaded module, add it to the default location
395 if (!enabledModuleNames.contains(loadedModule) && !disabledModuleNames.contains(loadedModule)) {
396 if (DEFAULT_DISABLED_MODULES.contains(loadedModule)) {
397 disabledModuleNames.add(loadedModule);
398 } else {
399 enabledModuleNames.add(loadedModule);
400 }
401 }
402 }
403
407 List<String> missingModuleNames = new ArrayList<>();
408 for (String moduleName : enabledModuleNames) {
409 if (!loadedModuleNames.contains(moduleName)) {
410 missingModuleNames.add(moduleName);
411 }
412 }
413 for (String moduleName : disabledModuleNames) {
414 if (!loadedModuleNames.contains(moduleName)) {
415 logger.log(Level.WARNING, MessageFormat.format("A module marked as disabled in the ingest job settings, ''{0}'', could not be found.", moduleName));
416 }
417 }
418 for (String moduleName : missingModuleNames) {
419 enabledModuleNames.remove(moduleName);
420 disabledModuleNames.remove(moduleName);
421 String warning = NbBundle.getMessage(IngestJobSettings.class, "IngestJobSettings.missingModule.warning", moduleName); //NON-NLS
422 logger.log(Level.WARNING, warning);
423 this.warnings.add(warning);
424 }
425
430 for (IngestModuleFactory moduleFactory : moduleFactories) {
431 IngestModuleTemplate moduleTemplate = new IngestModuleTemplate(moduleFactory, loadModuleSettings(moduleFactory));
432 String moduleName = moduleTemplate.getModuleName();
433 if (enabledModuleNames.contains(moduleName)) {
434 moduleTemplate.setEnabled(true);
435 } else if (disabledModuleNames.contains(moduleName)) {
436 moduleTemplate.setEnabled(false);
437 } else {
438 // The module factory was loaded, but the module name does not
439 // appear in the enabled/disabled module settings. Treat the
440 // module as a new module and enable it by default.
441 moduleTemplate.setEnabled(true);
442 enabledModuleNames.add(moduleName);
443 }
444 this.moduleTemplates.add(moduleTemplate);
445 }
446
451 String ingestModuleResource = getModuleSettingsResource(this.executionContext);
452 ModuleSettings.setConfigSetting(ingestModuleResource, IngestJobSettings.ENABLED_MODULES_PROPERTY, makeCsvList(enabledModuleNames));
453 ModuleSettings.setConfigSetting(ingestModuleResource, IngestJobSettings.DISABLED_MODULES_PROPERTY, makeCsvList(disabledModuleNames));
454
458 if (ModuleSettings.settingExists(ingestModuleResource, IngestJobSettings.LAST_FILE_INGEST_FILTER_PROPERTY) == false) {
459 ModuleSettings.setConfigSetting(ingestModuleResource, IngestJobSettings.LAST_FILE_INGEST_FILTER_PROPERTY, FilesSetsManager.getDefaultFilter().getName());
460 }
461 try {
462 Map<String, FilesSet> fileIngestFilters = FilesSetsManager.getInstance()
465 fileIngestFilters.put(fSet.getName(), fSet);
466 }
467 this.fileFilter = fileIngestFilters.get(ModuleSettings.getConfigSetting(ingestModuleResource, IngestJobSettings.LAST_FILE_INGEST_FILTER_PROPERTY));
469 this.fileFilter = FilesSetsManager.getDefaultFilter();
470 logger.log(Level.SEVERE, "Failed to get file filter from .properties file, default filter being used", ex); //NON-NLS
471 }
472 }
473
485 private static HashSet<String> getModulesNames(String executionContext, String propertyName, String defaultSetting) {
486 String ingestModuleResource = getModuleSettingsResource(executionContext);
487 if (ModuleSettings.settingExists(ingestModuleResource, propertyName) == false) {
488 ModuleSettings.setConfigSetting(ingestModuleResource, propertyName, defaultSetting);
489 }
490 HashSet<String> moduleNames = new HashSet<>();
491 String modulesSetting = ModuleSettings.getConfigSetting(ingestModuleResource, propertyName);
492 if (!modulesSetting.isEmpty()) {
493 String[] settingNames = modulesSetting.split(", ");
494 for (String name : settingNames) {
495 /*
496 * Map some obsolete core ingest module names to the current
497 * core ingest module names.
498 */
499 switch (name) {
500 case "Thunderbird Parser": //NON-NLS
501 case "MBox Parser": //NON-NLS
502 moduleNames.add("Email Parser"); //NON-NLS
503 break;
504 case "File Extension Mismatch Detection": //NON-NLS
505 moduleNames.add("Extension Mismatch Detector"); //NON-NLS
506 break;
507 case "EWF Verify": //NON-NLS
508 case "E01 Verify": //NON-NLS
509 case "E01 Verifier": // NON-NLS
510 moduleNames.add("Data Source Integrity"); //NON-NLS
511 break;
512 case "Archive Extractor": //NON-NLS
513 moduleNames.add("Embedded File Extractor"); //NON-NLS
514 break;
515 case "Correlation Engine": //NON-NLS
516 moduleNames.add("Central Repository"); //NON-NLS
517 break;
518 case "Exif Parser": //NON-NLS
519 moduleNames.add("Picture Analyzer"); //NON-NLS
520 break;
521 case "Drone Analyzer":
522 moduleNames.add("DJI Drone Analyzer");
523 break;
524 default:
525 moduleNames.add(name);
526 }
527 }
528 }
529 return moduleNames;
530 }
531
540 static List<String> getEnabledModules(String context) {
541 return new ArrayList<>(getModulesNames(context, ENABLED_MODULES_PROPERTY, ""));
542 }
543
554 private boolean isPythonModuleSettingsFile(String moduleSettingsFilePath) {
555 return moduleSettingsFilePath.contains(PYTHON_CLASS_PROXY_PREFIX);
556 }
557
566 IngestModuleIngestJobSettings settings = null;
567 String moduleSettingsFilePath = getModuleSettingsFilePath(factory);
568 File settingsFile = new File(moduleSettingsFilePath);
569 if (settingsFile.exists()) {
570 try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(settingsFile.getAbsolutePath()))) {
571 settings = (IngestModuleIngestJobSettings) in.readObject();
572 } catch (IOException | ClassNotFoundException ex) {
573 String warning = NbBundle.getMessage(IngestJobSettings.class, "IngestJobSettings.moduleSettingsLoad.warning", factory.getModuleDisplayName(), this.executionContext); //NON-NLS
574 logger.log(Level.WARNING, warning, ex);
575 this.warnings.add(warning);
576 }
577 }
578 if (settings == null) {
579 settings = factory.getDefaultIngestJobSettings();
580 }
581 return settings;
582 }
583
593 String fileName = FactoryClassNameNormalizer.normalize(factory.getClass().getCanonicalName()) + IngestJobSettings.MODULE_SETTINGS_FILE_EXT;
594 Path path = Paths.get(this.moduleSettingsFolderPath, fileName);
595 return path.toAbsolutePath().toString();
596 }
597
601 private void store() {
605 HashSet<String> enabledModuleNames = new HashSet<>();
606 HashSet<String> disabledModuleNames = new HashSet<>();
607 for (IngestModuleTemplate moduleTemplate : moduleTemplates) {
608 saveModuleSettings(moduleTemplate.getModuleFactory(), moduleTemplate.getModuleSettings());
609 String moduleName = moduleTemplate.getModuleName();
610 if (moduleTemplate.isEnabled()) {
611 enabledModuleNames.add(moduleName);
612 } else {
613 disabledModuleNames.add(moduleName);
614 }
615 }
616
617 String ingestModuleResource = getModuleSettingsResource(this.executionContext);
618 ModuleSettings.setConfigSetting(ingestModuleResource, IngestJobSettings.ENABLED_MODULES_PROPERTY, makeCsvList(enabledModuleNames));
619 ModuleSettings.setConfigSetting(ingestModuleResource, IngestJobSettings.DISABLED_MODULES_PROPERTY, makeCsvList(disabledModuleNames));
620
625 }
626
634 String moduleSettingsFilePath = getModuleSettingsFilePath(factory);
635 try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(moduleSettingsFilePath))) {
636 out.writeObject(settings);
637 } catch (IOException ex) {
638 String warning = NbBundle.getMessage(IngestJobSettings.class, "IngestJobSettings.moduleSettingsSave.warning", factory.getModuleDisplayName(), this.executionContext); //NON-NLS
639 logger.log(Level.SEVERE, warning, ex);
640 this.warnings.add(warning);
641 }
642 }
643
652 private static String makeCsvList(Collection<String> collection) {
653 if (collection == null || collection.isEmpty()) {
654 return "";
655 }
656
657 ArrayList<String> list = new ArrayList<>();
658 list.addAll(collection);
659 StringBuilder csvList = new StringBuilder();
660 for (int i = 0; i < list.size() - 1; ++i) {
661 csvList.append(list.get(i)).append(", ");
662 }
663 csvList.append(list.get(list.size() - 1));
664 return csvList.toString();
665 }
666
685
686}
synchronized static Logger getLogger(String name)
Definition Logger.java:124
static synchronized void setConfigSetting(String moduleName, String settingName, String settingVal)
static synchronized String getConfigSetting(String moduleName, String settingName)
static synchronized boolean settingExists(String moduleName, String settingName)
IngestModuleIngestJobSettings loadModuleSettings(IngestModuleFactory factory)
String getModuleSettingsFilePath(IngestModuleFactory factory)
void saveModuleSettings(IngestModuleFactory factory, IngestModuleIngestJobSettings settings)
IngestJobSettings(String executionContext, IngestType ingestType)
IngestJobSettings(String executionContext, IngestType ingestType, Collection< IngestModuleTemplate > moduleTemplates, FilesSet fileFilter)
boolean isPythonModuleSettingsFile(String moduleSettingsFilePath)
final List< IngestModuleTemplate > moduleTemplates
List< IngestModuleTemplate > getEnabledIngestModuleTemplates()
List< IngestModuleTemplate > getIngestModuleTemplates()
static String makeCsvList(Collection< String > collection)
IngestJobSettings(String executionContext, IngestType ingestType, Collection< IngestModuleTemplate > moduleTemplates)
void setIngestModuleTemplates(List< IngestModuleTemplate > moduleTemplates)
static HashSet< String > getModulesNames(String executionContext, String propertyName, String defaultSetting)
default IngestModuleIngestJobSettings getDefaultIngestJobSettings()

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.