def test_apply_diff_merge_detetion_points(): original_root = RootAnalysis() original_observable = original_root.add_observable("test", "test") modified_root = original_root.copy() modified_observable = modified_root.get_observable(original_observable) modified_observable.add_detection_point("test") target_root = original_root.copy() target_observable = target_root.get_observable(original_observable) assert not target_observable.has_detection_points() target_observable.apply_diff_merge(original_observable, modified_observable) assert target_observable.has_detection_points # exists before but not after original_root = RootAnalysis() original_observable = original_root.add_observable("test", "test") modified_root = original_root.copy() modified_observable = modified_root.get_observable(original_observable) target_root = original_root.copy() target_observable = target_root.get_observable(original_observable) original_observable.add_detection_point("test") assert not target_observable.has_detection_points() target_observable.apply_diff_merge(original_observable, modified_observable) assert not target_observable.has_detection_points()
def test_apply_diff_merge_directives(): # does not exist before but exists after original_root = RootAnalysis() original_observable = original_root.add_observable("test", "test") modified_root = copy.deepcopy(original_root) modified_observable = modified_root.get_observable(original_observable) modified_observable.add_directive("test") target_root = RootAnalysis() observable = target_root.add_observable("test", "test") assert not observable.has_directive("test") observable.apply_diff_merge(original_observable, modified_observable) assert observable.has_directive("test") # exists before but not after original_root = RootAnalysis() original_observable = original_root.add_observable("test", "test") modified_root = copy.deepcopy(original_root) original_observable.add_directive("test") modified_observable = modified_root.get_observable(original_observable) target_root = RootAnalysis() observable = target_root.add_observable("test", "test") assert not observable.has_directive("test") observable.apply_diff_merge(original_observable, modified_observable) # should still not exist assert not observable.has_directive("test")
def test_observable_serialization(): root = RootAnalysis() o_time = utc_now() target = root.add_observable("test", "other") o1 = root.add_observable( "test", "test", time=o_time, context="text context", directives=["directive1", "directive2"], limited_analysis=["limit1", "limit2"], excluded_analysis=["excluded1", "excluded2"], requested_analysis=["requested1", "requested2"], ) o1.add_relationship("test", target) root = RootAnalysis.from_dict(root.to_model().dict()) o2 = root.get_observable(o1) # should be two separate instances assert id(o1) != id(o2) assert o1.type == o2.type assert o1.value == o2.value assert o1.time == o2.time assert o1.context == o2.context assert o1.directives == o2.directives assert o1.limited_analysis == o2.limited_analysis assert o1.excluded_analysis == o2.excluded_analysis assert o1.requested_analysis == o2.requested_analysis assert o1.relationships == o2.relationships
def test_apply_diff_merge_excluded_analysis(): # does not exist before but exists after original_root = RootAnalysis() original_observable = original_root.add_observable("test", "test") modified_root = copy.deepcopy(original_root) modified_observable = modified_root.get_observable(original_observable) modified_observable.exclude_analysis("test") target_root = RootAnalysis() observable = target_root.add_observable("test", "test") assert not observable.excluded_analysis observable.apply_diff_merge(original_observable, modified_observable) assert observable.excluded_analysis[0] == "test" # exists before but not after original_root = RootAnalysis() original_observable = original_root.add_observable("test", "test") modified_root = copy.deepcopy(original_root) modified_observable = modified_root.get_observable(original_observable) original_observable.exclude_analysis("test") target_root = RootAnalysis() observable = target_root.add_observable("test", "test") assert not observable.excluded_analysis observable.apply_diff_merge(original_observable, modified_observable) # should still not exist assert not observable.excluded_analysis
def test_apply_diff_merge_tags(): original_root = RootAnalysis() original_observable = original_root.add_observable("test", "test") modified_root = original_root.copy() modified_observable = modified_root.get_observable(original_observable) modified_observable.add_tag("test") target_root = original_root.copy() target_observable = target_root.add_observable("test", "test") assert not target_observable.tags target_observable.apply_diff_merge(original_observable, modified_observable) assert target_observable.tags assert target_observable.tags[0] == "test" # exists before but not after original_root = RootAnalysis() original_observable = original_root.add_observable("test", "test") modified_root = original_root.copy() modified_observable = modified_root.get_observable(original_observable) target_root = original_root.copy() target_observable = target_root.add_observable("test", "test") original_observable.add_tag("test") assert not target_observable.tags target_observable.apply_diff_merge(original_observable, modified_observable) assert not target_observable.tags
def test_apply_merge_grouping_target(): root = RootAnalysis() observable = root.add_observable("some_type", "some_value") target_root = RootAnalysis() target_observable = target_root.add_observable("some_type", "some_value") target_observable.grouping_target = True assert not observable.grouping_target observable.apply_merge(target_observable) assert observable.grouping_target
def test_apply_merge_directives(): root = RootAnalysis() observable = root.add_observable("some_type", "some_value") target_root = RootAnalysis() target_observable = target_root.add_observable("some_type", "some_value") target_observable.add_directive("some_directive") assert not observable.has_directive("some_directive") observable.apply_merge(target_observable) assert observable.has_directive("some_directive")
def test_apply_merge_detetion_points(): root = RootAnalysis() observable = root.add_observable("test", "test") target_root = RootAnalysis() target_observable = target_root.add_observable("test", "test") target_observable.add_detection_point("test") assert not observable.has_detection_points() observable.apply_merge(target_observable) assert observable.has_detection_points
def test_search_down(): amt = AnalysisModuleType("test", "") root = RootAnalysis() observable = root.add_observable("test", "test") analysis = observable.add_analysis(type=amt) child = analysis.add_observable("test", "child") observable_2 = root.add_observable("test", "other") assert search_down(child, lambda obj: obj == analysis) == analysis assert search_down(child, lambda obj: obj == observable) == observable assert search_down(child, lambda obj: obj == root) == root assert search_down(child, lambda obj: False) is None
def test_apply_merge_tags(): root = RootAnalysis() observable = root.add_observable("some_type", "some_value") target_root = RootAnalysis() target_observable = target_root.add_observable("some_type", "some_value") target_observable.add_tag("test") assert not observable.tags observable.apply_merge(target_observable) assert observable.tags assert observable.tags[0] == "test"
def test_apply_merge_excluded_analysis(): root = RootAnalysis() observable = root.add_observable("some_type", "some_value") target_root = RootAnalysis() target_observable = target_root.add_observable("some_type", "some_value") target_observable.exclude_analysis("some_module") assert not observable.excluded_analysis observable.apply_merge(target_observable) assert observable.excluded_analysis assert observable.excluded_analysis[0] == "some_module"
def test_apply_merge_links(): root = RootAnalysis() observable = root.add_observable("some_type", "some_value") # test the case where the link target does not exist in the root analysis target_root = RootAnalysis() target_observable = target_root.add_observable("some_type", "some_value") linked_observable = target_root.add_observable("other_type", "other_value") target_observable.add_link(linked_observable) assert not observable.links observable.apply_merge(target_observable) assert observable.links assert observable.links[0] == linked_observable # also test the case where the link target already exists in the root analysis root = RootAnalysis() observable = root.add_observable("some_type", "some_value") root.add_observable("other_type", "other_value") target_root = RootAnalysis() target_observable = target_root.add_observable("some_type", "some_value") linked_observable = target_root.add_observable("other_type", "other_value") target_observable.add_link(linked_observable) assert not observable.links observable.apply_merge(target_observable) assert observable.links assert observable.links[0] == linked_observable
def test_apply_merge_relationships(): root = RootAnalysis() observable = root.add_observable("some_type", "some_value") # test the case where the relationship target does not exist in the root analysis target_root = RootAnalysis() target_observable = target_root.add_observable("some_type", "some_value") r_observable = target_root.add_observable("other_type", "other_value") target_observable.add_relationship("downloaded_from", r_observable) assert not observable.relationships observable.apply_merge(target_observable) assert observable.relationships["downloaded_from"] == [r_observable] # also test the case where the relationship target already exists in the root analysis root = RootAnalysis() observable = root.add_observable("some_type", "some_value") root.add_observable("other_type", "other_value") # test the case where the relationship target does not exist in the root analysis target_root = RootAnalysis() target_observable = target_root.add_observable("some_type", "some_value") r_observable = target_root.add_observable("other_type", "other_value") target_observable.add_relationship("downloaded_from", r_observable) assert not observable.relationships observable.apply_merge(target_observable) assert observable.relationships["downloaded_from"] == [r_observable]
def test_apply_merge_redirection(): root = RootAnalysis() observable = root.add_observable("some_type", "some_value") # test the case where the redirection target does not exist in the root analysis target_root = RootAnalysis() target_observable = target_root.add_observable("some_type", "some_value") target_redirection_observable = target_root.add_observable( "other_type", "other_value") target_observable.redirection = target_redirection_observable assert observable.redirection is None observable.apply_merge(target_observable) assert observable.redirection == target_redirection_observable # also test the case where the redirection target already exists in the root analysis root = RootAnalysis() observable = root.add_observable("some_type", "some_value") root.add_observable("other_type", "other_value") target_root = RootAnalysis() target_observable = target_root.add_observable("some_type", "some_value") target_redirection_observable = target_root.add_observable( "other_type", "other_value") target_observable.redirection = target_redirection_observable assert observable.redirection is None observable.apply_merge(target_observable) assert observable.redirection == target_redirection_observable
def test_apply_merge_analysis(): amt = AnalysisModuleType("test", "") root = RootAnalysis() observable = root.add_observable("some_type", "some_value") target_root = RootAnalysis() target_observable = target_root.add_observable("some_type", "some_value") target_observable.add_analysis(Analysis(type=amt, details={"test": "test"})) assert not observable.analysis observable.apply_merge(target_observable) assert observable.analysis assert observable.get_analysis("test") is not None assert observable.get_analysis("test")._details == {"test": "test"}
def test_apply_diff_merge_grouping_target(): # grouping target modified original_root = RootAnalysis() original_observable = original_root.add_observable("test", "test") modified_root = copy.deepcopy(original_root) modified_observable = modified_root.get_observable(original_observable) modified_observable.grouping_target = True target_root = RootAnalysis() target_observable = target_root.add_observable("test", "test") assert not target_observable.grouping_target target_observable.apply_diff_merge(original_observable, modified_observable) assert target_observable.grouping_target
def test_add_analysis(): amt = AnalysisModuleType("test", "") root = RootAnalysis() observable = root.add_observable("test", "test") # test adding an Analysis object analysis = Analysis(details={"hello": "world"}, type=amt) result = observable.add_analysis(analysis) assert result == analysis # test adding just a details, type root = RootAnalysis() observable = root.add_observable("test", "test") analysis = observable.add_analysis(details={"hello": "world"}, type=amt) assert result == analysis
def test_root_all_detection_points(): amt = AnalysisModuleType("test", "") root = RootAnalysis() observable = root.add_observable("test", "test") analysis = observable.add_analysis(type=amt) observable_2 = analysis.add_observable("test", "test2") root.add_detection_point("test") assert root.all_detection_points == [DetectionPoint("test")] observable.add_detection_point("test") assert root.all_detection_points == [ DetectionPoint("test"), DetectionPoint("test") ] analysis.add_detection_point("test") assert root.all_detection_points == [ DetectionPoint("test"), DetectionPoint("test"), DetectionPoint("test") ] observable_2.add_detection_point("test") assert root.all_detection_points == [ DetectionPoint("test"), DetectionPoint("test"), DetectionPoint("test"), DetectionPoint("test"), ]
def test_recurse_down(): amt = AnalysisModuleType("test", "") root = RootAnalysis() observable = root.add_observable("test", "test") analysis = observable.add_analysis(type=amt) child = analysis.add_observable("test", "child") observable_2 = root.add_observable("test", "other") # we'll build a list of the nodes we visit result = [] def _callback(node): result.append(node) # R -> O1 -> A -> O2 # -> O3 recurse_down(root, _callback) assert result == [root] result = [] recurse_down(observable, _callback) assert result == [observable, root] result = [] recurse_down(analysis, _callback) assert result == [analysis, observable, root] result = [] recurse_down(child, _callback) assert result == [child, analysis, observable, root] result = [] recurse_down(observable_2, _callback) assert result == [observable_2, root] # R -> O1 -> A -> O1 root = RootAnalysis() observable = root.add_observable("test", "test") analysis = observable.add_analysis(type=amt) # this points to the same observable as before child = analysis.add_observable("test", "test") result = [] recurse_down(observable, _callback) assert len(result) == 3 # (order is random when there are multiple paths to root) assert analysis in result and observable in result and root in result
def test_observable_properties(): amt = AnalysisModuleType("test", "") root = RootAnalysis() observable = root.add_observable("test", "test") analysis = observable.add_analysis(type=amt) assert observable.all_analysis == [analysis] assert observable.children == [analysis]
def test_has_observable(): root = RootAnalysis() observable = root.add_observable("test", "test") assert root.has_observable("test", "test") assert not root.has_observable("test", "t3st") assert root.has_observable(Observable("test", "test")) assert not root.has_observable(Observable("t3st", "test")) assert not root.has_observable(Observable("test", "t3st"))
def test_root_analysis_get_observables_by_type(): amt = AnalysisModuleType("test", "") root = RootAnalysis() observable_1 = root.add_observable("test", "test_1") observable_2 = root.add_observable("test", "test_2") observable_3 = root.add_observable("test_3", "test_3") analysis = observable_3.add_analysis(type=amt) observable_4 = analysis.add_observable("test_4", "test_4") assert root.get_observables_by_type("test") == [observable_1, observable_2] assert root.get_observables_by_type("test_3") == [observable_3] assert root.get_observables_by_type("test_4") == [observable_4] assert root.get_observables_by_type("unknown") == [] assert root.get_observable_by_type("test") in [observable_1, observable_2] assert root.get_observable_by_type("test_3") == observable_3 assert root.get_observable_by_type("test_4") == observable_4 assert root.get_observable_by_type("unknown") is None
def test_root_all(): amt = AnalysisModuleType("test", "") root = RootAnalysis() observable = root.add_observable("test", "test") analysis = observable.add_analysis(type=amt) observable_2 = analysis.add_observable("test", "test2") assert sorted(root.all) == sorted( [root, analysis, observable, observable_2])
def test_add_duplicate_analysis(): amt = AnalysisModuleType("test", "") root = RootAnalysis() observable = root.add_observable("test", "test") analysis = observable.add_analysis(type=amt) # adding the same analysis twice will fail with pytest.raises(ValueError): observable.add_analysis(type=amt)
def test_add_link(): root = RootAnalysis() observable_1 = root.add_observable("test", "test1") observable_2 = root.add_observable("test", "test2") observable_3 = root.add_observable("test", "test3") observable_2.add_link(observable_1) assert observable_2.links == [observable_1] observable_2.add_link(observable_3) assert sorted(observable_2.links) == sorted([observable_1, observable_3]) observable_2.add_tag("test") assert observable_2.has_tag("test") assert observable_1.has_tag("test") assert observable_3.has_tag("test") with pytest.raises(ValueError): # cannot do this since 2 already points to 1 observable_1.add_link(observable_2)
def test_root_copy(): root = RootAnalysis() observable = root.add_observable("test", "test") amt = AnalysisModuleType("test", "") analysis = observable.add_analysis(type=amt, details={"test": "test"}) root_copy = root.copy() observable_copy = root_copy.get_observable(observable) assert observable_copy == observable assert not (observable_copy is observable) analysis_copy = observable_copy.get_analysis(amt) assert analysis_copy == analysis assert not (analysis_copy is analysis)
def test_relationships(): root = RootAnalysis() observable_1 = root.add_observable("test", "test1") observable_2 = root.add_observable("test", "test2") observable_1.add_relationship("test", observable_2) assert observable_1.has_relationship("test") assert observable_1.has_relationship("test", observable_2) assert observable_1.get_relationships_by_type("test") == [observable_2] assert observable_1.get_relationship_by_type("test") == observable_2 assert observable_1.get_relationships_by_type("unknown") == [] assert observable_1.get_relationship_by_type("unknown") is None
def test_apply_diff_merge_redirection(): # test redirection created original_root = RootAnalysis() original_observable = original_root.add_observable("test", "test") modified_root = copy.deepcopy(original_root) modified_observable = modified_root.get_observable(original_observable) modified_observable.redirection = modified_root.add_observable( "target", "target") target_root = RootAnalysis() target_observable = target_root.add_observable("test", "test") assert target_observable.redirection is None target_observable.apply_diff_merge(original_observable, modified_observable) assert target_root.get_observable(modified_observable.redirection) assert target_observable.redirection == target_root.get_observable( modified_observable.redirection) # test redirection modified original_root = RootAnalysis() original_observable = original_root.add_observable("test", "test") original_observable.redirection = original_root.add_observable( "target", "target") modified_root = copy.deepcopy(original_root) modified_observable = modified_root.get_observable(original_observable) modified_observable.redirection = modified_root.add_observable( "other", "other") target_root = RootAnalysis() target_observable = target_root.add_observable("test", "test") assert target_observable.redirection is None target_observable.apply_diff_merge(original_observable, modified_observable) assert target_root.get_observable(modified_observable.redirection) assert target_observable.redirection == target_root.get_observable( modified_observable.redirection)
def test_apply_diff_merge_links(): # does not exist before but exists after original_root = RootAnalysis() original_observable = original_root.add_observable("test", "test") modified_root = copy.deepcopy(original_root) modified_observable = modified_root.get_observable(original_observable) link_target = modified_root.add_observable("target", "target") modified_observable.add_link(link_target) target_root = RootAnalysis() observable = target_root.add_observable("test", "test") assert not observable.links observable.apply_diff_merge(original_observable, modified_observable) linked_observable = target_root.get_observable(link_target) assert linked_observable assert observable.links[0] == linked_observable # exists before but not after original_root = RootAnalysis() original_observable = original_root.add_observable("test", "test") modified_root = copy.deepcopy(original_root) modified_observable = modified_root.get_observable(original_observable) link_target = original_root.add_observable("target", "target") original_observable.add_link(link_target) target_root = RootAnalysis() observable = target_root.add_observable("test", "test") assert not observable.links observable.apply_diff_merge(original_observable, modified_observable) # should still not exist assert not observable.links # exists before and after original_root = RootAnalysis() original_observable = original_root.add_observable("test", "test") link_target = original_root.add_observable("target", "target") original_observable.add_link(link_target) modified_root = copy.deepcopy(original_root) modified_observable = modified_root.get_observable(original_observable) target_root = RootAnalysis() observable = target_root.add_observable("test", "test") assert not observable.links observable.apply_diff_merge(original_observable, modified_observable) # should still not exist assert not observable.links
def test_root_analysis_serialization(): root = RootAnalysis( tool="test", tool_instance="test", alert_type="test", desc="test", event_time=datetime.datetime.now(), name="test", analysis_mode="test", queue="test", instructions="test", ) amt = AnalysisModuleType("test", "") observable = root.add_observable("test", "test") analysis = observable.add_analysis(type=amt, details={"test": "test"}) root.add_detection_point("test") new_root = RootAnalysis.from_dict(root.to_dict()) assert root == new_root assert root.tool == new_root.tool assert root.tool_instance == new_root.tool assert root.alert_type == new_root.alert_type assert root.description == new_root.description assert root.event_time == new_root.event_time assert root.name == new_root.name assert root.analysis_mode == new_root.analysis_mode assert root.queue == new_root.queue assert root.instructions == new_root.instructions assert root.detections == new_root.detections # the observable property for the root should always be None assert root.observable is None assert len(root.observables) == 1 new_root = RootAnalysis.from_json(root.to_json()) assert root == new_root assert root.tool == new_root.tool assert root.tool_instance == new_root.tool assert root.alert_type == new_root.alert_type assert root.description == new_root.description assert root.event_time == new_root.event_time assert root.name == new_root.name assert root.analysis_mode == new_root.analysis_mode assert root.queue == new_root.queue assert root.instructions == new_root.instructions # the observable property for the root should always be None assert root.observable is None assert len(root.observables) == 1