Beispiel #1
0
def recalculate_score(lens: LensView) -> int:
    scope = lens.get_scope()
    key_to_analyzers = defaultdict(set)
    node_risk_scores = defaultdict(int)
    total_risk_score = 0
    for node in scope:
        node_risks = node.get_risks()
        risks_by_analyzer = {}
        for risk in node_risks:
            risk_score = risk.get_risk_score()
            analyzer_name = risk.get_analyzer_name()
            risks_by_analyzer[analyzer_name] = risk_score
            key_to_analyzers[node.node_key].add(analyzer_name)

        analyzer_risk_sum = sum([a for a in risks_by_analyzer.values() if a])
        node_risk_scores[node.node_key] = analyzer_risk_sum
        total_risk_score += analyzer_risk_sum

    # Bonus is calculated by finding nodes with multiple analyzers
    for key, analyzers in key_to_analyzers.items():
        if len(analyzers) <= 1:
            continue
        overlapping_analyzer_count = len(analyzers)
        bonus = node_risk_scores[key] * 2 * (overlapping_analyzer_count // 100)
        total_risk_score += bonus
    return total_risk_score
Beispiel #2
0
 def get_or_create(
     eg_client: GraphClient, lens_name: str, lens_type: str = "engagement"
 ) -> "EngagementView":
     lens = LensView.get_or_create(eg_client, lens_name, "engagement")
     engagement_client = EngagementClient(
         lens.uid,
         eg_client,
     )
     lens.graph_client = engagement_client
     return cast("EngagementView", lens.into_view(EngagementView))
Beispiel #3
0
 def test_weird_chars_in_lens_name(self, lens_name: str) -> None:
     """
     Roundabout way to ensure some basic properties of filter generation.
     """
     client = GraphClient()
     lens = LensView.get_or_create(
         gclient=client,
         lens_name=lens_name,
         lens_type="engagement",
     )
     requery_lens = LensQuery().with_lens_name(lens_name).query_first(
         client)
     assert requery_lens.get_lens_name() == lens_name
Beispiel #4
0
def _process_one_event(
    event: S3PutRecordDict,
    s3: S3ServiceResource,
    mg_client: GraphClient,
    metrics: EngagementCreatorMetrics,
) -> None:
    data = parse_s3_event(s3, event)
    incident_graph = json.loads(data)
    """
    The `incident_graph` dict is emitted from analyzer-executor.py#emit_event
    """
    analyzer_name = incident_graph["analyzer_name"]
    nodes_raw: Dict[str, Any] = incident_graph[
        "nodes"]  # same type as `.to_adjacency_list()["nodes"]`
    edges = incident_graph["edges"]
    risk_score = incident_graph["risk_score"]
    lens_dict: Sequence[Tuple[str, str]] = incident_graph["lenses"]
    risky_node_keys = incident_graph["risky_node_keys"]

    LOGGER.debug(
        f"AnalyzerName {analyzer_name}, nodes: {nodes_raw} edges: {type(edges)} {edges}"
    )

    _nodes = (BaseView.from_node_key(mg_client, n["node_key"])
              for n in nodes_raw.values())
    nodes = [n for n in _nodes if n]

    uid_map = {node.node_key: node.uid for node in nodes}

    lenses = {}  # type: Dict[str, LensView]
    for node in nodes:
        LOGGER.debug(f"Copying node: {node}")

        for lens_type, lens_name in lens_dict:
            # i.e. "hostname", "DESKTOP-WHATEVER"
            LOGGER.debug(f"Getting lens for: {lens_type} {lens_name}")
            lens_id = lens_name + lens_type
            lens: LensView = lenses.get(lens_id) or LensView.get_or_create(
                mg_client, lens_name, lens_type)
            lenses[lens_id] = lens

            # Attach to scope
            create_edge(mg_client, lens.uid, "scope", node.uid)
            create_edge(mg_client, node.uid, "in_scope", lens.uid)

            # If a node shows up in a lens all of its connected nodes should also show up in that lens
            for edge_list in edges.values():
                for edge in edge_list:
                    from_uid = uid_map[edge["from"]]
                    to_uid = uid_map[edge["to"]]
                    create_edge(mg_client, lens.uid, "scope", from_uid)
                    create_edge(mg_client, lens.uid, "scope", to_uid)

                    create_edge(mg_client, from_uid, "in_scope", lens.uid)
                    create_edge(mg_client, to_uid, "in_scope", lens.uid)

    risk = upsert(
        mg_client,
        "Risk",
        RiskView,
        analyzer_name,
        {
            "analyzer_name": analyzer_name,
            "risk_score": risk_score,
        },
    )

    risky_nodes = nodes_to_attach_risk_to(nodes, risky_node_keys)
    for node in risky_nodes:
        create_edge(mg_client, node.uid, "risks", risk.uid)
        create_edge(mg_client, risk.uid, "risky_nodes", node.uid)

        # Or perhaps we should just emit per-risk instead of per-risky-node?
        # (this alarming path is definitely a candidate for changing later)
        metrics.risk_node(analyzer_name=analyzer_name)

    for edge_list in edges.values():
        for edge in edge_list:
            from_uid = uid_map[edge["from"]]
            edge_name = edge["edge_name"]
            to_uid = uid_map[edge["to"]]

            create_edge(mg_client, from_uid, edge_name, to_uid)

    for lens in lenses.values():
        lens_score = recalculate_score(lens)
        upsert(
            mg_client,
            "Lens",
            LensView,
            lens.node_key,
            {
                "score": lens_score,
            },
        )
Beispiel #5
0
def _process_one_event(
    event: Any,
    s3: S3ServiceResource,
    mg_client: GraphClient,
) -> None:
    if not IS_LOCAL:
        event = json.loads(event["body"])["Records"][0]

    data = parse_s3_event(s3, event)
    incident_graph = json.loads(data)
    """
    The `incident_graph` dict is emitted from analyzer-executor.py#emit_event
    """
    analyzer_name = incident_graph["analyzer_name"]
    nodes_raw: Dict[str, Any] = incident_graph[
        "nodes"]  # same type as `.to_adjacency_list()["nodes"]`
    edges = incident_graph["edges"]
    risk_score = incident_graph["risk_score"]
    lens_dict = incident_graph["lenses"]
    risky_node_keys = incident_graph["risky_node_keys"]

    LOGGER.debug(
        f"AnalyzerName {analyzer_name}, nodes: {nodes_raw} edges: {type(edges)} {edges}"
    )

    _nodes = (BaseView.from_node_key(mg_client, n["node_key"])
              for n in nodes_raw.values())
    nodes = [n for n in _nodes if n]

    uid_map = {node.node_key: node.uid for node in nodes}

    lenses = {}  # type: Dict[str, LensView]
    for node in nodes:
        LOGGER.debug(f"Copying node: {node}")

        for lens_type, lens_name in lens_dict:
            LOGGER.debug(f"Getting lens for: {lens_type} {lens_name}")
            lens_id = lens_name + lens_type
            lens: LensView = lenses.get(lens_name) or LensView.get_or_create(
                mg_client, lens_name, lens_type)
            lenses[lens_id] = lens

            # Attach to scope
            create_edge(mg_client, lens.uid, "scope", node.uid)

            # If a node shows up in a lens all of its connected nodes should also show up in that lens
            for edge_list in edges.values():
                for edge in edge_list:
                    from_uid = uid_map[edge["from"]]
                    to_uid = uid_map[edge["to"]]
                    create_edge(mg_client, lens.uid, "scope", from_uid)
                    create_edge(mg_client, lens.uid, "scope", to_uid)

    risk = upsert(
        mg_client,
        "Risk",
        RiskView,
        analyzer_name,
        {
            "analyzer_name": analyzer_name,
            "risk_score": risk_score,
        },
    )

    risky_nodes = nodes_to_attach_risk_to(nodes, risky_node_keys)
    for node in risky_nodes:
        create_edge(mg_client, node.uid, "risks", risk.uid)
        create_edge(mg_client, risk.uid, "risky_nodes", node.uid)

    for edge_list in edges.values():
        for edge in edge_list:
            from_uid = uid_map[edge["from"]]
            edge_name = edge["edge_name"]
            to_uid = uid_map[edge["to"]]

            create_edge(mg_client, from_uid, edge_name, to_uid)

    for lens in lenses.values():
        recalculate_score(lens)