diff --git a/features/firewall/api_firewall.go b/features/firewall/api_firewall.go index 4dd25ea4..48b17e27 100644 --- a/features/firewall/api_firewall.go +++ b/features/firewall/api_firewall.go @@ -80,3 +80,92 @@ func (s *FirewallApi) Rule(w http.ResponseWriter, r *http.Request) { ctx.JSON(w, 200, result.OkData(data)) } + +package firewall + +import ( + "net/http" + + "ems.agt/features/firewall/model" + "ems.agt/features/firewall/service" + "ems.agt/lib/core/utils/ctx" + "ems.agt/lib/core/vo/result" + "ems.agt/lib/services" + "ems.agt/restagent/config" +) + +// 防火墙管理接口添加到路由 +func Routers() []services.RouterItem { + // 实例化控制层 FirewallApi 结构体 + var apis = &FirewallApi{ + firewallService: *service.NewServiceFirewall, + } + + rs := [...]services.RouterItem{ + { + Method: "GET", + Pattern: "/base", + Handler: apis.BaseInfo, + Middleware: nil, //midware.Authorize(nil), + }, + { + Method: "POST", + Pattern: "/rule", + Handler: apis.Rule, + Middleware: nil, //midware.Authorize(nil), + }, + // 添加更多的 Router 对象... + } + + // 生成两组前缀路由 + rsPrefix := []services.RouterItem{} + for _, v := range rs { + path := "/firewallManage/{apiVersion}" + v.Pattern + // 固定前缀 + v.Pattern = config.DefaultUriPrefix + path + rsPrefix = append(rsPrefix, v) + // 可配置 + v.Pattern = config.UriPrefix + path + rsPrefix = append(rsPrefix, v) + } + return rsPrefix +} + +// 防火墙管理 +// +// PATH /firewallManage +type FirewallApi struct { + firewallService service.ServiceFirewall +} + +// 获取防火墙基础信息 +// +// GET /base +func (s *FirewallApi) BaseInfo(w http.ResponseWriter, r *http.Request) { + data, err := s.firewallService.LoadBaseInfo() + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + + ctx.JSON(w, 200, result.OkData(data)) +} + +// 获取防火墙规则列表分页 +// +// GET /rule +func (s *FirewallApi) Rule(w http.ResponseWriter, r *http.Request) { + var body model.RuleQuerys + err := ctx.ShouldBindJSON(r, &body) + if err != nil || body.Type == "" { + ctx.JSON(w, 400, result.CodeMsg(400, "参数错误")) + return + } + data, err := s.firewallService.RulePage(body) + if err != nil { + ctx.JSON(w, 400, result.ErrMsg(err.Error())) + return + } + + ctx.JSON(w, 200, result.OkData(data)) +} diff --git a/features/firewall/model/firewall.go b/features/firewall/model/firewall.go index 8ab7c13d..782aa89f 100644 --- a/features/firewall/model/firewall.go +++ b/features/firewall/model/firewall.go @@ -1,6 +1,9 @@ package model type Firewall struct { + ID int64 `json:"id" xorm:"id"` + CreatedAt int64 `json:"createdAt" xorm:"created_at"` + UpdatedAt int64 `json:"updatedAt" xorm:"updated_at"` Type string `json:"type" xorm:"type"` Port string `json:"port" xorm:"port"` Protocol string `json:"protocol" xorm:"protocol"` diff --git a/features/firewall/repo/repo_firewall.go b/features/firewall/repo/repo_firewall.go new file mode 100644 index 00000000..e95a0564 --- /dev/null +++ b/features/firewall/repo/repo_firewall.go @@ -0,0 +1,133 @@ +package repo + +import ( + "strings" + + "ems.agt/features/firewall/model" + "ems.agt/lib/core/datasource" + "ems.agt/lib/log" +) + +// 实例化数据层 RepoFirewall 结构体 +var NewRepoFirewall = &RepoFirewall{ + selectSql: `select + id, created_at, updated_at, type, port, protocol, address, strategy, description + from monitor_firewall`, + + resultMap: map[string]string{ + "id": "ID", + "created_at": "CreatedAt", + "updated_at": "UpdatedAt", + "type": "Type", + "port": "Port", + "protocol": "Protocol", + "address": "Address", + "strategy": "Strategy", + "description": "Description", + }, +} + +// RepoFirewall 防火墙 数据层处理 +type RepoFirewall struct { + // 查询视图对象SQL + selectSql string + // 结果字段与实体映射 + resultMap map[string]string +} + +// convertResultRows 将结果记录转实体结果组 +func (r *RepoFirewall) convertResultRows(rows []map[string]any) []model.Firewall { + arr := make([]model.Firewall, 0) + for _, row := range rows { + UdmUser := model.Firewall{} + for key, value := range row { + if keyMapper, ok := r.resultMap[key]; ok { + datasource.SetFieldValue(&UdmUser, keyMapper, value) + } + } + arr = append(arr, UdmUser) + } + return arr +} + +// List 根据实体查询 +func (r *RepoFirewall) List(f model.Firewall) []model.Firewall { + // 查询条件拼接 + var conditions []string + var params []any + if f.Type != "" { + conditions = append(conditions, "type = ?") + params = append(params, f.Type) + } + if f.Protocol != "" { + conditions = append(conditions, "protocol = ?") + params = append(params, f.Protocol) + } + + // 构建查询条件语句 + whereSql := "" + if len(conditions) > 0 { + whereSql += " where " + strings.Join(conditions, " and ") + } + + // 查询数据 + querySql := r.selectSql + whereSql + results, err := datasource.RawDB("", querySql, params) + if err != nil { + log.Errorf("query err => %v", err) + } + + // 转换实体 + return r.convertResultRows(results) +} + +// Insert 新增实体 +func (r *RepoFirewall) Insert(f model.Firewall) int64 { + results, err := datasource.DefaultDB().Table("monitor_firewall").Insert(f) + if err != nil { + return results + } + return results +} + +// Update 修改更新 +func (r *RepoFirewall) Update(f model.Firewall) int64 { + // 查询先 + var fd model.Firewall + if f.Type == "port" { + has, err := datasource.DefaultDB().Table("monitor_firewall").Where("type = ? AND port = ? AND protocol = ? AND address = ? AND strategy = ?", "port", f.Port, f.Protocol, f.Address, f.Strategy).Get(&fd) + if !has || err != nil { + return 0 + } + } else { + has, err := datasource.DefaultDB().Table("monitor_firewall").Where("type = ? AND address = ? AND strategy = ?", "address", f.Address, f.Strategy).Get(&fd) + if !has || err != nil { + return 0 + } + } + f.ID = fd.ID + + results, err := datasource.DefaultDB().Table("monitor_firewall").Where("id = ?", f.ID).Update(f) + if err != nil { + return 0 + } + return results +} + +// Delete 删除实体 +func (r *RepoFirewall) Delete(id int64) int64 { + results, err := datasource.DefaultDB().Table("u_sub_user").Where("id = ?", id).Delete() + if err != nil { + return results + } + return results +} + +// DeleteFirewallRecord 删除实体 +func (r *RepoFirewall) DeleteFirewallRecord(fType, port, protocol, address, strategy string) int64 { + results, err := datasource.DefaultDB().Table("u_sub_user").Where("type = ? AND port = ? AND protocol = ? AND address = ? AND strategy = ?", fType, port, protocol, address, strategy).Delete() + if err != nil { + return results + } + return results +} diff --git a/features/firewall/service/service_firewall.go b/features/firewall/service/service_firewall.go index 9347a045..62579a25 100644 --- a/features/firewall/service/service_firewall.go +++ b/features/firewall/service/service_firewall.go @@ -7,6 +7,7 @@ import ( "strings" "ems.agt/features/firewall/model" + "ems.agt/features/firewall/repo" "ems.agt/lib/core/cmd" "ems.agt/lib/core/utils/firewall" fireClient "ems.agt/lib/core/utils/firewall/client" @@ -14,10 +15,13 @@ import ( ) // 实例化服务层 ServiceFirewall 结构体 -var NewServiceFirewall = &ServiceFirewall{} +var NewServiceFirewall = &ServiceFirewall{ + repoFirewall: *repo.NewRepoFirewall, +} // ServiceFirewall 防火墙 服务层处理 type ServiceFirewall struct { + repoFirewall repo.RepoFirewall } // LoadBaseInfo 获取防火墙基础信息 @@ -130,44 +134,37 @@ func (s *ServiceFirewall) RulePage(querys model.RuleQuerys) (map[string]any, err backDatas = datasFilterStrategy[start:end] } - // datasFromDB, _ := hostRepo.ListFirewallRecord() + datasFromDB := s.repoFirewall.List(model.Firewall{}) for i := 0; i < len(backDatas); i++ { - // for _, des := range datasFromDB { - // if querys.Type != des.Type { - // continue - // } - // if backDatas[i].Port == des.Port && querys.Type == "port" && - // backDatas[i].Protocol == des.Protocol && - // backDatas[i].Strategy == des.Strategy && - // backDatas[i].Address == des.Address { - // backDatas[i].Description = des.Description - // break - // } - // if querys.Type == "address" && backDatas[i].Strategy == des.Strategy && backDatas[i].Address == des.Address { - // backDatas[i].Description = des.Description - // break - // } - // } + for _, des := range datasFromDB { + if querys.Type != des.Type { + continue + } + if backDatas[i].Port == des.Port && querys.Type == "port" && + backDatas[i].Protocol == des.Protocol && + backDatas[i].Strategy == des.Strategy && + backDatas[i].Address == des.Address { + backDatas[i].Description = des.Description + break + } + if querys.Type == "address" && backDatas[i].Strategy == des.Strategy && backDatas[i].Address == des.Address { + backDatas[i].Description = des.Description + break + } + } } - // if req.Type == "port" { - // apps := u.loadPortByApp() - // for i := 0; i < len(backDatas); i++ { - // port, _ := strconv.Atoi(backDatas[i].Port) - // backDatas[i].IsUsed = common.ScanPort(port) - // if backDatas[i].Protocol == "udp" { - // backDatas[i].IsUsed = common.ScanUDPPort(port) - // continue - // } - // for _, app := range apps { - // if app.HttpPort == backDatas[i].Port || app.HttpsPort == backDatas[i].Port { - // backDatas[i].APPName = app.AppName - // break - // } - // } - // } - // } - // go u.cleanUnUsedData(client) + if querys.Type == "port" { + for i := 0; i < len(backDatas); i++ { + port, _ := strconv.Atoi(backDatas[i].Port) + backDatas[i].IsUsed = scan.ScanPort(port) + if backDatas[i].Protocol == "udp" { + backDatas[i].IsUsed = scan.ScanUDPPort(port) + continue + } + } + } + go s.cleanUnUsedData(client) return data, nil } @@ -184,3 +181,27 @@ func (s *ServiceFirewall) pingStatus() string { } return "Disable" } + +func (s *ServiceFirewall) cleanUnUsedData(client firewall.FirewallClient) { + list, _ := client.ListPort() + addressList, _ := client.ListAddress() + list = append(list, addressList...) + if len(list) == 0 { + return + } + records := s.repoFirewall.List(model.Firewall{}) + if len(records) == 0 { + return + } + for _, item := range list { + for i := 0; i < len(records); i++ { + if records[i].Port == item.Port && records[i].Protocol == item.Protocol && records[i].Strategy == item.Strategy && records[i].Address == item.Address { + records = append(records[:i], records[i+1:]...) + } + } + } + + for _, record := range records { + _ = s.repoFirewall.Delete(record.ID) + } +}