11"""
22Audit logging configuration for DefectDojo.
33
4- This module handles conditional registration of models with either django-auditlog
5- or django-pghistory based on the DD_AUDITLOG_TYPE setting .
4+ This module handles registration of models with django-pghistory.
5+ django-auditlog support has been removed .
66"""
7- import contextlib
87import logging
8+ import os
99import sys
1010
1111import pghistory
@@ -80,13 +80,6 @@ def _flush_models_in_batches(models_to_flush, timestamp_field: str, retention_pe
8080 return total_deleted , total_batches , reached_any_limit
8181
8282
83- def _flush_django_auditlog (retention_period : int , batch_size : int , max_batches : int , * , dry_run : bool = False ) -> tuple [int , int , bool ]:
84- # Import inside to avoid model import issues at startup
85- from auditlog .models import LogEntry # noqa: PLC0415
86-
87- return _flush_models_in_batches ([LogEntry ], "timestamp" , retention_period , batch_size , max_batches , dry_run = dry_run )
88-
89-
9083def _iter_pghistory_event_models ():
9184 """Yield pghistory Event models registered under the dojo app."""
9285 for model in apps .get_app_config ("dojo" ).get_models ():
@@ -107,8 +100,7 @@ def run_flush_auditlog(retention_period: int | None = None,
107100 * ,
108101 dry_run : bool = False ) -> tuple [int , int , bool ]:
109102 """
110- Deletes audit entries older than the configured retention from both
111- django-auditlog and django-pghistory log entries.
103+ Deletes audit entries older than the configured retention from django-pghistory log entries.
112104
113105 Returns a tuple of (deleted_total, batches_done, reached_limit).
114106 """
@@ -121,93 +113,13 @@ def run_flush_auditlog(retention_period: int | None = None,
121113 max_batches = max_batches if max_batches is not None else getattr (settings , "AUDITLOG_FLUSH_MAX_BATCHES" , 100 )
122114
123115 phase = "DRY RUN" if dry_run else "Cleanup"
124- logger .info ("Running %s for django-auditlog entries with %d Months retention across all backends" , phase , retention_period )
125- d_deleted , d_batches , d_limit = _flush_django_auditlog (retention_period , batch_size , max_batches , dry_run = dry_run )
126116 logger .info ("Running %s for django-pghistory entries with %d Months retention across all backends" , phase , retention_period )
127117 p_deleted , p_batches , p_limit = _flush_pghistory_events (retention_period , batch_size , max_batches , dry_run = dry_run )
128118
129- total_deleted = d_deleted + p_deleted
130- total_batches = d_batches + p_batches
131- reached_limit = bool (d_limit or p_limit )
132-
133119 verb = "would delete" if dry_run else "deleted"
134- logger .info ("Audit flush summary: django-auditlog %s=%s batches=%s; pghistory %s=%s batches=%s; total_%s=%s total_batches=%s" ,
135- verb , d_deleted , d_batches , verb , p_deleted , p_batches , verb .replace (" " , "_" ), total_deleted , total_batches )
136-
137- return total_deleted , total_batches , reached_limit
138-
139-
140- def enable_django_auditlog ():
141- """Enable django-auditlog by registering models."""
142- # Import inside function to avoid AppRegistryNotReady errors
143- from auditlog .registry import auditlog # noqa: PLC0415
144-
145- from dojo .models import ( # noqa: PLC0415
146- Cred_User ,
147- Dojo_User ,
148- Endpoint ,
149- Engagement ,
150- Finding ,
151- Finding_Group ,
152- Finding_Template ,
153- Notification_Webhooks ,
154- Product ,
155- Product_Type ,
156- Risk_Acceptance ,
157- Test ,
158- )
159-
160- logger .info ("Enabling django-auditlog: Registering models" )
161- auditlog .register (Dojo_User , exclude_fields = ["password" ])
162- auditlog .register (Endpoint )
163- auditlog .register (Engagement )
164- auditlog .register (Finding , m2m_fields = {"reviewers" })
165- auditlog .register (Finding_Group )
166- auditlog .register (Product_Type )
167- auditlog .register (Product )
168- auditlog .register (Test )
169- auditlog .register (Risk_Acceptance )
170- auditlog .register (Finding_Template )
171- auditlog .register (Cred_User , exclude_fields = ["password" ])
172- auditlog .register (Notification_Webhooks , exclude_fields = ["header_name" , "header_value" ])
173- logger .info ("Successfully enabled django-auditlog" )
174-
175-
176- def disable_django_auditlog ():
177- """Disable django-auditlog by unregistering models."""
178- # Import inside function to avoid AppRegistryNotReady errors
179- from auditlog .registry import auditlog # noqa: PLC0415
180-
181- from dojo .models import ( # noqa: PLC0415
182- Cred_User ,
183- Dojo_User ,
184- Endpoint ,
185- Engagement ,
186- Finding ,
187- Finding_Group ,
188- Finding_Template ,
189- Notification_Webhooks ,
190- Product ,
191- Product_Type ,
192- Risk_Acceptance ,
193- Test ,
194- )
120+ logger .info ("Audit flush summary: pghistory %s=%s batches=%s" , verb , p_deleted , p_batches )
195121
196- # Only log during actual application startup, not during shell commands
197- if "shell" not in sys .argv :
198- logger .info ("Django-auditlog disabled - unregistering models" )
199-
200- # Unregister all models from auditlog
201- models_to_unregister = [
202- Dojo_User , Endpoint , Engagement , Finding , Finding_Group ,
203- Product_Type , Product , Test , Risk_Acceptance , Finding_Template ,
204- Cred_User , Notification_Webhooks ,
205- ]
206-
207- for model in models_to_unregister :
208- with contextlib .suppress (Exception ):
209- # Model might not be registered, ignore the error
210- auditlog .unregister (model )
122+ return p_deleted , p_batches , bool (p_limit )
211123
212124
213125def register_django_pghistory_models ():
@@ -308,6 +220,26 @@ def register_django_pghistory_models():
308220 },
309221 )(Finding )
310222
223+ # # Track the reviewers ManyToMany relationship through table
224+ # # This tracks additions/removals of reviewers from findings
225+ # reviewers_through = Finding._meta.get_field("reviewers").remote_field.through
226+ # if reviewers_through:
227+ # logger.info(f"Tracking reviewers M2M through table: {reviewers_through} (db_table: {reviewers_through._meta.db_table})")
228+ # pghistory.track(
229+ # pghistory.InsertEvent(),
230+ # pghistory.DeleteEvent(),
231+ # meta={
232+ # "indexes": [
233+ # models.Index(fields=["pgh_created_at"]),
234+ # models.Index(fields=["pgh_label"]),
235+ # models.Index(fields=["pgh_context_id"]),
236+ # ],
237+ # },
238+ # )(reviewers_through)
239+ # logger.info("Successfully registered pghistory tracking for reviewers through table")
240+ # else:
241+ # logger.warning("Could not find reviewers through table for Finding model!")
242+
311243 pghistory .track (
312244 pghistory .InsertEvent (),
313245 pghistory .UpdateEvent (condition = pghistory .AnyChange (exclude_auto = True )),
@@ -427,30 +359,6 @@ def register_django_pghistory_models():
427359 logger .info ("Successfully registered models with django-pghistory" )
428360
429361
430- def enable_django_pghistory ():
431- """Enable django-pghistory by enabling triggers."""
432- logger .info ("Enabling django-pghistory: Enabling triggers" )
433-
434- # Enable pghistory triggers
435- try :
436- call_command ("pgtrigger" , "enable" )
437- logger .info ("Successfully enabled pghistory triggers" )
438- except Exception as e :
439- logger .warning (f"Failed to enable pgtrigger triggers: { e } " )
440- # Don't raise the exception as this shouldn't prevent Django from starting
441-
442-
443- def disable_django_pghistory ():
444- """Disable django-pghistory by disabling triggers."""
445- logger .info ("Disabling django-pghistory: Disabling triggers" )
446- try :
447- call_command ("pgtrigger" , "disable" )
448- logger .info ("Successfully disabled pghistory triggers" )
449- except Exception as e :
450- logger .warning (f"Failed to disable pgtrigger triggers: { e } " )
451- # Don't raise the exception as this shouldn't prevent Django from starting
452-
453-
454362def configure_pghistory_triggers ():
455363 """
456364 Configure pghistory triggers based on audit settings.
@@ -466,44 +374,52 @@ def configure_pghistory_triggers():
466374 except Exception as e :
467375 logger .error (f"Failed to disable pghistory triggers: { e } " )
468376 raise
469- elif settings .AUDITLOG_TYPE == "django-pghistory" :
377+ else :
378+ # Only pghistory is supported now
470379 try :
471380 call_command ("pgtrigger" , "enable" )
472381 logger .info ("Successfully enabled pghistory triggers" )
473382 except Exception as e :
474383 logger .error (f"Failed to enable pghistory triggers: { e } " )
475384 raise
476- else :
477- try :
478- call_command ("pgtrigger" , "disable" )
479- logger .info ("Successfully disabled pghistory triggers" )
480- except Exception as e :
481- logger .error (f"Failed to disable pghistory triggers: { e } " )
482- raise
483385
484386
485387def configure_audit_system ():
486388 """
487389 Configure the audit system based on settings.
488390
489- Note: This function only handles auditlog registration. pghistory model registration
490- is handled in apps.py, and trigger management should be done via the
491- configure_pghistory_triggers() function to avoid database access during initialization.
391+ django-auditlog is no longer supported. Only django-pghistory is allowed.
492392 """
493393 # Only log during actual application startup, not during shell commands
494394 log_enabled = "shell" not in sys .argv
495395
396+ # Fail if DD_AUDITLOG_TYPE is still configured (removed setting)
397+ auditlog_type_env = os .environ .get ("DD_AUDITLOG_TYPE" )
398+ if auditlog_type_env :
399+ error_msg = (
400+ "DD_AUDITLOG_TYPE environment variable is no longer supported. "
401+ "DefectDojo now exclusively uses django-pghistory for audit logging. "
402+ "Please remove DD_AUDITLOG_TYPE from your environment configuration. "
403+ "All new audit entries will be created using django-pghistory automatically."
404+ )
405+ logger .error (error_msg )
406+ raise ValueError (error_msg )
407+
408+ # Fail if AUDITLOG_TYPE is manually set in settings files (removed setting)
409+ if hasattr (settings , "AUDITLOG_TYPE" ):
410+ error_msg = (
411+ "AUDITLOG_TYPE setting is no longer supported. "
412+ "DefectDojo now exclusively uses django-pghistory for audit logging. "
413+ "Please remove AUDITLOG_TYPE from your settings file (settings.dist.py or local_settings.py). "
414+ "All new audit entries will be created using django-pghistory automatically."
415+ )
416+ logger .error (error_msg )
417+ raise ValueError (error_msg )
418+
496419 if not settings .ENABLE_AUDITLOG :
497420 if log_enabled :
498421 logger .info ("Audit logging disabled" )
499- disable_django_auditlog ()
500422 return
501423
502- if settings .AUDITLOG_TYPE == "django-auditlog" :
503- if log_enabled :
504- logger .info ("Configuring audit system: django-auditlog enabled" )
505- enable_django_auditlog ()
506- else :
507- if log_enabled :
508- logger .info ("django-auditlog disabled (pghistory or other audit type selected)" )
509- disable_django_auditlog ()
424+ if log_enabled :
425+ logger .info ("Audit logging configured: django-pghistory" )
0 commit comments