pywebguard 0.0.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.
Files changed (48) hide show
  1. pywebguard-0.0.1/LICENSE +21 -0
  2. pywebguard-0.0.1/PKG-INFO +385 -0
  3. pywebguard-0.0.1/README.md +346 -0
  4. pywebguard-0.0.1/pywebguard/__init__.py +87 -0
  5. pywebguard-0.0.1/pywebguard/cli.py +1022 -0
  6. pywebguard-0.0.1/pywebguard/core/__init__.py +0 -0
  7. pywebguard-0.0.1/pywebguard/core/base.py +792 -0
  8. pywebguard-0.0.1/pywebguard/core/config.py +455 -0
  9. pywebguard-0.0.1/pywebguard/filters/__init__.py +0 -0
  10. pywebguard-0.0.1/pywebguard/filters/base.py +44 -0
  11. pywebguard-0.0.1/pywebguard/filters/ip_filter.py +233 -0
  12. pywebguard-0.0.1/pywebguard/filters/user_agent.py +102 -0
  13. pywebguard-0.0.1/pywebguard/frameworks/__init__.py +0 -0
  14. pywebguard-0.0.1/pywebguard/frameworks/_fastapi.py +191 -0
  15. pywebguard-0.0.1/pywebguard/frameworks/_flask.py +182 -0
  16. pywebguard-0.0.1/pywebguard/limiters/__init__.py +0 -0
  17. pywebguard-0.0.1/pywebguard/limiters/base.py +46 -0
  18. pywebguard-0.0.1/pywebguard/limiters/rate_limit.py +415 -0
  19. pywebguard-0.0.1/pywebguard/logging/__init__.py +0 -0
  20. pywebguard-0.0.1/pywebguard/logging/backends/__init__.py +17 -0
  21. pywebguard-0.0.1/pywebguard/logging/backends/_elasticsearch.py +307 -0
  22. pywebguard-0.0.1/pywebguard/logging/backends/_meilisearch.py +310 -0
  23. pywebguard-0.0.1/pywebguard/logging/backends/_mongodb.py +303 -0
  24. pywebguard-0.0.1/pywebguard/logging/base.py +117 -0
  25. pywebguard-0.0.1/pywebguard/logging/logger.py +408 -0
  26. pywebguard-0.0.1/pywebguard/security/__init__.py +0 -0
  27. pywebguard-0.0.1/pywebguard/security/base.py +44 -0
  28. pywebguard-0.0.1/pywebguard/security/cors.py +204 -0
  29. pywebguard-0.0.1/pywebguard/security/penetration.py +265 -0
  30. pywebguard-0.0.1/pywebguard/storage/__init__.py +0 -0
  31. pywebguard-0.0.1/pywebguard/storage/_mongodb.py +396 -0
  32. pywebguard-0.0.1/pywebguard/storage/_postgresql.py +539 -0
  33. pywebguard-0.0.1/pywebguard/storage/_redis.py +314 -0
  34. pywebguard-0.0.1/pywebguard/storage/_sqlite.py +374 -0
  35. pywebguard-0.0.1/pywebguard/storage/_tinydb.py +271 -0
  36. pywebguard-0.0.1/pywebguard/storage/base.py +327 -0
  37. pywebguard-0.0.1/pywebguard/storage/memory.py +245 -0
  38. pywebguard-0.0.1/pywebguard/utils/__init__.py +0 -0
  39. pywebguard-0.0.1/pywebguard/utils/ip.py +84 -0
  40. pywebguard-0.0.1/pywebguard/utils/request.py +65 -0
  41. pywebguard-0.0.1/pywebguard.egg-info/PKG-INFO +385 -0
  42. pywebguard-0.0.1/pywebguard.egg-info/SOURCES.txt +46 -0
  43. pywebguard-0.0.1/pywebguard.egg-info/dependency_links.txt +1 -0
  44. pywebguard-0.0.1/pywebguard.egg-info/entry_points.txt +2 -0
  45. pywebguard-0.0.1/pywebguard.egg-info/requires.txt +73 -0
  46. pywebguard-0.0.1/pywebguard.egg-info/top_level.txt +1 -0
  47. pywebguard-0.0.1/setup.cfg +4 -0
  48. pywebguard-0.0.1/setup.py +97 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 py-daily
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,385 @@
1
+ Metadata-Version: 2.1
2
+ Name: pywebguard
3
+ Version: 0.0.1
4
+ Summary: A comprehensive security library for Python web applications
5
+ Home-page: https://github.com/py-daily/pywebguard
6
+ Author: py-daily
7
+ Author-email: mm@ktechhub.com
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python :: 3.14
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.8
19
+ Classifier: Programming Language :: Python :: 3
20
+ Classifier: Topic :: Security
21
+ Classifier: Topic :: Internet :: WWW/HTTP
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Requires-Python: >=3.8
24
+ Description-Content-Type: text/markdown
25
+ Provides-Extra: fastapi
26
+ Provides-Extra: flask
27
+ Provides-Extra: redis
28
+ Provides-Extra: sqlite
29
+ Provides-Extra: tinydb
30
+ Provides-Extra: mongodb
31
+ Provides-Extra: postgresql
32
+ Provides-Extra: elasticsearch
33
+ Provides-Extra: all-storage
34
+ Provides-Extra: all-frameworks
35
+ Provides-Extra: all
36
+ Provides-Extra: dev
37
+ License-File: LICENSE
38
+
39
+
40
+ # PyWebGuard
41
+
42
+ A comprehensive security library for Python web applications, providing middleware for IP filtering, rate limiting, and other security features with both synchronous and asynchronous support.
43
+
44
+ For detailed installation instructions and configuration options, see [Installation Guide](docs/installation.md).
45
+
46
+ ## Key Features
47
+
48
+ - **IP Whitelisting and Blacklisting**: Control access based on IP addresses
49
+ - **User Agent Filtering**: Block requests from specific user agents
50
+ - **Rate Limiting**: Limit the number of requests from a single IP
51
+ - **Per-Route Rate Limiting**: Set different rate limits for different endpoints
52
+ - **Bulk Configuration**: Configure rate limits for multiple routes at once
53
+ - **Pattern Matching**: Use wildcards to apply rate limits to groups of routes
54
+ - **Automatic IP Banning**: Automatically ban IPs after a certain number of suspicious requests
55
+ - **Penetration Attempt Detection**: Detect and log potential penetration attempts
56
+ - **Custom Logging**: Log security events to a custom file
57
+ - **CORS Configuration**: Configure CORS settings for your web application
58
+ - **IP Geolocation**: Determine the country of an IP address
59
+ - **Flexible Storage**: Redis-enabled distributed storage, nosql, sql or in-memory storage
60
+ - **Async/Sync Support**: Works with both synchronous (Flask) and asynchronous (FastAPI) frameworks
61
+ - **Logging Backends**: Configurable logging backends with current support for Meilisearch
62
+
63
+
64
+
65
+ ## Quick Start
66
+
67
+ ```python
68
+ from fastapi import FastAPI
69
+ from pywebguard import FastAPIGuard, GuardConfig, RateLimitConfig
70
+ from pywebguard.storage.memory import AsyncMemoryStorage
71
+ from pywebguard.core.config import LoggingConfig
72
+
73
+ config = GuardConfig(
74
+ # IP filtering configuration
75
+ ip_filter={
76
+ "enabled": True,
77
+ "whitelist": ["127.0.0.1", "::1", "192.168.1.0/24"],
78
+ "blacklist": ["10.0.0.1", "172.16.0.0/16"],
79
+ },
80
+ # Global rate limiting configuration
81
+ rate_limit={
82
+ "enabled": True,
83
+ "requests_per_minute": 100,
84
+ "burst_size": 20,
85
+ "auto_ban_threshold": 200,
86
+ "auto_ban_duration": 3600, # 1 hour in seconds
87
+ },
88
+ # User agent filtering
89
+ user_agent={
90
+ "enabled": True,
91
+ "blocked_agents": ["curl", "wget", "Scrapy", "bot", "Bot"],
92
+ },
93
+ # CORS configuration
94
+ cors={
95
+ "enabled": True,
96
+ "allow_origins": ["http://localhost:3000", "https://example.com"],
97
+ "allow_methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
98
+ "allow_headers": ["Content-Type", "Authorization"],
99
+ "allow_credentials": True,
100
+ "max_age": 3600,
101
+ },
102
+ # Penetration detection
103
+ penetration={
104
+ "enabled": True,
105
+ "detect_sql_injection": True,
106
+ "detect_xss": True,
107
+ "detect_path_traversal": True,
108
+ "block_suspicious_requests": True,
109
+ },
110
+ # Logging configuration
111
+ logging={
112
+ "enabled": True,
113
+ "level": "DEBUG", # Change to DEBUG to see all messages
114
+ "log_blocked_requests": True,
115
+ "stream": True,
116
+ "stream_levels": ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
117
+ "meilisearch": {
118
+ "url": "https://meilisearch.dev.pydaily.com",
119
+ "api_key": os.getenv("MEILISEARCH_API_KEY"),
120
+ "index_name": "pywebguard",
121
+ },
122
+ },
123
+ )
124
+ # Define route-specific rate limits
125
+ route_rate_limits = [
126
+ {
127
+ "endpoint": "/api/limited",
128
+ "requests_per_minute": 5,
129
+ "burst_size": 2,
130
+ "auto_ban_threshold": 10,
131
+ "auto_ban_duration": 1800, # 30 minutes
132
+ },
133
+ {
134
+ "endpoint": "/api/uploads/*",
135
+ "requests_per_minute": 10,
136
+ "burst_size": 5,
137
+ "auto_ban_duration": 1800,
138
+ },
139
+ {
140
+ "endpoint": "/api/admin/**",
141
+ "requests_per_minute": 20,
142
+ "burst_size": 5,
143
+ "auto_ban_threshold": 50,
144
+ "auto_ban_duration": 7200, # 2 hours
145
+ },
146
+ ]
147
+
148
+
149
+ # Initialize storage (async in-memory for this example)
150
+ storage = AsyncMemoryStorage()
151
+
152
+ # Uncomment to use Redis storage instead or import any of the storage supports
153
+ # storage = AsyncRedisStorage(url="redis://localhost:6379")
154
+
155
+
156
+ # Add PyWebGuard middleware
157
+ app.add_middleware(
158
+ FastAPIGuard,
159
+ config=config,
160
+ storage=storage,
161
+ route_rate_limits=route_rate_limits,
162
+ )
163
+
164
+ Basic routes
165
+ @app.get("/", tags=["main"])
166
+ async def root():
167
+ """Root endpoint with default rate limit (100 req/min)"""
168
+ return {"message": "Hello World - Default rate limit (100 req/min)"}
169
+
170
+
171
+ @app.get("/api/limited", tags=["main"])
172
+ async def limited_endpoint():
173
+ """Strictly rate limited endpoint (5 req/min)"""
174
+ return {"message": "This endpoint is strictly rate limited (5 req/min)"}
175
+
176
+
177
+ @app.get("/api/uploads/files", tags=["main"])
178
+ async def upload_files():
179
+ """File upload endpoint with custom rate limit (10 req/min)"""
180
+ return {"message": "File upload endpoint with custom rate limit (10 req/min)"}
181
+
182
+
183
+ @app.get("/api/admin/dashboard", tags=["main"])
184
+ async def admin_dashboard():
185
+ """Admin dashboard with custom rate limit (20 req/min)"""
186
+ return {"message": "Admin dashboard with custom rate limit (20 req/min)"}
187
+
188
+
189
+ @app.get("/api/admin/users/list", tags=["main"])
190
+ async def admin_users():
191
+ """Admin users list with custom rate limit (20 req/min)"""
192
+ return {"message": "Admin users list with custom rate limit (20 req/min)"}
193
+
194
+
195
+ @app.get("/protected", tags=["main"])
196
+ async def protected(request: Request):
197
+ """Protected endpoint with default rate limit"""
198
+ return {
199
+ "message": "This is a protected endpoint with default rate limit",
200
+ "client_ip": request.client.host,
201
+ "user_agent": request.headers.get("user-agent", "Unknown"),
202
+ }
203
+
204
+
205
+ # Example of a path that might trigger penetration detection
206
+ @app.get("/search", tags=["main"])
207
+ async def search(q: str):
208
+ """
209
+ Search endpoint that might trigger penetration detection if malicious queries are used
210
+
211
+ Args:
212
+ q: Search query
213
+
214
+ Returns:
215
+ Search results
216
+ """
217
+ # PyWebGuard will check for SQL injection, XSS, etc. in the query parameter
218
+ return {"results": f"Search results for: {q}"}
219
+
220
+
221
+ # Helper endpoint to check remaining rate limits
222
+ @app.get("/rate-limit-status", tags=["helper"])
223
+ async def rate_limit_status(request: Request, path: str = "/"):
224
+ """
225
+ Check rate limit status for a specific path
226
+
227
+ Args:
228
+ request: The FastAPI request object
229
+ path: The path to check rate limits for (default: /)
230
+
231
+ Returns:
232
+ Rate limit information for the specified path
233
+ """
234
+ client_ip = request.client.host
235
+
236
+ # Get rate limit info for the specified path
237
+ guard = request.app.state.guard
238
+ rate_info = await guard.guard.rate_limiter.check_limit(client_ip, path)
239
+
240
+ return {
241
+ "path": path,
242
+ "allowed": rate_info["allowed"],
243
+ "remaining": rate_info["remaining"],
244
+ "reset": rate_info["reset"],
245
+ "client_ip": client_ip,
246
+ }
247
+
248
+
249
+ # Endpoint to check if an IP is banned
250
+ @app.get("/check-ban-status", tags=["helper"])
251
+ async def check_ban_status(request: Request, ip: Optional[str] = None):
252
+ """
253
+ Check if an IP is banned
254
+
255
+ Args:
256
+ request: The FastAPI request object
257
+ ip: The IP to check (default: client IP)
258
+
259
+ Returns:
260
+ Ban status information
261
+ """
262
+ check_ip = ip or request.client.host
263
+ guard = request.app.state.guard
264
+ is_banned = await guard.guard.is_ip_banned(check_ip)
265
+
266
+ return {
267
+ "ip": check_ip,
268
+ "is_banned": is_banned,
269
+ "timestamp": time.time(),
270
+ }
271
+
272
+
273
+ # Admin endpoint to get metrics
274
+ @app.get("/admin/metrics", tags=["admin"])
275
+ async def get_metrics(request: Request):
276
+ """
277
+ Get PyWebGuard metrics
278
+
279
+ Args:
280
+ request: The FastAPI request object
281
+
282
+ Returns:
283
+ Current metrics from PyWebGuard
284
+ """
285
+ # This would typically be protected by authentication
286
+ guard = request.app.state.guard
287
+ # Get rate limit info for all paths
288
+ rate_limits = {}
289
+ for path in ["/", "/api/limited", "/api/uploads/*", "/api/admin/**"]:
290
+ rate_info = await guard.guard.rate_limiter.check_limit(
291
+ request.client.host, path
292
+ )
293
+ rate_limits[path] = {
294
+ "allowed": rate_info["allowed"],
295
+ "remaining": rate_info["remaining"],
296
+ "reset": rate_info["reset"],
297
+ }
298
+
299
+ return {
300
+ "timestamp": time.time(),
301
+ "metrics": {
302
+ "rate_limits": rate_limits,
303
+ "client_ip": request.client.host,
304
+ "user_agent": request.headers.get("user-agent", "Unknown"),
305
+ },
306
+ }
307
+
308
+
309
+ # Admin endpoint to ban an IP
310
+ @app.post("/admin/ban-ip", tags=["admin"])
311
+ async def ban_ip(request: Request, ip: str, duration: int = 60):
312
+ """
313
+ Ban an IP address
314
+
315
+ Args:
316
+ request: The FastAPI request object
317
+ ip: The IP to ban
318
+ duration: Ban duration in seconds (default: 1 hour)
319
+
320
+ Returns:
321
+ Ban confirmation
322
+ """
323
+ # This would typically be protected by authentication
324
+ guard = request.app.state.guard
325
+ ban_key = f"banned_ip:{ip}"
326
+ await guard.guard.storage.set(
327
+ ban_key,
328
+ {"reason": "Manually banned via API", "timestamp": time.time()},
329
+ duration,
330
+ )
331
+
332
+ return {
333
+ "message": f"IP {ip} banned for {duration} seconds",
334
+ "timestamp": time.time(),
335
+ }
336
+
337
+
338
+ # Admin endpoint to unban an IP
339
+ @app.post("/admin/unban-ip", tags=["admin"])
340
+ async def unban_ip(request: Request, ip: str):
341
+ """
342
+ Unban an IP address
343
+
344
+ Args:
345
+ request: The FastAPI request object
346
+ ip: The IP to unban
347
+
348
+ Returns:
349
+ Unban confirmation
350
+ """
351
+ # This would typically be protected by authentication
352
+ guard = request.app.state.guard
353
+ ban_key = f"banned_ip:{ip}"
354
+ await guard.guard.storage.delete(ban_key)
355
+
356
+ return {
357
+ "message": f"IP {ip} unbanned",
358
+ "timestamp": time.time(),
359
+ }
360
+
361
+
362
+ if __name__ == "__main__":
363
+ logger.info("Starting PyWebGuard FastAPI example server...")
364
+ uvicorn.run(app, host="0.0.0.0", port=8000)
365
+ ```
366
+
367
+
368
+ ## Documentation
369
+
370
+ - [Installation Guide](docs/installation.md)
371
+ - [CLI Usage](docs/cli.md)
372
+ - [Core Features](docs/core/)
373
+ - [Framework Integration](docs/frameworks/)
374
+ - [Storage Backends](docs/storage/)
375
+
376
+ ## Contributors
377
+
378
+ <a href="https://github.com/py-daily/pywebguard/graphs/contributors">
379
+ <img src="https://contrib.rocks/image?repo=py-daily/pywebguard" width="80" />
380
+ </a>
381
+
382
+ ## License
383
+
384
+ This project is licensed under the [MIT License](LICENSE).
385
+