Exemple #1
0
    def test_remove_opinion(self):
        os.environ["MOCK_TE_API"] = "True"
        os.environ["CONFIG_TABLE_NAME"] = "test-HMAConfig"

        writeback = WritebackTypes.RemoveOpinion
        writeback_message = WritebackMessage.from_match_message_and_type(
            self.match_message, writeback
        )
        event = {"Records": [{"body": writeback_message.to_aws_json()}]}

        result = lambda_handler(event, None)
        assert result == {
            "writebacks_performed": {
                "te": [
                    "\n".join(
                        (
                            "Deleted decriptor a1|2862392437204724 for indicator 2862392437204724",
                            "Removed reaction DISAGREE_WITH_TAGS from descriptor a2|2862392437204724",
                            "Removed reaction DISAGREE_WITH_TAGS from descriptor a3|2862392437204724",
                        )
                    ),
                    "\n".join(
                        (
                            "Deleted decriptor a1|4194946153908639 for indicator 4194946153908639",
                            "Removed reaction DISAGREE_WITH_TAGS from descriptor a2|4194946153908639",
                            "Removed reaction DISAGREE_WITH_TAGS from descriptor a3|4194946153908639",
                        )
                    ),
                    "No writeback performed for banked content id 3027465034605137 becuase writebacks were disabled",
                ]
            }
        }

        os.environ["MOCK_TE_API"] = "False"
Exemple #2
0
def lambda_handler(event, context):
    """
    This is the main entry point for writing back to ThreatExchange. The action evaluator
    sends a writeback message by way of the writebacks queue and here's where they're
    popped off and dealt with.
    """
    HMAConfig.initialize(os.environ["CONFIG_TABLE_NAME"])

    writebacks_performed = {}
    for sqs_record in event["Records"]:
        # TODO research max # sqs records / lambda_handler invocation
        writeback_message = WritebackMessage.from_aws_json(sqs_record["body"])
        logger.info("Writing Back: %s", writeback_message)

        # get all sources that are related to this writeback
        sources = {
            banked_signal.bank_source
            for banked_signal in writeback_message.banked_signals
        }
        source_writebackers = [
            Writebacker.get_writebacker_for_source(source)
            for source in sources
            if Writebacker.get_writebacker_for_source(source)
        ]
        for writebacker in source_writebackers:
            result = writebacker.perform_writeback(writeback_message)
            logger.info("Writeback result: %s", result)
            writebacks_performed[writebacker.source] = result

    return {"writebacks_performed": writebacks_performed}
def lambda_handler(event, context):
    """
    This lambda is called when one or more matches are found. If a single hash matches
    multiple datasets, this will be called only once.

    Action labels are generated for each match message, then an action is performed
    corresponding to each action label.
    """
    config = ActionEvaluatorConfig.get()

    for sqs_record in event["Records"]:
        # TODO research max # sqs records / lambda_handler invocation
        sqs_record_body = json.loads(sqs_record["body"])
        logger.info("sqs record body %s", sqs_record["body"])
        match_message = MatchMessage.from_aws_json(sqs_record_body["Message"])

        logger.info("Evaluating match_message: %s", match_message)

        action_rules = get_action_rules()

        logger.info("Evaluating against action_rules: %s", action_rules)

        action_label_to_action_rules = get_actions_to_take(
            match_message, action_rules)
        action_labels = list(action_label_to_action_rules.keys())
        for action_label in action_labels:
            action_message = (
                ActionMessage.from_match_message_action_label_and_action_rules(
                    match_message,
                    action_label,
                    action_label_to_action_rules[action_label],
                ))

            logger.info("Sending Action message: %s", action_message)
            config.sqs_client.send_message(
                QueueUrl=config.actions_queue_url,
                MessageBody=action_message.to_aws_json(),
            )

        writeback_message = WritebackMessage.from_match_message_and_type(
            match_message, WritebackTypes.SawThisToo)
        writeback_message.send_to_queue()

    return {"evaluation_completed": "true"}
Exemple #4
0
    def test_true_positve(self):
        os.environ["MOCK_TE_API"] = "True"
        os.environ["CONFIG_TABLE_NAME"] = "test-HMAConfig"

        writeback = WritebackTypes.TruePositive
        writeback_message = WritebackMessage.from_match_message_and_type(
            self.match_message, writeback
        )
        event = {"Records": [{"body": writeback_message.to_aws_json()}]}

        result = lambda_handler(event, None)
        assert result == {
            "writebacks_performed": {
                "te": [
                    "Wrote back TruePositive for indicator 2862392437204724\nBuilt descriptor a1|2862392437204724 with privacy groups pg 4",
                    "Wrote back TruePositive for indicator 4194946153908639\nBuilt descriptor a1|4194946153908639 with privacy groups pg 4",
                    "No writeback performed for banked content id 3027465034605137 becuase writebacks were disabled",
                ]
            }
        }

        os.environ["MOCK_TE_API"] = "False"
Exemple #5
0
    def test_false_positive(self):
        os.environ["MOCK_TE_API"] = "True"
        os.environ["CONFIG_TABLE_NAME"] = "test-HMAConfig"

        writeback = WritebackTypes.FalsePositive
        writeback_message = WritebackMessage.from_match_message_and_type(
            self.match_message, writeback
        )
        event = {"Records": [{"body": writeback_message.to_aws_json()}]}

        result = lambda_handler(event, None)
        assert result == {
            "writebacks_performed": {
                "te": [
                    "Reacted DISAGREE_WITH_TAGS to descriptor a2|2862392437204724\nReacted DISAGREE_WITH_TAGS to descriptor a3|2862392437204724",
                    "Reacted DISAGREE_WITH_TAGS to descriptor a2|4194946153908639\nReacted DISAGREE_WITH_TAGS to descriptor a3|4194946153908639",
                    "No writeback performed for banked content id 3027465034605137 becuase writebacks were disabled",
                ]
            }
        }

        os.environ["MOCK_TE_API"] = "False"
    def request_signal_opinion_change() -> ChangeSignalOpinionResponse:
        """
        request a change to the opinion for a signal in a dataset
        """
        signal_id = bottle.request.query.signal_q or None
        signal_source = bottle.request.query.signal_source or None
        ds_id = bottle.request.query.dataset_q or None
        opinion_change = bottle.request.query.opinion_change or None

        if not signal_id or not signal_source or not ds_id or not opinion_change:
            return ChangeSignalOpinionResponse(False)

        signal_id = str(signal_id)
        pending_opinion_change = PendingOpinionChange(opinion_change)

        writeback_message = WritebackMessage.from_banked_signal_and_opinion_change(
            BankedSignal(signal_id, ds_id, signal_source),
            pending_opinion_change)
        writeback_message.send_to_queue()
        logger.info(
            f"Opinion change enqueued for {signal_source}:{signal_id} in {ds_id} change={opinion_change}"
        )

        signal = PDQSignalMetadata(
            signal_id=signal_id,
            ds_id=ds_id,
            updated_at=datetime.datetime.now(),
            signal_source=signal_source,
            signal_hash="",  # SignalHash not needed for update
            tags=[],  # Tags not needed for update
            pending_opinion_change=pending_opinion_change,
        )
        success = signal.update_pending_opinion_change_in_table_if_exists(
            dynamodb_table)
        if not success:
            logger.info(f"Attempting to update {signal} in db failed")

        return ChangeSignalOpinionResponse(success)
Exemple #7
0
        sources = {
            banked_signal.bank_source
            for banked_signal in writeback_message.banked_signals
        }
        source_writebackers = [
            Writebacker.get_writebacker_for_source(source)
            for source in sources
            if Writebacker.get_writebacker_for_source(source)
        ]
        for writebacker in source_writebackers:
            result = writebacker.perform_writeback(writeback_message)
            logger.info("Writeback result: %s", result)
            writebacks_performed[writebacker.source] = result

    return {"writebacks_performed": writebacks_performed}


if __name__ == "__main__":
    # For basic debugging
    # This will react to real descriptors if WRITEBACK_LOCAL is on
    if os.environ.get("WRITEBACK_LOCAL"):
        writeback_message = WritebackMessage(
            [
                BankedSignal("2915547128556957", "303636684709969", "te"),
            ],
            WritebackTypes.RemoveOpinion,
        )
        event = {"Records": [{"body": writeback_message.to_aws_json()}]}
        result = lambda_handler(event, None)
        print(result)