7938 Changes to allow working O column for OS Accounts

This commit is contained in:
William Schaefer 2021-09-23 12:34:42 -04:00
parent b39978b968
commit a36710ce05
7 changed files with 133 additions and 23 deletions

View File

@ -1503,24 +1503,27 @@ abstract class RdbmsCentralRepo implements CentralRepository {
Long sourceObjID = instance.getFileObjectId();
//The CorrelationAttributeInstance will have a CorrelationCase, however that correlation case's ID will be null if the case is not in the CR.
int correlationCaseId = instance.getCorrelationCase().getID();
int correlationDataSourceId = instance.getCorrelationDataSource().getID();
String normalizedValue = CorrelationAttributeNormalizer.normalize(instance.getCorrelationType(), instance.getCorrelationValue());
Connection conn = connect();
PreparedStatement preparedStatement = null;
String tableName = CentralRepoDbUtil.correlationTypeToInstanceTableName(instance.getCorrelationType());
ResultSet resultSet = null;
try {
if (correlationCaseId > 0 && sourceObjID != null) {
if (correlationCaseId > 0 && sourceObjID != null && correlationDataSourceId > 0) {
//The CorrelationCase is in the Central repository.
String sql
= "SELECT count(*) FROM (SELECT DISTINCT case_id FROM " //Get distinct cases with a matching value in the corresponding table from the central repository.
+ tableName
+ " WHERE value=? AND NOT (file_obj_id=? AND case_id=?)) AS " //Check the file_obj_id AND case_id to ensure we ignore the currently selected instance.
+ " WHERE value=? AND NOT (file_obj_id=? AND case_id=? AND data_source_id=?)) AS " //Check the file_obj_id AND case_id to ensure we ignore the currently selected instance.
+ tableName
+ "_other_case_count";
preparedStatement = conn.prepareStatement(sql);
preparedStatement.setString(1, normalizedValue);
preparedStatement.setLong(2, sourceObjID);
preparedStatement.setInt(3, correlationCaseId);
preparedStatement.setInt(4, correlationDataSourceId);
} else {
//The CorrelationCase is NOT in the central repository.
String sql

View File

@ -178,8 +178,8 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
} else if (eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString())) {
ContentTagAddedEvent event = (ContentTagAddedEvent) evt;
if (event.getAddedTag().getContent().equals(content)) {
List<Tag> tags = this.getAllTagsFromDatabase();
Pair<Score, String> scorePropAndDescr = getScorePropertyAndDescription(tags);
Pair<Score, String> scorePropAndDescr = getScorePropertyAndDescription();
Score value = scorePropAndDescr.getLeft();
String descr = scorePropAndDescr.getRight();
List<CorrelationAttributeInstance> listWithJustFileAttr = new ArrayList<>();
@ -188,14 +188,14 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
listWithJustFileAttr.add(corrInstance);
}
updateSheet(new NodeProperty<>(SCORE.toString(), SCORE.toString(), descr, value),
new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), NO_DESCR, getCommentProperty(tags, listWithJustFileAttr))
new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), NO_DESCR, getCommentProperty(getAllTagsFromDatabase(), listWithJustFileAttr))
);
}
} else if (eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) {
ContentTagDeletedEvent event = (ContentTagDeletedEvent) evt;
if (event.getDeletedTagInfo().getContentID() == content.getId()) {
List<Tag> tags = getAllTagsFromDatabase();
Pair<Score, String> scorePropAndDescr = getScorePropertyAndDescription(tags);
Pair<Score, String> scorePropAndDescr = getScorePropertyAndDescription();
Score value = scorePropAndDescr.getLeft();
String descr = scorePropAndDescr.getRight();
List<CorrelationAttributeInstance> listWithJustFileAttr = new ArrayList<>();
@ -204,19 +204,18 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
listWithJustFileAttr.add(corrInstance);
}
updateSheet(new NodeProperty<>(SCORE.toString(), SCORE.toString(), descr, value),
new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), NO_DESCR, getCommentProperty(tags, listWithJustFileAttr))
new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), NO_DESCR, getCommentProperty(getAllTagsFromDatabase(), listWithJustFileAttr))
);
}
} else if (eventType.equals(Case.Events.CR_COMMENT_CHANGED.toString())) {
CommentChangedEvent event = (CommentChangedEvent) evt;
if (event.getContentID() == content.getId()) {
List<Tag> tags = getAllTagsFromDatabase();
List<CorrelationAttributeInstance> listWithJustFileAttr = new ArrayList<>();
CorrelationAttributeInstance corrInstance = CorrelationAttributeUtil.getCorrAttrForFile(content);
if (corrInstance != null) {
listWithJustFileAttr.add(corrInstance);
}
updateSheet(new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), NO_DESCR, getCommentProperty(tags, listWithJustFileAttr)));
updateSheet(new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), NO_DESCR, getCommentProperty(getAllTagsFromDatabase(), listWithJustFileAttr)));
}
} else if (eventType.equals(NodeSpecificEvents.TRANSLATION_AVAILABLE.toString())) {
this.setDisplayName(evt.getNewValue().toString());

View File

@ -327,15 +327,13 @@ public abstract class AbstractContentNode<T extends Content> extends ContentNode
/**
* Returns Score property for the node.
*
* @param tags list of tags.
*
* @return Score property for the underlying content of the node.
*/
@Messages({
"# {0} - significanceDisplayName",
"AbstractContentNode_getScorePropertyAndDescription_description=Has an {0} analysis result score"
})
protected Pair<Score, String> getScorePropertyAndDescription(List<Tag> tags) {
protected Pair<Score, String> getScorePropertyAndDescription() {
Score score = Score.SCORE_UNKNOWN;
try {
score = this.content.getAggregateScore();

View File

@ -1214,7 +1214,7 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
"BlackboardArtifactNode.createSheet.noScore.description=No score"})
@Deprecated
protected final void addScorePropertyAndDescription(Sheet.Set sheetSet, List<Tag> tags) {
Pair<Score, String> scoreAndDescription = getScorePropertyAndDescription(tags);
Pair<Score, String> scoreAndDescription = getScorePropertyAndDescription();
sheetSet.put(new NodeProperty<>(Bundle.BlackboardArtifactNode_createSheet_score_name(), Bundle.BlackboardArtifactNode_createSheet_score_displayName(), scoreAndDescription.getRight(), scoreAndDescription.getLeft()));
}

View File

@ -331,7 +331,10 @@ OpenReportAction.actionPerformed.ReportFileOpenPermissionDeniedMessage=Permissio
OsAccount_listNode_name=OS Accounts
OsAccounts.createSheet.comment.displayName=C
OsAccounts.createSheet.comment.name=C
# {0} - occurrenceCount
OsAccounts.createSheet.count.description=There were {0} datasource(s) found with occurrences of the OS Account correlation value
OsAccounts.createSheet.count.displayName=O
OsAccounts.createSheet.count.hashLookupNotRun.description=Hash lookup had not been run on this file when the column was populated
OsAccounts.createSheet.count.name=O
OsAccounts.createSheet.score.displayName=S
OsAccounts.createSheet.score.name=S

View File

@ -23,17 +23,21 @@ import java.beans.PropertyChangeListener;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.events.AutopsyEvent;
import org.sleuthkit.datamodel.Tag;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeUtil;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.AnalysisResult;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.DataArtifact;
import org.sleuthkit.datamodel.OsAccount;
import org.sleuthkit.datamodel.OsAccountInstance;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Background task to get Score, Comment and Occurrences values for an Abstract
@ -43,6 +47,7 @@ import org.sleuthkit.datamodel.DataArtifact;
class GetSCOTask implements Runnable {
private final WeakReference<AbstractContentNode<?>> weakNodeRef;
private static final Logger logger = Logger.getLogger(GetSCOTask.class.getName());
private final PropertyChangeListener listener;
GetSCOTask(WeakReference<AbstractContentNode<?>> weakContentRef, PropertyChangeListener listener) {
@ -55,19 +60,16 @@ class GetSCOTask implements Runnable {
@Override
public void run() {
AbstractContentNode<?> contentNode = weakNodeRef.get();
//Check for stale reference or if columns are disabled
if (contentNode == null || UserPreferences.getHideSCOColumns()) {
return;
}
// get the SCO column values
List<Tag> tags = contentNode.getAllTagsFromDatabase();
SCOData scoData = new SCOData();
scoData.setScoreAndDescription(contentNode.getScorePropertyAndDescription(tags));
scoData.setScoreAndDescription(contentNode.getScorePropertyAndDescription());
//getting the correlation attribute and setting the comment column is done before the eamdb isEnabled check
//because the Comment column will reflect the presence of comments in the CR when the CR is enabled, but reflect tag comments regardless
String description = Bundle.GetSCOTask_occurrences_defaultDescription();
List<CorrelationAttributeInstance> listOfPossibleAttributes = new ArrayList<>();
Content contentFromNode = contentNode.getContent();
if (contentFromNode instanceof AbstractFile) {
@ -76,10 +78,18 @@ class GetSCOTask implements Runnable {
listOfPossibleAttributes.addAll(CorrelationAttributeUtil.makeCorrAttrsForSearch((AnalysisResult) contentFromNode));
} else if (contentFromNode instanceof DataArtifact) {
listOfPossibleAttributes.addAll(CorrelationAttributeUtil.makeCorrAttrsForSearch((DataArtifact) contentFromNode));
} else {
//JIRA-TODO : add code for Jira-7938 OsAccounts
} else if (contentFromNode instanceof OsAccount) {
try {
List<OsAccountInstance> osAccountInstances = ((OsAccount) contentFromNode).getOsAccountInstances();
OsAccountInstance osAccountInstance = osAccountInstances.isEmpty() ? null : osAccountInstances.get(0);
listOfPossibleAttributes.addAll(CorrelationAttributeUtil.makeCorrAttrsForSearch(osAccountInstance));
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Unable to get OsAccountInstances for OsAccount with ID: " + contentFromNode.getId(), ex);
}
}
scoData.setComment(contentNode.getCommentProperty(tags, listOfPossibleAttributes));
scoData.setComment(contentNode.getCommentProperty(contentNode.getAllTagsFromDatabase(), listOfPossibleAttributes));
CorrelationAttributeInstance corInstance = null;
if (CentralRepository.isEnabled()) {
if (listOfPossibleAttributes.size() > 1) {
@ -91,7 +101,6 @@ class GetSCOTask implements Runnable {
}
scoData.setCountAndDescription(contentNode.getCountPropertyAndDescription(corInstance, description));
}
// signal SCO data is available.
if (listener
!= null) {

View File

@ -29,25 +29,34 @@ import java.util.List;
import java.util.Optional;
import java.util.logging.Level;
import javax.swing.Action;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.nodes.Sheet;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.openide.util.WeakListeners;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.events.OsAccountsUpdatedEvent;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeNormalizationException;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.TimeZoneUtils;
import static org.sleuthkit.autopsy.datamodel.AbstractContentNode.NO_DESCR;
import static org.sleuthkit.autopsy.datamodel.AbstractContentNode.VALUE_LOADING;
import static org.sleuthkit.autopsy.datamodel.AbstractContentNode.backgroundTasksPool;
import org.sleuthkit.autopsy.events.AutopsyEvent;
import org.sleuthkit.datamodel.Host;
import org.sleuthkit.datamodel.OsAccount;
import org.sleuthkit.datamodel.OsAccountRealm;
import org.sleuthkit.datamodel.Score;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.Tag;
import org.sleuthkit.datamodel.TskCoreException;
@ -207,6 +216,28 @@ public final class OsAccounts implements AutopsyVisitableItem {
Bundle.OsAccounts_accountRealmNameProperty_desc(),
realmNames.get(0)));
}
} else if (evt.getPropertyName().equals(NodeSpecificEvents.SCO_AVAILABLE.toString()) && !UserPreferences.getHideSCOColumns()) {
SCOData scoData = (SCOData) evt.getNewValue();
if (scoData.getScoreAndDescription() != null) {
updateSheet(new NodeProperty<>(
Bundle.BlackboardArtifactNode_createSheet_score_name(),
Bundle.BlackboardArtifactNode_createSheet_score_displayName(),
scoData.getScoreAndDescription().getRight(),
scoData.getScoreAndDescription().getLeft()));
}
if (scoData.getComment() != null) {
updateSheet(new NodeProperty<>(
Bundle.BlackboardArtifactNode_createSheet_comment_name(),
Bundle.BlackboardArtifactNode_createSheet_comment_displayName(),
NO_DESCR, scoData.getComment()));
}
if (scoData.getCountAndDescription() != null) {
updateSheet(new NodeProperty<>(
Bundle.BlackboardArtifactNode_createSheet_count_name(),
Bundle.BlackboardArtifactNode_createSheet_count_displayName(),
scoData.getCountAndDescription().getRight(),
scoData.getCountAndDescription().getLeft()));
}
}
}
};
@ -365,7 +396,7 @@ public final class OsAccounts implements AutopsyVisitableItem {
@Override
protected List<Tag> getAllTagsFromDatabase() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
return new ArrayList<>();
}
@Override
@ -415,5 +446,72 @@ public final class OsAccounts implements AutopsyVisitableItem {
}
}
}
@NbBundle.Messages({
"OsAccounts.createSheet.count.hashLookupNotRun.description=Hash lookup had not been run on this file when the column was populated",
"# {0} - occurrenceCount",
"OsAccounts.createSheet.count.description=There were {0} datasource(s) found with occurrences of the OS Account correlation value"})
@Override
protected Pair<Long, String> getCountPropertyAndDescription(CorrelationAttributeInstance attributeInstance, String defaultDescription) {
Long count = -1L; //The column renderer will not display negative values, negative value used when count unavailble to preserve sorting
String description = defaultDescription;
try {
//don't perform the query if there is no correlation value
if (attributeInstance != null && StringUtils.isNotBlank(attributeInstance.getCorrelationValue())) {
count = CentralRepository.getInstance().getCountCasesWithOtherInstances(attributeInstance);
description = Bundle.OsAccounts_createSheet_count_description(count);
} else if (attributeInstance != null) {
description = Bundle.OsAccounts_createSheet_count_hashLookupNotRun_description();
}
} catch (CentralRepoException ex) {
logger.log(Level.WARNING, "Error getting count of datasources with correlation attribute", ex);
} catch (CorrelationAttributeNormalizationException ex) {
logger.log(Level.WARNING, "Unable to normalize data to get count of datasources with correlation attribute", ex);
}
return Pair.of(count, description);
}
/**
* Returns comment property for the node.
*
* @param tags The list of tags.
* @param attributes The list of correlation attribute instances.
*
* @return Comment property for the underlying content of the node.
*/
@Override
protected DataResultViewerTable.HasCommentStatus getCommentProperty(List<Tag> tags, List<CorrelationAttributeInstance> attributes) {
/*
* Has a tag with a comment been applied to the OsAccount or its
* source content?
*/
DataResultViewerTable.HasCommentStatus status = tags.size() > 0 ? DataResultViewerTable.HasCommentStatus.TAG_NO_COMMENT : DataResultViewerTable.HasCommentStatus.NO_COMMENT;
for (Tag tag : tags) {
if (!StringUtils.isBlank(tag.getComment())) {
status = DataResultViewerTable.HasCommentStatus.TAG_COMMENT;
break;
}
}
/*
* Does the given correlation attribute instance have a comment in
* the central repository?
*/
if (attributes != null && !attributes.isEmpty()) {
for (CorrelationAttributeInstance attribute : attributes) {
if (attribute != null && !StringUtils.isBlank(attribute.getComment())) {
if (status == DataResultViewerTable.HasCommentStatus.TAG_COMMENT) {
status = DataResultViewerTable.HasCommentStatus.CR_AND_TAG_COMMENTS;
} else {
status = DataResultViewerTable.HasCommentStatus.CR_COMMENT;
}
break;
}
}
}
return status;
}
}
}