github.com/TeaOSLab/EdgeNode@v1.3.8/internal/iplibrary/action_manager.go (about)

     1  package iplibrary
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"errors"
     7  	"fmt"
     8  	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
     9  	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
    10  	"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
    11  	"strconv"
    12  	"sync"
    13  )
    14  
    15  var SharedActionManager = NewActionManager()
    16  
    17  // ActionManager 动作管理器定义
    18  type ActionManager struct {
    19  	locker sync.Mutex
    20  
    21  	eventMap    map[string][]ActionInterface                    // eventLevel => []instance
    22  	configMap   map[int64]*firewallconfigs.FirewallActionConfig // id => config
    23  	instanceMap map[int64]ActionInterface                       // id => instance
    24  }
    25  
    26  // NewActionManager 获取动作管理对象
    27  func NewActionManager() *ActionManager {
    28  	return &ActionManager{
    29  		configMap:   map[int64]*firewallconfigs.FirewallActionConfig{},
    30  		instanceMap: map[int64]ActionInterface{},
    31  	}
    32  }
    33  
    34  // UpdateActions 更新配置
    35  func (this *ActionManager) UpdateActions(actions []*firewallconfigs.FirewallActionConfig) {
    36  	this.locker.Lock()
    37  	defer this.locker.Unlock()
    38  
    39  	// 关闭不存在的
    40  	newActionsMap := map[int64]*firewallconfigs.FirewallActionConfig{}
    41  	for _, action := range actions {
    42  		newActionsMap[action.Id] = action
    43  	}
    44  	for _, oldAction := range this.configMap {
    45  		_, ok := newActionsMap[oldAction.Id]
    46  		if !ok {
    47  			instance, ok := this.instanceMap[oldAction.Id]
    48  			if ok {
    49  				_ = instance.Close()
    50  				delete(this.instanceMap, oldAction.Id)
    51  				remotelogs.Println("IPLIBRARY/ACTION_MANAGER", "close action "+strconv.FormatInt(oldAction.Id, 10))
    52  			}
    53  		}
    54  	}
    55  
    56  	// 添加新的或者更新老的
    57  	for _, newAction := range newActionsMap {
    58  		oldInstance, ok := this.instanceMap[newAction.Id]
    59  		if ok {
    60  			// 检查配置是否一致
    61  			oldConfigJSON, err := json.Marshal(this.configMap[newAction.Id])
    62  			if err != nil {
    63  				remotelogs.Error("IPLIBRARY/ACTION_MANAGER", "action "+strconv.FormatInt(newAction.Id, 10)+", type:"+newAction.Type+": "+err.Error())
    64  				continue
    65  			}
    66  			newConfigJSON, err := json.Marshal(newAction)
    67  			if err != nil {
    68  				remotelogs.Error("IPLIBRARY/ACTION_MANAGER", "action "+strconv.FormatInt(newAction.Id, 10)+", type:"+newAction.Type+": "+err.Error())
    69  				continue
    70  			}
    71  			if !bytes.Equal(newConfigJSON, oldConfigJSON) {
    72  				_ = oldInstance.Close()
    73  
    74  				// 重新创建
    75  				// 之所以要重新创建,是因为前后的动作类型可能有变化,完全重建可以避免不必要的麻烦
    76  				newInstance, err := this.createInstance(newAction)
    77  				if err != nil {
    78  					remotelogs.Error("IPLIBRARY/ACTION_MANAGER", "reload action "+strconv.FormatInt(newAction.Id, 10)+", type:"+newAction.Type+": "+err.Error())
    79  					continue
    80  				}
    81  				remotelogs.Println("IPLIBRARY/ACTION_MANAGER", "reloaded "+strconv.FormatInt(newAction.Id, 10)+", type:"+newAction.Type)
    82  				this.instanceMap[newAction.Id] = newInstance
    83  			}
    84  		} else {
    85  			// 创建
    86  			instance, err := this.createInstance(newAction)
    87  			if err != nil {
    88  				remotelogs.Error("IPLIBRARY/ACTION_MANAGER", "load new action "+strconv.FormatInt(newAction.Id, 10)+", type:"+newAction.Type+": "+err.Error())
    89  				continue
    90  			}
    91  			remotelogs.Println("IPLIBRARY/ACTION_MANAGER", "loaded action "+strconv.FormatInt(newAction.Id, 10)+", type:"+newAction.Type)
    92  			this.instanceMap[newAction.Id] = instance
    93  		}
    94  	}
    95  
    96  	// 更新配置
    97  	this.configMap = newActionsMap
    98  	this.eventMap = map[string][]ActionInterface{}
    99  	for _, action := range this.configMap {
   100  		instance, ok := this.instanceMap[action.Id]
   101  		if !ok {
   102  			continue
   103  		}
   104  
   105  		var instances = this.eventMap[action.EventLevel]
   106  		instances = append(instances, instance)
   107  		this.eventMap[action.EventLevel] = instances
   108  	}
   109  }
   110  
   111  // FindEventActions 查找事件对应的动作
   112  func (this *ActionManager) FindEventActions(eventLevel string) []ActionInterface {
   113  	this.locker.Lock()
   114  	defer this.locker.Unlock()
   115  	return this.eventMap[eventLevel]
   116  }
   117  
   118  // AddItem 执行添加IP动作
   119  func (this *ActionManager) AddItem(listType IPListType, item *pb.IPItem) {
   120  	instances, ok := this.eventMap[item.EventLevel]
   121  	if ok {
   122  		for _, instance := range instances {
   123  			err := instance.AddItem(listType, item)
   124  			if err != nil {
   125  				remotelogs.Error("IPLIBRARY/ACTION_MANAGER", "add item '"+fmt.Sprintf("%d", item.Id)+"': "+err.Error())
   126  			}
   127  		}
   128  	}
   129  }
   130  
   131  // DeleteItem 执行删除IP动作
   132  func (this *ActionManager) DeleteItem(listType IPListType, item *pb.IPItem) {
   133  	instances, ok := this.eventMap[item.EventLevel]
   134  	if ok {
   135  		for _, instance := range instances {
   136  			err := instance.DeleteItem(listType, item)
   137  			if err != nil {
   138  				remotelogs.Error("IPLIBRARY/ACTION_MANAGER", "delete item '"+fmt.Sprintf("%d", item.Id)+"': "+err.Error())
   139  			}
   140  		}
   141  	}
   142  }
   143  
   144  func (this *ActionManager) createInstance(config *firewallconfigs.FirewallActionConfig) (ActionInterface, error) {
   145  	var instance ActionInterface
   146  	switch config.Type {
   147  	case firewallconfigs.FirewallActionTypeIPSet:
   148  		instance = NewIPSetAction()
   149  	case firewallconfigs.FirewallActionTypeFirewalld:
   150  		instance = NewFirewalldAction()
   151  	case firewallconfigs.FirewallActionTypeIPTables:
   152  		instance = NewIPTablesAction()
   153  	case firewallconfigs.FirewallActionTypeScript:
   154  		instance = NewScriptAction()
   155  	case firewallconfigs.FirewallActionTypeHTTPAPI:
   156  		instance = NewHTTPAPIAction()
   157  	case firewallconfigs.FirewallActionTypeHTML:
   158  		instance = NewHTMLAction()
   159  	}
   160  	if instance == nil {
   161  		return nil, errors.New("can not create instance for type '" + config.Type + "'")
   162  	}
   163  	err := instance.Init(config)
   164  	if err != nil {
   165  		// 如果是警告错误,我们只是提示
   166  		if !IsFatalError(err) {
   167  			remotelogs.Error("IPLIBRARY/ACTION_MANAGER/CREATE_INSTANCE", "init '"+config.Type+"' failed: "+err.Error())
   168  		} else {
   169  			return nil, err
   170  		}
   171  	}
   172  	return instance, nil
   173  }