mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-09-14 14:06:44 +08:00

- 重构插件注册架构采用现代工厂模式和自动发现机制 - 新增完整的插件元数据管理系统支持版本能力标签等信息 - 实现智能插件适配器提供向后兼容的桥接功能 - 建立MySQL Redis SSH三个标准插件作为新架构参考实现 - 优化插件扫描逻辑支持按端口按类型的智能查询和过滤 - 添加国际化支持和完善的文档体系 - 代码量减少67%维护成本大幅降低扩展性显著提升 新架构特点: - 零配置插件注册import即用 - 工厂模式延迟初始化和依赖注入 - 丰富元数据系统和能力声明 - 完全解耦的模块化设计 - 面向未来的可扩展架构 测试验证: MySQL和Redis插件功能完整包括弱密码检测未授权访问检测和自动利用攻击
135 lines
3.3 KiB
Go
135 lines
3.3 KiB
Go
package core
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"github.com/shadow1ng/fscan/common"
|
|
"github.com/shadow1ng/fscan/plugins/base"
|
|
)
|
|
|
|
// PluginAdapter 插件适配器
|
|
// 提供从新插件系统到旧扫描接口的适配
|
|
type PluginAdapter struct {
|
|
registry *base.PluginRegistry
|
|
}
|
|
|
|
// NewPluginAdapter 创建插件适配器
|
|
func NewPluginAdapter() *PluginAdapter {
|
|
return &PluginAdapter{
|
|
registry: base.GlobalPluginRegistry,
|
|
}
|
|
}
|
|
|
|
// 全局插件适配器实例
|
|
var GlobalPluginAdapter = NewPluginAdapter()
|
|
|
|
// GetAllPluginNames 获取所有插件名称
|
|
func (pa *PluginAdapter) GetAllPluginNames() []string {
|
|
return pa.registry.GetAll()
|
|
}
|
|
|
|
// PluginExists 检查插件是否存在
|
|
func (pa *PluginAdapter) PluginExists(name string) bool {
|
|
metadata := pa.registry.GetMetadata(name)
|
|
return metadata != nil
|
|
}
|
|
|
|
// GetPluginPorts 获取插件支持的端口
|
|
func (pa *PluginAdapter) GetPluginPorts(name string) []int {
|
|
metadata := pa.registry.GetMetadata(name)
|
|
if metadata != nil {
|
|
return metadata.Ports
|
|
}
|
|
return []int{}
|
|
}
|
|
|
|
// GetPluginsByPort 根据端口获取支持的插件
|
|
func (pa *PluginAdapter) GetPluginsByPort(port int) []string {
|
|
var plugins []string
|
|
for _, name := range pa.registry.GetAll() {
|
|
metadata := pa.registry.GetMetadata(name)
|
|
if metadata != nil {
|
|
for _, p := range metadata.Ports {
|
|
if p == port {
|
|
plugins = append(plugins, name)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return plugins
|
|
}
|
|
|
|
// GetPluginsByType 根据类型获取插件
|
|
func (pa *PluginAdapter) GetPluginsByType(pluginType string) []string {
|
|
var plugins []string
|
|
for _, name := range pa.registry.GetAll() {
|
|
metadata := pa.registry.GetMetadata(name)
|
|
if metadata != nil {
|
|
if metadata.Category == pluginType {
|
|
plugins = append(plugins, name)
|
|
}
|
|
}
|
|
}
|
|
return plugins
|
|
}
|
|
|
|
// ScanWithPlugin 使用插件进行扫描
|
|
func (pa *PluginAdapter) ScanWithPlugin(pluginName string, info *common.HostInfo) error {
|
|
common.LogDebug(fmt.Sprintf("使用新插件架构扫描: %s", pluginName))
|
|
|
|
// 创建插件实例
|
|
plugin, err := pa.registry.Create(pluginName)
|
|
if err != nil {
|
|
return fmt.Errorf("创建插件 %s 失败: %v", pluginName, err)
|
|
}
|
|
|
|
// 执行扫描
|
|
result, err := plugin.Scan(context.Background(), info)
|
|
if err != nil {
|
|
return fmt.Errorf("插件 %s 扫描失败: %v", pluginName, err)
|
|
}
|
|
|
|
// 处理扫描结果
|
|
if result != nil && result.Success {
|
|
common.LogDebug(fmt.Sprintf("插件 %s 扫描成功", pluginName))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// FilterPluginsByType 按类型过滤插件名称
|
|
func FilterPluginsByType(pluginType string) func(name string) bool {
|
|
return func(name string) bool {
|
|
metadata := GlobalPluginAdapter.registry.GetMetadata(name)
|
|
if metadata == nil {
|
|
return false
|
|
}
|
|
|
|
switch pluginType {
|
|
case common.PluginTypeService:
|
|
return metadata.Category == "service"
|
|
case common.PluginTypeWeb:
|
|
return metadata.Category == "web"
|
|
case common.PluginTypeLocal:
|
|
return metadata.Category == "local"
|
|
default:
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
|
|
// GetServicePlugins 获取所有服务插件
|
|
func GetServicePlugins() []string {
|
|
return GlobalPluginAdapter.GetPluginsByType("service")
|
|
}
|
|
|
|
// GetWebPlugins 获取所有Web插件
|
|
func GetWebPlugins() []string {
|
|
return GlobalPluginAdapter.GetPluginsByType("web")
|
|
}
|
|
|
|
// GetLocalPlugins 获取所有本地插件
|
|
func GetLocalPlugins() []string {
|
|
return GlobalPluginAdapter.GetPluginsByType("local")
|
|
} |