Autopsy  4.19.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
CommandLineOptionProcessor.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2019-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.commandlineingest;
20 
21 import java.io.File;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.Collections;
25 import java.util.HashSet;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Set;
29 import java.util.logging.Level;
30 import java.util.stream.Collectors;
31 import java.util.stream.Stream;
33 import org.netbeans.api.sendopts.CommandException;
34 import org.netbeans.spi.sendopts.Env;
35 import org.netbeans.spi.sendopts.Option;
36 import org.netbeans.spi.sendopts.OptionProcessor;
37 import org.openide.util.lookup.ServiceProvider;
39 
43 @ServiceProvider(service = OptionProcessor.class)
44 public class CommandLineOptionProcessor extends OptionProcessor {
45 
46  private static final Logger logger = Logger.getLogger(CommandLineOptionProcessor.class.getName());
47  private final Option caseNameOption = Option.requiredArgument('n', "caseName");
48  private final Option caseTypeOption = Option.requiredArgument('t', "caseType");
49  private final Option caseBaseDirOption = Option.requiredArgument('o', "caseBaseDir");
50  private final Option createCaseCommandOption = Option.withoutArgument('c', "createCase");
51  private final Option dataSourcePathOption = Option.requiredArgument('s', "dataSourcePath");
52  private final Option dataSourceObjectIdOption = Option.requiredArgument('i', "dataSourceObjectId");
53  private final Option addDataSourceCommandOption = Option.withoutArgument('a', "addDataSource");
54  private final Option caseDirOption = Option.requiredArgument('d', "caseDir");
55  private final Option runIngestCommandOption = Option.optionalArgument('r', "runIngest");
56  private final Option listAllDataSourcesCommandOption = Option.withoutArgument('l', "listAllDataSources");
57  private final Option generateReportsOption = Option.optionalArgument('g', "generateReports");
58  private final Option defaultArgument = Option.defaultArguments();
59 
60  private boolean runFromCommandLine = false;
61 
62  private final List<CommandLineCommand> commands = new ArrayList<>();
63 
64  final static String CASETYPE_MULTI = "multi";
65  final static String CASETYPE_SINGLE = "single";
66 
67  private String defaultArgumentValue = null;
68 
69  @Override
70  protected Set<Option> getOptions() {
71  Set<Option> set = new HashSet<>();
72  set.add(createCaseCommandOption);
73  set.add(caseNameOption);
74  set.add(caseTypeOption);
75  set.add(caseBaseDirOption);
76  set.add(dataSourcePathOption);
77  set.add(addDataSourceCommandOption);
78  set.add(dataSourceObjectIdOption);
79  set.add(caseDirOption);
80  set.add(runIngestCommandOption);
81  set.add(listAllDataSourcesCommandOption);
82  set.add(generateReportsOption);
83  set.add(defaultArgument);
84  return set;
85  }
86 
87  @Override
88  protected void process(Env env, Map<Option, String[]> values) throws CommandException {
89  logger.log(Level.INFO, "Processing Autopsy command line options"); //NON-NLS
90  System.out.println("Processing Autopsy command line options");
91 
92  if (values.containsKey(defaultArgument)) {
93  defaultArgumentValue = values.get(defaultArgument)[0];
94  runFromCommandLine = true;
95  return;
96  }
97 
98  // input arguments must contain at least one command
99  if (!(values.containsKey(createCaseCommandOption) || values.containsKey(addDataSourceCommandOption)
100  || values.containsKey(runIngestCommandOption) || values.containsKey(listAllDataSourcesCommandOption)
101  || values.containsKey(generateReportsOption))) {
102  // not running from command line
103  handleError("Invalid command line, an input option must be supplied.");
104  }
105 
106  // parse input parameters
107  String[] argDirs;
108  String inputCaseName = "";
109  if (values.containsKey(caseNameOption)) {
110  argDirs = values.get(caseNameOption);
111  if (argDirs.length < 1) {
112  handleError("Missing argument 'caseName'");
113  }
114  inputCaseName = argDirs[0];
115 
116  if (inputCaseName == null || inputCaseName.isEmpty()) {
117  handleError("'caseName' argument is empty");
118  }
119  }
120 
121  String caseType = "";
122  if (values.containsKey(caseTypeOption)) {
123  argDirs = values.get(caseTypeOption);
124 
125  if (argDirs.length < 1) {
126  handleError("Missing argument 'caseType'");
127  }
128  caseType = argDirs[0];
129 
130  if (caseType == null || caseType.isEmpty()) {
131  handleError("'caseType' argument is empty");
132  } else if (!caseType.equalsIgnoreCase(CASETYPE_MULTI) && !caseType.equalsIgnoreCase(CASETYPE_SINGLE)) {
133  handleError("'caseType' argument is invalid");
134  } else if (caseType.equalsIgnoreCase(CASETYPE_MULTI) && !FeatureAccessUtils.canCreateMultiUserCases()) {
135  handleError("Unable to create multi user case. Confirm that multi user settings are configured correctly.");
136  }
137  }
138 
139  String caseBaseDir = "";
140  if (values.containsKey(caseBaseDirOption)) {
141  argDirs = values.get(caseBaseDirOption);
142  if (argDirs.length < 1) {
143  handleError("Missing argument 'caseBaseDir'");
144  }
145  caseBaseDir = argDirs[0];
146 
147  if (caseBaseDir == null || caseBaseDir.isEmpty()) {
148  handleError("Missing argument 'caseBaseDir' option");
149  }
150 
151  if (!(new File(caseBaseDir).exists()) || !(new File(caseBaseDir).isDirectory())) {
152  handleError("'caseBaseDir' directory doesn't exist or is not a directory: " + caseBaseDir);
153  }
154  }
155 
156  String dataSourcePath = "";
157  if (values.containsKey(dataSourcePathOption)) {
158 
159  argDirs = values.get(dataSourcePathOption);
160  if (argDirs.length < 1) {
161  handleError("Missing argument 'dataSourcePath'");
162  }
163  dataSourcePath = argDirs[0];
164 
165  // verify inputs
166  if (dataSourcePath == null || dataSourcePath.isEmpty()) {
167  handleError("Missing argument 'dataSourcePath'");
168  }
169 
170  if (!(new File(dataSourcePath).exists())) {
171  handleError("Input data source file " + dataSourcePath + " doesn't exist");
172  }
173  }
174 
175  String dataSourceId = "";
176  if (values.containsKey(dataSourceObjectIdOption)) {
177 
178  argDirs = values.get(dataSourceObjectIdOption);
179  if (argDirs.length < 1) {
180  handleError("Missing argument 'dataSourceObjectIdOption'");
181  }
182  dataSourceId = argDirs[0];
183 
184  // verify inputs
185  if (dataSourceId == null || dataSourceId.isEmpty()) {
186  handleError("Input data source id is empty");
187  }
188  }
189 
190  String caseDir = "";
191  if (values.containsKey(caseDirOption)) {
192 
193  argDirs = values.get(caseDirOption);
194  if (argDirs.length < 1) {
195  handleError("Argument missing from 'caseDir' option");
196  }
197  caseDir = argDirs[0];
198 
199  // verify inputs
200  if (caseDir == null || caseDir.isEmpty()) {
201  handleError("Argument missing from 'caseDir'");
202  }
203 
204  if (!(new File(caseDir).exists()) || !(new File(caseDir).isDirectory())) {
205  handleError("Case directory " + caseDir + " does not exist or is not a directory");
206  }
207  }
208 
209  // Create commands in order in which they should be executed:
210  // First create the "CREATE_CASE" command, if present
211  if (values.containsKey(createCaseCommandOption)) {
212 
213  // 'caseName' must always be specified for "CREATE_CASE" command
214  if (inputCaseName == null || inputCaseName.isEmpty()) {
215  handleError("'caseName' argument is empty");
216  }
217 
218  // 'caseBaseDir' must always be specified for "CREATE_CASE" command
219  if (caseBaseDir == null || caseBaseDir.isEmpty()) {
220  handleError("'caseBaseDir' argument is empty");
221  }
222 
223  CommandLineCommand newCommand = new CommandLineCommand(CommandLineCommand.CommandType.CREATE_CASE);
224  newCommand.addInputValue(CommandLineCommand.InputType.CASE_NAME.name(), inputCaseName);
225  newCommand.addInputValue(CommandLineCommand.InputType.CASES_BASE_DIR_PATH.name(), caseBaseDir);
226  newCommand.addInputValue(CommandLineCommand.InputType.CASE_TYPE.name(), caseType);
227  commands.add(newCommand);
228  runFromCommandLine = true;
229  }
230 
231  // Add ADD_DATA_SOURCE command, if present
232  if (values.containsKey(addDataSourceCommandOption)) {
233 
234  // 'caseDir' must only be specified if the case is not being created during the current run
235  if (!values.containsKey(createCaseCommandOption) && caseDir.isEmpty()) {
236  // new case is not being created during this run, so 'caseDir' should have been specified
237  handleError("'caseDir' argument is empty");
238  }
239 
240  // 'dataSourcePath' must always be specified for "ADD_DATA_SOURCE" command
241  if (dataSourcePath == null || dataSourcePath.isEmpty()) {
242  handleError("'dataSourcePath' argument is empty");
243  }
244 
245  CommandLineCommand newCommand = new CommandLineCommand(CommandLineCommand.CommandType.ADD_DATA_SOURCE);
246  newCommand.addInputValue(CommandLineCommand.InputType.CASE_FOLDER_PATH.name(), caseDir);
247  newCommand.addInputValue(CommandLineCommand.InputType.DATA_SOURCE_PATH.name(), dataSourcePath);
248  commands.add(newCommand);
249  runFromCommandLine = true;
250  }
251 
252  String ingestProfile = "";
253  // Add RUN_INGEST command, if present
254  if (values.containsKey(runIngestCommandOption)) {
255 
256  argDirs = values.get(runIngestCommandOption);
257  if(argDirs != null && argDirs.length > 0) {
258  ingestProfile = argDirs[0];
259  }
260 
261  // 'caseDir' must only be specified if the case is not being created during the current run
262  if (!values.containsKey(createCaseCommandOption) && caseDir.isEmpty()) {
263  // new case is not being created during this run, so 'caseDir' should have been specified
264  handleError("'caseDir' argument is empty");
265  }
266 
267  // if new data source is being added during this run, then 'dataSourceId' is not specified
268  if (!values.containsKey(addDataSourceCommandOption) && dataSourceId.isEmpty()) {
269  // data source is not being added during this run, so 'dataSourceId' should have been specified
270  handleError("'dataSourceId' argument is empty");
271  }
272 
273  CommandLineCommand newCommand = new CommandLineCommand(CommandLineCommand.CommandType.RUN_INGEST);
274  newCommand.addInputValue(CommandLineCommand.InputType.CASE_FOLDER_PATH.name(), caseDir);
275  newCommand.addInputValue(CommandLineCommand.InputType.DATA_SOURCE_ID.name(), dataSourceId);
276  newCommand.addInputValue(CommandLineCommand.InputType.INGEST_PROFILE_NAME.name(), ingestProfile);
277  commands.add(newCommand);
278  runFromCommandLine = true;
279  }
280 
281  // Add "LIST_ALL_DATA_SOURCES" command, if present
282  if (values.containsKey(listAllDataSourcesCommandOption)) {
283 
284  // 'caseDir' must only be specified if the case is not being created during the current run
285  if (!values.containsKey(createCaseCommandOption) && (caseDir == null || caseDir.isEmpty())) {
286  // new case is not being created during this run, so 'caseDir' should have been specified
287  handleError("'caseDir' argument is empty");
288  }
289 
290  CommandLineCommand newCommand = new CommandLineCommand(CommandLineCommand.CommandType.LIST_ALL_DATA_SOURCES);
291  newCommand.addInputValue(CommandLineCommand.InputType.CASE_FOLDER_PATH.name(), caseDir);
292  commands.add(newCommand);
293  runFromCommandLine = true;
294  }
295 
296  // Add "GENERATE_REPORTS" command, if present
297  if (values.containsKey(generateReportsOption)) {
298 
299  // 'caseDir' must only be specified if the case is not being created during the current run
300  if (!values.containsKey(createCaseCommandOption) && caseDir.isEmpty()) {
301  // new case is not being created during this run, so 'caseDir' should have been specified
302  handleError("'caseDir' argument is empty");
303  }
304 
305  List<String> reportProfiles;
306  argDirs = values.get(generateReportsOption);
307  if (argDirs.length > 0) {
308  // use custom report configuration(s)
309  reportProfiles = Stream.of(argDirs[0].split(","))
310  .map(String::trim)
311  .collect(Collectors.toList());
312 
313  if (reportProfiles == null || reportProfiles.isEmpty()) {
314  handleError("'generateReports' argument is empty");
315  }
316 
317  for (String reportProfile : reportProfiles) {
318  if (reportProfile.isEmpty()) {
319  handleError("Empty report profile name");
320  }
321  CommandLineCommand newCommand = new CommandLineCommand(CommandLineCommand.CommandType.GENERATE_REPORTS);
322  newCommand.addInputValue(CommandLineCommand.InputType.CASE_FOLDER_PATH.name(), caseDir);
323  newCommand.addInputValue(CommandLineCommand.InputType.REPORT_PROFILE_NAME.name(), reportProfile);
324  commands.add(newCommand);
325  }
326  } else {
327  // use default report configuration
328  CommandLineCommand newCommand = new CommandLineCommand(CommandLineCommand.CommandType.GENERATE_REPORTS);
329  newCommand.addInputValue(CommandLineCommand.InputType.CASE_FOLDER_PATH.name(), caseDir);
330  commands.add(newCommand);
331  }
332 
333  runFromCommandLine = true;
334  }
335  }
336 
342  public boolean isRunFromCommandLine() {
343  return runFromCommandLine;
344  }
345 
351  public String getDefaultArgument() {
352  return defaultArgumentValue;
353  }
354 
360  List<CommandLineCommand> getCommands() {
361  return Collections.unmodifiableList(commands);
362  }
363 
371  private void handleError(String errorMessage) throws CommandException {
372  logger.log(Level.SEVERE, errorMessage);
373  throw new CommandException(1, errorMessage);
374  }
375 }
synchronized static Logger getLogger(String name)
Definition: Logger.java:124

Copyright © 2012-2021 Basis Technology. Generated on: Thu Sep 30 2021
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.