aiwaf 0.1.9.1.9__tar.gz → 0.1.9.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of aiwaf might be problematic. Click here for more details.

Files changed (43) hide show
  1. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/PKG-INFO +126 -12
  2. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/README.md +125 -11
  3. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf/__init__.py +1 -1
  4. aiwaf-0.1.9.2.1/aiwaf/management/commands/aiwaf_reset.py +183 -0
  5. aiwaf-0.1.9.2.1/aiwaf/middleware.py +621 -0
  6. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf/storage.py +13 -0
  7. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf/trainer.py +184 -9
  8. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf.egg-info/PKG-INFO +126 -12
  9. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/pyproject.toml +1 -1
  10. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/setup.py +1 -1
  11. aiwaf-0.1.9.1.9/aiwaf/management/commands/aiwaf_reset.py +0 -136
  12. aiwaf-0.1.9.1.9/aiwaf/middleware.py +0 -352
  13. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/LICENSE +0 -0
  14. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf/apps.py +0 -0
  15. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf/blacklist_manager.py +0 -0
  16. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf/decorators.py +0 -0
  17. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf/management/__init__.py +0 -0
  18. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf/management/commands/__init__.py +0 -0
  19. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf/management/commands/add_exemption.py +0 -0
  20. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf/management/commands/add_ipexemption.py +0 -0
  21. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf/management/commands/aiwaf_diagnose.py +0 -0
  22. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf/management/commands/aiwaf_logging.py +0 -0
  23. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf/management/commands/check_dependencies.py +0 -0
  24. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf/management/commands/clear_blacklist.py +0 -0
  25. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf/management/commands/clear_cache.py +0 -0
  26. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf/management/commands/debug_csv.py +0 -0
  27. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf/management/commands/detect_and_train.py +0 -0
  28. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf/management/commands/diagnose_blocking.py +0 -0
  29. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf/management/commands/regenerate_model.py +0 -0
  30. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf/management/commands/setup_models.py +0 -0
  31. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf/management/commands/test_exemption.py +0 -0
  32. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf/management/commands/test_exemption_fix.py +0 -0
  33. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf/middleware_logger.py +0 -0
  34. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf/models.py +0 -0
  35. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf/resources/model.pkl +0 -0
  36. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf/templatetags/__init__.py +0 -0
  37. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf/templatetags/aiwaf_tags.py +0 -0
  38. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf/utils.py +0 -0
  39. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf.egg-info/SOURCES.txt +0 -0
  40. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf.egg-info/dependency_links.txt +0 -0
  41. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf.egg-info/requires.txt +0 -0
  42. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/aiwaf.egg-info/top_level.txt +0 -0
  43. {aiwaf-0.1.9.1.9 → aiwaf-0.1.9.2.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aiwaf
3
- Version: 0.1.9.1.9
3
+ Version: 0.1.9.2.1
4
4
  Summary: AI-powered Web Application Firewall
5
5
  Home-page: https://github.com/aayushgauba/aiwaf
6
6
  Author: Aayush Gauba
@@ -25,7 +25,13 @@ Dynamic: requires-python
25
25
  # AI‑WAF
26
26
 
27
27
  > A self‑learning, Django‑friendly Web Application Firewall
28
- > with rate‑limiting, anomaly detection, honeypots, UUID‑tamper protection, dynamic keyword extraction, file‑extension probing detection, exempt path awareness, and daily retraining.
28
+ > with **enhanced context-aware protection**, rate‑limiting, anomaly detection, honeypots, UUID‑tamper protection, **smart keyword learning**, file‑extension probing detection, exempt path awareness, and daily retraining.
29
+
30
+ **🆕 Latest Enhancements:**
31
+ - ✅ **Smart Keyword Filtering** - Prevents blocking legitimate pages like `/profile/`
32
+ - ✅ **Granular Reset Commands** - Clear specific data types (`--blacklist`, `--keywords`, `--exemptions`)
33
+ - ✅ **Context-Aware Learning** - Only learns from suspicious requests, not legitimate site functionality
34
+ - ✅ **Enhanced Configuration** - `AIWAF_ALLOWED_PATH_KEYWORDS` and `AIWAF_EXEMPT_KEYWORDS`
29
35
 
30
36
  ---
31
37
 
@@ -88,9 +94,19 @@ aiwaf/
88
94
  - Burst count
89
95
  - Total 404s
90
96
 
91
- - **Dynamic Keyword Extraction & Cleanup**
92
- - Every retrain adds top 10 keyword segments from 4xx/5xx paths
93
- - **If a path is added to `AIWAF_EXEMPT_PATHS`, its keywords are automatically removed from the database**
97
+ - **Enhanced Dynamic Keyword Learning with Django Route Protection**
98
+ - **Smart Context-Aware Learning**: Only learns keywords from suspicious requests on non-existent paths
99
+ - **Automatic Django Route Extraction**: Automatically excludes keywords from:
100
+ - Valid Django URL patterns (`/profile/`, `/admin/`, `/api/`, etc.)
101
+ - Django app names and model names (users, posts, categories)
102
+ - View function names and URL namespaces
103
+ - **Unified Logic**: Both trainer and middleware use identical legitimate keyword detection
104
+ - **Configuration Options**:
105
+ - `AIWAF_ALLOWED_PATH_KEYWORDS` - Explicitly allow certain keywords in legitimate paths
106
+ - `AIWAF_EXEMPT_KEYWORDS` - Keywords that should never trigger blocking
107
+ - **Automatic Cleanup**: Keywords from `AIWAF_EXEMPT_PATHS` are automatically removed from the database
108
+ - **False Positive Prevention**: Stops learning legitimate site functionality as "malicious"
109
+ - **Inherent Malicious Detection**: Middleware also blocks obviously malicious keywords (`hack`, `exploit`, `attack`) even if not yet learned
94
110
 
95
111
  - **File‑Extension Probing Detection**
96
112
  Tracks repeated 404s on common extensions (e.g. `.php`, `.asp`) and blocks IPs.
@@ -196,20 +212,44 @@ python manage.py add_ipexemption <ip-address> --reason "optional reason"
196
212
 
197
213
  ### Resetting AI-WAF
198
214
 
199
- Clear all blacklist and exemption entries:
215
+ The `aiwaf_reset` command provides **granular control** for clearing different types of data:
200
216
 
201
217
  ```bash
202
- # Clear everything (with confirmation prompt)
218
+ # Clear everything (default - backward compatible)
203
219
  python manage.py aiwaf_reset
204
220
 
205
- # Clear everything without confirmation
221
+ # Clear everything without confirmation prompt
206
222
  python manage.py aiwaf_reset --confirm
207
223
 
208
- # Clear only blacklist entries
209
- python manage.py aiwaf_reset --blacklist-only
224
+ # 🆕 GRANULAR CONTROL - Clear specific data types
225
+ python manage.py aiwaf_reset --blacklist # Clear only blocked IPs
226
+ python manage.py aiwaf_reset --exemptions # Clear only exempted IPs
227
+ python manage.py aiwaf_reset --keywords # Clear only learned keywords
228
+
229
+ # 🔧 COMBINE OPTIONS - Mix and match as needed
230
+ python manage.py aiwaf_reset --blacklist --keywords # Keep exemptions
231
+ python manage.py aiwaf_reset --exemptions --keywords # Keep blacklist
232
+ python manage.py aiwaf_reset --blacklist --exemptions # Keep keywords
233
+
234
+ # 🚀 COMMON USE CASES
235
+ # Fix false positive keywords (like "profile" blocking legitimate pages)
236
+ python manage.py aiwaf_reset --keywords --confirm
237
+ python manage.py detect_and_train # Retrain with enhanced filtering
238
+
239
+ # Clear blocked IPs but preserve exemptions and learning
240
+ python manage.py aiwaf_reset --blacklist --confirm
241
+
242
+ # Legacy support (still works for backward compatibility)
243
+ python manage.py aiwaf_reset --blacklist-only # Legacy: blacklist only
244
+ python manage.py aiwaf_reset --exemptions-only # Legacy: exemptions only
245
+ ```
210
246
 
211
- # Clear only exemption entries
212
- python manage.py aiwaf_reset --exemptions-only
247
+ **Enhanced Feedback:**
248
+ ```bash
249
+ $ python manage.py aiwaf_reset --keywords
250
+ 🔧 AI-WAF Reset: Clear 15 learned keywords
251
+ Are you sure you want to proceed? [y/N]: y
252
+ ✅ Reset complete: Deleted 15 learned keywords
213
253
  ```
214
254
 
215
255
  ### Checking Dependencies
@@ -482,6 +522,21 @@ AIWAF_EXEMPT_PATHS = [ # optional but highly recommended
482
522
  "/media/",
483
523
  "/health/",
484
524
  ]
525
+
526
+ # 🆕 ENHANCED KEYWORD FILTERING OPTIONS
527
+ AIWAF_ALLOWED_PATH_KEYWORDS = [ # Keywords allowed in legitimate paths
528
+ "profile", "user", "account", "settings", "dashboard",
529
+ "admin", "api", "auth", "search", "contact", "about",
530
+ # Add your site-specific legitimate keywords
531
+ "buddycraft", "sc2", "starcraft", # Example: gaming site keywords
532
+ ]
533
+
534
+ AIWAF_EXEMPT_KEYWORDS = [ # Keywords that never trigger blocking
535
+ "api", "webhook", "health", "static", "media",
536
+ "upload", "download", "backup", "profile"
537
+ ]
538
+
539
+ AIWAF_DYNAMIC_TOP_N = 10 # Number of dynamic keywords to learn (default: 10)
485
540
  ```
486
541
 
487
542
  > **Note:** You no longer need to define `AIWAF_MALICIOUS_KEYWORDS` or `AIWAF_STATUS_CODES` — they evolve dynamically.
@@ -680,6 +735,65 @@ python manage.py detect_and_train
680
735
 
681
736
  ---
682
737
 
738
+ ## 🔧 Troubleshooting
739
+
740
+ ### Legitimate Pages Being Blocked
741
+
742
+ **Problem**: Users can't access legitimate pages like `/en/profile/` due to keyword blocking.
743
+
744
+ **Cause**: AIWAF learned legitimate keywords (like "profile") as suspicious from previous traffic.
745
+
746
+ **Solution**:
747
+ ```bash
748
+ # 1. Clear problematic learned keywords
749
+ python manage.py aiwaf_reset --keywords --confirm
750
+
751
+ # 2. Add legitimate keywords to settings
752
+ # In settings.py:
753
+ AIWAF_ALLOWED_PATH_KEYWORDS = [
754
+ "profile", "user", "account", "dashboard",
755
+ # Add your site-specific keywords
756
+ ]
757
+
758
+ # 3. Retrain with enhanced filtering (won't learn legitimate keywords)
759
+ python manage.py detect_and_train
760
+
761
+ # 4. Test - legitimate pages should now work!
762
+ ```
763
+
764
+ ### Preventing Future False Positives
765
+
766
+ Configure AIWAF to recognize your site's legitimate keywords:
767
+
768
+ ```python
769
+ # settings.py
770
+ AIWAF_ALLOWED_PATH_KEYWORDS = [
771
+ # Common legitimate keywords
772
+ "profile", "user", "account", "settings", "dashboard",
773
+ "admin", "search", "contact", "about", "help",
774
+
775
+ # Your site-specific keywords
776
+ "buddycraft", "sc2", "starcraft", # Gaming site example
777
+ "shop", "cart", "checkout", # E-commerce example
778
+ "blog", "article", "news", # Content site example
779
+ ]
780
+ ```
781
+
782
+ ### Reset Command Options
783
+
784
+ ```bash
785
+ # Clear everything (safest for troubleshooting)
786
+ python manage.py aiwaf_reset --confirm
787
+
788
+ # Clear only problematic keywords
789
+ python manage.py aiwaf_reset --keywords --confirm
790
+
791
+ # Clear blocked IPs but keep exemptions
792
+ python manage.py aiwaf_reset --blacklist --confirm
793
+ ```
794
+
795
+ ---
796
+
683
797
  ## 🧠 How It Works
684
798
 
685
799
  | Middleware | Purpose |
@@ -2,7 +2,13 @@
2
2
  # AI‑WAF
3
3
 
4
4
  > A self‑learning, Django‑friendly Web Application Firewall
5
- > with rate‑limiting, anomaly detection, honeypots, UUID‑tamper protection, dynamic keyword extraction, file‑extension probing detection, exempt path awareness, and daily retraining.
5
+ > with **enhanced context-aware protection**, rate‑limiting, anomaly detection, honeypots, UUID‑tamper protection, **smart keyword learning**, file‑extension probing detection, exempt path awareness, and daily retraining.
6
+
7
+ **🆕 Latest Enhancements:**
8
+ - ✅ **Smart Keyword Filtering** - Prevents blocking legitimate pages like `/profile/`
9
+ - ✅ **Granular Reset Commands** - Clear specific data types (`--blacklist`, `--keywords`, `--exemptions`)
10
+ - ✅ **Context-Aware Learning** - Only learns from suspicious requests, not legitimate site functionality
11
+ - ✅ **Enhanced Configuration** - `AIWAF_ALLOWED_PATH_KEYWORDS` and `AIWAF_EXEMPT_KEYWORDS`
6
12
 
7
13
  ---
8
14
 
@@ -65,9 +71,19 @@ aiwaf/
65
71
  - Burst count
66
72
  - Total 404s
67
73
 
68
- - **Dynamic Keyword Extraction & Cleanup**
69
- - Every retrain adds top 10 keyword segments from 4xx/5xx paths
70
- - **If a path is added to `AIWAF_EXEMPT_PATHS`, its keywords are automatically removed from the database**
74
+ - **Enhanced Dynamic Keyword Learning with Django Route Protection**
75
+ - **Smart Context-Aware Learning**: Only learns keywords from suspicious requests on non-existent paths
76
+ - **Automatic Django Route Extraction**: Automatically excludes keywords from:
77
+ - Valid Django URL patterns (`/profile/`, `/admin/`, `/api/`, etc.)
78
+ - Django app names and model names (users, posts, categories)
79
+ - View function names and URL namespaces
80
+ - **Unified Logic**: Both trainer and middleware use identical legitimate keyword detection
81
+ - **Configuration Options**:
82
+ - `AIWAF_ALLOWED_PATH_KEYWORDS` - Explicitly allow certain keywords in legitimate paths
83
+ - `AIWAF_EXEMPT_KEYWORDS` - Keywords that should never trigger blocking
84
+ - **Automatic Cleanup**: Keywords from `AIWAF_EXEMPT_PATHS` are automatically removed from the database
85
+ - **False Positive Prevention**: Stops learning legitimate site functionality as "malicious"
86
+ - **Inherent Malicious Detection**: Middleware also blocks obviously malicious keywords (`hack`, `exploit`, `attack`) even if not yet learned
71
87
 
72
88
  - **File‑Extension Probing Detection**
73
89
  Tracks repeated 404s on common extensions (e.g. `.php`, `.asp`) and blocks IPs.
@@ -173,20 +189,44 @@ python manage.py add_ipexemption <ip-address> --reason "optional reason"
173
189
 
174
190
  ### Resetting AI-WAF
175
191
 
176
- Clear all blacklist and exemption entries:
192
+ The `aiwaf_reset` command provides **granular control** for clearing different types of data:
177
193
 
178
194
  ```bash
179
- # Clear everything (with confirmation prompt)
195
+ # Clear everything (default - backward compatible)
180
196
  python manage.py aiwaf_reset
181
197
 
182
- # Clear everything without confirmation
198
+ # Clear everything without confirmation prompt
183
199
  python manage.py aiwaf_reset --confirm
184
200
 
185
- # Clear only blacklist entries
186
- python manage.py aiwaf_reset --blacklist-only
201
+ # 🆕 GRANULAR CONTROL - Clear specific data types
202
+ python manage.py aiwaf_reset --blacklist # Clear only blocked IPs
203
+ python manage.py aiwaf_reset --exemptions # Clear only exempted IPs
204
+ python manage.py aiwaf_reset --keywords # Clear only learned keywords
205
+
206
+ # 🔧 COMBINE OPTIONS - Mix and match as needed
207
+ python manage.py aiwaf_reset --blacklist --keywords # Keep exemptions
208
+ python manage.py aiwaf_reset --exemptions --keywords # Keep blacklist
209
+ python manage.py aiwaf_reset --blacklist --exemptions # Keep keywords
210
+
211
+ # 🚀 COMMON USE CASES
212
+ # Fix false positive keywords (like "profile" blocking legitimate pages)
213
+ python manage.py aiwaf_reset --keywords --confirm
214
+ python manage.py detect_and_train # Retrain with enhanced filtering
215
+
216
+ # Clear blocked IPs but preserve exemptions and learning
217
+ python manage.py aiwaf_reset --blacklist --confirm
218
+
219
+ # Legacy support (still works for backward compatibility)
220
+ python manage.py aiwaf_reset --blacklist-only # Legacy: blacklist only
221
+ python manage.py aiwaf_reset --exemptions-only # Legacy: exemptions only
222
+ ```
187
223
 
188
- # Clear only exemption entries
189
- python manage.py aiwaf_reset --exemptions-only
224
+ **Enhanced Feedback:**
225
+ ```bash
226
+ $ python manage.py aiwaf_reset --keywords
227
+ 🔧 AI-WAF Reset: Clear 15 learned keywords
228
+ Are you sure you want to proceed? [y/N]: y
229
+ ✅ Reset complete: Deleted 15 learned keywords
190
230
  ```
191
231
 
192
232
  ### Checking Dependencies
@@ -459,6 +499,21 @@ AIWAF_EXEMPT_PATHS = [ # optional but highly recommended
459
499
  "/media/",
460
500
  "/health/",
461
501
  ]
502
+
503
+ # 🆕 ENHANCED KEYWORD FILTERING OPTIONS
504
+ AIWAF_ALLOWED_PATH_KEYWORDS = [ # Keywords allowed in legitimate paths
505
+ "profile", "user", "account", "settings", "dashboard",
506
+ "admin", "api", "auth", "search", "contact", "about",
507
+ # Add your site-specific legitimate keywords
508
+ "buddycraft", "sc2", "starcraft", # Example: gaming site keywords
509
+ ]
510
+
511
+ AIWAF_EXEMPT_KEYWORDS = [ # Keywords that never trigger blocking
512
+ "api", "webhook", "health", "static", "media",
513
+ "upload", "download", "backup", "profile"
514
+ ]
515
+
516
+ AIWAF_DYNAMIC_TOP_N = 10 # Number of dynamic keywords to learn (default: 10)
462
517
  ```
463
518
 
464
519
  > **Note:** You no longer need to define `AIWAF_MALICIOUS_KEYWORDS` or `AIWAF_STATUS_CODES` — they evolve dynamically.
@@ -657,6 +712,65 @@ python manage.py detect_and_train
657
712
 
658
713
  ---
659
714
 
715
+ ## 🔧 Troubleshooting
716
+
717
+ ### Legitimate Pages Being Blocked
718
+
719
+ **Problem**: Users can't access legitimate pages like `/en/profile/` due to keyword blocking.
720
+
721
+ **Cause**: AIWAF learned legitimate keywords (like "profile") as suspicious from previous traffic.
722
+
723
+ **Solution**:
724
+ ```bash
725
+ # 1. Clear problematic learned keywords
726
+ python manage.py aiwaf_reset --keywords --confirm
727
+
728
+ # 2. Add legitimate keywords to settings
729
+ # In settings.py:
730
+ AIWAF_ALLOWED_PATH_KEYWORDS = [
731
+ "profile", "user", "account", "dashboard",
732
+ # Add your site-specific keywords
733
+ ]
734
+
735
+ # 3. Retrain with enhanced filtering (won't learn legitimate keywords)
736
+ python manage.py detect_and_train
737
+
738
+ # 4. Test - legitimate pages should now work!
739
+ ```
740
+
741
+ ### Preventing Future False Positives
742
+
743
+ Configure AIWAF to recognize your site's legitimate keywords:
744
+
745
+ ```python
746
+ # settings.py
747
+ AIWAF_ALLOWED_PATH_KEYWORDS = [
748
+ # Common legitimate keywords
749
+ "profile", "user", "account", "settings", "dashboard",
750
+ "admin", "search", "contact", "about", "help",
751
+
752
+ # Your site-specific keywords
753
+ "buddycraft", "sc2", "starcraft", # Gaming site example
754
+ "shop", "cart", "checkout", # E-commerce example
755
+ "blog", "article", "news", # Content site example
756
+ ]
757
+ ```
758
+
759
+ ### Reset Command Options
760
+
761
+ ```bash
762
+ # Clear everything (safest for troubleshooting)
763
+ python manage.py aiwaf_reset --confirm
764
+
765
+ # Clear only problematic keywords
766
+ python manage.py aiwaf_reset --keywords --confirm
767
+
768
+ # Clear blocked IPs but keep exemptions
769
+ python manage.py aiwaf_reset --blacklist --confirm
770
+ ```
771
+
772
+ ---
773
+
660
774
  ## 🧠 How It Works
661
775
 
662
776
  | Middleware | Purpose |
@@ -1,6 +1,6 @@
1
1
  default_app_config = "aiwaf.apps.AiwafConfig"
2
2
 
3
- __version__ = "0.1.9.1.9"
3
+ __version__ = "0.1.9.2.1"
4
4
 
5
5
  # Note: Middleware classes are available from aiwaf.middleware
6
6
  # Import them only when needed to avoid circular imports during Django app loading
@@ -0,0 +1,183 @@
1
+ from django.core.management.base import BaseCommand
2
+ from aiwaf.storage import get_blacklist_store, get_exemption_store, get_keyword_store
3
+ import sys
4
+
5
+ class Command(BaseCommand):
6
+ help = 'Reset AI-WAF by clearing blacklist, exemption, and/or keyword entries'
7
+
8
+ def add_arguments(self, parser):
9
+ parser.add_argument(
10
+ '--blacklist',
11
+ action='store_true',
12
+ help='Clear blacklist entries (default: all)'
13
+ )
14
+ parser.add_argument(
15
+ '--exemptions',
16
+ action='store_true',
17
+ help='Clear exemption entries (default: all)'
18
+ )
19
+ parser.add_argument(
20
+ '--keywords',
21
+ action='store_true',
22
+ help='Clear learned dynamic keywords (default: all)'
23
+ )
24
+ parser.add_argument(
25
+ '--confirm',
26
+ action='store_true',
27
+ help='Skip confirmation prompt'
28
+ )
29
+
30
+ # Legacy flags for backward compatibility
31
+ parser.add_argument(
32
+ '--blacklist-only',
33
+ action='store_true',
34
+ help='(Legacy) Clear only blacklist entries'
35
+ )
36
+ parser.add_argument(
37
+ '--exemptions-only',
38
+ action='store_true',
39
+ help='(Legacy) Clear only exemption entries'
40
+ )
41
+
42
+ def handle(self, *args, **options):
43
+ # Parse arguments
44
+ blacklist_flag = options.get('blacklist', False)
45
+ exemptions_flag = options.get('exemptions', False)
46
+ keywords_flag = options.get('keywords', False)
47
+ confirm = options.get('confirm', False)
48
+
49
+ # Legacy support
50
+ blacklist_only = options.get('blacklist_only', False)
51
+ exemptions_only = options.get('exemptions_only', False)
52
+
53
+ # Handle legacy flags
54
+ if blacklist_only:
55
+ blacklist_flag = True
56
+ exemptions_flag = False
57
+ keywords_flag = False
58
+ elif exemptions_only:
59
+ blacklist_flag = False
60
+ exemptions_flag = True
61
+ keywords_flag = False
62
+
63
+ # If no specific flags, clear everything
64
+ if not (blacklist_flag or exemptions_flag or keywords_flag):
65
+ blacklist_flag = exemptions_flag = keywords_flag = True
66
+
67
+ try:
68
+ blacklist_store = get_blacklist_store()
69
+ exemption_store = get_exemption_store()
70
+ keyword_store = get_keyword_store()
71
+ except Exception as e:
72
+ self.stdout.write(self.style.ERROR(f'Error initializing stores: {e}'))
73
+ return
74
+
75
+ # Count current entries safely
76
+ counts = {'blacklist': 0, 'exemptions': 0, 'keywords': 0}
77
+ entries = {'blacklist': [], 'exemptions': [], 'keywords': []}
78
+
79
+ if blacklist_flag:
80
+ try:
81
+ entries['blacklist'] = blacklist_store.get_all()
82
+ counts['blacklist'] = len(entries['blacklist'])
83
+ except Exception as e:
84
+ self.stdout.write(self.style.WARNING(f'Warning: Could not count blacklist entries: {e}'))
85
+
86
+ if exemptions_flag:
87
+ try:
88
+ entries['exemptions'] = exemption_store.get_all()
89
+ counts['exemptions'] = len(entries['exemptions'])
90
+ except Exception as e:
91
+ self.stdout.write(self.style.WARNING(f'Warning: Could not count exemption entries: {e}'))
92
+
93
+ if keywords_flag:
94
+ try:
95
+ entries['keywords'] = keyword_store.get_all_keywords()
96
+ counts['keywords'] = len(entries['keywords'])
97
+ except Exception as e:
98
+ self.stdout.write(self.style.WARNING(f'Warning: Could not count keyword entries: {e}'))
99
+
100
+ # Build action description
101
+ actions = []
102
+ if blacklist_flag:
103
+ actions.append(f"{counts['blacklist']} blacklist entries")
104
+ if exemptions_flag:
105
+ actions.append(f"{counts['exemptions']} exemption entries")
106
+ if keywords_flag:
107
+ actions.append(f"{counts['keywords']} learned keywords")
108
+
109
+ action = "Clear " + ", ".join(actions)
110
+
111
+ # Show what will be cleared
112
+ self.stdout.write(f"🔧 AI-WAF Reset: {action}")
113
+
114
+ if not confirm:
115
+ try:
116
+ response = input("Are you sure you want to proceed? [y/N]: ")
117
+ if response.lower() not in ['y', 'yes']:
118
+ self.stdout.write(self.style.WARNING('Operation cancelled'))
119
+ return
120
+ except (EOFError, KeyboardInterrupt):
121
+ self.stdout.write(self.style.WARNING('\nOperation cancelled'))
122
+ return
123
+
124
+ # Perform the reset
125
+ deleted_counts = {'blacklist': 0, 'exemptions': 0, 'keywords': 0, 'errors': []}
126
+
127
+ if blacklist_flag:
128
+ # Clear blacklist entries
129
+ try:
130
+ for entry in entries['blacklist']:
131
+ try:
132
+ blacklist_store.remove_ip(entry['ip_address'])
133
+ deleted_counts['blacklist'] += 1
134
+ except Exception as e:
135
+ deleted_counts['errors'].append(f"Error removing blacklist IP {entry.get('ip_address', 'unknown')}: {e}")
136
+ except Exception as e:
137
+ deleted_counts['errors'].append(f"Error clearing blacklist: {e}")
138
+
139
+ if exemptions_flag:
140
+ # Clear exemption entries
141
+ try:
142
+ for entry in entries['exemptions']:
143
+ try:
144
+ exemption_store.remove_ip(entry['ip_address'])
145
+ deleted_counts['exemptions'] += 1
146
+ except Exception as e:
147
+ deleted_counts['errors'].append(f"Error removing exemption IP {entry.get('ip_address', 'unknown')}: {e}")
148
+ except Exception as e:
149
+ deleted_counts['errors'].append(f"Error clearing exemptions: {e}")
150
+
151
+ if keywords_flag:
152
+ # Clear keyword entries
153
+ try:
154
+ for keyword in entries['keywords']:
155
+ try:
156
+ keyword_store.remove_keyword(keyword)
157
+ deleted_counts['keywords'] += 1
158
+ except Exception as e:
159
+ deleted_counts['errors'].append(f"Error removing keyword '{keyword}': {e}")
160
+ except Exception as e:
161
+ deleted_counts['errors'].append(f"Error clearing keywords: {e}")
162
+
163
+ # Report results
164
+ if deleted_counts['errors']:
165
+ for error in deleted_counts['errors']:
166
+ self.stdout.write(self.style.WARNING(f"⚠️ {error}"))
167
+
168
+ # Build success message
169
+ success_parts = []
170
+ if blacklist_flag:
171
+ success_parts.append(f"{deleted_counts['blacklist']} blacklist entries")
172
+ if exemptions_flag:
173
+ success_parts.append(f"{deleted_counts['exemptions']} exemption entries")
174
+ if keywords_flag:
175
+ success_parts.append(f"{deleted_counts['keywords']} learned keywords")
176
+
177
+ success_message = "✅ Reset complete: Deleted " + ", ".join(success_parts)
178
+ self.stdout.write(self.style.SUCCESS(success_message))
179
+
180
+ if deleted_counts['errors']:
181
+ self.stdout.write(
182
+ self.style.WARNING(f"⚠️ Completed with {len(deleted_counts['errors'])} errors (see above)")
183
+ )