mirror of
https://github.com/TeaOSLab/EdgeAdmin.git
synced 2025-11-03 12:20:28 +08:00
实现WAF部分功能
This commit is contained in:
1
go.mod
1
go.mod
@@ -13,6 +13,7 @@ require (
|
|||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.1 // indirect
|
github.com/modern-go/reflect2 v1.0.1 // indirect
|
||||||
github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7 // indirect
|
github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7 // indirect
|
||||||
|
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa
|
||||||
google.golang.org/grpc v1.32.0
|
google.golang.org/grpc v1.32.0
|
||||||
google.golang.org/protobuf v1.25.0 // indirect
|
google.golang.org/protobuf v1.25.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
1
go.sum
1
go.sum
@@ -154,6 +154,7 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm
|
|||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa h1:5E4dL8+NgFOgjwbTKz+OOEGGhP+ectTmF842l6KjupQ=
|
||||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
|
|||||||
@@ -131,6 +131,10 @@ func (this *RPCClient) HTTPFirewallRuleGroupRPC() pb.HTTPFirewallRuleGroupServic
|
|||||||
return pb.NewHTTPFirewallRuleGroupServiceClient(this.pickConn())
|
return pb.NewHTTPFirewallRuleGroupServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *RPCClient) HTTPFirewallRuleSetRPC() pb.HTTPFirewallRuleSetServiceClient {
|
||||||
|
return pb.NewHTTPFirewallRuleSetServiceClient(this.pickConn())
|
||||||
|
}
|
||||||
|
|
||||||
func (this *RPCClient) HTTPLocationRPC() pb.HTTPLocationServiceClient {
|
func (this *RPCClient) HTTPLocationRPC() pb.HTTPLocationServiceClient {
|
||||||
return pb.NewHTTPLocationServiceClient(this.pickConn())
|
return pb.NewHTTPLocationServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,104 @@
|
|||||||
|
package waf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||||
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
"github.com/iwind/TeaGo/lists"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CreateRulePopupAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CreateRulePopupAction) Init() {
|
||||||
|
this.Nav("", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CreateRulePopupAction) RunGet(params struct {
|
||||||
|
Type string
|
||||||
|
}) {
|
||||||
|
// check points
|
||||||
|
checkpointList := []maps.Map{}
|
||||||
|
for _, def := range firewallconfigs.AllCheckpoints {
|
||||||
|
if (params.Type == "inbound" && def.IsRequest) || (params.Type == "outbound" && !def.IsRequest) {
|
||||||
|
checkpointList = append(checkpointList, maps.Map{
|
||||||
|
"name": def.Name,
|
||||||
|
"prefix": def.Prefix,
|
||||||
|
"description": def.Description,
|
||||||
|
"hasParams": len(def.Params) > 0,
|
||||||
|
"params": def.Params,
|
||||||
|
"options": def.Options,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// operators
|
||||||
|
this.Data["operators"] = lists.Map(firewallconfigs.AllRuleOperators, func(k int, v interface{}) interface{} {
|
||||||
|
def := v.(*firewallconfigs.RuleOperatorDefinition)
|
||||||
|
return maps.Map{
|
||||||
|
"name": def.Name,
|
||||||
|
"code": def.Code,
|
||||||
|
"description": def.Description,
|
||||||
|
"case": def.CaseInsensitive,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
this.Data["checkpoints"] = checkpointList
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CreateRulePopupAction) RunPost(params struct {
|
||||||
|
RuleId int64
|
||||||
|
Prefix string
|
||||||
|
Operator string
|
||||||
|
Param string
|
||||||
|
OptionsJSON []byte
|
||||||
|
Value string
|
||||||
|
Case bool
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
}) {
|
||||||
|
params.Must.
|
||||||
|
Field("prefix", params.Prefix).
|
||||||
|
Require("请选择参数")
|
||||||
|
|
||||||
|
rule := &firewallconfigs.HTTPFirewallRule{
|
||||||
|
Id: params.RuleId,
|
||||||
|
IsOn: true,
|
||||||
|
}
|
||||||
|
if len(params.Param) > 0 {
|
||||||
|
rule.Param = "${" + params.Prefix + "." + params.Param + "}"
|
||||||
|
} else {
|
||||||
|
rule.Param = "${" + params.Prefix + "}"
|
||||||
|
}
|
||||||
|
rule.Operator = params.Operator
|
||||||
|
rule.Value = params.Value
|
||||||
|
rule.IsCaseInsensitive = params.Case
|
||||||
|
|
||||||
|
if len(params.OptionsJSON) > 0 {
|
||||||
|
options := []maps.Map{}
|
||||||
|
err := json.Unmarshal(params.OptionsJSON, &options)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rule.CheckpointOptions = map[string]interface{}{}
|
||||||
|
for _, option := range options {
|
||||||
|
rule.CheckpointOptions[option.GetString("code")] = option.GetString("value")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 校验
|
||||||
|
err := rule.Init()
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("校验规则 '" + rule.Param + " " + rule.Operator + " " + rule.Value + "' 失败,原因:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["rule"] = rule
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -0,0 +1,159 @@
|
|||||||
|
package waf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/models"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||||
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CreateSetPopupAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CreateSetPopupAction) Init() {
|
||||||
|
this.Nav("", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CreateSetPopupAction) RunGet(params struct {
|
||||||
|
FirewallPolicyId int64
|
||||||
|
GroupId int64
|
||||||
|
Type string
|
||||||
|
}) {
|
||||||
|
this.Data["groupId"] = params.GroupId
|
||||||
|
this.Data["type"] = params.Type
|
||||||
|
|
||||||
|
firewallPolicy, err := models.SharedHTTPFirewallPolicyDAO.FindEnabledPolicyConfig(this.AdminContext(), params.FirewallPolicyId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if firewallPolicy == nil {
|
||||||
|
this.NotFound("firewallPolicy", params.FirewallPolicyId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.Data["firewallPolicy"] = firewallPolicy
|
||||||
|
|
||||||
|
// 一些配置
|
||||||
|
this.Data["connectors"] = []maps.Map{
|
||||||
|
{
|
||||||
|
"name": "和(AND)",
|
||||||
|
"value": firewallconfigs.HTTPFirewallRuleConnectorAnd,
|
||||||
|
"description": "所有规则都满足才视为匹配",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "或(OR)",
|
||||||
|
"value": firewallconfigs.HTTPFirewallRuleConnectorOr,
|
||||||
|
"description": "任一规则满足了就视为匹配",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
actionMaps := []maps.Map{}
|
||||||
|
for _, action := range firewallconfigs.AllActions {
|
||||||
|
actionMaps = append(actionMaps, maps.Map{
|
||||||
|
"name": action.Name,
|
||||||
|
"description": action.Description,
|
||||||
|
"code": action.Code,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["actions"] = actionMaps
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CreateSetPopupAction) RunPost(params struct {
|
||||||
|
GroupId int64
|
||||||
|
|
||||||
|
Name string
|
||||||
|
RulesJSON []byte
|
||||||
|
Connector string
|
||||||
|
Action string
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
}) {
|
||||||
|
groupConfig, err := models.SharedHTTPFirewallRuleGroupDAO.FindRuleGroupConfig(this.AdminContext(), params.GroupId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if groupConfig == nil {
|
||||||
|
this.Fail("找不到分组,Id:" + strconv.FormatInt(params.GroupId, 10))
|
||||||
|
}
|
||||||
|
|
||||||
|
params.Must.
|
||||||
|
Field("name", params.Name).
|
||||||
|
Require("请输入规则集名称")
|
||||||
|
|
||||||
|
if len(params.RulesJSON) == 0 {
|
||||||
|
this.Fail("请添加至少一个规则")
|
||||||
|
}
|
||||||
|
rules := []*firewallconfigs.HTTPFirewallRule{}
|
||||||
|
err = json.Unmarshal(params.RulesJSON, &rules)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
}
|
||||||
|
if len(rules) == 0 {
|
||||||
|
this.Fail("请添加至少一个规则")
|
||||||
|
}
|
||||||
|
|
||||||
|
setConfig := &firewallconfigs.HTTPFirewallRuleSet{
|
||||||
|
Id: 0,
|
||||||
|
IsOn: true,
|
||||||
|
Name: params.Name,
|
||||||
|
Code: "",
|
||||||
|
Description: "",
|
||||||
|
Connector: params.Connector,
|
||||||
|
RuleRefs: nil,
|
||||||
|
Rules: rules,
|
||||||
|
Action: params.Action,
|
||||||
|
ActionOptions: maps.Map{},
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range this.ParamsMap {
|
||||||
|
if len(v) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
index := strings.Index(k, "action_")
|
||||||
|
if index > -1 {
|
||||||
|
setConfig.ActionOptions[k[len("action_"):]] = v[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setConfigJSON, err := json.Marshal(setConfig)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
createUpdateResp, err := this.RPC().HTTPFirewallRuleSetRPC().CreateOrUpdateHTTPFirewallRuleSetFromConfig(this.AdminContext(), &pb.CreateOrUpdateHTTPFirewallRuleSetFromConfigRequest{FirewallRuleSetConfigJSON: setConfigJSON})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
groupConfig.SetRefs = append(groupConfig.SetRefs, &firewallconfigs.HTTPFirewallRuleSetRef{
|
||||||
|
IsOn: true,
|
||||||
|
SetId: createUpdateResp.FirewallRuleSetId,
|
||||||
|
})
|
||||||
|
|
||||||
|
setRefsJSON, err := json.Marshal(groupConfig.SetRefs)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, err = this.RPC().HTTPFirewallRuleGroupRPC().UpdateHTTPFirewallRuleGroupSets(this.AdminContext(), &pb.UpdateHTTPFirewallRuleGroupSetsRequest{
|
||||||
|
FirewallRuleGroupId: params.GroupId,
|
||||||
|
FirewallRuleSetsJSON: setRefsJSON,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package waf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/models"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DeleteSetAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *DeleteSetAction) RunPost(params struct {
|
||||||
|
GroupId int64
|
||||||
|
SetId int64
|
||||||
|
}) {
|
||||||
|
groupConfig, err := models.SharedHTTPFirewallRuleGroupDAO.FindRuleGroupConfig(this.AdminContext(), params.GroupId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if groupConfig == nil {
|
||||||
|
this.NotFound("firewallRuleGroup", params.GroupId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
newRefs := []*firewallconfigs.HTTPFirewallRuleSetRef{}
|
||||||
|
for _, ref := range groupConfig.SetRefs {
|
||||||
|
if ref.SetId != params.SetId {
|
||||||
|
newRefs = append(newRefs, ref)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newRefsJSON, err := json.Marshal(newRefs)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, err = this.RPC().HTTPFirewallRuleGroupRPC().UpdateHTTPFirewallRuleGroupSets(this.AdminContext(), &pb.UpdateHTTPFirewallRuleGroupSetsRequest{
|
||||||
|
FirewallRuleGroupId: params.GroupId,
|
||||||
|
FirewallRuleSetsJSON: newRefsJSON,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
107
internal/web/actions/default/servers/components/waf/group.go
Normal file
107
internal/web/actions/default/servers/components/waf/group.go
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
package waf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/models"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||||
|
"github.com/iwind/TeaGo/lists"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GroupAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *GroupAction) Init() {
|
||||||
|
this.Nav("", "", this.ParamString("type"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *GroupAction) RunGet(params struct {
|
||||||
|
FirewallPolicyId int64
|
||||||
|
GroupId int64
|
||||||
|
Type string
|
||||||
|
}) {
|
||||||
|
this.Data["type"] = params.Type
|
||||||
|
|
||||||
|
// policy
|
||||||
|
firewallPolicy, err := models.SharedHTTPFirewallPolicyDAO.FindEnabledPolicyConfig(this.AdminContext(), params.FirewallPolicyId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if firewallPolicy == nil {
|
||||||
|
this.NotFound("firewallPolicy", params.FirewallPolicyId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// group config
|
||||||
|
groupConfig, err := models.SharedHTTPFirewallRuleGroupDAO.FindRuleGroupConfig(this.AdminContext(), params.GroupId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if groupConfig == nil {
|
||||||
|
this.NotFound("firewallRuleGroup", params.GroupId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["group"] = groupConfig
|
||||||
|
|
||||||
|
// rule sets
|
||||||
|
this.Data["sets"] = lists.Map(groupConfig.Sets, func(k int, v interface{}) interface{} {
|
||||||
|
set := v.(*firewallconfigs.HTTPFirewallRuleSet)
|
||||||
|
|
||||||
|
// 动作说明
|
||||||
|
actionLinks := []maps.Map{}
|
||||||
|
if set.Action == firewallconfigs.HTTPFirewallActionGoGroup {
|
||||||
|
nextGroup := firewallPolicy.FindRuleGroup(set.ActionOptions.GetInt64("groupId"))
|
||||||
|
if nextGroup != nil {
|
||||||
|
actionLinks = append(actionLinks, maps.Map{
|
||||||
|
"name": nextGroup.Name,
|
||||||
|
"url": "/servers/components/waf/group?firewallPolicyId=" + strconv.FormatInt(params.FirewallPolicyId, 10) + "&type=" + params.Type + "&groupId=" + strconv.FormatInt(nextGroup.Id, 10),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else if set.Action == firewallconfigs.HTTPFirewallActionGoSet {
|
||||||
|
nextGroup := firewallPolicy.FindRuleGroup(set.ActionOptions.GetInt64("groupId"))
|
||||||
|
if nextGroup != nil {
|
||||||
|
actionLinks = append(actionLinks, maps.Map{
|
||||||
|
"name": nextGroup.Name,
|
||||||
|
"url": "/servers/components/waf/group?firewallPolicyId=" + strconv.FormatInt(params.FirewallPolicyId, 10) + "&type=" + params.Type + "&groupId=" + strconv.FormatInt(nextGroup.Id, 10),
|
||||||
|
})
|
||||||
|
|
||||||
|
nextSet := nextGroup.FindRuleSet(set.ActionOptions.GetInt64("setId"))
|
||||||
|
if nextSet != nil {
|
||||||
|
actionLinks = append(actionLinks, maps.Map{
|
||||||
|
"name": nextSet.Name,
|
||||||
|
"url": "/servers/components/waf/group?firewallPolicyId=" + strconv.FormatInt(params.FirewallPolicyId, 10) + "&type=" + params.Type + "&groupId=" + strconv.FormatInt(nextGroup.Id, 10),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return maps.Map{
|
||||||
|
"id": set.Id,
|
||||||
|
"name": set.Name,
|
||||||
|
"rules": lists.Map(set.Rules, func(k int, v interface{}) interface{} {
|
||||||
|
rule := v.(*firewallconfigs.HTTPFirewallRule)
|
||||||
|
|
||||||
|
return maps.Map{
|
||||||
|
"param": rule.Param,
|
||||||
|
"operator": rule.Operator,
|
||||||
|
"value": rule.Value,
|
||||||
|
"isCaseInsensitive": rule.IsCaseInsensitive,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
"isOn": set.IsOn,
|
||||||
|
"action": strings.ToUpper(set.Action),
|
||||||
|
"actionOptions": set.ActionOptions,
|
||||||
|
"actionName": firewallconfigs.FindActionName(set.Action),
|
||||||
|
"actionLinks": actionLinks,
|
||||||
|
"connector": strings.ToUpper(set.Connector),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
@@ -18,7 +18,7 @@ func init() {
|
|||||||
Post("/delete", new(DeleteAction)).
|
Post("/delete", new(DeleteAction)).
|
||||||
Get("/policy", new(PolicyAction)).
|
Get("/policy", new(PolicyAction)).
|
||||||
Get("/groups", new(GroupsAction)).
|
Get("/groups", new(GroupsAction)).
|
||||||
Get("/sets", new(SetsAction)).
|
Get("/group", new(GroupAction)).
|
||||||
Get("/log", new(LogAction)).
|
Get("/log", new(LogAction)).
|
||||||
GetPost("/update", new(UpdateAction)).
|
GetPost("/update", new(UpdateAction)).
|
||||||
GetPost("/test", new(TestAction)).
|
GetPost("/test", new(TestAction)).
|
||||||
@@ -29,6 +29,13 @@ func init() {
|
|||||||
GetPost("/ipadmin", new(IpadminAction)).
|
GetPost("/ipadmin", new(IpadminAction)).
|
||||||
GetPost("/createGroupPopup", new(CreateGroupPopupAction)).
|
GetPost("/createGroupPopup", new(CreateGroupPopupAction)).
|
||||||
Post("/sortGroups", new(SortGroupsAction)).
|
Post("/sortGroups", new(SortGroupsAction)).
|
||||||
|
GetPost("/updateGroupPopup", new(UpdateGroupPopupAction)).
|
||||||
|
GetPost("/createSetPopup", new(CreateSetPopupAction)).
|
||||||
|
GetPost("/createRulePopup", new(CreateRulePopupAction)).
|
||||||
|
Post("/sortSets", new(SortSetsAction)).
|
||||||
|
Post("/updateSetOn", new(UpdateSetOnAction)).
|
||||||
|
Post("/deleteSet", new(DeleteSetAction)).
|
||||||
|
GetPost("/updateSetPopup", new(UpdateSetPopupAction)).
|
||||||
EndAll()
|
EndAll()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
package waf
|
|
||||||
|
|
||||||
import "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
|
||||||
|
|
||||||
type SetsAction struct {
|
|
||||||
actionutils.ParentAction
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *SetsAction) Init() {
|
|
||||||
this.Nav("", "", "")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *SetsAction) RunGet(params struct{}) {
|
|
||||||
this.Show()
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package waf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/models"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SortSetsAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *SortSetsAction) RunPost(params struct {
|
||||||
|
GroupId int64
|
||||||
|
SetIds []int64
|
||||||
|
}) {
|
||||||
|
groupConfig, err := models.SharedHTTPFirewallRuleGroupDAO.FindRuleGroupConfig(this.AdminContext(), params.GroupId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if groupConfig == nil {
|
||||||
|
this.NotFound("firewallRuleGroup", params.GroupId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setMap := map[int64]*firewallconfigs.HTTPFirewallRuleSetRef{}
|
||||||
|
for _, setRef := range groupConfig.SetRefs {
|
||||||
|
setMap[setRef.SetId] = setRef
|
||||||
|
}
|
||||||
|
|
||||||
|
newRefs := []*firewallconfigs.HTTPFirewallRuleSetRef{}
|
||||||
|
for _, setId := range params.SetIds {
|
||||||
|
ref, ok := setMap[setId]
|
||||||
|
if ok {
|
||||||
|
newRefs = append(newRefs, ref)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newRefsJSON, err := json.Marshal(newRefs)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = this.RPC().HTTPFirewallRuleGroupRPC().UpdateHTTPFirewallRuleGroupSets(this.AdminContext(), &pb.UpdateHTTPFirewallRuleGroupSetsRequest{
|
||||||
|
FirewallRuleGroupId: params.GroupId,
|
||||||
|
FirewallRuleSetsJSON: newRefsJSON,
|
||||||
|
})
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package waf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/models"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UpdateGroupPopupAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpdateGroupPopupAction) Init() {
|
||||||
|
this.Nav("", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpdateGroupPopupAction) RunGet(params struct {
|
||||||
|
GroupId int64
|
||||||
|
}) {
|
||||||
|
groupConfig, err := models.SharedHTTPFirewallRuleGroupDAO.FindRuleGroupConfig(this.AdminContext(), params.GroupId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if groupConfig == nil {
|
||||||
|
this.NotFound("ruleGroup", params.GroupId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["group"] = maps.Map{
|
||||||
|
"id": groupConfig.Id,
|
||||||
|
"name": groupConfig.Name,
|
||||||
|
"description": groupConfig.Description,
|
||||||
|
"isOn": groupConfig.IsOn,
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpdateGroupPopupAction) RunPost(params struct {
|
||||||
|
GroupId int64
|
||||||
|
Name string
|
||||||
|
Description string
|
||||||
|
IsOn bool
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
}) {
|
||||||
|
params.Must.
|
||||||
|
Field("name", params.Name).
|
||||||
|
Require("请输入分组名称")
|
||||||
|
|
||||||
|
_, err := this.RPC().HTTPFirewallRuleGroupRPC().UpdateHTTPFirewallRuleGroup(this.AdminContext(), &pb.UpdateHTTPFirewallRuleGroupRequest{
|
||||||
|
FirewallRuleGroupId: params.GroupId,
|
||||||
|
IsOn: params.IsOn,
|
||||||
|
Name: params.Name,
|
||||||
|
Description: params.Description,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package waf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UpdateSetOnAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpdateSetOnAction) RunPost(params struct {
|
||||||
|
SetId int64
|
||||||
|
IsOn bool
|
||||||
|
}) {
|
||||||
|
_, err := this.RPC().HTTPFirewallRuleSetRPC().UpdateHTTPFirewallRuleSetIsOn(this.AdminContext(), &pb.UpdateHTTPFirewallRuleSetIsOnRequest{
|
||||||
|
FirewallRuleSetId: params.SetId,
|
||||||
|
IsOn: params.IsOn,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -0,0 +1,152 @@
|
|||||||
|
package waf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/models"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||||
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UpdateSetPopupAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpdateSetPopupAction) Init() {
|
||||||
|
this.Nav("", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpdateSetPopupAction) RunGet(params struct {
|
||||||
|
FirewallPolicyId int64
|
||||||
|
GroupId int64
|
||||||
|
Type string
|
||||||
|
SetId int64
|
||||||
|
}) {
|
||||||
|
this.Data["groupId"] = params.GroupId
|
||||||
|
this.Data["type"] = params.Type
|
||||||
|
|
||||||
|
firewallPolicy, err := models.SharedHTTPFirewallPolicyDAO.FindEnabledPolicyConfig(this.AdminContext(), params.FirewallPolicyId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if firewallPolicy == nil {
|
||||||
|
this.NotFound("firewallPolicy", params.FirewallPolicyId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.Data["firewallPolicy"] = firewallPolicy
|
||||||
|
|
||||||
|
// 一些配置
|
||||||
|
this.Data["connectors"] = []maps.Map{
|
||||||
|
{
|
||||||
|
"name": "和(AND)",
|
||||||
|
"value": firewallconfigs.HTTPFirewallRuleConnectorAnd,
|
||||||
|
"description": "所有规则都满足才视为匹配",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "或(OR)",
|
||||||
|
"value": firewallconfigs.HTTPFirewallRuleConnectorOr,
|
||||||
|
"description": "任一规则满足了就视为匹配",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
actionMaps := []maps.Map{}
|
||||||
|
for _, action := range firewallconfigs.AllActions {
|
||||||
|
actionMaps = append(actionMaps, maps.Map{
|
||||||
|
"name": action.Name,
|
||||||
|
"description": action.Description,
|
||||||
|
"code": action.Code,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["actions"] = actionMaps
|
||||||
|
|
||||||
|
// 规则集信息
|
||||||
|
setConfig, err := models.SharedHTTPFirewallRuleSetDAO.FindRuleSetConfig(this.AdminContext(), params.SetId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if setConfig == nil {
|
||||||
|
this.NotFound("firewallRuleSet", params.SetId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.Data["setConfig"] = setConfig
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpdateSetPopupAction) RunPost(params struct {
|
||||||
|
GroupId int64
|
||||||
|
SetId int64
|
||||||
|
|
||||||
|
Name string
|
||||||
|
RulesJSON []byte
|
||||||
|
Connector string
|
||||||
|
Action string
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
}) {
|
||||||
|
// 规则集信息
|
||||||
|
setConfig, err := models.SharedHTTPFirewallRuleSetDAO.FindRuleSetConfig(this.AdminContext(), params.SetId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if setConfig == nil {
|
||||||
|
this.NotFound("firewallRuleSet", params.SetId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
params.Must.
|
||||||
|
Field("name", params.Name).
|
||||||
|
Require("请输入规则集名称")
|
||||||
|
|
||||||
|
if len(params.RulesJSON) == 0 {
|
||||||
|
this.Fail("请添加至少一个规则")
|
||||||
|
}
|
||||||
|
rules := []*firewallconfigs.HTTPFirewallRule{}
|
||||||
|
err = json.Unmarshal(params.RulesJSON, &rules)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
}
|
||||||
|
if len(rules) == 0 {
|
||||||
|
this.Fail("请添加至少一个规则")
|
||||||
|
}
|
||||||
|
|
||||||
|
setConfig.Name = params.Name
|
||||||
|
setConfig.Connector = params.Connector
|
||||||
|
setConfig.Rules = rules
|
||||||
|
setConfig.Action = params.Action
|
||||||
|
setConfig.ActionOptions = maps.Map{}
|
||||||
|
|
||||||
|
for k, v := range this.ParamsMap {
|
||||||
|
if len(v) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
index := strings.Index(k, "action_")
|
||||||
|
if index > -1 {
|
||||||
|
setConfig.ActionOptions[k[len("action_"):]] = v[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setConfigJSON, err := json.Marshal(setConfig)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = this.RPC().HTTPFirewallRuleSetRPC().CreateOrUpdateHTTPFirewallRuleSetFromConfig(this.AdminContext(), &pb.CreateOrUpdateHTTPFirewallRuleSetFromConfigRequest{FirewallRuleSetConfigJSON: setConfigJSON})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
39
internal/web/models/http_firewall_rule_group_dao.go
Normal file
39
internal/web/models/http_firewall_rule_group_dao.go
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||||
|
)
|
||||||
|
|
||||||
|
var SharedHTTPFirewallRuleGroupDAO = new(HTTPFirewallRuleGroupDAO)
|
||||||
|
|
||||||
|
type HTTPFirewallRuleGroupDAO struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找分组配置
|
||||||
|
func (this *HTTPFirewallRuleGroupDAO) FindRuleGroupConfig(ctx context.Context, groupId int64) (*firewallconfigs.HTTPFirewallRuleGroup, error) {
|
||||||
|
client, err := rpc.SharedRPC()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
groupResp, err := client.HTTPFirewallRuleGroupRPC().FindHTTPFirewallRuleGroupConfig(ctx, &pb.FindHTTPFirewallRuleGroupConfigRequest{FirewallRuleGroupId: groupId})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(groupResp.FirewallRuleGroupJSON) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
groupConfig := &firewallconfigs.HTTPFirewallRuleGroup{}
|
||||||
|
err = json.Unmarshal(groupResp.FirewallRuleGroupJSON, groupConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return groupConfig, nil
|
||||||
|
}
|
||||||
35
internal/web/models/http_firewall_rule_set_dao.go
Normal file
35
internal/web/models/http_firewall_rule_set_dao.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||||
|
)
|
||||||
|
|
||||||
|
var SharedHTTPFirewallRuleSetDAO = new(HTTPFirewallRuleSetDAO)
|
||||||
|
|
||||||
|
type HTTPFirewallRuleSetDAO struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找规则集配置
|
||||||
|
func (this *HTTPFirewallRuleSetDAO) FindRuleSetConfig(ctx context.Context, setId int64) (*firewallconfigs.HTTPFirewallRuleSet, error) {
|
||||||
|
client, err := rpc.SharedRPC()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resp, err := client.HTTPFirewallRuleSetRPC().FindHTTPFirewallRuleSetConfig(ctx, &pb.FindHTTPFirewallRuleSetConfigRequest{FirewallRuleSetId: setId})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(resp.FirewallRuleSetJSON) == 0 {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
config := &firewallconfigs.HTTPFirewallRuleSet{}
|
||||||
|
err = json.Unmarshal(resp.FirewallRuleSetJSON, config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
@@ -6,6 +6,9 @@ function sortTable(callback) {
|
|||||||
jsFile.addEventListener("load", function () {
|
jsFile.addEventListener("load", function () {
|
||||||
// 初始化
|
// 初始化
|
||||||
let box = document.querySelector("#sortable-table")
|
let box = document.querySelector("#sortable-table")
|
||||||
|
if (box == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
Sortable.create(box, {
|
Sortable.create(box, {
|
||||||
draggable: "tbody",
|
draggable: "tbody",
|
||||||
handle: ".icon.handle",
|
handle: ".icon.handle",
|
||||||
|
|||||||
50
web/public/js/components/server/http-firewall-rules-box.js
Normal file
50
web/public/js/components/server/http-firewall-rules-box.js
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
Vue.component("http-firewall-rules-box", {
|
||||||
|
props: ["v-rules", "v-type"],
|
||||||
|
data: function () {
|
||||||
|
let rules = this.vRules
|
||||||
|
if (rules == null) {
|
||||||
|
rules = []
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
rules: rules
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
addRule: function () {
|
||||||
|
window.UPDATING_RULE = null
|
||||||
|
let that = this
|
||||||
|
teaweb.popup("/servers/components/waf/createRulePopup?type=" + this.vType, {
|
||||||
|
callback: function (resp) {
|
||||||
|
that.rules.push(resp.data.rule)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
updateRule: function (index, rule) {
|
||||||
|
window.UPDATING_RULE = rule
|
||||||
|
let that = this
|
||||||
|
teaweb.popup("/servers/components/waf/createRulePopup?type=" + this.vType, {
|
||||||
|
callback: function (resp) {
|
||||||
|
Vue.set(that.rules, index, resp.data.rule)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
removeRule: function (index) {
|
||||||
|
let that = this
|
||||||
|
teaweb.confirm("确定要删除此规则吗?", function () {
|
||||||
|
that.rules.$remove(index)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
template: `<div>
|
||||||
|
<input type="hidden" name="rulesJSON" :value="JSON.stringify(rules)"/>
|
||||||
|
<div v-if="rules.length > 0">
|
||||||
|
<div v-for="(rule, index) in rules" class="ui label tiny" style="margin-bottom: 0.5em">
|
||||||
|
<span>{{rule.param}} <var>{{rule.operator}}</var> {{rule.value}}</span>
|
||||||
|
<a href="" title="修改" @click.prevent="updateRule(index, rule)"><i class="icon pencil small"></i></a>
|
||||||
|
<a href="" title="删除" @click.prevent="removeRule(index)"><i class="icon remove"></i></a>
|
||||||
|
</div>
|
||||||
|
<div class="ui divider"></div>
|
||||||
|
</div>
|
||||||
|
<button class="ui button tiny" type="button" @click.prevent="addRule()">+</button>
|
||||||
|
</div>`
|
||||||
|
})
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
{$layout "layout_popup"}
|
||||||
|
|
||||||
|
<h3 v-if="!isUpdating">添加规则</h3>
|
||||||
|
<h3 v-if="isUpdating">修改规则</h3>
|
||||||
|
|
||||||
|
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
||||||
|
<input type="hidden" name="ruleId" :value="rule.id"/>
|
||||||
|
<input type="hidden" name="optionsJSON" v-if="checkpoint != null && checkpoint.options != null" :value="JSON.stringify(checkpoint.options)"/>
|
||||||
|
<table class="ui table definition selectable">
|
||||||
|
<tr>
|
||||||
|
<td class="title">参数</td>
|
||||||
|
<td>
|
||||||
|
<select name="prefix" class="ui dropdown auto-width" @change="changeCheckpoint()" v-model="rule.checkpointPrefix">
|
||||||
|
<option value="">[选择参数]</option>
|
||||||
|
<option v-for="cp in checkpoints" :value="cp.prefix">{{cp.name}} - [ {{cp.prefix}}]</option>
|
||||||
|
</select>
|
||||||
|
<p class="comment" v-if="checkpoint != null"><span class="ui label tiny">${<em style="font-style: normal;">{{checkpoint.prefix}}</em>}</span>{{checkpoint.description}}</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="checkpoint != null && checkpoint.hasParams">
|
||||||
|
<td>参数名</td>
|
||||||
|
<td>
|
||||||
|
<select name="param" v-model="rule.checkpointParam" class="ui dropdown auto-width" v-if="checkpoint.params != null">
|
||||||
|
<option v-for="o in checkpoint.params" :value="o.value">{{o.name}}</option>
|
||||||
|
</select>
|
||||||
|
<input type="text" maxlength="100" v-model="rule.checkpointParam" v-if="checkpoint.params == null"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<!-- 选项 -->
|
||||||
|
<tbody v-if="checkpoint != null && checkpoint.options != null && checkpoint.options.length > 0">
|
||||||
|
<tr v-for="option in checkpoint.options">
|
||||||
|
<td>{{option.name}}</td>
|
||||||
|
<td>
|
||||||
|
<div class="ui fields inline" v-if="option.type == 'field'">
|
||||||
|
<div class="ui field">
|
||||||
|
<input type="text" name="" :placeholder="option.placeholder" :maxlength="(option.maxLength > 0)?option.maxLength:1024" :size="option.size" v-model="option.value"/>
|
||||||
|
</div>
|
||||||
|
<div class="ui field">
|
||||||
|
{{option.rightLabel}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ui fields inline" v-if="option.type == 'options'">
|
||||||
|
<div class="ui field">
|
||||||
|
<select class="ui dropdown" :style="'width:' + option.size + 'em'" name="" v-model="option.value">
|
||||||
|
<option v-for="opt in option.options" :value="opt.value">{{opt.name}}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="ui field">
|
||||||
|
{{option.rightLabel}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="comment" v-if="option.comment != null && option.comment.length > 0">{{option.comment}}</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>操作符</td>
|
||||||
|
<td>
|
||||||
|
<select class="ui dropdown" name="operator" style="width:10em" v-model="rule.operator" @change="changeOperator()">
|
||||||
|
<option v-for="op in operators" :value="op.code">{{op.name}}</option>
|
||||||
|
</select>
|
||||||
|
<p class="comment" v-if="operator != null" v-html="operator.description"></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="operator.case != 'none'">
|
||||||
|
<td>开启大小写不敏感</td>
|
||||||
|
<td>
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<input name="case" type="checkbox" value="1" v-model="rule.isCaseInsensitive"/>
|
||||||
|
<label></label>
|
||||||
|
</div>
|
||||||
|
<p class="comment">开启后忽略英文字母大小写</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>对比值</td>
|
||||||
|
<td>
|
||||||
|
<textarea rows="3" maxlength="4096" name="value" v-model="rule.value"></textarea>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<submit-btn></submit-btn>
|
||||||
|
</form>
|
||||||
70
web/views/@default/servers/components/waf/createRulePopup.js
Normal file
70
web/views/@default/servers/components/waf/createRulePopup.js
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
Tea.context(function () {
|
||||||
|
this.success = NotifyPopup
|
||||||
|
|
||||||
|
this.isUpdating = (window.parent.UPDATING_RULE != null)
|
||||||
|
this.rule = {
|
||||||
|
id: 0,
|
||||||
|
param: "",
|
||||||
|
checkpointPrefix: "",
|
||||||
|
checkpointParam: "",
|
||||||
|
value: "",
|
||||||
|
isCaseInsensitive: false,
|
||||||
|
operator: "match",
|
||||||
|
checkpointOptions: null,
|
||||||
|
description: "",
|
||||||
|
isOn: true
|
||||||
|
}
|
||||||
|
if (window.parent.UPDATING_RULE != null) {
|
||||||
|
this.rule = window.parent.UPDATING_RULE
|
||||||
|
|
||||||
|
let param = this.rule.param.substring(this.rule.param.indexOf("${") + 2, this.rule.param.indexOf("}"))
|
||||||
|
let index = param.indexOf(".")
|
||||||
|
if (index > 0) {
|
||||||
|
this.rule.checkpointPrefix = param.substring(0, index)
|
||||||
|
this.rule.checkpointParam = param.substring(index + 1)
|
||||||
|
} else {
|
||||||
|
this.rule.checkpointPrefix = param
|
||||||
|
}
|
||||||
|
this.$delay(function () {
|
||||||
|
this.changeCheckpoint()
|
||||||
|
if (this.rule.checkpointOptions != null && this.checkpoint != null && this.checkpoint.options != null) {
|
||||||
|
let that = this
|
||||||
|
this.checkpoint.options.forEach(function (option) {
|
||||||
|
if (typeof (that.rule.checkpointOptions[option.code]) != "undefined") {
|
||||||
|
option.value = that.rule.checkpointOptions[option.code]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checkpoint
|
||||||
|
*/
|
||||||
|
this.checkpoint = null
|
||||||
|
this.changeCheckpoint = function () {
|
||||||
|
if (this.rule.checkpointPrefix.length == 0) {
|
||||||
|
this.checkpoint = null
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let that = this
|
||||||
|
this.checkpoint = this.checkpoints.$find(function (k, v) {
|
||||||
|
return v.prefix == that.rule.checkpointPrefix
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* operator
|
||||||
|
*/
|
||||||
|
this.changeOperator = function () {
|
||||||
|
let that = this;
|
||||||
|
this.operator = this.operators.$find(function (k, v) {
|
||||||
|
return v.code == that.rule.operator
|
||||||
|
})
|
||||||
|
if (!this.isUpdating) {
|
||||||
|
this.rule.isCaseInsensitive = (this.operator.case == "yes")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.changeOperator()
|
||||||
|
})
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
{$layout "layout_popup"}
|
||||||
|
|
||||||
|
<h3>添加规则集</h3>
|
||||||
|
|
||||||
|
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
||||||
|
<input type="hidden" name="groupId" :value="groupId"/>
|
||||||
|
<table class="ui table definition selectable">
|
||||||
|
<tr>
|
||||||
|
<td class="title">规则集名称 *</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="name" maxlength="100" ref="focus"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>规则</td>
|
||||||
|
<td>
|
||||||
|
<http-firewall-rules-box :v-rules="rules" :v-type="type"></http-firewall-rules-box>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>规则之间的关系</td>
|
||||||
|
<td>
|
||||||
|
<select class="ui dropdown" name="connector" style="width:10em" @change="changeConnector()" v-model="selectedConnector">
|
||||||
|
<option v-for="connector in connectors" :value="connector.value">{{connector.name}}</option>
|
||||||
|
</select>
|
||||||
|
<p class="comment">{{selectedConnectorDescription}}</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td :class="{'color-border':action == 'go_group' || action == 'go_set'}">动作</td>
|
||||||
|
<td>
|
||||||
|
<select class="ui dropdown auto-width" name="action" v-model="action">
|
||||||
|
<option v-for="a in actions" :value="a.code">{{a.name}}({{a.code.toUpperCase()}})</option>
|
||||||
|
</select>
|
||||||
|
<p class="comment">匹配当前规则集后要执行的动作。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="action == 'go_group'">
|
||||||
|
<td class="color-border">下一个规则分组</td>
|
||||||
|
<td>
|
||||||
|
<select class="ui dropdown" name="action_groupId" style="width:12em" v-model="actionGroupId">
|
||||||
|
<option v-for="g in firewallPolicy.inbound.groups" :value="g.id">{{g.name}}</option>
|
||||||
|
</select>
|
||||||
|
<p class="comment">当动作为"跳到下一个规则分组"时出现此选择。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="action == 'go_set'">
|
||||||
|
<td class="color-border">下一个规则分组</td>
|
||||||
|
<td>
|
||||||
|
<select class="ui dropdown" name="action_groupId" style="width:12em" v-model="actionGroupId">
|
||||||
|
<option v-for="g in firewallPolicy.inbound.groups" :value="g.id">{{g.name}}</option>
|
||||||
|
</select>
|
||||||
|
<p class="comment">当动作为"跳到下一个规则集"时出现此选择。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="action == 'go_set'">
|
||||||
|
<td class="color-border">下一个规则集</td>
|
||||||
|
<td>
|
||||||
|
<select class="ui dropdown" name="action_setId" style="width:12em" v-model="actionSetId">
|
||||||
|
<option v-for="r in groupSets(actionGroupId)" :value="r.id">{{r.name}}</option>
|
||||||
|
</select>
|
||||||
|
<p class="comment">当动作为"跳到下一个规则集"时出现此选择。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<submit-btn></submit-btn>
|
||||||
|
</form>
|
||||||
43
web/views/@default/servers/components/waf/createSetPopup.js
Normal file
43
web/views/@default/servers/components/waf/createSetPopup.js
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
Tea.context(function () {
|
||||||
|
this.success = NotifyPopup
|
||||||
|
|
||||||
|
// rules
|
||||||
|
this.rules = []
|
||||||
|
|
||||||
|
// connector
|
||||||
|
this.selectedConnector = this.connectors[1].value
|
||||||
|
this.selectedConnectorDescription = ""
|
||||||
|
this.changeConnector = function () {
|
||||||
|
let that = this
|
||||||
|
this.selectedConnectorDescription = this.connectors.$find(function (k, v) {
|
||||||
|
return v.value == that.selectedConnector
|
||||||
|
}).description
|
||||||
|
}
|
||||||
|
this.changeConnector()
|
||||||
|
|
||||||
|
// action
|
||||||
|
this.action = "block"
|
||||||
|
|
||||||
|
// action:go_group
|
||||||
|
this.actionGroupId = 0
|
||||||
|
|
||||||
|
// action:go_set
|
||||||
|
this.actionSetId = 0
|
||||||
|
this.groupSets = function (groupId) {
|
||||||
|
let group = null
|
||||||
|
this.firewallPolicy.inbound.groups.forEach(function (v) {
|
||||||
|
if (v.id == groupId) {
|
||||||
|
group = v
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.firewallPolicy.outbound.groups.forEach(function (v) {
|
||||||
|
if (v.id == groupId) {
|
||||||
|
group = v
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (group == null) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
return group.sets
|
||||||
|
}
|
||||||
|
})
|
||||||
69
web/views/@default/servers/components/waf/group.html
Normal file
69
web/views/@default/servers/components/waf/group.html
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
{$layout}
|
||||||
|
{$template "/left_menu"}
|
||||||
|
|
||||||
|
<div class="right-box">
|
||||||
|
{$template "waf_menu"}
|
||||||
|
|
||||||
|
<h3>分组<a href="" @click.prevent="updateGroup(group.id)">[修改]</a></h3>
|
||||||
|
<table class="ui table selectable definition">
|
||||||
|
<tr>
|
||||||
|
<td class="title">名称</td>
|
||||||
|
<td>{{group.name}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>描述</td>
|
||||||
|
<td>
|
||||||
|
<span v-if="group.description.length == 0" class="disabled">暂时还没有描述。</span>
|
||||||
|
<span v-if="group.description.length > 0">{{group.description}}</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>启用状态</td>
|
||||||
|
<td>
|
||||||
|
<label-on :v-is-on="group.isOn"></label-on>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h3 style="padding-top:0.8em">规则集<a href="" @click.prevent="createSet(group.id)">[添加规则集]</a> </h3>
|
||||||
|
<p class="comment" v-if="sets == null || sets.length == 0">暂时还没有规则。</p>
|
||||||
|
<table class="ui table selectable" id="sortable-table" v-if="sets != null && sets.length > 0">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width:3em"></th>
|
||||||
|
<th nowrap="">规则集名称</th>
|
||||||
|
<th nowrap="">规则</th>
|
||||||
|
<th nowrap="">关系</th>
|
||||||
|
<th nowrap="">动作</th>
|
||||||
|
<th class="three op">操作</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody v-for="set in sets" :data-set-id="set.id">
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;"><i class="icon bars handle grey"></i> </td>
|
||||||
|
<td><span :class="{disabled:!set.isOn}">{{set.name}}</span>
|
||||||
|
<p style="margin-top:0.5em">
|
||||||
|
<label-on :v-is-on="set.isOn"></label-on>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
<td class="rules-box">
|
||||||
|
<div v-for="rule in set.rules" style="margin-top: 0.4em;margin-bottom:0.4em">
|
||||||
|
<span class="ui label tiny">{{rule.name}}[{{rule.param}}] <var :class="{dash:rule.isCaseInsensitive}" :title="rule.isCaseInsensitive ? '大小写不敏感':''">{{rule.operator}}</var> {{rule.value}}</span>
|
||||||
|
</div>
|
||||||
|
<span class="ui disabled" v-if="set.rules.length == 0">暂时还没有规则</span>
|
||||||
|
</td>
|
||||||
|
<td>{{set.connector.toUpperCase()}}</td>
|
||||||
|
<td><span :class="{red:set.action == 'BLOCK' || set.action == 'CAPTCHA', green:set.action != 'BLOCK' && set.action != 'CAPTCHA'}">{{set.actionName}}[{{set.action.toUpperCase()}}]</span>
|
||||||
|
<div v-if="set.actionLinks != null && set.actionLinks.length > 0" style="margin-top:0.3em">
|
||||||
|
<span class="disabled">-></span> <span v-for="link in set.actionLinks"><a :href="link.url"><span class="disabled">[{{link.name}}]</span></a> </span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="" @click.prevent="updateSet(set.id)">修改</a> <a href="" @click.prevent="updateSetOn(set.id, false)" v-if="set.isOn">停用</a><a href="" @click.prevent="updateSetOn(set.id, true)" v-if="!set.isOn">启用</a> <a href="" @click.prevent="deleteSet(set.id)">删除</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p class="comment" v-if="group.sets != null && group.sets.length > 1">所有规则匹配顺序为从上到下,可以拖动左侧的<i class="icon bars"></i>排序。</p>
|
||||||
|
</div>
|
||||||
82
web/views/@default/servers/components/waf/group.js
Normal file
82
web/views/@default/servers/components/waf/group.js
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
Tea.context(function () {
|
||||||
|
this.$delay(function () {
|
||||||
|
let that = this
|
||||||
|
sortTable(function () {
|
||||||
|
let setIds = []
|
||||||
|
document
|
||||||
|
.querySelectorAll("tbody[data-set-id]")
|
||||||
|
.forEach(function (v) {
|
||||||
|
setIds.push(v.getAttribute("data-set-id"))
|
||||||
|
})
|
||||||
|
that.$post(".sortSets")
|
||||||
|
.params({
|
||||||
|
groupId: that.group.id,
|
||||||
|
setIds: setIds
|
||||||
|
})
|
||||||
|
.success(function () {
|
||||||
|
teaweb.successToast("排序保存成功")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// 更改分组
|
||||||
|
this.updateGroup = function (groupId) {
|
||||||
|
teaweb.popup("/servers/components/waf/updateGroupPopup?groupId=" + groupId, {
|
||||||
|
height: "16em",
|
||||||
|
callback: function () {
|
||||||
|
teaweb.success("保存成功", function () {
|
||||||
|
window.location.reload()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建规则集
|
||||||
|
this.createSet = function (groupId) {
|
||||||
|
teaweb.popup("/servers/components/waf/createSetPopup?firewallPolicyId=" + this.firewallPolicyId + "&groupId=" + groupId + "&type=" + this.type, {
|
||||||
|
width: "50em",
|
||||||
|
height: "30em",
|
||||||
|
callback: function () {
|
||||||
|
teaweb.success("保存成功", function () {
|
||||||
|
window.location.reload()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改规则集
|
||||||
|
this.updateSet = function (setId) {
|
||||||
|
teaweb.popup("/servers/components/waf/updateSetPopup?firewallPolicyId=" + this.firewallPolicyId + "&groupId=" + this.group.id + "&type=" + this.type + "&setId=" + setId, {
|
||||||
|
width: "50em",
|
||||||
|
height: "30em",
|
||||||
|
callback: function () {
|
||||||
|
teaweb.success("保存成功", function () {
|
||||||
|
window.location.reload()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 停用|启用规则集
|
||||||
|
this.updateSetOn = function (setId, isOn) {
|
||||||
|
this.$post(".updateSetOn")
|
||||||
|
.params({
|
||||||
|
setId: setId,
|
||||||
|
isOn: isOn ? 1 : 0
|
||||||
|
})
|
||||||
|
.refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除规则集
|
||||||
|
this.deleteSet = function (setId) {
|
||||||
|
let that = this
|
||||||
|
teaweb.confirm("确定要删除此规则集吗?", function () {
|
||||||
|
that.$post(".deleteSet")
|
||||||
|
.params({
|
||||||
|
groupId: this.group.id,
|
||||||
|
setId: setId
|
||||||
|
})
|
||||||
|
.refresh()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
</p>
|
</p>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a :href="'/proxy/components/waf/sets?firewallPolicyId=' + firewallPolicyId + '&type=' + type + '&groupId=' + group.id">{{group.countSets}}</a>
|
<a :href="'/servers/components/waf/group?firewallPolicyId=' + firewallPolicyId + '&type=' + type + '&groupId=' + group.id">{{group.countSets}}</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a :href="'/servers/components/waf/group?firewallPolicyId=' + firewallPolicyId + '&type=' + type + '&groupId=' + group.id">详情</a>
|
<a :href="'/servers/components/waf/group?firewallPolicyId=' + firewallPolicyId + '&type=' + type + '&groupId=' + group.id">详情</a>
|
||||||
@@ -42,4 +42,6 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
<p class="comment" v-if="groups.length > 0">所有规则匹配顺序为从上到下,可以拖动左侧的<i class="icon bars"></i>排序。</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
{$layout "layout_popup"}
|
||||||
|
|
||||||
|
<h3>修改分组</h3>
|
||||||
|
|
||||||
|
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
||||||
|
<input type="hidden" name="groupId" :value="group.id"/>
|
||||||
|
<table class="ui table definition selectable">
|
||||||
|
<tr>
|
||||||
|
<td class="title">分组名称 *</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="name" maxlength="100" ref="focus" v-model="group.name"/>
|
||||||
|
<p class="comment">给分组起一个容易识别的名称</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2"><more-options-indicator></more-options-indicator></td>
|
||||||
|
</tr>
|
||||||
|
<tbody v-show="moreOptionsVisible">
|
||||||
|
<tr>
|
||||||
|
<td>分组描述</td>
|
||||||
|
<td>
|
||||||
|
<textarea name="description" maxlength="200" rows="3" v-model="group.description"></textarea>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>是否启用</td>
|
||||||
|
<td>
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<input type="checkbox" name="isOn" value="1" v-model="group.isOn" />
|
||||||
|
<label></label>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<submit-btn></submit-btn>
|
||||||
|
</form>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
Tea.context(function () {
|
||||||
|
this.success = NotifyPopup
|
||||||
|
})
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
{$layout "layout_popup"}
|
||||||
|
|
||||||
|
<h3>修改规则集</h3>
|
||||||
|
|
||||||
|
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
||||||
|
<input type="hidden" name="setId" :value="setConfig.id"/>
|
||||||
|
<table class="ui table definition selectable">
|
||||||
|
<tr>
|
||||||
|
<td class="title">规则集名称 *</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="name" maxlength="100" ref="focus" v-model="setConfig.name"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>规则</td>
|
||||||
|
<td>
|
||||||
|
<http-firewall-rules-box :v-rules="rules" :v-type="type"></http-firewall-rules-box>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>规则之间的关系</td>
|
||||||
|
<td>
|
||||||
|
<select class="ui dropdown" name="connector" style="width:10em" @change="changeConnector()" v-model="selectedConnector">
|
||||||
|
<option v-for="connector in connectors" :value="connector.value">{{connector.name}}</option>
|
||||||
|
</select>
|
||||||
|
<p class="comment">{{selectedConnectorDescription}}</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td :class="{'color-border':action == 'go_group' || action == 'go_set'}">动作</td>
|
||||||
|
<td>
|
||||||
|
<select class="ui dropdown auto-width" name="action" v-model="action">
|
||||||
|
<option v-for="a in actions" :value="a.code">{{a.name}}({{a.code.toUpperCase()}})</option>
|
||||||
|
</select>
|
||||||
|
<p class="comment">匹配当前规则集后要执行的动作。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="action == 'go_group'">
|
||||||
|
<td class="color-border">下一个规则分组</td>
|
||||||
|
<td>
|
||||||
|
<select class="ui dropdown" name="action_groupId" style="width:12em" v-model="actionGroupId">
|
||||||
|
<option v-for="g in firewallPolicy.inbound.groups" :value="g.id">{{g.name}}</option>
|
||||||
|
</select>
|
||||||
|
<p class="comment">当动作为"跳到下一个规则分组"时出现此选择。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="action == 'go_set'">
|
||||||
|
<td class="color-border">下一个规则分组</td>
|
||||||
|
<td>
|
||||||
|
<select class="ui dropdown" name="action_groupId" style="width:12em" v-model="actionGroupId">
|
||||||
|
<option v-for="g in firewallPolicy.inbound.groups" :value="g.id">{{g.name}}</option>
|
||||||
|
</select>
|
||||||
|
<p class="comment">当动作为"跳到下一个规则集"时出现此选择。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="action == 'go_set'">
|
||||||
|
<td class="color-border">下一个规则集</td>
|
||||||
|
<td>
|
||||||
|
<select class="ui dropdown" name="action_setId" style="width:12em" v-model="actionSetId">
|
||||||
|
<option v-for="r in groupSets(actionGroupId)" :value="r.id">{{r.name}}</option>
|
||||||
|
</select>
|
||||||
|
<p class="comment">当动作为"跳到下一个规则集"时出现此选择。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<submit-btn></submit-btn>
|
||||||
|
</form>
|
||||||
57
web/views/@default/servers/components/waf/updateSetPopup.js
Normal file
57
web/views/@default/servers/components/waf/updateSetPopup.js
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
Tea.context(function () {
|
||||||
|
this.success = NotifyPopup
|
||||||
|
|
||||||
|
// rules
|
||||||
|
this.rules = this.setConfig.rules
|
||||||
|
|
||||||
|
// connector
|
||||||
|
this.selectedConnector = this.setConfig.connector
|
||||||
|
this.selectedConnectorDescription = ""
|
||||||
|
this.changeConnector = function () {
|
||||||
|
let that = this
|
||||||
|
this.selectedConnectorDescription = this.connectors.$find(function (k, v) {
|
||||||
|
return v.value == that.selectedConnector
|
||||||
|
}).description
|
||||||
|
}
|
||||||
|
this.changeConnector()
|
||||||
|
|
||||||
|
// action
|
||||||
|
this.action = this.setConfig.action
|
||||||
|
|
||||||
|
// action:go_group
|
||||||
|
this.actionGroupId = 0
|
||||||
|
if (this.action == "go_group" || this.action == "go_set" && this.setConfig.actionOptions != null) {
|
||||||
|
this.$delay(function () {
|
||||||
|
this.actionGroupId = this.setConfig.actionOptions["groupId"]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// action:go_set
|
||||||
|
this.actionSetId = 0
|
||||||
|
if (this.action == "go_set" && this.setConfig.actionOptions != null) {
|
||||||
|
this.$delay(function () {
|
||||||
|
this.actionSetId = this.setConfig.actionOptions["setId"]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.groupSets = function (groupId) {
|
||||||
|
if (this.firewallPolicy == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let group = null
|
||||||
|
this.firewallPolicy.inbound.groups.forEach(function (v) {
|
||||||
|
if (v.id == groupId) {
|
||||||
|
group = v
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.firewallPolicy.outbound.groups.forEach(function (v) {
|
||||||
|
if (v.id == groupId) {
|
||||||
|
group = v
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (group == null) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
return group.sets
|
||||||
|
}
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user