package nodeconfigs import ( "encoding/json" "fmt" "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs" "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs" "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared" "github.com/iwind/TeaGo/Tea" "github.com/iwind/TeaGo/logs" "github.com/iwind/TeaGo/maps" "io/ioutil" "strconv" ) var sharedNodeConfig *NodeConfig = nil // NodeConfig 边缘节点配置 type NodeConfig struct { Id int64 `yaml:"id" json:"id"` NodeId string `yaml:"nodeId" json:"nodeId"` Secret string `yaml:"secret" json:"secret"` IsOn bool `yaml:"isOn" json:"isOn"` Servers []*serverconfigs.ServerConfig `yaml:"servers" json:"servers"` Version int64 `yaml:"version" json:"version"` Name string `yaml:"name" json:"name"` MaxCPU int32 `yaml:"maxCPU" json:"maxCPU"` RegionId int64 `yaml:"regionId" json:"regionId"` MaxCacheDiskCapacity *shared.SizeCapacity `yaml:"maxCacheDiskCapacity" json:"maxCacheDiskCapacity"` MaxCacheMemoryCapacity *shared.SizeCapacity `yaml:"maxCacheMemoryCapacity" json:"maxCacheMemoryCapacity"` // 全局配置 GlobalConfig *serverconfigs.GlobalConfig `yaml:"globalConfig" json:"globalConfig"` // 全局配置 // 集群统一配置 HTTPFirewallPolicies []*firewallconfigs.HTTPFirewallPolicy `yaml:"httpFirewallPolicies" json:"httpFirewallPolicies"` HTTPCachePolicies []*serverconfigs.HTTPCachePolicy `yaml:"httpCachePolicies" json:"httpCachePolicies"` TOA *TOAConfig `yaml:"toa" json:"toa"` SystemServices map[string]maps.Map `yaml:"systemServices" json:"systemServices"` // 系统服务配置 type => params FirewallActions []*firewallconfigs.FirewallActionConfig `yaml:"firewallActions" json:"firewallActions"` TimeZone string `yaml:"timeZone" json:"timeZone"` MetricItems []*serverconfigs.MetricItemConfig `yaml:"metricItems" json:"metricItems"` paddedId string // firewall firewallPolicies []*firewallconfigs.HTTPFirewallPolicy // metrics hasHTTPConnectionMetrics bool // 源站集合 originMap map[int64]*serverconfigs.OriginConfig } // SharedNodeConfig 取得当前节点配置单例 func SharedNodeConfig() (*NodeConfig, error) { shared.Locker.Lock() defer shared.Locker.Unlock() if sharedNodeConfig != nil { return sharedNodeConfig, nil } data, err := ioutil.ReadFile(Tea.ConfigFile("node.json")) if err != nil { return &NodeConfig{}, err } config := &NodeConfig{} err = json.Unmarshal(data, &config) if err != nil { return &NodeConfig{}, err } sharedNodeConfig = config return config, nil } // ResetNodeConfig 重置节点配置 func ResetNodeConfig(nodeConfig *NodeConfig) { shared.Locker.Lock() sharedNodeConfig = nodeConfig shared.Locker.Unlock() } // Init 初始化 func (this *NodeConfig) Init() error { this.paddedId = fmt.Sprintf("%08d", this.Id) // servers for _, server := range this.Servers { err := server.Init() if err != nil { // 这里不返回错误,而是继续往下,防止单个服务错误而影响其他服务 logs.Println("[INIT]server '" + strconv.FormatInt(server.Id, 10) + "' init failed: " + err.Error()) } } // global config if this.GlobalConfig != nil { err := this.GlobalConfig.Init() if err != nil { return err } } // cache policy if len(this.HTTPCachePolicies) > 0 { for _, policy := range this.HTTPCachePolicies { err := policy.Init() if err != nil { return err } } } // firewall policy if len(this.HTTPFirewallPolicies) > 0 { for _, policy := range this.HTTPFirewallPolicies { err := policy.Init() if err != nil { return err } } } // TOA if this.TOA != nil { err := this.TOA.Init() if err != nil { return err } } // 源站 this.originMap = map[int64]*serverconfigs.OriginConfig{} // 查找FirewallPolicy this.firewallPolicies = []*firewallconfigs.HTTPFirewallPolicy{} for _, policy := range this.HTTPFirewallPolicies { if policy.IsOn { this.firewallPolicies = append(this.firewallPolicies, policy) } } for _, server := range this.Servers { if !server.IsOk() || !server.IsOn { continue } // WAF策略 if server.HTTPFirewallPolicyId > 0 { for _, policy := range this.HTTPFirewallPolicies { if server.HTTPFirewallPolicyId == policy.Id { server.HTTPFirewallPolicy = policy break } } } // 缓存策略 if server.HTTPCachePolicyId > 0 { for _, policy := range this.HTTPCachePolicies { if server.HTTPCachePolicyId == policy.Id { server.HTTPCachePolicy = policy } } } // 源站 if server.ReverseProxyRef != nil && server.ReverseProxyRef.IsOn && server.ReverseProxy != nil && server.ReverseProxy.IsOn { for _, origin := range server.ReverseProxy.PrimaryOrigins { if origin.IsOn { this.originMap[origin.Id] = origin } } for _, origin := range server.ReverseProxy.BackupOrigins { if origin.IsOn { this.originMap[origin.Id] = origin } } } if server.Web != nil { this.lookupWeb(server, server.Web) } } // firewall actions for _, action := range this.FirewallActions { err := action.Init() if err != nil { return err } } // metric items this.hasHTTPConnectionMetrics = false for _, item := range this.MetricItems { err := item.Init() if err != nil { return err } if item.IsOn && item.HasHTTPConnectionValue() { this.hasHTTPConnectionMetrics = true } } return nil } // AvailableGroups 根据网络地址和协议分组 func (this *NodeConfig) AvailableGroups() []*serverconfigs.ServerAddressGroup { groupMapping := map[string]*serverconfigs.ServerAddressGroup{} // protocol://addr => Server Group for _, server := range this.Servers { if !server.IsOk() || !server.IsOn { continue } for _, addr := range server.FullAddresses() { group, ok := groupMapping[addr] if ok { group.Add(server) } else { group = serverconfigs.NewServerAddressGroup(addr) group.Add(server) } groupMapping[addr] = group } } result := []*serverconfigs.ServerAddressGroup{} for _, group := range groupMapping { result = append(result, group) } return result } // FindAllFirewallPolicies 获取所有的防火墙策略 func (this *NodeConfig) FindAllFirewallPolicies() []*firewallconfigs.HTTPFirewallPolicy { return this.firewallPolicies } // Save 写入到文件 func (this *NodeConfig) Save() error { shared.Locker.Lock() defer shared.Locker.Unlock() data, err := json.Marshal(this) if err != nil { return err } return ioutil.WriteFile(Tea.ConfigFile("node.json"), data, 0777) } // PaddedId 获取填充后的ID func (this *NodeConfig) PaddedId() string { return this.paddedId } // HasHTTPConnectionMetrics 是否含有HTTP连接数的指标 func (this *NodeConfig) HasHTTPConnectionMetrics() bool { return this.hasHTTPConnectionMetrics } // FindOrigin 读取源站配置 func (this *NodeConfig) FindOrigin(originId int64) *serverconfigs.OriginConfig { if this.originMap == nil { return nil } config, ok := this.originMap[originId] if ok { return config } return nil } // 搜索WAF策略 func (this *NodeConfig) lookupWeb(server *serverconfigs.ServerConfig, web *serverconfigs.HTTPWebConfig) { if web == nil || !web.IsOn { return } if web.FirewallPolicy != nil && web.FirewallPolicy.IsOn { // 复用节点的拦截选项设置 if web.FirewallPolicy.BlockOptions == nil && server.HTTPFirewallPolicy != nil && server.HTTPFirewallPolicy.BlockOptions != nil { web.FirewallPolicy.BlockOptions = server.HTTPFirewallPolicy.BlockOptions web.FirewallPolicy.Mode = server.HTTPFirewallPolicy.Mode } this.firewallPolicies = append(this.firewallPolicies, web.FirewallPolicy) } if len(web.Locations) > 0 { for _, location := range web.Locations { // 源站 if location.IsOn && location.ReverseProxyRef != nil && location.ReverseProxyRef.IsOn && location.ReverseProxy != nil && location.ReverseProxy.IsOn { for _, origin := range location.ReverseProxy.PrimaryOrigins { if origin.IsOn { this.originMap[origin.Id] = origin } } for _, origin := range location.ReverseProxy.BackupOrigins { if origin.IsOn { this.originMap[origin.Id] = origin } } } // Web if location.Web != nil && location.Web.IsOn { this.lookupWeb(server, location.Web) } } } }