11import logging
22
33from django .apps import AppConfig
4+ from django .conf import settings
45from django .core .checks import register as register_check
56from django .db import models
67from watson import search as watson
@@ -21,54 +22,11 @@ def ready(self):
2122 # commented out ^ as it prints in manage.py dumpdata, docker logs and many other places
2223 # logger doesn't work yet at this stage
2324
24- # Watson doesn't have a way to let it index extra fields, so we have to explicitly list all the fields
25- # to make it easier, we get the charfields/textfields from the model and then add our extra fields.
26- # charfields/textfields are the fields that watson indexes by default (but we have to repeat here if we add extra fields)
27- # and watson likes to have tuples instead of lists
28-
29- watson .register (self .get_model ("Product" ), fields = get_model_fields_with_extra (self .get_model ("Product" ), ("id" , "prod_type__name" )), store = ("prod_type__name" , ))
30-
31- watson .register (self .get_model ("Test" ), fields = get_model_fields_with_extra (self .get_model ("Test" ), ("id" , "engagement__product__name" )), store = ("engagement__product__name" , )) # test_type__name?
32-
33- watson .register (self .get_model ("Finding" ), fields = get_model_fields_with_extra (self .get_model ("Finding" ), ("id" , "url" , "unique_id_from_tool" , "test__engagement__product__name" , "jira_issue__jira_key" )),
34- store = ("status" , "jira_issue__jira_key" , "test__engagement__product__name" , "severity" , "severity_display" , "latest_note" ))
35-
36- # some thoughts on Finding fields that are not indexed yet:
37- # CWE can't be indexed as it is an integer
38-
39- # would endpoints be good to index? or would it clutter search results?
40- # endpoints = models.ManyToManyField(Endpoint, blank=True)
41- # endpoint_status = models.ManyToManyField(Endpoint_Status, blank=True, related_name='finding_endpoint_status')
42-
43- # index test name/title?
44- # test = models.ForeignKey(Test, editable=False, on_delete=models.CASCADE)
45-
46- # index reporter name?
47- # reporter = models.ForeignKey(User, editable=False, default=1, related_name='reporter', on_delete=models.CASCADE)
48- # index notes?
49- # notes = models.ManyToManyField(Notes, blank=True, editable=False)
50-
51- # index found_by?
52- # found_by = models.ManyToManyField(Test_Type, editable=False)
53-
54- # exclude these to avoid cluttering?
55- # sast_source_object = models.CharField(null=True, blank=True, max_length=500, help_text="Source object (variable, function...) of the attack vector")
56- # sast_sink_object = models.CharField(null=True, blank=True, max_length=500, help_text="Sink object (variable, function...) of the attack vector")
57- # sast_source_line = models.IntegerField(null=True, blank=True,
58- # verbose_name="Line number",
59- # help_text="Source line number of the attack vector")
60- # sast_source_file_path = models.CharField(null=True, blank=True, max_length=4000, help_text="Source filepath of the attack vector")
61-
62- watson .register (self .get_model ("Finding_Template" ))
63- # TODO: Delete this after the move to Locations
64- watson .register (self .get_model ("Endpoint" ), store = ("product__name" , )) # add product name also?
65- watson .register (self .get_model ("Location" ))
66- watson .register (self .get_model ("Engagement" ), fields = get_model_fields_with_extra (self .get_model ("Engagement" ), ("id" , "product__name" )), store = ("product__name" , ))
67- watson .register (self .get_model ("App_Analysis" ))
68- watson .register (self .get_model ("Vulnerability_Id" ), store = ("finding__test__engagement__product__name" , ))
69-
70- # YourModel = self.get_model("YourModel")
71- # watson.register(YourModel)
25+ # Registering watson attaches post-save/pre-delete search indexers to 9
26+ # models (Finding is on the import hot path); skip it entirely when watson
27+ # is disabled so imports don't pay the write-amplification cost.
28+ if settings .WATSON_SEARCH_ENABLED :
29+ register_watson_models (self )
7230
7331 register_check (check_configuration_deduplication , "dojo" )
7432
@@ -110,6 +68,57 @@ def ready(self):
11068 install_intermediate_flush_hook ()
11169
11270
71+ def register_watson_models (app_config ):
72+ # Watson doesn't have a way to let it index extra fields, so we have to explicitly list all the fields
73+ # to make it easier, we get the charfields/textfields from the model and then add our extra fields.
74+ # charfields/textfields are the fields that watson indexes by default (but we have to repeat here if we add extra fields)
75+ # and watson likes to have tuples instead of lists
76+
77+ watson .register (app_config .get_model ("Product" ), fields = get_model_fields_with_extra (app_config .get_model ("Product" ), ("id" , "prod_type__name" )), store = ("prod_type__name" , ))
78+
79+ watson .register (app_config .get_model ("Test" ), fields = get_model_fields_with_extra (app_config .get_model ("Test" ), ("id" , "engagement__product__name" )), store = ("engagement__product__name" , )) # test_type__name?
80+
81+ watson .register (app_config .get_model ("Finding" ), fields = get_model_fields_with_extra (app_config .get_model ("Finding" ), ("id" , "url" , "unique_id_from_tool" , "test__engagement__product__name" , "jira_issue__jira_key" )),
82+ store = ("status" , "jira_issue__jira_key" , "test__engagement__product__name" , "severity" , "severity_display" , "latest_note" ))
83+
84+ # some thoughts on Finding fields that are not indexed yet:
85+ # CWE can't be indexed as it is an integer
86+
87+ # would endpoints be good to index? or would it clutter search results?
88+ # endpoints = models.ManyToManyField(Endpoint, blank=True)
89+ # endpoint_status = models.ManyToManyField(Endpoint_Status, blank=True, related_name='finding_endpoint_status')
90+
91+ # index test name/title?
92+ # test = models.ForeignKey(Test, editable=False, on_delete=models.CASCADE)
93+
94+ # index reporter name?
95+ # reporter = models.ForeignKey(User, editable=False, default=1, related_name='reporter', on_delete=models.CASCADE)
96+ # index notes?
97+ # notes = models.ManyToManyField(Notes, blank=True, editable=False)
98+
99+ # index found_by?
100+ # found_by = models.ManyToManyField(Test_Type, editable=False)
101+
102+ # exclude these to avoid cluttering?
103+ # sast_source_object = models.CharField(null=True, blank=True, max_length=500, help_text="Source object (variable, function...) of the attack vector")
104+ # sast_sink_object = models.CharField(null=True, blank=True, max_length=500, help_text="Sink object (variable, function...) of the attack vector")
105+ # sast_source_line = models.IntegerField(null=True, blank=True,
106+ # verbose_name="Line number",
107+ # help_text="Source line number of the attack vector")
108+ # sast_source_file_path = models.CharField(null=True, blank=True, max_length=4000, help_text="Source filepath of the attack vector")
109+
110+ watson .register (app_config .get_model ("Finding_Template" ))
111+ # TODO: Delete this after the move to Locations
112+ watson .register (app_config .get_model ("Endpoint" ), store = ("product__name" , )) # add product name also?
113+ watson .register (app_config .get_model ("Location" ))
114+ watson .register (app_config .get_model ("Engagement" ), fields = get_model_fields_with_extra (app_config .get_model ("Engagement" ), ("id" , "product__name" )), store = ("product__name" , ))
115+ watson .register (app_config .get_model ("App_Analysis" ))
116+ watson .register (app_config .get_model ("Vulnerability_Id" ), store = ("finding__test__engagement__product__name" , ))
117+
118+ # YourModel = app_config.get_model("YourModel")
119+ # watson.register(YourModel)
120+
121+
113122def get_model_fields_with_extra (model , extra_fields = ()):
114123 return get_model_fields (get_model_default_fields (model ), extra_fields )
115124
0 commit comments