Commit f9077078 authored by qiuqunfeng's avatar qiuqunfeng
Browse files

Add ListWafs endpoint and service method for WAF management

- Introduce ListWafs method in WafController to retrieve a list of WAF services
- Update WAF router to include new GET routes for listing WAFs
- Implement ListWafs method in the service layer to fetch WAF data from the database
- Enhance the MatcherExpr and WafService structures to support new functionality
parent efd47f51
...@@ -13,6 +13,7 @@ func SetWafRouter(e *gin.Engine, clusterClientManager *utils.ClusterClientManage ...@@ -13,6 +13,7 @@ func SetWafRouter(e *gin.Engine, clusterClientManager *utils.ClusterClientManage
wafController := controller.NewWafController(clusterClientManager, db, gatewayUrl, elasticClient) wafController := controller.NewWafController(clusterClientManager, db, gatewayUrl, elasticClient)
v1.GET("", wafController.Waf) v1.GET("", wafController.Waf)
v1.GET("list", wafController.ListWafs)
v1.POST("/", wafController.CreateWaf) v1.POST("/", wafController.CreateWaf)
v1.PUT("mode", wafController.UpdateMode) v1.PUT("mode", wafController.UpdateMode)
v1.PUT("rules", wafController.UpdateRule) v1.PUT("rules", wafController.UpdateRule)
...@@ -32,4 +33,5 @@ func SetWafRouter(e *gin.Engine, clusterClientManager *utils.ClusterClientManage ...@@ -32,4 +33,5 @@ func SetWafRouter(e *gin.Engine, clusterClientManager *utils.ClusterClientManage
v2.PUT("blackwhitelist/enabling", wafController.EnableBlackWhiteList) v2.PUT("blackwhitelist/enabling", wafController.EnableBlackWhiteList)
v2.DELETE("blackwhitelist/{id}", wafController.DeleteBlackWhiteList) v2.DELETE("blackwhitelist/{id}", wafController.DeleteBlackWhiteList)
v2.GET("blackwhitelists", wafController.GetBlackWhiteLists) v2.GET("blackwhitelists", wafController.GetBlackWhiteLists)
v2.GET("services", wafController.ListWafs)
} }
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"strconv" "strconv"
"strings"
"time" "time"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
...@@ -45,6 +46,18 @@ func (c *WafController) Waf(ctx *gin.Context) { ...@@ -45,6 +46,18 @@ func (c *WafController) Waf(ctx *gin.Context) {
utils.AssembleResponse(ctx, resp, nil) utils.AssembleResponse(ctx, resp, nil)
} }
func (c *WafController) ListWafs(ctx *gin.Context) {
ctx1, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
wafs, err := c.service.ListWafs(ctx1)
if err != nil {
utils.AssembleResponse(ctx, nil, err)
return
}
utils.AssembleResponse(ctx, wafs, nil)
}
func (c *WafController) GetWafGatewayInfo(ctx *gin.Context) { func (c *WafController) GetWafGatewayInfo(ctx *gin.Context) {
ctx1, cancel := context.WithTimeout(context.Background(), 10*time.Second) ctx1, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel() defer cancel()
...@@ -298,6 +311,7 @@ func (c *WafController) ListAttackLogs(ctx *gin.Context) { ...@@ -298,6 +311,7 @@ func (c *WafController) ListAttackLogs(ctx *gin.Context) {
filter.AttackIp = ctx.Query("attackIp") filter.AttackIp = ctx.Query("attackIp")
filter.AttackType = ctx.Query("attackType") filter.AttackType = ctx.Query("attackType")
filter.AttackApp = ctx.Query("attackApp") filter.AttackApp = ctx.Query("attackApp")
filter.AttackListener = ctx.Query("attackListener")
filter.Token = ctx.Query("token") filter.Token = ctx.Query("token")
filter.Action = ctx.Query("action") filter.Action = ctx.Query("action")
stime := ctx.Query("startTime") stime := ctx.Query("startTime")
...@@ -387,13 +401,67 @@ func (c *WafController) EnableBlackWhiteList(ctx *gin.Context) { ...@@ -387,13 +401,67 @@ func (c *WafController) EnableBlackWhiteList(ctx *gin.Context) {
} }
func (c *WafController) DeleteBlackWhiteList(ctx *gin.Context) { func (c *WafController) DeleteBlackWhiteList(ctx *gin.Context) {
// ctx1, cancel := context.WithTimeout(context.Background(), 10*time.Second) ctx1, cancel := context.WithTimeout(context.Background(), 10*time.Second)
// defer cancel() defer cancel()
id := ctx.Param("id")
idUint, err := strconv.ParseUint(id, 10, 32)
if err != nil {
utils.AssembleResponse(ctx, nil, err)
return
}
err = c.service.DeleteBlackWhiteList(ctx1, uint32(idUint))
if err != nil {
utils.AssembleResponse(ctx, nil, err)
return
}
utils.AssembleResponse(ctx, nil, nil)
} }
func (c *WafController) GetBlackWhiteLists(ctx *gin.Context) { func (c *WafController) GetBlackWhiteLists(ctx *gin.Context) {
// ctx1, cancel := context.WithTimeout(context.Background(), 10*time.Second) ctx1, cancel := context.WithTimeout(context.Background(), 10*time.Second)
// defer cancel() defer cancel()
limit, offset, err := getLimitAndOffset(ctx)
if err != nil {
utils.AssembleResponse(ctx, nil, err)
return
}
name := ctx.Query("name")
status := ctx.Query("status")
mode := ctx.Query("mode")
expr := ctx.Query("expr")
query := service.MatchExprQuery()
if status != "" {
statusList := strings.Split(status, ",")
if len(statusList) == 1 && statusList[0] != "" {
switch status {
case "0":
query.WithStatus(0)
case "1":
query.WithStatus(1)
}
}
}
if name != "" {
query.WithFuzzyName(name)
}
if mode != "" {
modes := strings.Split(mode, ",")
query.WithInConditionCustom("mode", modes)
}
if expr != "" {
query.WithFuzzyExpr(expr)
}
lists, err := c.service.GetBlackWhiteLists(ctx1, query, limit, offset)
if err != nil {
utils.AssembleResponse(ctx, nil, err)
return
}
utils.AssembleResponse(ctx, lists, nil)
} }
...@@ -5,6 +5,7 @@ import "context" ...@@ -5,6 +5,7 @@ import "context"
type Service interface { type Service interface {
// QueryIP(ip string) (*model.IPInfo, error) // QueryIP(ip string) (*model.IPInfo, error)
GetWaf(ctx context.Context, regionCode, namespace, gatewayName string) (*WafService, error) GetWaf(ctx context.Context, regionCode, namespace, gatewayName string) (*WafService, error)
ListWafs(ctx context.Context) ([]WafService, error)
GetWafGatewayInfo(ctx context.Context, req *GetWafGatewayInfoReq) (*WafService, error) GetWafGatewayInfo(ctx context.Context, req *GetWafGatewayInfoReq) (*WafService, error)
CreateWaf(ctx context.Context, req *CreateWafReq) (*WafService, error) CreateWaf(ctx context.Context, req *CreateWafReq) (*WafService, error)
UpdateMode(ctx context.Context, req *UpdateModeReq) (*WafService, error) UpdateMode(ctx context.Context, req *UpdateModeReq) (*WafService, error)
...@@ -20,6 +21,6 @@ type Service interface { ...@@ -20,6 +21,6 @@ type Service interface {
CreateBlackWhiteList(ctx context.Context, req *MatcherExpr) error CreateBlackWhiteList(ctx context.Context, req *MatcherExpr) error
UpdateBlackWhiteList(ctx context.Context, req *MatcherExpr) error UpdateBlackWhiteList(ctx context.Context, req *MatcherExpr) error
EnableBlackWhiteList(ctx context.Context, req *MatcherExpr) error EnableBlackWhiteList(ctx context.Context, req *MatcherExpr) error
DeleteBlackWhiteList(ctx context.Context, req *MatcherExpr) error DeleteBlackWhiteList(ctx context.Context, ID uint32) error
GetBlackWhiteLists(ctx context.Context, req *MatcherExpr) ([]MatcherExpr, error) GetBlackWhiteLists(ctx context.Context, query *MatchExprQueryOption, limit int, offset int) ([]MatcherExpr, error)
} }
...@@ -165,6 +165,7 @@ type IPInfoPrivateResp struct { ...@@ -165,6 +165,7 @@ type IPInfoPrivateResp struct {
type WafService struct { type WafService struct {
GatewayName string `json:"gateway_name"` GatewayName string `json:"gateway_name"`
Name string `json:"name"`
Mode string `json:"mode"` Mode string `json:"mode"`
RuleNum int `json:"rule_num"` RuleNum int `json:"rule_num"`
AttackNum int `json:"attack_num"` AttackNum int `json:"attack_num"`
...@@ -328,29 +329,31 @@ type GatewayListenerResponseList struct { ...@@ -328,29 +329,31 @@ type GatewayListenerResponseList struct {
} }
type AttackLog struct { type AttackLog struct {
Uuid string `json:"uuid"` Uuid string `json:"uuid"`
AttackIp string `json:"attack_ip"` AttackIp string `json:"attack_ip"`
AttackedAddr string `json:"attacked_addr"` AttackedAddr string `json:"attacked_addr"`
AttackType string `json:"attack_type"` AttackType string `json:"attack_type"`
AttackTime int64 `json:"attack_time"` AttackTime int64 `json:"attack_time"`
AttackedApp string `json:"attacked_app"` AttackedApp string `json:"attacked_app"`
ClusterKey string `json:"cluster_key"` AttackListener string `json:"attack_listener"`
Action string `json:"action"` ClusterKey string `json:"cluster_key"`
Action string `json:"action"`
} }
type AttackLogFilter struct { type AttackLogFilter struct {
Offset int `json:"offset"` Offset int `json:"offset"`
Limit int `json:"limit"` Limit int `json:"limit"`
ServiceId int64 `json:"service_id"` ServiceId int64 `json:"service_id"`
Cluster string `json:"cluster"` Cluster string `json:"cluster"`
AttackUrl string `json:"attack_url"` AttackUrl string `json:"attack_url"`
AttackIp string `json:"attack_ip"` AttackIp string `json:"attack_ip"`
AttackType string `json:"attack_type"` AttackType string `json:"attack_type"`
AttackApp string `json:"attack_app"` AttackApp string `json:"attack_app"`
Action string `json:"action"` AttackListener string `json:"attack_listener"`
Token string `json:"token"` Action string `json:"action"`
StartTime int64 `json:"start_time"` Token string `json:"token"`
EndTime int64 `json:"end_time"` StartTime int64 `json:"start_time"`
EndTime int64 `json:"end_time"`
} }
type MatcherExpr struct { type MatcherExpr struct {
...@@ -363,3 +366,42 @@ type MatcherExpr struct { ...@@ -363,3 +366,42 @@ type MatcherExpr struct {
Global bool `json:"global"` Global bool `json:"global"`
Status int32 `json:"status"` Status int32 `json:"status"`
} }
type MatchExprQueryOption struct {
WhereLikeCondition map[string]string
whereEqCondition map[string]interface{}
whereInCondition map[string]interface{}
}
func MatchExprQuery() *MatchExprQueryOption {
return &MatchExprQueryOption{
WhereLikeCondition: make(map[string]string, 3),
whereEqCondition: make(map[string]interface{}, 3),
whereInCondition: make(map[string]interface{}, 3),
}
}
func (n *MatchExprQueryOption) WithFuzzyName(name string) *MatchExprQueryOption {
n.WhereLikeCondition["name"] = name
return n
}
func (n *MatchExprQueryOption) WithFuzzyExpr(expr string) *MatchExprQueryOption {
n.WhereLikeCondition["expr"] = expr
return n
}
func (n *MatchExprQueryOption) WithStatus(status int32) *MatchExprQueryOption {
n.whereEqCondition["status"] = status
return n
}
func (n *MatchExprQueryOption) WithMode(mode string) *MatchExprQueryOption {
n.whereEqCondition["mode"] = mode
return n
}
func (q *MatchExprQueryOption) WithInConditionCustom(column string, value interface{}) *MatchExprQueryOption {
q.whereInCondition[column] = value
return q
}
...@@ -13,6 +13,7 @@ import ( ...@@ -13,6 +13,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
"time"
jsoniter "github.com/json-iterator/go" jsoniter "github.com/json-iterator/go"
"github.com/olivere/elastic/v7" "github.com/olivere/elastic/v7"
...@@ -79,6 +80,17 @@ func (s *wafService) GetWaf(ctx context.Context, regionCode, namespace, gatewayN ...@@ -79,6 +80,17 @@ func (s *wafService) GetWaf(ctx context.Context, regionCode, namespace, gatewayN
}, nil }, nil
} }
func (s *wafService) ListWafs(ctx context.Context) ([]WafService, error) {
var wafs []WafService
if err := s.db.Model(&model.WafService{}).Find(&wafs).Error; err != nil {
return nil, err
}
for i, waf := range wafs {
wafs[i].Name = waf.GatewayName
}
return wafs, nil
}
func (s *wafService) GetWafGatewayInfo(ctx context.Context, req *GetWafGatewayInfoReq) (*WafService, error) { func (s *wafService) GetWafGatewayInfo(ctx context.Context, req *GetWafGatewayInfoReq) (*WafService, error) {
wafService := &model.WafService{} wafService := &model.WafService{}
err := s.db.Model(&model.WafService{}).Where("gateway_name = ? AND namespace = ? AND region_code = ?", req.GatewayName, req.Namespace, req.RegionCode).First(wafService).Error err := s.db.Model(&model.WafService{}).Where("gateway_name = ? AND namespace = ? AND region_code = ?", req.GatewayName, req.Namespace, req.RegionCode).First(wafService).Error
...@@ -852,14 +864,15 @@ func (s *wafService) ListAttackLogs(ctx context.Context, req *AttackLogFilter) ( ...@@ -852,14 +864,15 @@ func (s *wafService) ListAttackLogs(ctx context.Context, req *AttackLogFilter) (
attackLogs := make([]AttackLog, len(list)) attackLogs := make([]AttackLog, len(list))
for i, wafDetection := range list { for i, wafDetection := range list {
attackLogs[i] = AttackLog{ attackLogs[i] = AttackLog{
Uuid: wafDetection.ID, Uuid: wafDetection.ID,
AttackTime: wafDetection.AttackTime, AttackTime: wafDetection.AttackTime,
AttackIp: wafDetection.AttackIP, AttackIp: wafDetection.AttackIP,
AttackedApp: wafDetection.AttackedApp, AttackedApp: wafDetection.AttackedApp,
AttackType: wafDetection.AttackType, AttackListener: wafDetection.ResName,
Action: wafDetection.Action, AttackType: wafDetection.AttackType,
ClusterKey: wafDetection.ClusterKey, Action: wafDetection.Action,
AttackedAddr: wafDetection.AttackedURL, ClusterKey: wafDetection.ClusterKey,
AttackedAddr: wafDetection.AttackedURL,
} }
} }
return attackLogs, pageToken, nil return attackLogs, pageToken, nil
...@@ -1021,10 +1034,84 @@ func (s *wafService) EnableBlackWhiteList(ctx context.Context, req *MatcherExpr) ...@@ -1021,10 +1034,84 @@ func (s *wafService) EnableBlackWhiteList(ctx context.Context, req *MatcherExpr)
return nil return nil
} }
func (s *wafService) DeleteBlackWhiteList(ctx context.Context, req *MatcherExpr) error { func (s *wafService) deleteConfigMap(ctx context.Context, id uint32, regionCode string, wafSvc []model.WafService) error {
client := s.clusterClientManager.GetClient(regionCode)
if client == nil {
return fmt.Errorf("failed to get cluster client")
}
name := fmt.Sprintf("waf-black-white-list-%d", id)
return client.Clientset.CoreV1().ConfigMaps(wafSvc[0].Namespace).Delete(ctx, name, metav1.DeleteOptions{})
}
func (s *wafService) DeleteBlackWhiteList(ctx context.Context, ID uint32) error {
matcherExpr := model.MatcherExpr{}
err := s.db.WithContext(ctx).Where("id = ?", ID).First(&matcherExpr).Error
if err != nil {
return err
}
svcMap, err := s.getWafServiceMap(ctx, &MatcherExpr{
ID: ID,
Name: matcherExpr.Name,
Scope: matcherExpr.Scope,
Mode: matcherExpr.Mode,
Expr: matcherExpr.Expr,
Global: matcherExpr.Global,
})
if err != nil {
return err
}
for regionCode, wafServices := range svcMap {
err := s.deleteConfigMap(ctx, ID, regionCode, wafServices)
if err != nil {
return err
}
}
err = s.db.WithContext(ctx).Delete(&model.MatcherExpr{}, ID).Error
if err != nil {
return err
}
return nil return nil
} }
func (s *wafService) GetBlackWhiteLists(ctx context.Context, req *MatcherExpr) ([]MatcherExpr, error) { func GetLikeExpr(s string) string {
return nil, nil sb := strings.Builder{}
sb.WriteByte('%')
sb.WriteString(s)
sb.WriteByte('%')
return sb.String()
}
func (s *wafService) GetBlackWhiteLists(ctx context.Context, query *MatchExprQueryOption, limit int, offset int) ([]MatcherExpr, error) {
oneCtx, oneCancel := context.WithTimeout(ctx, 750*time.Millisecond)
defer oneCancel()
exprs := []model.MatcherExpr{}
db := s.db.WithContext(oneCtx).Model(&model.MatcherExpr{})
if len(query.whereEqCondition) > 0 {
db = db.Where(query.whereEqCondition)
}
for column, val := range query.WhereLikeCondition {
db = db.Where(fmt.Sprintf("%s LIKE ?", column), GetLikeExpr(val))
}
for column, val := range query.whereInCondition {
db = db.Where(fmt.Sprintf("%s in ?", column), val)
}
if limit > 0 && offset >= 0 {
db = db.Offset(offset).Limit(limit)
}
err := db.Order("updated_at DESC").Find(&exprs).Error
if err != nil {
return nil, err
}
exprsResp := []MatcherExpr{}
for _, expr := range exprs {
exprsResp = append(exprsResp, MatcherExpr{
ID: expr.ID,
Name: expr.Name,
})
}
return exprsResp, nil
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment