aiwaf 0.1.8.8__tar.gz → 0.1.8.9__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.
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/PKG-INFO +13 -1
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/README.md +12 -0
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/aiwaf/storage.py +74 -33
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/aiwaf.egg-info/PKG-INFO +13 -1
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/pyproject.toml +1 -1
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/setup.py +1 -1
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/LICENSE +0 -0
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/aiwaf/__init__.py +0 -0
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/aiwaf/apps.py +0 -0
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/aiwaf/blacklist_manager.py +0 -0
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/aiwaf/decorators.py +0 -0
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/aiwaf/management/__init__.py +0 -0
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/aiwaf/management/commands/__init__.py +0 -0
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/aiwaf/management/commands/add_ipexemption.py +0 -0
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/aiwaf/management/commands/aiwaf_logging.py +0 -0
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/aiwaf/management/commands/aiwaf_reset.py +0 -0
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/aiwaf/management/commands/detect_and_train.py +0 -0
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/aiwaf/middleware.py +0 -0
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/aiwaf/middleware_logger.py +0 -0
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/aiwaf/models.py +0 -0
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/aiwaf/resources/model.pkl +0 -0
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/aiwaf/templatetags/__init__.py +0 -0
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/aiwaf/templatetags/aiwaf_tags.py +0 -0
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/aiwaf/trainer.py +0 -0
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/aiwaf/utils.py +0 -0
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/aiwaf.egg-info/SOURCES.txt +0 -0
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/aiwaf.egg-info/dependency_links.txt +0 -0
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/aiwaf.egg-info/requires.txt +0 -0
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/aiwaf.egg-info/top_level.txt +0 -0
- {aiwaf-0.1.8.8 → aiwaf-0.1.8.9}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aiwaf
|
|
3
|
-
Version: 0.1.8.
|
|
3
|
+
Version: 0.1.8.9
|
|
4
4
|
Summary: AI-powered Web Application Firewall
|
|
5
5
|
Home-page: https://github.com/aayushgauba/aiwaf
|
|
6
6
|
Author: Aayush Gauba
|
|
@@ -27,6 +27,18 @@ Dynamic: requires-python
|
|
|
27
27
|
|
|
28
28
|
---
|
|
29
29
|
|
|
30
|
+
## 🚀 Quick Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install aiwaf
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**⚠️ Important:** Add `'aiwaf'` to your Django `INSTALLED_APPS` to avoid setup errors.
|
|
37
|
+
|
|
38
|
+
**📋 Complete Setup Guide:** See [INSTALLATION.md](INSTALLATION.md) for detailed installation instructions and troubleshooting.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
30
42
|
## System Requirements
|
|
31
43
|
|
|
32
44
|
No GPU needed—AI-WAF runs entirely on CPU with just Python 3.8+, Django 3.2+, a single vCPU and ~512 MB RAM for small sites; for moderate production traffic you can bump to 2–4 vCPUs and 2–4 GB RAM, offload the daily detect-and-train job to a worker, and rotate logs to keep memory use bounded.
|
|
@@ -6,6 +6,18 @@
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
+
## 🚀 Quick Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install aiwaf
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
**⚠️ Important:** Add `'aiwaf'` to your Django `INSTALLED_APPS` to avoid setup errors.
|
|
16
|
+
|
|
17
|
+
**📋 Complete Setup Guide:** See [INSTALLATION.md](INSTALLATION.md) for detailed installation instructions and troubleshooting.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
9
21
|
## System Requirements
|
|
10
22
|
|
|
11
23
|
No GPU needed—AI-WAF runs entirely on CPU with just Python 3.8+, Django 3.2+, a single vCPU and ~512 MB RAM for small sites; for moderate production traffic you can bump to 2–4 vCPUs and 2–4 GB RAM, offload the daily detect-and-train job to a worker, and rotate logs to keep memory use bounded.
|
|
@@ -3,7 +3,18 @@ import numpy as np
|
|
|
3
3
|
import pandas as pd
|
|
4
4
|
from django.conf import settings
|
|
5
5
|
from django.utils import timezone
|
|
6
|
-
|
|
6
|
+
|
|
7
|
+
# Only import models if aiwaf is in INSTALLED_APPS
|
|
8
|
+
try:
|
|
9
|
+
from django.apps import apps
|
|
10
|
+
if apps.is_installed('aiwaf'):
|
|
11
|
+
from .models import FeatureSample, BlacklistEntry, IPExemption, DynamicKeyword
|
|
12
|
+
else:
|
|
13
|
+
# Create dummy classes to avoid import errors
|
|
14
|
+
FeatureSample = BlacklistEntry = IPExemption = DynamicKeyword = None
|
|
15
|
+
except (ImportError, RuntimeError):
|
|
16
|
+
# Handle cases where Django isn't fully initialized yet
|
|
17
|
+
FeatureSample = BlacklistEntry = IPExemption = DynamicKeyword = None
|
|
7
18
|
|
|
8
19
|
# Configuration
|
|
9
20
|
STORAGE_MODE = getattr(settings, "AIWAF_STORAGE_MODE", "models") # "models" or "csv"
|
|
@@ -52,22 +63,25 @@ class CsvFeatureStore:
|
|
|
52
63
|
class DbFeatureStore:
|
|
53
64
|
@staticmethod
|
|
54
65
|
def persist_rows(rows):
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
66
|
+
if FeatureSample is not None:
|
|
67
|
+
objs = []
|
|
68
|
+
for ip,pl,kw,rt,si,bc,t404,label in rows:
|
|
69
|
+
objs.append(FeatureSample(
|
|
70
|
+
ip=ip, path_len=pl, kw_hits=kw,
|
|
71
|
+
resp_time=rt, status_idx=si,
|
|
72
|
+
burst_count=bc, total_404=t404,
|
|
73
|
+
label=label
|
|
74
|
+
))
|
|
75
|
+
FeatureSample.objects.bulk_create(objs, ignore_conflicts=True)
|
|
64
76
|
|
|
65
77
|
@staticmethod
|
|
66
78
|
def load_matrix():
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
79
|
+
if FeatureSample is not None:
|
|
80
|
+
qs = FeatureSample.objects.all().values_list(
|
|
81
|
+
"path_len","kw_hits","resp_time","status_idx","burst_count","total_404"
|
|
82
|
+
)
|
|
83
|
+
return np.array(list(qs), dtype=float)
|
|
84
|
+
return np.empty((0,6))
|
|
71
85
|
|
|
72
86
|
def get_store():
|
|
73
87
|
if getattr(settings, "AIWAF_FEATURE_STORE", "csv") == "db":
|
|
@@ -266,8 +280,12 @@ def get_blacklist_store():
|
|
|
266
280
|
if STORAGE_MODE == "csv":
|
|
267
281
|
return CsvBlacklistStore
|
|
268
282
|
else:
|
|
269
|
-
# Return a wrapper for Django models
|
|
270
|
-
|
|
283
|
+
# Return a wrapper for Django models (only if models are available)
|
|
284
|
+
if BlacklistEntry is not None:
|
|
285
|
+
return ModelBlacklistStore
|
|
286
|
+
else:
|
|
287
|
+
# Fallback to CSV if models aren't available
|
|
288
|
+
return CsvBlacklistStore
|
|
271
289
|
|
|
272
290
|
|
|
273
291
|
def get_exemption_store():
|
|
@@ -275,7 +293,10 @@ def get_exemption_store():
|
|
|
275
293
|
if STORAGE_MODE == "csv":
|
|
276
294
|
return CsvExemptionStore
|
|
277
295
|
else:
|
|
278
|
-
|
|
296
|
+
if IPExemption is not None:
|
|
297
|
+
return ModelExemptionStore
|
|
298
|
+
else:
|
|
299
|
+
return CsvExemptionStore
|
|
279
300
|
|
|
280
301
|
|
|
281
302
|
def get_keyword_store():
|
|
@@ -283,7 +304,10 @@ def get_keyword_store():
|
|
|
283
304
|
if STORAGE_MODE == "csv":
|
|
284
305
|
return CsvKeywordStore
|
|
285
306
|
else:
|
|
286
|
-
|
|
307
|
+
if DynamicKeyword is not None:
|
|
308
|
+
return ModelKeywordStore
|
|
309
|
+
else:
|
|
310
|
+
return CsvKeywordStore
|
|
287
311
|
|
|
288
312
|
|
|
289
313
|
# ============= Django Model Wrappers =============
|
|
@@ -293,19 +317,25 @@ class ModelBlacklistStore:
|
|
|
293
317
|
|
|
294
318
|
@staticmethod
|
|
295
319
|
def add_ip(ip_address, reason):
|
|
296
|
-
BlacklistEntry
|
|
320
|
+
if BlacklistEntry is not None:
|
|
321
|
+
BlacklistEntry.objects.get_or_create(ip_address=ip_address, defaults={"reason": reason})
|
|
297
322
|
|
|
298
323
|
@staticmethod
|
|
299
324
|
def is_blocked(ip_address):
|
|
300
|
-
|
|
325
|
+
if BlacklistEntry is not None:
|
|
326
|
+
return BlacklistEntry.objects.filter(ip_address=ip_address).exists()
|
|
327
|
+
return False
|
|
301
328
|
|
|
302
329
|
@staticmethod
|
|
303
330
|
def get_all():
|
|
304
|
-
|
|
331
|
+
if BlacklistEntry is not None:
|
|
332
|
+
return list(BlacklistEntry.objects.values("ip_address", "reason", "created_at"))
|
|
333
|
+
return []
|
|
305
334
|
|
|
306
335
|
@staticmethod
|
|
307
336
|
def remove_ip(ip_address):
|
|
308
|
-
BlacklistEntry
|
|
337
|
+
if BlacklistEntry is not None:
|
|
338
|
+
BlacklistEntry.objects.filter(ip_address=ip_address).delete()
|
|
309
339
|
|
|
310
340
|
|
|
311
341
|
class ModelExemptionStore:
|
|
@@ -313,19 +343,25 @@ class ModelExemptionStore:
|
|
|
313
343
|
|
|
314
344
|
@staticmethod
|
|
315
345
|
def add_ip(ip_address, reason=""):
|
|
316
|
-
IPExemption
|
|
346
|
+
if IPExemption is not None:
|
|
347
|
+
IPExemption.objects.get_or_create(ip_address=ip_address, defaults={"reason": reason})
|
|
317
348
|
|
|
318
349
|
@staticmethod
|
|
319
350
|
def is_exempted(ip_address):
|
|
320
|
-
|
|
351
|
+
if IPExemption is not None:
|
|
352
|
+
return IPExemption.objects.filter(ip_address=ip_address).exists()
|
|
353
|
+
return False
|
|
321
354
|
|
|
322
355
|
@staticmethod
|
|
323
356
|
def get_all():
|
|
324
|
-
|
|
357
|
+
if IPExemption is not None:
|
|
358
|
+
return list(IPExemption.objects.values("ip_address", "reason", "created_at"))
|
|
359
|
+
return []
|
|
325
360
|
|
|
326
361
|
@staticmethod
|
|
327
362
|
def remove_ip(ip_address):
|
|
328
|
-
IPExemption
|
|
363
|
+
if IPExemption is not None:
|
|
364
|
+
IPExemption.objects.filter(ip_address=ip_address).delete()
|
|
329
365
|
|
|
330
366
|
|
|
331
367
|
class ModelKeywordStore:
|
|
@@ -333,19 +369,24 @@ class ModelKeywordStore:
|
|
|
333
369
|
|
|
334
370
|
@staticmethod
|
|
335
371
|
def add_keyword(keyword, count=1):
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
372
|
+
if DynamicKeyword is not None:
|
|
373
|
+
obj, created = DynamicKeyword.objects.get_or_create(keyword=keyword, defaults={"count": count})
|
|
374
|
+
if not created:
|
|
375
|
+
obj.count += count
|
|
376
|
+
obj.save()
|
|
340
377
|
|
|
341
378
|
@staticmethod
|
|
342
379
|
def get_top_keywords(limit=10):
|
|
343
|
-
|
|
380
|
+
if DynamicKeyword is not None:
|
|
381
|
+
return list(DynamicKeyword.objects.order_by("-count").values_list("keyword", flat=True)[:limit])
|
|
382
|
+
return []
|
|
344
383
|
|
|
345
384
|
@staticmethod
|
|
346
385
|
def remove_keyword(keyword):
|
|
347
|
-
DynamicKeyword
|
|
386
|
+
if DynamicKeyword is not None:
|
|
387
|
+
DynamicKeyword.objects.filter(keyword=keyword).delete()
|
|
348
388
|
|
|
349
389
|
@staticmethod
|
|
350
390
|
def clear_all():
|
|
351
|
-
DynamicKeyword
|
|
391
|
+
if DynamicKeyword is not None:
|
|
392
|
+
DynamicKeyword.objects.all().delete()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aiwaf
|
|
3
|
-
Version: 0.1.8.
|
|
3
|
+
Version: 0.1.8.9
|
|
4
4
|
Summary: AI-powered Web Application Firewall
|
|
5
5
|
Home-page: https://github.com/aayushgauba/aiwaf
|
|
6
6
|
Author: Aayush Gauba
|
|
@@ -27,6 +27,18 @@ Dynamic: requires-python
|
|
|
27
27
|
|
|
28
28
|
---
|
|
29
29
|
|
|
30
|
+
## 🚀 Quick Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install aiwaf
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**⚠️ Important:** Add `'aiwaf'` to your Django `INSTALLED_APPS` to avoid setup errors.
|
|
37
|
+
|
|
38
|
+
**📋 Complete Setup Guide:** See [INSTALLATION.md](INSTALLATION.md) for detailed installation instructions and troubleshooting.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
30
42
|
## System Requirements
|
|
31
43
|
|
|
32
44
|
No GPU needed—AI-WAF runs entirely on CPU with just Python 3.8+, Django 3.2+, a single vCPU and ~512 MB RAM for small sites; for moderate production traffic you can bump to 2–4 vCPUs and 2–4 GB RAM, offload the daily detect-and-train job to a worker, and rotate logs to keep memory use bounded.
|
|
@@ -9,7 +9,7 @@ long_description = (HERE / "README.md").read_text(encoding="utf-8")
|
|
|
9
9
|
|
|
10
10
|
setup(
|
|
11
11
|
name="aiwaf",
|
|
12
|
-
version="0.1.8.
|
|
12
|
+
version="0.1.8.9",
|
|
13
13
|
description="AI‑driven, self‑learning Web Application Firewall for Django",
|
|
14
14
|
long_description=long_description,
|
|
15
15
|
long_description_content_type="text/markdown",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|