import demistomock as demisto # noqa: F401 from CommonServerPython import * # noqa: F401 from typing import Any FINAL_VERDICT_VENDOR = "XSOAR" def reliability_level(reliability: str | None) -> int: if reliability is None: return -1 return { DBotScoreReliability.A_PLUS: 6, DBotScoreReliability.A: 5, DBotScoreReliability.B: 4, DBotScoreReliability.C: 3, DBotScoreReliability.D: 2, DBotScoreReliability.E: 1, DBotScoreReliability.F: 0, }.get(reliability, -1) def is_source_reliable(final: dict[str, Any] | None, source: dict[str, Any]) -> bool: if source.get("Vendor") == "Manual": return True source_reliability = reliability_level(source.get("Reliability")) if source_reliability < 0: return False if final is None: return True final_reliability = reliability_level(final.get("Reliability")) if source_reliability > final_reliability: return True elif source_reliability == final_reliability: source_score = source.get("Score") or 0 final_score = final.get("Score") or 0 if source_score > final_score: return True return False def get_final_verdict(sources: list[dict[str, Any]], indicator_value: str) -> dict[str, Any] | None: """Get the DBotScore of the final verdict of an indicator from list of source DBotScores Vendor = Manual: - The most reliable DBotScore If DBotScore by Manual is not found: - The most reliable DBotScore is decided by 'Reliability' If some different DBotScores having the same Reliability are found: - The DBotScores having the highest risk are applied for the final verdict. (Malicious > Suspicious > Benign > Unknown) If there are some different DBotScores filtered by the highest risk: - The DBotScore found at first is applied for the final verdict. :param sources: The list of source DBotScore :param indicator_value: The indicator value :return: The DBotScore of the final verdict. """ final = None for source in sources: source_indicator = source.get("Indicator") if source_indicator == indicator_value and is_source_reliable(final, source): final = assign_params( Indicator=source_indicator, Type=source.get("Type"), Score=source.get("Score") or 0, Reliability=source.get("Reliability"), Vendor=FINAL_VERDICT_VENDOR, ) return final def main(): try: args = demisto.args() indicator_value = args.get("indicator_value") final_dbot_store = None if source_dbot_scores := demisto.dt(demisto.context(), "DBotScore(val.Indicator && val.Score)"): source_dbot_scores = source_dbot_scores if isinstance(source_dbot_scores, list) else [source_dbot_scores] final_dbot_store = get_final_verdict(source_dbot_scores, indicator_value) if final_dbot_store: return_results( CommandResults( outputs_prefix="FinalDBotScore", outputs_key_field="Indicator", outputs=final_dbot_store, readable_output=tblToMd("Final Verdict", final_dbot_store), raw_response=final_dbot_store, ) ) else: return_results(f"No DBotScore found for {indicator_value}") except Exception as err: return_error(f"Failed to execute GetIndicatorDBotScoreFromContext script. Error: {str(err)}") if __name__ in ("__builtin__", "builtins", "__main__"): main()