initial work

This commit is contained in:
Greg DiCristofaro 2020-09-15 22:15:31 -04:00
parent e6d53a03c6
commit c2333b7b59
2 changed files with 308 additions and 0 deletions

View File

@ -0,0 +1,146 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.datasourcesummary.datamodel;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException;
import org.sleuthkit.datamodel.DataSource;
import org.sleuthkit.datamodel.IngestJobInfo;
import org.sleuthkit.datamodel.IngestModuleInfo;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Utilities for checking if an ingest module has been run on a datasource.
*/
@Messages({
"IngestModuleCheckUtil_recentActivityModuleName=Recent Activity",
})
public class IngestModuleCheckUtil {
public static final String RECENT_ACTIVITY_FACTORY = "org.sleuthkit.autopsy.recentactivity.RecentActivityExtracterModuleFactory";
public static final String RECENT_ACTIVITY_MODULE_NAME = Bundle.IngestModuleCheckUtil_recentActivityModuleName();
// IngestModuleInfo separator for unique_name
private static final String UNIQUE_NAME_SEPARATOR = "-";
private final SleuthkitCaseProvider caseProvider;
/**
* Main constructor.
*/
public IngestModuleCheckUtil() {
this(SleuthkitCaseProvider.DEFAULT);
}
/**
* Main constructor with external dependencies specified. This constructor
* is designed with unit testing in mind since mocked dependencies can be
* utilized.
*
* @param provider The object providing the current SleuthkitCase.
* @param logger The logger to use.
*/
public IngestModuleCheckUtil(SleuthkitCaseProvider provider) {
this.caseProvider = provider;
}
/**
* Gets the fully qualified factory from the IngestModuleInfo.
* @param info The IngestJobInfo.
* @return The fully qualified factory.
*/
private static String getFullyQualifiedFactory(IngestModuleInfo info) {
if (info == null) {
return null;
}
String qualifiedName = info.getUniqueName();
if (StringUtils.isBlank(qualifiedName)) {
return null;
}
return qualifiedName.split(UNIQUE_NAME_SEPARATOR)[0];
}
/**
* Whether or not the ingest job info contains the ingest modulename.
* @param info The IngestJobInfo.
* @param fullyQualifiedFactory The fully qualified classname of the relevant factory.
* @return True if the ingest module name is contained in the data.
*/
private static boolean hasIngestModule(IngestJobInfo info, String fullyQualifiedFactory) {
if (info == null || info.getIngestModuleInfo() == null || StringUtils.isBlank(fullyQualifiedFactory)) {
return false;
}
return info.getIngestModuleInfo().stream()
.anyMatch((moduleInfo) -> {
String thisQualifiedFactory = getFullyQualifiedFactory(moduleInfo);
return fullyQualifiedFactory.equalsIgnoreCase(thisQualifiedFactory);
});
}
/**
* Whether or not a data source has been ingested with a particular ingest module.
* @param dataSource The datasource.
* @param fullyQualifiedFactory The fully qualified classname of the relevant factory.
* @return Whether or not a data source has been ingested with a particular ingest module.
* @throws TskCoreException
* @throws SleuthkitCaseProviderException
*/
public boolean isModuleIngested(DataSource dataSource, String fullyQualifiedFactory)
throws TskCoreException, SleuthkitCaseProviderException {
if (dataSource == null) {
return false;
}
long dataSourceId = dataSource.getId();
return caseProvider.get().getIngestJobs().stream()
.anyMatch((ingestJob) -> {
return ingestJob != null
&& ingestJob.getObjectId() == dataSourceId
&& hasIngestModule(ingestJob, fullyQualifiedFactory);
});
}
/**
* Get a mapping of fully qualified factory name to display name.
* @param skCase The SleuthkitCase.
* @return The mapping of fully qualified factory name to display name.
* @throws TskCoreException
*/
public static Map<String, String> getFactoryDisplayNames(SleuthkitCase skCase) throws TskCoreException {
return skCase.getIngestJobs().stream()
.flatMap(ingestJob -> ingestJob.getIngestModuleInfo().stream())
.collect(Collectors.toMap(
(moduleInfo) -> getFullyQualifiedFactory(moduleInfo),
(moduleInfo) -> moduleInfo.getDisplayName(),
(a,b) -> a));
}
}

View File

@ -0,0 +1,162 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.datasourcesummary.uiutils;
import java.awt.BorderLayout;
import java.beans.PropertyChangeListener;
import java.net.URL;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Set;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.ingest.IngestManager;
/**
* JLabel that shows ingest is running.
*/
@Messages({
"IngestRunningLabel_defaultMessage=Ingest is currently running."
})
public class IngestRunningLabel extends JPanel {
public static final String DEFAULT_MESSAGE = Bundle.IngestRunningLabel_defaultMessage();
private static final URL DEFAULT_ICON = IngestRunningLabel.class.getResource("/org/sleuthkit/autopsy/modules/filetypeid/warning16.png");
private static final Set<IngestManager.IngestJobEvent> INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(
IngestManager.IngestJobEvent.STARTED,
IngestManager.IngestJobEvent.CANCELLED,
IngestManager.IngestJobEvent.COMPLETED
);
private static Set<IngestRunningLabel> activeLabels = new HashSet<>();
private static PropertyChangeListener classListener = null;
private static Object lockObject = new Object();
/**
* Setup ingest event listener for the current label.
*
* @param label The label.
*/
private static void setupListener(IngestRunningLabel label) {
synchronized (lockObject) {
// if listener is not initialized, initialize it.
if (classListener == null) {
classListener = (evt) -> {
if (evt.getPropertyName().equals(IngestManager.IngestJobEvent.STARTED.toString())) {
// ingest started
notifyListeners(true);
} else if (evt.getPropertyName().equals(IngestManager.IngestJobEvent.CANCELLED.toString())
|| evt.getPropertyName().equals(IngestManager.IngestJobEvent.COMPLETED.toString())) {
// ingest cancelled or finished
notifyListeners(false);
}
};
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, classListener);
}
// add the item to the set
activeLabels.add(label);
}
}
/**
* Notifies all listening instances of an update in ingest state.
*
* @param ingestIsRunning Whether or not ingest is running currently.
*/
private static void notifyListeners(boolean ingestIsRunning) {
synchronized (lockObject) {
for (IngestRunningLabel label : activeLabels) {
label.refreshState(ingestIsRunning);
}
}
}
/**
* Removes a label from listening events.
*
* @param label The label to remove from listening events.
*/
private static void removeListener(IngestRunningLabel label) {
synchronized (lockObject) {
activeLabels.remove(label);
if (activeLabels.isEmpty() && classListener != null) {
IngestManager.getInstance().removeIngestJobEventListener(classListener);
classListener = null;
}
}
}
/**
* Main constructor with default message and showing icon.
*/
public IngestRunningLabel() {
this(DEFAULT_MESSAGE, true);
}
/**
* Constructor.
*
* @param message The message to be shown.
* @param showWarningIcon Whether or not to show warning icon.
*/
public IngestRunningLabel(String message, boolean showWarningIcon) {
JLabel jlabel = new JLabel();
jlabel.setText(message);
if (showWarningIcon) {
jlabel.setIcon(new ImageIcon(DEFAULT_ICON));
}
setLayout(new BorderLayout());
add(jlabel, BorderLayout.CENTER);
setupListener(this);
refreshState();
}
/**
* Refresh state of this label based on ingest status.
*/
protected final void refreshState() {
refreshState(IngestManager.getInstance().isIngestRunning());
}
/**
* Refresh state of this label based on ingest status.
*
* @param ingestIsRunning True if ingest is running.
*/
protected final void refreshState(boolean ingestIsRunning) {
setVisible(ingestIsRunning);
}
/**
* Unregister this instance from listening for ingest status changes.
*/
public void unregister() {
removeListener(this);
}
}