mirror of
https://github.com/TeaOSLab/EdgeNode.git
synced 2025-11-03 23:20:25 +08:00
174 lines
5.5 KiB
Go
174 lines
5.5 KiB
Go
package iplibrary
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
|
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
|
"strconv"
|
|
"sync"
|
|
)
|
|
|
|
var SharedActionManager = NewActionManager()
|
|
|
|
// ActionManager 动作管理器定义
|
|
type ActionManager struct {
|
|
locker sync.Mutex
|
|
|
|
eventMap map[string][]ActionInterface // eventLevel => []instance
|
|
configMap map[int64]*firewallconfigs.FirewallActionConfig // id => config
|
|
instanceMap map[int64]ActionInterface // id => instance
|
|
}
|
|
|
|
// NewActionManager 获取动作管理对象
|
|
func NewActionManager() *ActionManager {
|
|
return &ActionManager{
|
|
configMap: map[int64]*firewallconfigs.FirewallActionConfig{},
|
|
instanceMap: map[int64]ActionInterface{},
|
|
}
|
|
}
|
|
|
|
// UpdateActions 更新配置
|
|
func (this *ActionManager) UpdateActions(actions []*firewallconfigs.FirewallActionConfig) {
|
|
this.locker.Lock()
|
|
defer this.locker.Unlock()
|
|
|
|
// 关闭不存在的
|
|
newActionsMap := map[int64]*firewallconfigs.FirewallActionConfig{}
|
|
for _, action := range actions {
|
|
newActionsMap[action.Id] = action
|
|
}
|
|
for _, oldAction := range this.configMap {
|
|
_, ok := newActionsMap[oldAction.Id]
|
|
if !ok {
|
|
instance, ok := this.instanceMap[oldAction.Id]
|
|
if ok {
|
|
_ = instance.Close()
|
|
delete(this.instanceMap, oldAction.Id)
|
|
remotelogs.Println("IPLIBRARY/ACTION_MANAGER", "close action "+strconv.FormatInt(oldAction.Id, 10))
|
|
}
|
|
}
|
|
}
|
|
|
|
// 添加新的或者更新老的
|
|
for _, newAction := range newActionsMap {
|
|
oldInstance, ok := this.instanceMap[newAction.Id]
|
|
if ok {
|
|
// 检查配置是否一致
|
|
oldConfigJSON, err := json.Marshal(this.configMap[newAction.Id])
|
|
if err != nil {
|
|
remotelogs.Error("IPLIBRARY/ACTION_MANAGER", "action "+strconv.FormatInt(newAction.Id, 10)+", type:"+newAction.Type+": "+err.Error())
|
|
continue
|
|
}
|
|
newConfigJSON, err := json.Marshal(newAction)
|
|
if err != nil {
|
|
remotelogs.Error("IPLIBRARY/ACTION_MANAGER", "action "+strconv.FormatInt(newAction.Id, 10)+", type:"+newAction.Type+": "+err.Error())
|
|
continue
|
|
}
|
|
if !bytes.Equal(newConfigJSON, oldConfigJSON) {
|
|
_ = oldInstance.Close()
|
|
|
|
// 重新创建
|
|
// 之所以要重新创建,是因为前后的动作类型可能有变化,完全重建可以避免不必要的麻烦
|
|
newInstance, err := this.createInstance(newAction)
|
|
if err != nil {
|
|
remotelogs.Error("IPLIBRARY/ACTION_MANAGER", "reload action "+strconv.FormatInt(newAction.Id, 10)+", type:"+newAction.Type+": "+err.Error())
|
|
continue
|
|
}
|
|
remotelogs.Println("IPLIBRARY/ACTION_MANAGER", "reloaded "+strconv.FormatInt(newAction.Id, 10)+", type:"+newAction.Type)
|
|
this.instanceMap[newAction.Id] = newInstance
|
|
}
|
|
} else {
|
|
// 创建
|
|
instance, err := this.createInstance(newAction)
|
|
if err != nil {
|
|
remotelogs.Error("IPLIBRARY/ACTION_MANAGER", "load new action "+strconv.FormatInt(newAction.Id, 10)+", type:"+newAction.Type+": "+err.Error())
|
|
continue
|
|
}
|
|
remotelogs.Println("IPLIBRARY/ACTION_MANAGER", "loaded action "+strconv.FormatInt(newAction.Id, 10)+", type:"+newAction.Type)
|
|
this.instanceMap[newAction.Id] = instance
|
|
}
|
|
}
|
|
|
|
// 更新配置
|
|
this.configMap = newActionsMap
|
|
this.eventMap = map[string][]ActionInterface{}
|
|
for _, action := range this.configMap {
|
|
instance, ok := this.instanceMap[action.Id]
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
var instances = this.eventMap[action.EventLevel]
|
|
instances = append(instances, instance)
|
|
this.eventMap[action.EventLevel] = instances
|
|
}
|
|
}
|
|
|
|
// FindEventActions 查找事件对应的动作
|
|
func (this *ActionManager) FindEventActions(eventLevel string) []ActionInterface {
|
|
this.locker.Lock()
|
|
defer this.locker.Unlock()
|
|
return this.eventMap[eventLevel]
|
|
}
|
|
|
|
// AddItem 执行添加IP动作
|
|
func (this *ActionManager) AddItem(listType IPListType, item *pb.IPItem) {
|
|
instances, ok := this.eventMap[item.EventLevel]
|
|
if ok {
|
|
for _, instance := range instances {
|
|
err := instance.AddItem(listType, item)
|
|
if err != nil {
|
|
remotelogs.Error("IPLIBRARY/ACTION_MANAGER", "add item '"+fmt.Sprintf("%d", item.Id)+"': "+err.Error())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// DeleteItem 执行删除IP动作
|
|
func (this *ActionManager) DeleteItem(listType IPListType, item *pb.IPItem) {
|
|
instances, ok := this.eventMap[item.EventLevel]
|
|
if ok {
|
|
for _, instance := range instances {
|
|
err := instance.DeleteItem(listType, item)
|
|
if err != nil {
|
|
remotelogs.Error("IPLIBRARY/ACTION_MANAGER", "delete item '"+fmt.Sprintf("%d", item.Id)+"': "+err.Error())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (this *ActionManager) createInstance(config *firewallconfigs.FirewallActionConfig) (ActionInterface, error) {
|
|
var instance ActionInterface
|
|
switch config.Type {
|
|
case firewallconfigs.FirewallActionTypeIPSet:
|
|
instance = NewIPSetAction()
|
|
case firewallconfigs.FirewallActionTypeFirewalld:
|
|
instance = NewFirewalldAction()
|
|
case firewallconfigs.FirewallActionTypeIPTables:
|
|
instance = NewIPTablesAction()
|
|
case firewallconfigs.FirewallActionTypeScript:
|
|
instance = NewScriptAction()
|
|
case firewallconfigs.FirewallActionTypeHTTPAPI:
|
|
instance = NewHTTPAPIAction()
|
|
case firewallconfigs.FirewallActionTypeHTML:
|
|
instance = NewHTMLAction()
|
|
}
|
|
if instance == nil {
|
|
return nil, errors.New("can not create instance for type '" + config.Type + "'")
|
|
}
|
|
err := instance.Init(config)
|
|
if err != nil {
|
|
// 如果是警告错误,我们只是提示
|
|
if !IsFatalError(err) {
|
|
remotelogs.Error("IPLIBRARY/ACTION_MANAGER/CREATE_INSTANCE", "init '"+config.Type+"' failed: "+err.Error())
|
|
} else {
|
|
return nil, err
|
|
}
|
|
}
|
|
return instance, nil
|
|
}
|