package controller import ( "context" "errors" "fmt" "strconv" "time" "github.com/gin-gonic/gin" "github.com/olivere/elastic/v7" "gitlab.com/tensorsecurity-rd/waf-console/internal/service" "gitlab.com/tensorsecurity-rd/waf-console/internal/utils" "gorm.io/gorm" ) type WafController struct { service service.Service } func NewWafController(clusterClientManager *utils.ClusterClientManager, db *gorm.DB, gatewayUrl string, elasticClient *elastic.Client) *WafController { return &WafController{ service: service.NewWafService(clusterClientManager, db, gatewayUrl, elasticClient), } } func (c *WafController) Waf(ctx *gin.Context) { ctx1, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() gatewayName := ctx.Query("gateway_name") regionCode := ctx.Query("region_code") namespace := ctx.Query("namespace") waf, err := c.service.GetWaf(ctx1, regionCode, namespace, gatewayName) if err != nil { // logging.Get().Err(err).Msgf("get waf") utils.AssembleResponse(ctx, nil, err) return } resp := &utils.SingleRespData{ Item: waf, } utils.AssembleResponse(ctx, resp, nil) } func (c *WafController) GetWafGatewayInfo(ctx *gin.Context) { ctx1, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() cookie := ctx.Request.Header.Get("Cookie") if cookie == "" { utils.AssembleResponse(ctx, nil, errors.New("cookie is required")) return } var req service.GetWafGatewayInfoReq if err := ctx.BindJSON(&req); err != nil { utils.AssembleResponse(ctx, nil, err) return } info, err := c.service.GetWafGatewayInfo(ctx1, &req) if err != nil { utils.AssembleResponse(ctx, nil, err) return } utils.AssembleResponse(ctx, info, nil) } func (c *WafController) CreateWaf(ctx *gin.Context) { ctx1, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() var req []service.CreateWafReq if err := ctx.BindJSON(&req); err != nil { utils.AssembleResponse(ctx, nil, err) return } for _, r := range req { _, err := c.service.CreateWaf(ctx1, &r) if err != nil { utils.AssembleResponse(ctx, nil, err) return } } utils.AssembleResponse(ctx, nil, nil) } // ` // curl -X POST http://127.0.0.1:8080/v1/api/waf \ // -H "Content-Type: application/json" \ // -d '[ // { // "region_code": "cn-east-1", // "gatewayname": "istio-ingressgateway", // "namespace": "istio-system", // "port": 80, // "host": ["*"] // } // ]' // ` func (c *WafController) UpdateMode(ctx *gin.Context) { ctx1, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() var req service.UpdateModeReq if err := ctx.BindJSON(&req); err != nil { utils.AssembleResponse(ctx, nil, err) return } _, err := c.service.UpdateMode(ctx1, &req) if err != nil { utils.AssembleResponse(ctx, nil, err) return } utils.AssembleResponse(ctx, nil, nil) } func (c *WafController) UpdateRule(ctx *gin.Context) { ctx1, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() var req service.RuleRequest if err := ctx.BindJSON(&req); err != nil { utils.AssembleResponse(ctx, nil, err) return } err := c.service.UpdateRule(ctx1, &req) if err != nil { utils.AssembleResponse(ctx, nil, err) return } utils.AssembleResponse(ctx, nil, nil) } func (c *WafController) ListRules(ctx *gin.Context) { ctx1, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() regionCode := ctx.Query("region_code") namespace := ctx.Query("namespace") gatewayName := ctx.Query("gateway_name") language := ctx.Request.Header.Get("Accept-Language") name := ctx.Query("name") if language == "" { language = "zh" } rules, err := c.service.ListRules(ctx1, regionCode, namespace, gatewayName, language, name) if err != nil { utils.AssembleResponse(ctx, nil, err) return } utils.AssembleResponse(ctx, rules, nil) } func (c *WafController) SaveRuleCategoryToDB(ctx *gin.Context) { ctx1, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() err := c.service.SaveRuleCategoryToDB(ctx1) if err != nil { utils.AssembleResponse(ctx, nil, err) return } utils.AssembleResponse(ctx, nil, nil) } func (c *WafController) EnableListenerWaf(ctx *gin.Context) { ctx1, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() var req service.EnableListenerWafReq if err := ctx.BindJSON(&req); err != nil { utils.AssembleResponse(ctx, nil, err) return } err := c.service.EnableListenerWaf(ctx1, &req) if err != nil { utils.AssembleResponse(ctx, nil, err) return } utils.AssembleResponse(ctx, nil, nil) } func (c *WafController) EnableGatewayWaf(ctx *gin.Context) { ctx1, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() var req service.EnableGatewayWafReq if err := ctx.BindJSON(&req); err != nil { utils.AssembleResponse(ctx, nil, err) return } req.Cookie = ctx.Request.Header.Get("Cookie") err := c.service.EnableGatewayWaf(ctx1, &req) if err != nil { utils.AssembleResponse(ctx, nil, err) return } utils.AssembleResponse(ctx, nil, nil) } func (c *WafController) EnableListenerWafs(ctx *gin.Context) { ctx1, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() var req service.EnableListenerWafsReq if err := ctx.BindJSON(&req); err != nil { utils.AssembleResponse(ctx, nil, err) return } err := c.service.EnableListenerWafs(ctx1, &req) if err != nil { utils.AssembleResponse(ctx, nil, err) return } utils.AssembleResponse(ctx, nil, nil) } func (c *WafController) DeleteListenerWaf(ctx *gin.Context) { ctx1, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() regionCode := ctx.Param("region_code") namespace := ctx.Param("namespace") gatewayName := ctx.Param("gateway_name") port, err := strconv.Atoi(ctx.Param("port")) if err != nil { utils.AssembleResponse(ctx, nil, err) return } err = c.service.DeleteListenerWaf(ctx1, &service.DeleteListenerReq{ GatewateInfo: service.GatewateInfo{ RegionCode: regionCode, Namespace: namespace, GatewayName: gatewayName, }, Port: port, }) if err != nil { utils.AssembleResponse(ctx, nil, err) return } utils.AssembleResponse(ctx, nil, nil) } func (c *WafController) DeleteGatewayWaf(ctx *gin.Context) { ctx1, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() regionCode := ctx.Param("region_code") namespace := ctx.Param("namespace") gatewayName := ctx.Param("gateway_name") err := c.service.DeleteGatewayWaf(ctx1, &service.GatewateInfo{ RegionCode: regionCode, Namespace: namespace, GatewayName: gatewayName, }) if err != nil { utils.AssembleResponse(ctx, nil, err) return } utils.AssembleResponse(ctx, nil, nil) } func (c *WafController) ListAttackLogs(ctx *gin.Context) { var filter service.AttackLogFilter id := ctx.Query("serviceId") filter.ServiceId, _ = strconv.ParseInt(id, 10, 64) filter.Limit, filter.Offset, _ = getLimitAndOffset(ctx) filter.Cluster = ctx.Query("cluster") filter.AttackUrl = ctx.Query("attackAddr") filter.AttackIp = ctx.Query("attackIp") filter.AttackType = ctx.Query("attackType") filter.AttackApp = ctx.Query("attackApp") filter.Token = ctx.Query("token") filter.Action = ctx.Query("action") stime := ctx.Query("startTime") filter.StartTime, _ = strconv.ParseInt(stime, 10, 64) etime := ctx.Query("endTime") filter.EndTime, _ = strconv.ParseInt(etime, 10, 64) ctx1, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() logs, token, err := c.service.ListAttackLogs(ctx1, &filter) if err != nil { utils.AssembleResponse(ctx, nil, err) return } type resp struct { Items []service.AttackLog `json:"items"` Token string `json:"token"` } utils.AssembleResponse(ctx, resp{ Items: logs, Token: token, }, nil) } // getLimitAndOffset extracts pagination parameters from the context // Returns limit, offset, and error func getLimitAndOffset(ctx *gin.Context) (int, int, error) { limit := 10 // default limit offset := 0 // default offset // Get limit from query parameters if limitStr := ctx.Query("limit"); limitStr != "" { parsedLimit, err := strconv.Atoi(limitStr) if err != nil { return 0, 0, fmt.Errorf("invalid limit parameter: %v", err) } if parsedLimit > 0 { limit = parsedLimit } } // Get offset from query parameters if offsetStr := ctx.Query("offset"); offsetStr != "" { parsedOffset, err := strconv.Atoi(offsetStr) if err != nil { return 0, 0, fmt.Errorf("invalid offset parameter: %v", err) } if parsedOffset >= 0 { offset = parsedOffset } } return limit, offset, nil }