From c6a14708dfb5851aa467836ef095c0debff8cdd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E7=A5=A5=E8=B6=85?= Date: Mon, 18 Jan 2021 20:39:58 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E5=8D=95=E4=B8=AA=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E4=B8=AD=E7=9A=84WAF=E4=B8=AD=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E5=87=BA=E5=85=A5=E7=AB=99=E8=A7=84=E5=88=99=E3=80=81=E9=BB=91?= =?UTF-8?q?=E7=99=BD=E5=90=8D=E5=8D=95=E7=AD=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../servers/server/settings/waf/group.go | 110 ++++++++++++++++++ .../servers/server/settings/waf/groups.go | 74 ++++++++++++ .../servers/server/settings/waf/index.go | 12 ++ .../servers/server/settings/waf/init.go | 4 + .../server/settings/waf/ipadmin/allowList.go | 4 +- .../server/settings/waf/ipadmin/denyList.go | 4 +- .../servers/server/settings/waf/@menu.html | 6 +- .../servers/server/settings/waf/group.html | 69 +++++++++++ .../servers/server/settings/waf/group.js | 82 +++++++++++++ .../servers/server/settings/waf/groups.html | 48 ++++++++ .../servers/server/settings/waf/groups.js | 68 +++++++++++ 11 files changed, 477 insertions(+), 4 deletions(-) create mode 100644 internal/web/actions/default/servers/server/settings/waf/group.go create mode 100644 internal/web/actions/default/servers/server/settings/waf/groups.go create mode 100644 web/views/@default/servers/server/settings/waf/group.html create mode 100644 web/views/@default/servers/server/settings/waf/group.js create mode 100644 web/views/@default/servers/server/settings/waf/groups.html create mode 100644 web/views/@default/servers/server/settings/waf/groups.js diff --git a/internal/web/actions/default/servers/server/settings/waf/group.go b/internal/web/actions/default/servers/server/settings/waf/group.go new file mode 100644 index 00000000..e0b322be --- /dev/null +++ b/internal/web/actions/default/servers/server/settings/waf/group.go @@ -0,0 +1,110 @@ +package waf + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao" + "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("", "setting", this.ParamString("type")) + this.SecondMenu("waf") +} + +func (this *GroupAction) RunGet(params struct { + FirewallPolicyId int64 + GroupId int64 + Type string +}) { + this.Data["type"] = params.Type + this.Data["firewallPolicyId"] = params.FirewallPolicyId + + // policy + firewallPolicy, err := dao.SharedHTTPFirewallPolicyDAO.FindEnabledHTTPFirewallPolicyConfig(this.AdminContext(), params.FirewallPolicyId) + if err != nil { + this.ErrorPage(err) + return + } + if firewallPolicy == nil { + this.NotFound("firewallPolicy", params.FirewallPolicyId) + return + } + + // group config + groupConfig, err := dao.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, + "paramFilters": rule.ParamFilters, + "operator": rule.Operator, + "value": rule.Value, + "isCaseInsensitive": rule.IsCaseInsensitive, + "isComposed": firewallconfigs.CheckCheckpointIsComposed(rule.Prefix()), + } + }), + "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() +} diff --git a/internal/web/actions/default/servers/server/settings/waf/groups.go b/internal/web/actions/default/servers/server/settings/waf/groups.go new file mode 100644 index 00000000..f6c21d92 --- /dev/null +++ b/internal/web/actions/default/servers/server/settings/waf/groups.go @@ -0,0 +1,74 @@ +package waf + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao" + "github.com/iwind/TeaGo/maps" +) + +type GroupsAction struct { + actionutils.ParentAction +} + +func (this *GroupsAction) Init() { + this.Nav("", "setting", this.ParamString("type")) + this.SecondMenu("waf") +} + +func (this *GroupsAction) RunGet(params struct { + FirewallPolicyId int64 + Type string +}) { + this.Data["firewallPolicyId"] = params.FirewallPolicyId + this.Data["type"] = params.Type + + firewallPolicy, err := dao.SharedHTTPFirewallPolicyDAO.FindEnabledHTTPFirewallPolicyConfig(this.AdminContext(), params.FirewallPolicyId) + if err != nil { + this.ErrorPage(err) + return + } + if firewallPolicy == nil { + this.NotFound("firewallPolicy", params.FirewallPolicyId) + return + } + + groupMaps := []maps.Map{} + + // inbound + if params.Type == "inbound" { + if firewallPolicy.Inbound != nil { + for _, g := range firewallPolicy.Inbound.Groups { + groupMaps = append(groupMaps, maps.Map{ + "id": g.Id, + "name": g.Name, + "code": g.Code, + "isOn": g.IsOn, + "description": g.Description, + "countSets": len(g.Sets), + "canDelete": len(g.Code) == 0, + }) + } + } + } + + // outbound + if params.Type == "outbound" { + if firewallPolicy.Outbound != nil { + for _, g := range firewallPolicy.Outbound.Groups { + groupMaps = append(groupMaps, maps.Map{ + "id": g.Id, + "name": g.Name, + "code": g.Code, + "isOn": g.IsOn, + "description": g.Description, + "countSets": len(g.Sets), + "canDelete": len(g.Code) == 0, + }) + } + } + } + + this.Data["groups"] = groupMaps + + this.Show() +} diff --git a/internal/web/actions/default/servers/server/settings/waf/index.go b/internal/web/actions/default/servers/server/settings/waf/index.go index 2e662081..55f52d70 100644 --- a/internal/web/actions/default/servers/server/settings/waf/index.go +++ b/internal/web/actions/default/servers/server/settings/waf/index.go @@ -45,6 +45,18 @@ func (this *IndexAction) RunGet(params struct { this.Data["firewallPolicy"] = nil } + // 当前的Server独立设置 + if webConfig.FirewallRef == nil || webConfig.FirewallRef.FirewallPolicyId == 0 { + firewallPolicyId, err := dao.SharedHTTPWebDAO.InitEmptyHTTPFirewallPolicy(this.AdminContext(), webConfig.Id, webConfig.FirewallRef != nil && webConfig.FirewallRef.IsOn) + if err != nil { + this.ErrorPage(err) + return + } + this.Data["firewallPolicyId"] = firewallPolicyId + } else { + this.Data["firewallPolicyId"] = webConfig.FirewallRef.FirewallPolicyId + } + this.Show() } diff --git a/internal/web/actions/default/servers/server/settings/waf/init.go b/internal/web/actions/default/servers/server/settings/waf/init.go index eb2d352c..526a65d5 100644 --- a/internal/web/actions/default/servers/server/settings/waf/init.go +++ b/internal/web/actions/default/servers/server/settings/waf/init.go @@ -22,6 +22,10 @@ func init() { GetPost("/ipadmin/createIPPopup", new(ipadmin.CreateIPPopupAction)). GetPost("/ipadmin/updateIPPopup", new(ipadmin.UpdateIPPopupAction)). Post("/ipadmin/deleteIP", new(ipadmin.DeleteIPAction)). + + // 规则相关 + Get("/groups", new(GroupsAction)). + Get("/group", new(GroupAction)). EndAll() }) } diff --git a/internal/web/actions/default/servers/server/settings/waf/ipadmin/allowList.go b/internal/web/actions/default/servers/server/settings/waf/ipadmin/allowList.go index 3b622114..f52c227d 100644 --- a/internal/web/actions/default/servers/server/settings/waf/ipadmin/allowList.go +++ b/internal/web/actions/default/servers/server/settings/waf/ipadmin/allowList.go @@ -18,9 +18,11 @@ func (this *AllowListAction) Init() { } func (this *AllowListAction) RunGet(params struct { - ServerId int64 + ServerId int64 + FirewallPolicyId int64 }) { this.Data["featureIsOn"] = true + this.Data["firewallPolicyId"] = params.FirewallPolicyId listId, err := dao.SharedIPListDAO.FindAllowIPListIdWithServerId(this.AdminContext(), params.ServerId) if err != nil { diff --git a/internal/web/actions/default/servers/server/settings/waf/ipadmin/denyList.go b/internal/web/actions/default/servers/server/settings/waf/ipadmin/denyList.go index a703b424..e22f9a07 100644 --- a/internal/web/actions/default/servers/server/settings/waf/ipadmin/denyList.go +++ b/internal/web/actions/default/servers/server/settings/waf/ipadmin/denyList.go @@ -18,9 +18,11 @@ func (this *DenyListAction) Init() { } func (this *DenyListAction) RunGet(params struct { - ServerId int64 + FirewallPolicyId int64 + ServerId int64 }) { this.Data["featureIsOn"] = true + this.Data["firewallPolicyId"] = params.FirewallPolicyId listId, err := dao.SharedIPListDAO.FindDenyIPListIdWithServerId(this.AdminContext(), params.ServerId) if err != nil { diff --git a/web/views/@default/servers/server/settings/waf/@menu.html b/web/views/@default/servers/server/settings/waf/@menu.html index d2263917..b37d53cc 100644 --- a/web/views/@default/servers/server/settings/waf/@menu.html +++ b/web/views/@default/servers/server/settings/waf/@menu.html @@ -1,5 +1,7 @@ 设置 - 白名单 - 黑名单 + 入站规则 + 出站规则 + 白名单 + 黑名单 \ No newline at end of file diff --git a/web/views/@default/servers/server/settings/waf/group.html b/web/views/@default/servers/server/settings/waf/group.html new file mode 100644 index 00000000..690d52f1 --- /dev/null +++ b/web/views/@default/servers/server/settings/waf/group.html @@ -0,0 +1,69 @@ +{$layout} +{$template "/left_menu"} + +
+ {$template "menu"} + +

分组[修改]

+ + + + + + + + + + + + + +
名称{{group.name}}
描述 + 暂时还没有描述。 + {{group.description}} +
启用状态 + +
+ +

规则集[添加规则集]

+

暂时还没有规则。

+ + + + + + + + + + + + + + + + + + + + + +
规则集名称规则关系动作操作
{{set.name}} +

+ +

+
+
+ {{rule.name}}[{{rule.param}}] | {{paramFilter.code}} {{rule.operator}} {{rule.value}} +
+ 暂时还没有规则 +
{{set.connector.toUpperCase()}}{{set.actionName}}[{{set.action.toUpperCase()}}] +
+ -> [{{link.name}}]   +
+
+ 修改   停用启用   删除 +
+ +

所有规则匹配顺序为从上到下,可以拖动左侧的排序。

+
\ No newline at end of file diff --git a/web/views/@default/servers/server/settings/waf/group.js b/web/views/@default/servers/server/settings/waf/group.js new file mode 100644 index 00000000..5638a956 --- /dev/null +++ b/web/views/@default/servers/server/settings/waf/group.js @@ -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("/servers/components/waf/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("/servers/components/waf/updateSetOn") + .params({ + setId: setId, + isOn: isOn ? 1 : 0 + }) + .refresh() + } + + // 删除规则集 + this.deleteSet = function (setId) { + let that = this + teaweb.confirm("确定要删除此规则集吗?", function () { + that.$post("/servers/components/waf/deleteSet") + .params({ + groupId: this.group.id, + setId: setId + }) + .refresh() + }) + } +}) \ No newline at end of file diff --git a/web/views/@default/servers/server/settings/waf/groups.html b/web/views/@default/servers/server/settings/waf/groups.html new file mode 100644 index 00000000..dbb99e3f --- /dev/null +++ b/web/views/@default/servers/server/settings/waf/groups.html @@ -0,0 +1,48 @@ +{$layout} +{$template "/left_menu"} + +
+ {$template "menu"} + + + [添加分组] + + +

暂时还没有规则分组。

+ + + + + + + + + + + + + + + + + + +
规则分组规则集操作
{{group.name}} +

{{group.description}}

+

+ 启用 + 停用 + 预置 + 自定义 +

+
+ {{group.countSets}} + + 详情   + 启用停用   + 删除 +
+ +

所有规则匹配顺序为从上到下,可以拖动左侧的排序。

+ +
\ No newline at end of file diff --git a/web/views/@default/servers/server/settings/waf/groups.js b/web/views/@default/servers/server/settings/waf/groups.js new file mode 100644 index 00000000..f98b7fb2 --- /dev/null +++ b/web/views/@default/servers/server/settings/waf/groups.js @@ -0,0 +1,68 @@ +Tea.context(function () { + // 排序 + this.$delay(function () { + let that = this + sortTable(function () { + let groupIds = [] + document.querySelectorAll("tbody[data-group-id]") + .forEach(function (v) { + groupIds.push(v.getAttribute("data-group-id")) + }) + + that.$post("/servers/components/waf/sortGroups") + .params({ + firewallPolicyId: that.firewallPolicyId, + type: that.type, + groupIds: groupIds + }) + .success(function () { + teaweb.successToast("排序保存成功") + }) + }) + }) + + // 启用 + this.enableGroup = function (groupId) { + this.$post("/servers/components/waf/updateGroupOn") + .params({ + groupId: groupId, + isOn: 1 + }) + .refresh() + + } + + // 停用 + this.disableGroup = function (groupId) { + this.$post("/servers/components/waf/updateGroupOn") + .params({ + groupId: groupId, + isOn: 0 + }) + .refresh() + } + + // 删除 + this.deleteGroup = function (groupId) { + teaweb.confirm("确定要删除此规则分组吗?", function () { + this.$post("/servers/components/waf/deleteGroup") + .params({ + firewallPolicyId: this.firewallPolicyId, + groupId: groupId + }) + .refresh() + }) + } + + // 添加分组 + this.createGroup = function (type) { + teaweb.popup("/servers/components/waf/createGroupPopup?firewallPolicyId=" + this.firewallPolicyId + "&type=" + type, { + height: "16em", + callback: function () { + teaweb.success("保存成功", function () { + window.location.reload() + }) + } + }) + } +}) \ No newline at end of file