iotsploit-django 0.0.6__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.
- iotsploit_django-0.0.6/PKG-INFO +61 -0
- iotsploit_django-0.0.6/README.md +7 -0
- iotsploit_django-0.0.6/pyproject.toml +68 -0
- iotsploit_django-0.0.6/src/iotsploit_django/__init__.py +6 -0
- iotsploit_django-0.0.6/src/iotsploit_django/adapters/__init__.py +0 -0
- iotsploit_django-0.0.6/src/iotsploit_django/adapters/django/__init__.py +3 -0
- iotsploit_django-0.0.6/src/iotsploit_django/adapters/django/device_driver_manager_factory.py +35 -0
- iotsploit_django-0.0.6/src/iotsploit_django/adapters/django/device_models.py +251 -0
- iotsploit_django-0.0.6/src/iotsploit_django/adapters/django/device_registry_factory.py +13 -0
- iotsploit_django-0.0.6/src/iotsploit_django/adapters/django/driver_state_repo.py +62 -0
- iotsploit_django-0.0.6/src/iotsploit_django/adapters/django/exploit_manager_factory.py +33 -0
- iotsploit_django-0.0.6/src/iotsploit_django/adapters/django/iot_fuzzer/__init__.py +3 -0
- iotsploit_django-0.0.6/src/iotsploit_django/adapters/django/iot_fuzzer/models.py +821 -0
- iotsploit_django-0.0.6/src/iotsploit_django/adapters/django/plugins/__init__.py +3 -0
- iotsploit_django-0.0.6/src/iotsploit_django/adapters/django/plugins/models.py +183 -0
- iotsploit_django-0.0.6/src/iotsploit_django/adapters/django/plugins/repos.py +130 -0
- iotsploit_django-0.0.6/src/iotsploit_django/adapters/django/sqlalchemy_database.py +20 -0
- iotsploit_django-0.0.6/src/iotsploit_django/adapters/django/stream_manager.py +132 -0
- iotsploit_django-0.0.6/src/iotsploit_django/adapters/django/target_models.py +395 -0
- iotsploit_django-0.0.6/src/iotsploit_django/adapters/django/task_runner.py +27 -0
- iotsploit_django-0.0.6/src/iotsploit_django/adapters/memory/__init__.py +3 -0
- iotsploit_django-0.0.6/src/iotsploit_django/adapters/memory/driver_state_repo.py +20 -0
- iotsploit_django-0.0.6/src/iotsploit_django/adapters/memory/repos.py +41 -0
- iotsploit_django-0.0.6/src/iotsploit_django/adapters/memory/task_runner.py +29 -0
- iotsploit_django-0.0.6/src/iotsploit_django/adapters/sqlalchemy/__init__.py +3 -0
- iotsploit_django-0.0.6/src/iotsploit_django/adapters/sqlalchemy/database.py +29 -0
- iotsploit_django-0.0.6/src/iotsploit_django/apps.py +8 -0
- iotsploit_django-0.0.6/src/iotsploit_django/asgi.py +29 -0
- iotsploit_django-0.0.6/src/iotsploit_django/composition_root/__init__.py +7 -0
- iotsploit_django-0.0.6/src/iotsploit_django/composition_root/core_container.py +87 -0
- iotsploit_django-0.0.6/src/iotsploit_django/composition_root/fuzzer_container.py +32 -0
- iotsploit_django-0.0.6/src/iotsploit_django/composition_root/wiring.py +66 -0
- iotsploit_django-0.0.6/src/iotsploit_django/config.py +18 -0
- iotsploit_django-0.0.6/src/iotsploit_django/consumers.py +31 -0
- iotsploit_django-0.0.6/src/iotsploit_django/iot_fuzzer/__init__.py +3 -0
- iotsploit_django-0.0.6/src/iotsploit_django/iot_fuzzer/mappers.py +20 -0
- iotsploit_django-0.0.6/src/iotsploit_django/iot_fuzzer/service.py +10 -0
- iotsploit_django-0.0.6/src/iotsploit_django/iot_fuzzer/urls.py +215 -0
- iotsploit_django-0.0.6/src/iotsploit_django/iot_fuzzer/views.py +2385 -0
- iotsploit_django-0.0.6/src/iotsploit_django/migrations/0001_initial.py +437 -0
- iotsploit_django-0.0.6/src/iotsploit_django/migrations/__init__.py +0 -0
- iotsploit_django-0.0.6/src/iotsploit_django/models/AIModel_Model.py +313 -0
- iotsploit_django-0.0.6/src/iotsploit_django/models/ClassifiedInfo_Model.py +30 -0
- iotsploit_django-0.0.6/src/iotsploit_django/models/DoIP_Diagnostic_Database_Model.py +411 -0
- iotsploit_django-0.0.6/src/iotsploit_django/models/PassCondition_Model.py +23 -0
- iotsploit_django-0.0.6/src/iotsploit_django/models/Vehicle_Model.py +116 -0
- iotsploit_django-0.0.6/src/iotsploit_django/models/__init__.py +13 -0
- iotsploit_django-0.0.6/src/iotsploit_django/models.py +23 -0
- iotsploit_django-0.0.6/src/iotsploit_django/ports_impl/__init__.py +7 -0
- iotsploit_django-0.0.6/src/iotsploit_django/ports_impl/driver_state_repo.py +7 -0
- iotsploit_django-0.0.6/src/iotsploit_django/ports_impl/plugin_repo.py +12 -0
- iotsploit_django-0.0.6/src/iotsploit_django/ports_impl/stream_backend.py +7 -0
- iotsploit_django-0.0.6/src/iotsploit_django/ports_impl/task_runner.py +7 -0
- iotsploit_django-0.0.6/src/iotsploit_django/routing.py +24 -0
- iotsploit_django-0.0.6/src/iotsploit_django/settings/__init__.py +3 -0
- iotsploit_django-0.0.6/src/iotsploit_django/settings/base.py +160 -0
- iotsploit_django-0.0.6/src/iotsploit_django/settings/dev.py +5 -0
- iotsploit_django-0.0.6/src/iotsploit_django/settings/prod.py +5 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tasks/__init__.py +13 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tasks/celery_app.py +46 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tasks/fuzzer_tasks.py +20 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tasks/legacy_tasks_impl.py +420 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tasks/plugin_tasks.py +119 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tests/__init__.py +2 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tests/test_contracts_stage55.py +43 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/__init__.py +0 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/adb_mgr.py +907 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/apt_mgr.py +74 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/bash_script_engine.py +190 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/bluetooth_mgr.py +319 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/device_info.py +30 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/discovery_server.py +163 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/doip_mgr.py +500 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/env_mgr.py +207 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/file_obfuscator_service.py +245 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/input_mgr.py +314 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/iot_fuzzer_bridge.py +567 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/iot_fuzzer_manager.py +998 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/iot_fuzzer_service.py +1199 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/iot_protocol_adapter.py +1415 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/monitor_mgr.py +185 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/net_audit_mgr.py +373 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/obd_test.py +807 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/ota_mgr.py +63 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/plugin_sudo_runner.py +161 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/privilege_mgr.py +218 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/python_submodule_engine.py +136 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/report_mgr.py +725 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/sat_utils.py +113 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/ssh_mgr.py +109 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/third_party/INA219.py +213 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/usb_mgr.py +60 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/utils/__init__.py +23 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/vehicle_utils.py +373 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/wifi_mgr.py +404 -0
- iotsploit_django-0.0.6/src/iotsploit_django/tools/xlogger.py +122 -0
- iotsploit_django-0.0.6/src/iotsploit_django/urls.py +18 -0
- iotsploit_django-0.0.6/src/iotsploit_django/view_handlers/__init__.py +4 -0
- iotsploit_django-0.0.6/src/iotsploit_django/view_handlers/ai_model_views.py +493 -0
- iotsploit_django-0.0.6/src/iotsploit_django/view_handlers/console_logs_views.py +139 -0
- iotsploit_django-0.0.6/src/iotsploit_django/view_handlers/device_views.py +246 -0
- iotsploit_django-0.0.6/src/iotsploit_django/view_handlers/file_views.py +264 -0
- iotsploit_django-0.0.6/src/iotsploit_django/view_handlers/firmware_views.py +473 -0
- iotsploit_django-0.0.6/src/iotsploit_django/view_handlers/target_views.py +388 -0
- iotsploit_django-0.0.6/src/iotsploit_django/view_handlers/vehicle_views.py +16 -0
- iotsploit_django-0.0.6/src/iotsploit_django/web/__init__.py +4 -0
- iotsploit_django-0.0.6/src/iotsploit_django/web/api/__init__.py +3 -0
- iotsploit_django-0.0.6/src/iotsploit_django/web/api/ai_urls.py +30 -0
- iotsploit_django-0.0.6/src/iotsploit_django/web/api/console_logs_urls.py +16 -0
- iotsploit_django-0.0.6/src/iotsploit_django/web/api/devices_urls.py +25 -0
- iotsploit_django-0.0.6/src/iotsploit_django/web/api/files_urls.py +19 -0
- iotsploit_django-0.0.6/src/iotsploit_django/web/api/firmware_urls.py +30 -0
- iotsploit_django-0.0.6/src/iotsploit_django/web/api/misc_urls.py +15 -0
- iotsploit_django-0.0.6/src/iotsploit_django/web/api/plugins_urls.py +53 -0
- iotsploit_django-0.0.6/src/iotsploit_django/web/api/recovery_urls.py +12 -0
- iotsploit_django-0.0.6/src/iotsploit_django/web/api/targets_urls.py +26 -0
- iotsploit_django-0.0.6/src/iotsploit_django/web/api/tools_urls.py +14 -0
- iotsploit_django-0.0.6/src/iotsploit_django/web/api/urls.py +24 -0
- iotsploit_django-0.0.6/src/iotsploit_django/web/api/vehicle_urls.py +10 -0
- iotsploit_django-0.0.6/src/iotsploit_django/web/views.py +2048 -0
- iotsploit_django-0.0.6/src/iotsploit_django/websocket/__init__.py +3 -0
- iotsploit_django-0.0.6/src/iotsploit_django/websocket/ai_assistant_consumer.py +7 -0
- iotsploit_django-0.0.6/src/iotsploit_django/websocket/ai_assistant_consumer_impl.py +764 -0
- iotsploit_django-0.0.6/src/iotsploit_django/websocket/consumers.py +29 -0
- iotsploit_django-0.0.6/src/iotsploit_django/websocket/consumers_impl.py +728 -0
- iotsploit_django-0.0.6/src/iotsploit_django/websocket/routing.py +21 -0
- iotsploit_django-0.0.6/src/iotsploit_django/wsgi.py +15 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: iotsploit-django
|
|
3
|
+
Version: 0.0.6
|
|
4
|
+
Summary: IoTSploit Django ring package (HTTP/WS/ORM/Celery + composition root)
|
|
5
|
+
License: GPL-3.0-or-later
|
|
6
|
+
Keywords: iot,security,testing,pentest,django
|
|
7
|
+
Author: IoTSploit Team
|
|
8
|
+
Author-email: support@iotsploit.org
|
|
9
|
+
Requires-Python: >=3.10,<4.0
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Intended Audience :: Information Technology
|
|
13
|
+
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Security
|
|
20
|
+
Classifier: Topic :: System :: Hardware
|
|
21
|
+
Provides-Extra: platforms
|
|
22
|
+
Requires-Dist: Django (>=4.2,<5.0)
|
|
23
|
+
Requires-Dist: SQLAlchemy (>=2.0)
|
|
24
|
+
Requires-Dist: aiohttp (>=3.9)
|
|
25
|
+
Requires-Dist: asgiref (>=3.7)
|
|
26
|
+
Requires-Dist: bluepy (>=1.3)
|
|
27
|
+
Requires-Dist: celery (>=5.3)
|
|
28
|
+
Requires-Dist: channels (>=4.0)
|
|
29
|
+
Requires-Dist: channels-redis (>=4.1)
|
|
30
|
+
Requires-Dist: colorlog (>=6.8)
|
|
31
|
+
Requires-Dist: cryptography (>=41.0)
|
|
32
|
+
Requires-Dist: daphne (>=4.0)
|
|
33
|
+
Requires-Dist: django-cors-headers (>=4.0)
|
|
34
|
+
Requires-Dist: django-csp (>=3.7,<4.0)
|
|
35
|
+
Requires-Dist: django-extensions (>=3.2)
|
|
36
|
+
Requires-Dist: elevate (>=0.1)
|
|
37
|
+
Requires-Dist: iotsploit-core (>=0.0.6,<0.0.7)
|
|
38
|
+
Requires-Dist: iotsploit-platforms (>=0.0.6,<0.0.7) ; extra == "platforms"
|
|
39
|
+
Requires-Dist: mistune (>=3.0)
|
|
40
|
+
Requires-Dist: netifaces (>=0.11)
|
|
41
|
+
Requires-Dist: psutil (>=5.9)
|
|
42
|
+
Requires-Dist: pwntools (>=4.11)
|
|
43
|
+
Requires-Dist: pydantic (>=2.0)
|
|
44
|
+
Requires-Dist: pyusb (>=1.2)
|
|
45
|
+
Requires-Dist: pywifi (>=1.1)
|
|
46
|
+
Requires-Dist: redis (>=5.0)
|
|
47
|
+
Requires-Dist: requests (>=2.31)
|
|
48
|
+
Requires-Dist: smbus2 (>=0.4)
|
|
49
|
+
Project-URL: Documentation, https://www.iotsploit.org/
|
|
50
|
+
Project-URL: Homepage, https://www.iotsploit.org/
|
|
51
|
+
Project-URL: Repository, https://github.com/TKXB/iotsploit
|
|
52
|
+
Description-Content-Type: text/markdown
|
|
53
|
+
|
|
54
|
+
# iotsploit-django
|
|
55
|
+
|
|
56
|
+
`iotsploit-django` 是 IoTSploit 项目的 **Django 外圈(ring)**包:负责 HTTP/WS、ORM、Celery、Redis、以及对 `iotsploit-core` / `iosploit-fuzzer` 的组装注入(composition root)。
|
|
57
|
+
|
|
58
|
+
> 当前:`iotsploit-django` 已成为 Django 外圈宿主(settings/urls/asgi/celery/ws/models 等已迁入),不再依赖 `sat_toolkit` 作为 Django app。
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# iotsploit-django
|
|
2
|
+
|
|
3
|
+
`iotsploit-django` 是 IoTSploit 项目的 **Django 外圈(ring)**包:负责 HTTP/WS、ORM、Celery、Redis、以及对 `iotsploit-core` / `iosploit-fuzzer` 的组装注入(composition root)。
|
|
4
|
+
|
|
5
|
+
> 当前:`iotsploit-django` 已成为 Django 外圈宿主(settings/urls/asgi/celery/ws/models 等已迁入),不再依赖 `sat_toolkit` 作为 Django app。
|
|
6
|
+
|
|
7
|
+
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
[tool.poetry]
|
|
2
|
+
name = "iotsploit-django"
|
|
3
|
+
version = "0.0.6"
|
|
4
|
+
description = "IoTSploit Django ring package (HTTP/WS/ORM/Celery + composition root)"
|
|
5
|
+
authors = ["IoTSploit Team <support@iotsploit.org>"]
|
|
6
|
+
readme = "README.md"
|
|
7
|
+
license = "GPL-3.0-or-later"
|
|
8
|
+
homepage = "https://www.iotsploit.org/"
|
|
9
|
+
repository = "https://github.com/TKXB/iotsploit"
|
|
10
|
+
documentation = "https://www.iotsploit.org/"
|
|
11
|
+
keywords = ["iot", "security", "testing", "pentest", "django"]
|
|
12
|
+
classifiers = [
|
|
13
|
+
"Development Status :: 3 - Alpha",
|
|
14
|
+
"Intended Audience :: Developers",
|
|
15
|
+
"Intended Audience :: Information Technology",
|
|
16
|
+
"License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
|
|
17
|
+
"Topic :: Security",
|
|
18
|
+
"Topic :: System :: Hardware",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.10",
|
|
21
|
+
"Programming Language :: Python :: 3.11",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
]
|
|
24
|
+
packages = [{ include = "iotsploit_django", from = "src" }]
|
|
25
|
+
|
|
26
|
+
[tool.poetry.dependencies]
|
|
27
|
+
python = ">=3.10,<4.0"
|
|
28
|
+
iotsploit-core = "^0.0.6"
|
|
29
|
+
iotsploit-platforms = { version = "^0.0.6", optional = true }
|
|
30
|
+
Django = ">=4.2,<5.0"
|
|
31
|
+
channels = ">=4.0"
|
|
32
|
+
celery = ">=5.3"
|
|
33
|
+
redis = ">=5.0"
|
|
34
|
+
channels-redis = ">=4.1"
|
|
35
|
+
daphne = ">=4.0"
|
|
36
|
+
django-extensions = ">=3.2"
|
|
37
|
+
django-cors-headers = ">=4.0"
|
|
38
|
+
django-csp = ">=3.7,<4.0"
|
|
39
|
+
mistune = ">=3.0"
|
|
40
|
+
colorlog = ">=6.8"
|
|
41
|
+
SQLAlchemy = ">=2.0"
|
|
42
|
+
netifaces = ">=0.11"
|
|
43
|
+
psutil = ">=5.9"
|
|
44
|
+
requests = ">=2.31"
|
|
45
|
+
cryptography = ">=41.0"
|
|
46
|
+
pydantic = ">=2.0"
|
|
47
|
+
aiohttp = ">=3.9"
|
|
48
|
+
asgiref = ">=3.7"
|
|
49
|
+
elevate = ">=0.1"
|
|
50
|
+
pwntools = ">=4.11"
|
|
51
|
+
bluepy = ">=1.3"
|
|
52
|
+
pywifi = ">=1.1"
|
|
53
|
+
smbus2 = ">=0.4"
|
|
54
|
+
pyusb = ">=1.2"
|
|
55
|
+
|
|
56
|
+
[tool.poetry.extras]
|
|
57
|
+
platforms = ["iotsploit-platforms"]
|
|
58
|
+
|
|
59
|
+
[tool.poetry.group.dev.dependencies]
|
|
60
|
+
pytest = "^7.4.0"
|
|
61
|
+
|
|
62
|
+
[build-system]
|
|
63
|
+
requires = ["poetry-core>=1.8.0"]
|
|
64
|
+
build-backend = "poetry.core.masonry.api"
|
|
65
|
+
|
|
66
|
+
[tool.pytest.ini_options]
|
|
67
|
+
testpaths = ["tests"]
|
|
68
|
+
addopts = ["-q"]
|
|
File without changes
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from iotsploit_django.adapters.django.driver_state_repo import DjangoDriverStateRepository
|
|
6
|
+
from iotsploit_django.adapters.memory.driver_state_repo import MemoryDriverStateRepository
|
|
7
|
+
from iotsploit_core.core.device_manager import DeviceDriverManager
|
|
8
|
+
from iotsploit_django.config import DEVICE_PLUGINS_DIR
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_device_driver_manager(
|
|
12
|
+
*,
|
|
13
|
+
plugins_dir: str | Path | None = None,
|
|
14
|
+
usb_config_file: str | Path | None = None,
|
|
15
|
+
use_persistence: bool = True,
|
|
16
|
+
) -> DeviceDriverManager:
|
|
17
|
+
"""Composition root for Django runtime.
|
|
18
|
+
|
|
19
|
+
Core `DeviceDriverManager` is framework-free; this wires persistence adapters.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
repo = DjangoDriverStateRepository() if use_persistence else MemoryDriverStateRepository()
|
|
23
|
+
# Ensure stable defaults regardless of CWD (Django/gunicorn may change working directory).
|
|
24
|
+
if plugins_dir is None:
|
|
25
|
+
plugins_dir = DEVICE_PLUGINS_DIR
|
|
26
|
+
if usb_config_file is None:
|
|
27
|
+
# repo_root/conf/usb_devices.json
|
|
28
|
+
usb_config_file = str(Path(__file__).resolve().parents[3] / "conf" / "usb_devices.json")
|
|
29
|
+
return DeviceDriverManager(
|
|
30
|
+
driver_state_repo=repo,
|
|
31
|
+
plugins_dir=plugins_dir,
|
|
32
|
+
usb_config_file=usb_config_file,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
"""
|
|
2
|
+
SQLAlchemy ORM mappings for Device domain (adapter layer).
|
|
3
|
+
|
|
4
|
+
Kept under Django adapters because runtime wiring currently uses Django settings to locate DB.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import datetime
|
|
10
|
+
import json
|
|
11
|
+
import os
|
|
12
|
+
from typing import Any, Dict, List, Optional, Type
|
|
13
|
+
|
|
14
|
+
from sqlalchemy import Boolean, Column, DateTime, Enum as SQLAlchemyEnum, JSON, String
|
|
15
|
+
|
|
16
|
+
from iotsploit_django.adapters.django.sqlalchemy_database import get_default_sqlalchemy_db
|
|
17
|
+
from iotsploit_core.domain.device import Device, DeviceType, SerialDevice, SocketCANDevice, USBDevice
|
|
18
|
+
from iotsploit_django.tools.xlogger import xlog
|
|
19
|
+
|
|
20
|
+
_db = get_default_sqlalchemy_db()
|
|
21
|
+
Base = _db.Base
|
|
22
|
+
engine = _db.engine
|
|
23
|
+
SessionLocal = _db.SessionLocal
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class DeviceDBModel(Base):
|
|
27
|
+
__tablename__ = "devices"
|
|
28
|
+
|
|
29
|
+
device_id = Column(String, primary_key=True)
|
|
30
|
+
name = Column(String)
|
|
31
|
+
device_type = Column(SQLAlchemyEnum(DeviceType))
|
|
32
|
+
attributes = Column(JSON)
|
|
33
|
+
|
|
34
|
+
__mapper_args__ = {"polymorphic_on": device_type, "polymorphic_identity": "device"}
|
|
35
|
+
|
|
36
|
+
def __init__(self, device: Device):
|
|
37
|
+
self.device_id = device.device_id
|
|
38
|
+
self.name = device.name
|
|
39
|
+
self.device_type = device.device_type
|
|
40
|
+
self.attributes = device.attributes
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class SerialDeviceDBModel(DeviceDBModel):
|
|
44
|
+
__mapper_args__ = {"polymorphic_identity": DeviceType.Serial}
|
|
45
|
+
|
|
46
|
+
def __init__(self, device: SerialDevice):
|
|
47
|
+
super().__init__(device)
|
|
48
|
+
self.attributes["port"] = device.port
|
|
49
|
+
self.attributes["baud_rate"] = device.baud_rate
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class USBDeviceDBModel(DeviceDBModel):
|
|
53
|
+
__mapper_args__ = {"polymorphic_identity": DeviceType.USB}
|
|
54
|
+
|
|
55
|
+
def __init__(self, device: USBDevice):
|
|
56
|
+
super().__init__(device)
|
|
57
|
+
self.attributes["vendor_id"] = device.vendor_id
|
|
58
|
+
self.attributes["product_id"] = device.product_id
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class CANDeviceDBModel(DeviceDBModel):
|
|
62
|
+
__mapper_args__ = {"polymorphic_identity": DeviceType.CAN}
|
|
63
|
+
|
|
64
|
+
def __init__(self, device: SocketCANDevice):
|
|
65
|
+
super().__init__(device)
|
|
66
|
+
self.attributes["interface"] = device.interface
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class DeviceManager:
|
|
70
|
+
_instance = None
|
|
71
|
+
|
|
72
|
+
def __new__(cls):
|
|
73
|
+
if cls._instance is None:
|
|
74
|
+
cls._instance = super(DeviceManager, cls).__new__(cls)
|
|
75
|
+
cls._instance.initialize()
|
|
76
|
+
return cls._instance
|
|
77
|
+
|
|
78
|
+
def initialize(self):
|
|
79
|
+
self.devices: Dict[DeviceType, Type[Device]] = {}
|
|
80
|
+
Base.metadata.create_all(engine)
|
|
81
|
+
self.Session = SessionLocal
|
|
82
|
+
self.current_device: Optional[Device] = None
|
|
83
|
+
|
|
84
|
+
@classmethod
|
|
85
|
+
def get_instance(cls):
|
|
86
|
+
return cls()
|
|
87
|
+
|
|
88
|
+
def register_device(self, device_type: DeviceType, device_class: Type[Device]):
|
|
89
|
+
self.devices[device_type] = device_class
|
|
90
|
+
|
|
91
|
+
def create_device(self, device_type: DeviceType, **kwargs) -> Device:
|
|
92
|
+
if device_type in self.devices:
|
|
93
|
+
device_class = self.devices[device_type]
|
|
94
|
+
device = device_class(**kwargs)
|
|
95
|
+
self.save_device(device)
|
|
96
|
+
return device
|
|
97
|
+
raise ValueError(f"No device type registered for: {device_type}")
|
|
98
|
+
|
|
99
|
+
def save_device(self, device: Device):
|
|
100
|
+
session = self.Session()
|
|
101
|
+
try:
|
|
102
|
+
existing_device = session.query(DeviceDBModel).filter_by(device_id=device.device_id).first()
|
|
103
|
+
if existing_device:
|
|
104
|
+
xlog.info(
|
|
105
|
+
f"Device with device_id '{device.device_id}' already exists. Skipping insertion.",
|
|
106
|
+
name="device_model",
|
|
107
|
+
)
|
|
108
|
+
return
|
|
109
|
+
|
|
110
|
+
if isinstance(device, SerialDevice):
|
|
111
|
+
device_model = SerialDeviceDBModel(device)
|
|
112
|
+
elif isinstance(device, USBDevice):
|
|
113
|
+
device_model = USBDeviceDBModel(device)
|
|
114
|
+
elif isinstance(device, SocketCANDevice):
|
|
115
|
+
device_model = CANDeviceDBModel(device)
|
|
116
|
+
else:
|
|
117
|
+
device_model = DeviceDBModel(device)
|
|
118
|
+
|
|
119
|
+
session.add(device_model)
|
|
120
|
+
session.commit()
|
|
121
|
+
xlog.info(
|
|
122
|
+
f"Device with device_id '{device.device_id}' has been added to the database.",
|
|
123
|
+
name="device_model",
|
|
124
|
+
)
|
|
125
|
+
except Exception as e:
|
|
126
|
+
session.rollback()
|
|
127
|
+
xlog.error(f"An error occurred while saving device '{device.device_id}': {e}", name="device_model")
|
|
128
|
+
raise
|
|
129
|
+
finally:
|
|
130
|
+
session.close()
|
|
131
|
+
|
|
132
|
+
def get_all_devices(self) -> List[Dict[str, Any]]:
|
|
133
|
+
session = self.Session()
|
|
134
|
+
try:
|
|
135
|
+
devices = session.query(DeviceDBModel).all()
|
|
136
|
+
result = []
|
|
137
|
+
for d in devices:
|
|
138
|
+
if d.device_type == DeviceType.Serial:
|
|
139
|
+
device = SerialDevice(
|
|
140
|
+
device_id=d.device_id,
|
|
141
|
+
name=d.name,
|
|
142
|
+
port=d.attributes.get("port", ""),
|
|
143
|
+
baud_rate=d.attributes.get("baud_rate", 115200),
|
|
144
|
+
attributes=d.attributes,
|
|
145
|
+
)
|
|
146
|
+
elif d.device_type == DeviceType.USB:
|
|
147
|
+
device = USBDevice(
|
|
148
|
+
device_id=d.device_id,
|
|
149
|
+
name=d.name,
|
|
150
|
+
vendor_id=d.attributes.get("vendor_id", ""),
|
|
151
|
+
product_id=d.attributes.get("product_id", ""),
|
|
152
|
+
attributes=d.attributes,
|
|
153
|
+
)
|
|
154
|
+
elif d.device_type == DeviceType.CAN:
|
|
155
|
+
device = SocketCANDevice(
|
|
156
|
+
device_id=d.device_id,
|
|
157
|
+
name=d.name,
|
|
158
|
+
interface=d.attributes.get("interface", "can0"),
|
|
159
|
+
attributes=d.attributes,
|
|
160
|
+
)
|
|
161
|
+
else:
|
|
162
|
+
device = Device(
|
|
163
|
+
device_id=d.device_id,
|
|
164
|
+
name=d.name,
|
|
165
|
+
device_type=d.device_type,
|
|
166
|
+
attributes=d.attributes,
|
|
167
|
+
)
|
|
168
|
+
result.append(device.to_dict())
|
|
169
|
+
return result
|
|
170
|
+
except Exception as e:
|
|
171
|
+
xlog.error(f"Error getting devices: {e}", name="device_model")
|
|
172
|
+
return []
|
|
173
|
+
finally:
|
|
174
|
+
session.close()
|
|
175
|
+
|
|
176
|
+
def parse_and_set_device_from_json(self, json_file_path: str):
|
|
177
|
+
import warnings
|
|
178
|
+
|
|
179
|
+
warnings.warn(
|
|
180
|
+
"parse_and_set_device_from_json is deprecated. "
|
|
181
|
+
"Devices are now auto-discovered by drivers or use 'device_import' CLI command.",
|
|
182
|
+
DeprecationWarning,
|
|
183
|
+
stacklevel=2,
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
if not os.path.exists(json_file_path):
|
|
187
|
+
xlog.error(f"File not found: {json_file_path}", name="device_model")
|
|
188
|
+
return
|
|
189
|
+
|
|
190
|
+
with open(json_file_path, "r") as file:
|
|
191
|
+
data = json.load(file)
|
|
192
|
+
|
|
193
|
+
imported_count = 0
|
|
194
|
+
for device in data.get("devices", []):
|
|
195
|
+
device_type = DeviceType(device.get("device_type", "USB"))
|
|
196
|
+
device_class = self.devices.get(device_type, Device)
|
|
197
|
+
|
|
198
|
+
device_data: Dict[str, Any] = {
|
|
199
|
+
"device_id": device.get("device_id"),
|
|
200
|
+
"name": device.get("name"),
|
|
201
|
+
"attributes": device.get("attributes", {}),
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if device_type == DeviceType.Serial:
|
|
205
|
+
device_data["port"] = device.get("port")
|
|
206
|
+
device_data["baud_rate"] = device.get("baud_rate")
|
|
207
|
+
elif device_type == DeviceType.USB:
|
|
208
|
+
device_data["vendor_id"] = device.get("vendor_id")
|
|
209
|
+
device_data["product_id"] = device.get("product_id")
|
|
210
|
+
elif device_type == DeviceType.CAN:
|
|
211
|
+
device_data["interface"] = device.get("interface", "can0")
|
|
212
|
+
|
|
213
|
+
device_instance = self.create_device(device_type, **device_data)
|
|
214
|
+
self.current_device = device_instance
|
|
215
|
+
imported_count += 1
|
|
216
|
+
|
|
217
|
+
xlog.info(
|
|
218
|
+
f"Imported {imported_count} devices from JSON file: {json_file_path}",
|
|
219
|
+
name="device_model",
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
def get_current_device(self) -> Optional[Device]:
|
|
223
|
+
return self.current_device
|
|
224
|
+
|
|
225
|
+
def set_current_device(self, device: Device):
|
|
226
|
+
self.current_device = device
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
class DeviceDriverState(Base):
|
|
230
|
+
__tablename__ = "device_driver_states"
|
|
231
|
+
|
|
232
|
+
driver_name = Column(String, primary_key=True)
|
|
233
|
+
enabled = Column(Boolean, default=True)
|
|
234
|
+
description = Column(String, nullable=True)
|
|
235
|
+
last_updated = Column(DateTime, default=lambda: datetime.datetime.now())
|
|
236
|
+
|
|
237
|
+
def __init__(self, driver_name, enabled=True, description=None):
|
|
238
|
+
self.driver_name = driver_name
|
|
239
|
+
self.enabled = enabled
|
|
240
|
+
self.description = description
|
|
241
|
+
self.last_updated = datetime.datetime.now()
|
|
242
|
+
|
|
243
|
+
def to_dict(self):
|
|
244
|
+
return {
|
|
245
|
+
"driver_name": self.driver_name,
|
|
246
|
+
"enabled": self.enabled,
|
|
247
|
+
"description": self.description,
|
|
248
|
+
"last_updated": str(self.last_updated),
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from iotsploit_django.adapters.django.device_driver_manager_factory import get_device_driver_manager
|
|
4
|
+
from iotsploit_core.core.device_registry import DeviceRegistry
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def get_device_registry(*, use_persistence: bool = True) -> DeviceRegistry:
|
|
8
|
+
"""Composition root for Django runtime."""
|
|
9
|
+
|
|
10
|
+
driver_manager = get_device_driver_manager(use_persistence=use_persistence)
|
|
11
|
+
return DeviceRegistry.get_instance(driver_manager=driver_manager)
|
|
12
|
+
|
|
13
|
+
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import datetime
|
|
4
|
+
|
|
5
|
+
from iotsploit_django.adapters.django.device_models import DeviceDriverState
|
|
6
|
+
from iotsploit_django.adapters.django.sqlalchemy_database import get_default_sqlalchemy_db
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class DjangoDriverStateRepository:
|
|
10
|
+
"""SQLAlchemy-backed driver state repo (adapter layer).
|
|
11
|
+
|
|
12
|
+
NOTE: This uses the SQLAlchemy DB factory that is configured via Django settings.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
def __init__(self) -> None:
|
|
16
|
+
self._db = get_default_sqlalchemy_db()
|
|
17
|
+
# Ensure the table exists; previously this was implicitly created via other model managers.
|
|
18
|
+
try:
|
|
19
|
+
self._db.Base.metadata.create_all(self._db.engine)
|
|
20
|
+
except Exception:
|
|
21
|
+
# Keep repository resilient; callers will treat missing persistence as "no saved states".
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
def get_enabled(self, driver_name: str) -> bool | None:
|
|
25
|
+
session = self._db.SessionLocal()
|
|
26
|
+
try:
|
|
27
|
+
row = session.query(DeviceDriverState).filter_by(driver_name=driver_name).first()
|
|
28
|
+
return None if row is None else bool(row.enabled)
|
|
29
|
+
except Exception:
|
|
30
|
+
return None
|
|
31
|
+
finally:
|
|
32
|
+
session.close()
|
|
33
|
+
|
|
34
|
+
def set_enabled(self, driver_name: str, enabled: bool, description: str | None = None) -> None:
|
|
35
|
+
session = self._db.SessionLocal()
|
|
36
|
+
try:
|
|
37
|
+
row = session.query(DeviceDriverState).filter_by(driver_name=driver_name).first()
|
|
38
|
+
if row:
|
|
39
|
+
row.enabled = bool(enabled)
|
|
40
|
+
row.last_updated = datetime.datetime.now()
|
|
41
|
+
if description is not None:
|
|
42
|
+
row.description = description
|
|
43
|
+
else:
|
|
44
|
+
row = DeviceDriverState(driver_name=driver_name, enabled=bool(enabled), description=description)
|
|
45
|
+
session.add(row)
|
|
46
|
+
session.commit()
|
|
47
|
+
except Exception:
|
|
48
|
+
session.rollback()
|
|
49
|
+
finally:
|
|
50
|
+
session.close()
|
|
51
|
+
|
|
52
|
+
def list_enabled(self) -> dict[str, bool]:
|
|
53
|
+
session = self._db.SessionLocal()
|
|
54
|
+
try:
|
|
55
|
+
rows = session.query(DeviceDriverState).all()
|
|
56
|
+
return {r.driver_name: bool(r.enabled) for r in rows}
|
|
57
|
+
except Exception:
|
|
58
|
+
return {}
|
|
59
|
+
finally:
|
|
60
|
+
session.close()
|
|
61
|
+
|
|
62
|
+
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from iotsploit_django.adapters.django.plugins.repos import DjangoPluginGroupRepository, DjangoPluginMetaRepository
|
|
6
|
+
from iotsploit_django.adapters.django.task_runner import CeleryTaskRunner
|
|
7
|
+
from iotsploit_django.adapters.memory.task_runner import InProcessTaskRunner
|
|
8
|
+
from iotsploit_core.core.exploit_manager import ExploitPluginManager
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_exploit_plugin_manager(
|
|
12
|
+
*,
|
|
13
|
+
plugins_dir: str | Path | None = None,
|
|
14
|
+
use_celery: bool = True,
|
|
15
|
+
) -> ExploitPluginManager:
|
|
16
|
+
"""Composition root for Django runtime.
|
|
17
|
+
|
|
18
|
+
Core `ExploitPluginManager` is framework-free; this function wires Django ORM repos
|
|
19
|
+
and (optionally) Celery as the TaskRunner.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
repo = DjangoPluginMetaRepository()
|
|
23
|
+
group_repo = DjangoPluginGroupRepository()
|
|
24
|
+
runner = CeleryTaskRunner() if use_celery else InProcessTaskRunner()
|
|
25
|
+
|
|
26
|
+
return ExploitPluginManager(
|
|
27
|
+
plugin_repo=repo,
|
|
28
|
+
group_repo=group_repo,
|
|
29
|
+
task_runner=runner,
|
|
30
|
+
plugins_dir=plugins_dir,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|