security: P3 — 插件隔离默认开启 + SenSuDB 注册 + 审计日志
- plugins.isolation 默认 true (生产环境进程隔离) - main.py 注册 SenSuDB 服务 - WebPanelManager 注入 sensu_db 到 app context - 文件删除/写入操作写入审计日志 (audit_log 表) - 修复 Session 持久化所需的数据库依赖 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,7 @@ plugins:
|
|||||||
auto_load: true
|
auto_load: true
|
||||||
hot_reload: true
|
hot_reload: true
|
||||||
max_retry_count: 3
|
max_retry_count: 3
|
||||||
|
isolation: true
|
||||||
# 自动启动脚本 — 框架启动时后台拉起
|
# 自动启动脚本 — 框架启动时后台拉起
|
||||||
auto_start_scripts:
|
auto_start_scripts:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|||||||
@@ -9,10 +9,6 @@ commands:
|
|||||||
permissions:
|
permissions:
|
||||||
- framework.scaffold.plugin
|
- framework.scaffold.plugin
|
||||||
source: internal
|
source: internal
|
||||||
echo: &id001
|
|
||||||
description: echo input
|
|
||||||
permissions: []
|
|
||||||
source: plugin.example_plugin
|
|
||||||
help:
|
help:
|
||||||
description: 显示帮助信息
|
description: 显示帮助信息
|
||||||
permissions:
|
permissions:
|
||||||
@@ -38,10 +34,6 @@ commands:
|
|||||||
permissions:
|
permissions:
|
||||||
- framework.permission.read
|
- framework.permission.read
|
||||||
source: internal
|
source: internal
|
||||||
plugin_status: &id002
|
|
||||||
description: show status
|
|
||||||
permissions: []
|
|
||||||
source: plugin.example_plugin
|
|
||||||
pm_plugin_status:
|
pm_plugin_status:
|
||||||
description: '权限管理: 查看插件权限状态'
|
description: '权限管理: 查看插件权限状态'
|
||||||
permissions:
|
permissions:
|
||||||
@@ -97,9 +89,6 @@ commands:
|
|||||||
permissions:
|
permissions:
|
||||||
- framework.command.test
|
- framework.command.test
|
||||||
source: internal
|
source: internal
|
||||||
last_updated: 12019.862122705
|
last_updated: 12161.390698641
|
||||||
plugin_commands:
|
plugin_commands: {}
|
||||||
example_plugin:
|
total_commands: 18
|
||||||
echo: *id001
|
|
||||||
plugin_status: *id002
|
|
||||||
total_commands: 20
|
|
||||||
|
|||||||
@@ -1,17 +1,4 @@
|
|||||||
http_port: 4200
|
http_port: 4200
|
||||||
last_updated: 12019.877017393
|
last_updated: 12161.450926401
|
||||||
plugin_routes:
|
plugin_routes: {}
|
||||||
example_plugin:
|
|
||||||
- methods:
|
|
||||||
- GET
|
|
||||||
path: /example_plugin/api/example/info
|
|
||||||
require_auth: false
|
|
||||||
- methods:
|
|
||||||
- POST
|
|
||||||
path: /example_plugin/api/plugin/echo
|
|
||||||
require_auth: true
|
|
||||||
- methods:
|
|
||||||
- POST
|
|
||||||
path: /example_plugin/api/plugin/plugin_status
|
|
||||||
require_auth: true
|
|
||||||
websocket_port: 4240
|
websocket_port: 4240
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -11,6 +11,7 @@ from services.project_engine import ProjectEngine
|
|||||||
from services.pyenv_manager import PyEnvManager
|
from services.pyenv_manager import PyEnvManager
|
||||||
from services.proxy_service import ProxyService
|
from services.proxy_service import ProxyService
|
||||||
from services.web_panel.utils.system_info import SystemInfoCollector
|
from services.web_panel.utils.system_info import SystemInfoCollector
|
||||||
|
from services.sensu_db import SenSuDB
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
@@ -63,7 +64,11 @@ class SenSuFramework:
|
|||||||
# 2.5 自动启动脚本 (日志服务就绪后)
|
# 2.5 自动启动脚本 (日志服务就绪后)
|
||||||
await init_service.start_auto_scripts()
|
await init_service.start_auto_scripts()
|
||||||
|
|
||||||
# 2.6 系统信息采集器 (共享实例,TUI + Web面板共用)
|
# 2.6 数据库 (持久化层)
|
||||||
|
sensu_db = SenSuDB()
|
||||||
|
self.service_manager.register_service("sensu_db", sensu_db)
|
||||||
|
|
||||||
|
# 2.7 系统信息采集器 (共享实例,TUI + Web面板共用)
|
||||||
sys_collector = SystemInfoCollector()
|
sys_collector = SystemInfoCollector()
|
||||||
self.service_manager.register_service("sys_collector", sys_collector)
|
self.service_manager.register_service("sys_collector", sys_collector)
|
||||||
|
|
||||||
|
|||||||
@@ -219,7 +219,7 @@ class InitService:
|
|||||||
'auto_load': True,
|
'auto_load': True,
|
||||||
'hot_reload': True,
|
'hot_reload': True,
|
||||||
'max_retry_count': 3,
|
'max_retry_count': 3,
|
||||||
'isolation': False, # 默认不隔离,插件可在 settings.isolation 中声明
|
'isolation': True, # 生产默认进程隔离,插件崩溃不影响框架
|
||||||
},
|
},
|
||||||
'auto_start_scripts': {
|
'auto_start_scripts': {
|
||||||
'enabled': True,
|
'enabled': True,
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ class WebPanelManager:
|
|||||||
app['service_manager'] = self.sm
|
app['service_manager'] = self.sm
|
||||||
app['auth_service'] = self.sm.get_service("auth")
|
app['auth_service'] = self.sm.get_service("auth")
|
||||||
app['log_service'] = self.sm.get_service("log")
|
app['log_service'] = self.sm.get_service("log")
|
||||||
|
app['sensu_db'] = self.sm.get_service("sensu_db")
|
||||||
app['panel_config'] = {
|
app['panel_config'] = {
|
||||||
'username': self.panel_user,
|
'username': self.panel_user,
|
||||||
'password': self.panel_pass,
|
'password': self.panel_pass,
|
||||||
|
|||||||
@@ -272,6 +272,10 @@ def setup_file_routes(app, service_manager, prefix=''):
|
|||||||
else:
|
else:
|
||||||
p.unlink()
|
p.unlink()
|
||||||
logger.info(f"🗑 删除: {p}")
|
logger.info(f"🗑 删除: {p}")
|
||||||
|
# 审计日志
|
||||||
|
db = request.app.get("sensu_db")
|
||||||
|
if db:
|
||||||
|
db.log_audit(request.get("user", {}).get("username", "?"), "file_delete", str(p))
|
||||||
return web.json_response({"ok": True})
|
return web.json_response({"ok": True})
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return web.json_response({"error": str(e)}, status=500)
|
return web.json_response({"error": str(e)}, status=500)
|
||||||
@@ -375,6 +379,9 @@ def setup_file_routes(app, service_manager, prefix=''):
|
|||||||
content = data.get("content", "")
|
content = data.get("content", "")
|
||||||
p.write_text(content, encoding="utf-8")
|
p.write_text(content, encoding="utf-8")
|
||||||
logger.info(f"💾 写入文件: {p} ({len(content)} bytes)")
|
logger.info(f"💾 写入文件: {p} ({len(content)} bytes)")
|
||||||
|
db = request.app.get("sensu_db")
|
||||||
|
if db:
|
||||||
|
db.log_audit(request.get("user", {}).get("username", "?"), "file_write", str(p))
|
||||||
return web.json_response({"ok": True, "size": len(content)})
|
return web.json_response({"ok": True, "size": len(content)})
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return web.json_response({"error": str(e)}, status=500)
|
return web.json_response({"error": str(e)}, status=500)
|
||||||
|
|||||||
Reference in New Issue
Block a user