def get_actions() -> t.List[Action]: """ TODO implement Returns the Action objects stored in the config repository. Each Action will have the following attributes: ActionLabel, Priority, SupersededByActionLabel (Priority and SupersededByActionLabel are used by remove_superseded_actions). """ return [ Action( ActionLabel("EnqueueForReview"), 1, [ActionLabel("A_MORE_IMPORTANT_ACTION")], ) ]
def get_example_action_event(): enqueue_mini_castle_for_review_action_label = ActionLabel( TestContentModels.TEST_ACTION_LABEL) action_rules = [ ActionRule( name="Enqueue Mini-Castle for Review", action_label=enqueue_mini_castle_for_review_action_label, must_have_labels=set([ ClassificationLabel("true_positive"), ]), must_not_have_labels=set(), ), ] banked_signal = BankedSignal( banked_content_id="4169895076385542", bank_id="303636684709969", bank_source="te", ) banked_signal.add_classification("true_positive") action_performer = WebhookPostActionPerformer( name="EnqueueForReview", url="https://webhook.site/ff7ebc37-514a-439e-9a03-46f86989e195", headers='{"Connection":"keep-alive"}', # monitoring page: # https://webhook.site/#!/ff7ebc37-514a-439e-9a03-46f86989e195 ) action_message = ActionMessage( content_key=TestContentModels.TEST_CONTENT_ID, content_hash= "361da9e6cf1b72f5cea0344e5bb6e70939f4c70328ace762529cac704297354a", matching_banked_signals=[banked_signal], action_label=enqueue_mini_castle_for_review_action_label, action_rules=action_rules, ) return ActionEvent( content_id=action_message.content_key, performed_at=TestContentModels.TEST_TIME, action_label=action_message.action_label.value, action_performer=action_performer.to_aws_json(), action_rules=[ rule.to_aws_json() for rule in action_message.action_rules ], ) # .write_to_table(table)
class ActionMessage(MatchMessage): """ The action performer needs the match message plus which action to perform """ action_label: ActionLabel = ActionLabel("UnspecifiedAction") action_rules: t.List[ActionRule] = field(default_factory=list) @classmethod def from_match_message_action_label_and_action_rules( cls, match_message: MatchMessage, action_label: ActionLabel, action_rules: t.List[ActionRule], ) -> "ActionMessage": return cls( match_message.content_key, match_message.content_hash, match_message.matching_banked_signals, action_label, action_rules, )
def test_action_message_serialization_and_deserialization(self): enqueue_mini_castle_for_review_action_label = ActionLabel( "EnqueueMiniCastleForReview") action_rules = [ ActionRule( name="Enqueue Mini-Castle for Review", action_label=enqueue_mini_castle_for_review_action_label, must_have_labels=set([ BankIDClassificationLabel("303636684709969"), ClassificationLabel("true_positive"), ]), must_not_have_labels=set( [BankedContentIDClassificationLabel("3364504410306721")]), ), ] banked_signal = BankedSignal( banked_content_id="4169895076385542", bank_id="303636684709969", bank_source="te", ) banked_signal.add_classification("true_positive") action_message = ActionMessage( content_key="images/mini-castle.jpg", content_hash= "361da9e6cf1b72f5cea0344e5bb6e70939f4c70328ace762529cac704297354a", matching_banked_signals=[banked_signal], action_label=enqueue_mini_castle_for_review_action_label, action_rules=action_rules, ) action_message_aws_json = action_message.to_aws_json() action_message_2 = ActionMessage.from_aws_json(action_message_aws_json) self.assertEqual(action_message_2.action_label, enqueue_mini_castle_for_review_action_label)
def test_get_action_labels(self): enqueue_for_review_action_label = ActionLabel("EnqueueForReview") bank_id = "12345" banked_signal_without_foo = BankedSignal("67890", bank_id, "Test") banked_signal_without_foo.add_classification("Bar") banked_signal_without_foo.add_classification("Xyz") banked_signal_with_foo = BankedSignal("67890", bank_id, "Test") banked_signal_with_foo.add_classification("Foo") banked_signal_with_foo.add_classification("Bar") banked_signal_with_foo.add_classification("Xyz") match_message_without_foo = MatchMessage( "key", "hash", [banked_signal_without_foo] ) match_message_with_foo = MatchMessage("key", "hash", [banked_signal_with_foo]) action_rules = [ ActionRule( enqueue_for_review_action_label.value, enqueue_for_review_action_label, set([BankIDClassificationLabel(bank_id)]), set([ClassificationLabel("Foo")]), ) ] action_label_to_action_rules: t.Dict[ ActionLabel, t.List[ActionRule] ] = get_actions_to_take(match_message_without_foo, action_rules) assert len(action_label_to_action_rules) == 1 self.assertIn( enqueue_for_review_action_label, action_label_to_action_rules, "enqueue_for_review_action_label should be in action_label_to_action_rules", ) action_label_to_action_rules = get_actions_to_take( match_message_with_foo, action_rules ) assert len(action_label_to_action_rules) == 0 enqueue_mini_castle_for_review_action_label = ActionLabel( "EnqueueMiniCastleForReview" ) enqueue_sailboat_for_review_action_label = ActionLabel( "EnqueueSailboatForReview" ) action_rules = [ ActionRule( name="Enqueue Mini-Castle for Review", action_label=enqueue_mini_castle_for_review_action_label, must_have_labels=set( [ BankIDClassificationLabel("303636684709969"), ClassificationLabel("true_positive"), ] ), must_not_have_labels=set( [BankedContentIDClassificationLabel("3364504410306721")] ), ), ActionRule( name="Enqueue Sailboat for Review", action_label=enqueue_sailboat_for_review_action_label, must_have_labels=set( [ BankIDClassificationLabel("303636684709969"), ClassificationLabel("true_positive"), BankedContentIDClassificationLabel("3364504410306721"), ] ), must_not_have_labels=set(), ), ] mini_castle_banked_signal = BankedSignal( banked_content_id="4169895076385542", bank_id="303636684709969", bank_source="te", ) mini_castle_banked_signal.add_classification("true_positive") mini_castle_match_message = MatchMessage( content_key="images/mini-castle.jpg", content_hash="361da9e6cf1b72f5cea0344e5bb6e70939f4c70328ace762529cac704297354a", matching_banked_signals=[mini_castle_banked_signal], ) sailboat_banked_signal = BankedSignal( banked_content_id="3364504410306721", bank_id="303636684709969", bank_source="te", ) sailboat_banked_signal.add_classification("true_positive") sailboat_match_message = MatchMessage( content_key="images/sailboat-mast-and-sun.jpg", content_hash="388ff5e1084efef10096df9cb969296dff2b04d67a94065ecd292129ef6b1090", matching_banked_signals=[sailboat_banked_signal], ) action_label_to_action_rules = get_actions_to_take( mini_castle_match_message, action_rules ) assert len(action_label_to_action_rules) == 1 self.assertIn( enqueue_mini_castle_for_review_action_label, action_label_to_action_rules, "enqueue_mini_castle_for_review_action_label should be in action_label_to_action_rules", ) action_label_to_action_rules = get_actions_to_take( sailboat_match_message, action_rules ) assert len(action_label_to_action_rules) == 1 self.assertIn( enqueue_sailboat_for_review_action_label, action_label_to_action_rules, "enqueue_sailboat_for_review_action_label should be in action_label_to_action_rules", )
) -> t.List[Label]: """ TODO implement Evaluates a collection of action_labels against some yet to be defined configuration (and possible business login) to produce """ return [ThreatExchangeReactionLabel("SAW_THIS_TOO")] if __name__ == "__main__": # For basic debugging action_rules = [ ActionRule( name="Enqueue Mini-Castle for Review", action_label=ActionLabel("EnqueueMiniCastleForReview"), must_have_labels=set([ BankIDClassificationLabel("303636684709969"), ClassificationLabel("true_positive"), ]), must_not_have_labels=set( [BankedContentIDClassificationLabel("3364504410306721")]), ), ] banked_signal = BankedSignal( "4169895076385542", "303636684709969", "te", ) banked_signal.add_classification("true_positive")
return {"action_performed": "true"} if __name__ == "__main__": lambda_init_once() banked_signals = [ BankedSignal("2862392437204724", "bank 4", "te"), BankedSignal("4194946153908639", "bank 4", "te"), ] match_message = MatchMessage("key", "hash", banked_signals) configs: t.List[ActionPerformer] = [ WebhookPostActionPerformer( # type: ignore "EnqueueForReview", "https://webhook.site/ff7ebc37-514a-439e-9a03-46f86989e195", ), ] for performer_config in configs: config.create_config(performer_config) action_message = ActionMessage( "key", "hash", matching_banked_signals=banked_signals, action_label=ActionLabel("EnqueForReview"), ) event = {"Records": [{"body": action_message.to_aws()}]} lambda_handler(event, None)
def load_defaults(_args): """ Load a hardcoded set of defaults which are useful in testing """ # Could also put the default on the class, but seems too fancy configs = [ ThreatExchangeConfig( name="303636684709969", fetcher_active=True, privacy_group_name="Test Config 1", write_back=True, in_use=True, description="test description", matcher_active=True, ), ThreatExchangeConfig( name="258601789084078", fetcher_active=True, privacy_group_name="Test Config 2", write_back=True, in_use=True, description="test description", matcher_active=True, ), WebhookPostActionPerformer( name="EnqueueForReview", url="https://webhook.site/ff7ebc37-514a-439e-9a03-46f86989e195", headers='{"Connection":"keep-alive"}', # monitoring page: # https://webhook.site/#!/ff7ebc37-514a-439e-9a03-46f86989e195 ), WebhookPostActionPerformer( name="EnqueueMiniCastleForReview", url="https://webhook.site/01cef721-bdcc-4681-8430-679c75659867", headers='{"Connection":"keep-alive"}', # monitoring page: # https://webhook.site/#!/01cef721-bdcc-4681-8430-679c75659867 ), WebhookPostActionPerformer( name="EnqueueSailboatForReview", url="https://webhook.site/fa5c5ad5-f5cc-4692-bf03-a03a4ae3f714", headers='{"Connection":"keep-alive"}', # monitoring page: # https://webhook.site/#!/fa5c5ad5-f5cc-4692-bf03-a03a4ae3f714 ), ActionRule( name="Enqueue Mini-Castle for Review", action_label=ActionLabel("EnqueueMiniCastleForReview"), must_have_labels=set([ BankIDClassificationLabel("303636684709969"), ClassificationLabel("true_positive"), ]), must_not_have_labels=set( [BankedContentIDClassificationLabel("3364504410306721")]), ), ActionRule( name="Enqueue Sailboat for Review", action_label=ActionLabel("EnqueueSailboatForReview"), must_have_labels=set([ BankIDClassificationLabel("303636684709969"), ClassificationLabel("true_positive"), BankedContentIDClassificationLabel("3364504410306721"), ]), must_not_have_labels=set(), ), ] for config in configs: # Someday maybe can do filtering or something, I dunno # Add try catch block to avoid test failure try: hmaconfig.create_config(config) except ClientError as e: if e.response["Error"][ "Code"] == "ConditionalCheckFailedException": print( "Can't insert duplicated config, " + e.response["Error"]["Message"], ) else: raise print(config)