ci / go (push) Waiting to run
ci / go-db (agent) (push) Waiting to run
ci / go-db (config) (push) Waiting to run
ci / go-db (db) (push) Waiting to run
ci / go-db (evidence) (push) Waiting to run
ci / go-db (llmrec) (push) Waiting to run
ci / go-db (server) (push) Waiting to run
detections / detections (push) Waiting to run
web / web (push) Waiting to run
docs / links (push) Canceled after 0s
197 lines
5.3 KiB
Go
197 lines
5.3 KiB
Go
package server
|
||
|
||
import (
|
||
"errors"
|
||
"net/http"
|
||
|
||
"github.com/Autumn-27/artex/db"
|
||
)
|
||
|
||
// validateTaskInterceptRuleReq 의 action 검증 오류다. 이 검증기와 buildTaskInterceptRules
|
||
// 의 호출처는 작업 수준 규칙 CRUD 핸들러(taskInterceptCreateRule·taskInterceptUpdateRule)
|
||
// 와 작업·템플릿 생성/수정 핸들러(createTask·pgCreateTaskTemplate·pgUpdateTaskTemplate)뿐이고,
|
||
// 전부 writeErr 로 HTTP 400 을 돌려주는 사용자 전용 경로다(에이전트 도구를 거치지 않는다).
|
||
// action 열거값(block·allow)은 클라이언트가 그대로 주고받는 와이어 식별자라 원문을 유지한다.
|
||
const errTaskInterceptInvalidAction = "action 은 block 또는 allow 여야 합니다"
|
||
|
||
// 任务级资产拦截/允许规则的 CRUD。规则按 task_id 归属,仅对该任务生效:
|
||
// action=block 拦截(禁止测试),action=allow 允许(白名单)。执行判定见 db.EvaluateAssetGate。
|
||
|
||
type taskInterceptRuleReq struct {
|
||
Enabled bool `json:"enabled"`
|
||
Action string `json:"action"` // block | allow
|
||
Kind string `json:"kind"`
|
||
Pattern string `json:"pattern"`
|
||
Note string `json:"note"`
|
||
}
|
||
|
||
// validateTaskInterceptRuleReq 归一并校验;复用全局规则的 kind/pattern 校验器。
|
||
func validateTaskInterceptRuleReq(req *taskInterceptRuleReq) error {
|
||
if req.Action == "" {
|
||
req.Action = "block"
|
||
}
|
||
if req.Action != "block" && req.Action != "allow" {
|
||
return errors.New(errTaskInterceptInvalidAction)
|
||
}
|
||
v := assetInterceptRuleReq{Enabled: req.Enabled, Kind: req.Kind, Pattern: req.Pattern, Note: req.Note}
|
||
if err := validateAssetInterceptRuleReq(&v); err != nil {
|
||
return err
|
||
}
|
||
req.Pattern = v.Pattern // 已 trim
|
||
return nil
|
||
}
|
||
|
||
// buildTaskInterceptRules 校验创建任务时录入的任务级规则并转换为 db 输入形态。
|
||
func buildTaskInterceptRules(reqs []taskInterceptRuleReq) ([]db.TaskInterceptRuleInput, error) {
|
||
if len(reqs) == 0 {
|
||
return nil, nil
|
||
}
|
||
out := make([]db.TaskInterceptRuleInput, 0, len(reqs))
|
||
for i := range reqs {
|
||
rq := reqs[i]
|
||
if err := validateTaskInterceptRuleReq(&rq); err != nil {
|
||
return nil, err
|
||
}
|
||
out = append(out, db.TaskInterceptRuleInput{
|
||
Enabled: rq.Enabled,
|
||
Action: rq.Action,
|
||
Kind: rq.Kind,
|
||
Pattern: rq.Pattern,
|
||
Note: rq.Note,
|
||
})
|
||
}
|
||
return out, nil
|
||
}
|
||
|
||
func (s *Server) taskInterceptListRules(w http.ResponseWriter, r *http.Request) {
|
||
pg := s.pg(w)
|
||
if pg == nil {
|
||
return
|
||
}
|
||
taskID, ok := pathInt(r, "id")
|
||
if !ok || taskID <= 0 {
|
||
writeErr(w, 400, "bad task id")
|
||
return
|
||
}
|
||
rules, err := pg.Assets().ListTaskInterceptRules(taskID)
|
||
if err != nil {
|
||
writeErr(w, 500, err.Error())
|
||
return
|
||
}
|
||
if rules == nil {
|
||
rules = []db.AssetInterceptRule{}
|
||
}
|
||
writeJSON(w, 200, map[string]any{"rules": rules})
|
||
}
|
||
|
||
func (s *Server) taskInterceptCreateRule(w http.ResponseWriter, r *http.Request) {
|
||
pg := s.pg(w)
|
||
if pg == nil {
|
||
return
|
||
}
|
||
taskID, ok := pathInt(r, "id")
|
||
if !ok || taskID <= 0 {
|
||
writeErr(w, 400, "bad task id")
|
||
return
|
||
}
|
||
var req taskInterceptRuleReq
|
||
if err := decode(r, &req); err != nil {
|
||
writeErr(w, 400, err.Error())
|
||
return
|
||
}
|
||
if err := validateTaskInterceptRuleReq(&req); err != nil {
|
||
writeErr(w, 400, err.Error())
|
||
return
|
||
}
|
||
rule, err := pg.Assets().CreateTaskInterceptRule(taskID, req.Action, req.Kind, req.Pattern, req.Note, req.Enabled)
|
||
if err != nil {
|
||
writeErr(w, 500, err.Error())
|
||
return
|
||
}
|
||
writeJSON(w, 200, rule)
|
||
}
|
||
|
||
func (s *Server) taskInterceptUpdateRule(w http.ResponseWriter, r *http.Request) {
|
||
pg := s.pg(w)
|
||
if pg == nil {
|
||
return
|
||
}
|
||
taskID, ok := pathInt(r, "id")
|
||
if !ok || taskID <= 0 {
|
||
writeErr(w, 400, "bad task id")
|
||
return
|
||
}
|
||
ruleID, ok := pathInt(r, "rid")
|
||
if !ok || ruleID <= 0 {
|
||
writeErr(w, 400, "bad rule id")
|
||
return
|
||
}
|
||
var req taskInterceptRuleReq
|
||
if err := decode(r, &req); err != nil {
|
||
writeErr(w, 400, err.Error())
|
||
return
|
||
}
|
||
if err := validateTaskInterceptRuleReq(&req); err != nil {
|
||
writeErr(w, 400, err.Error())
|
||
return
|
||
}
|
||
rule, err := pg.Assets().UpdateTaskInterceptRule(taskID, ruleID, req.Action, req.Kind, req.Pattern, req.Note, req.Enabled)
|
||
if err != nil {
|
||
writeErr(w, 500, err.Error())
|
||
return
|
||
}
|
||
writeJSON(w, 200, rule)
|
||
}
|
||
|
||
func (s *Server) taskInterceptDeleteRule(w http.ResponseWriter, r *http.Request) {
|
||
pg := s.pg(w)
|
||
if pg == nil {
|
||
return
|
||
}
|
||
taskID, ok := pathInt(r, "id")
|
||
if !ok || taskID <= 0 {
|
||
writeErr(w, 400, "bad task id")
|
||
return
|
||
}
|
||
ruleID, ok := pathInt(r, "rid")
|
||
if !ok || ruleID <= 0 {
|
||
writeErr(w, 400, "bad rule id")
|
||
return
|
||
}
|
||
deleted, err := pg.Assets().DeleteTaskInterceptRule(taskID, ruleID)
|
||
if err != nil {
|
||
writeErr(w, 500, err.Error())
|
||
return
|
||
}
|
||
writeJSON(w, 200, map[string]any{"deleted": deleted})
|
||
}
|
||
|
||
func (s *Server) taskInterceptToggleRule(w http.ResponseWriter, r *http.Request) {
|
||
pg := s.pg(w)
|
||
if pg == nil {
|
||
return
|
||
}
|
||
taskID, ok := pathInt(r, "id")
|
||
if !ok || taskID <= 0 {
|
||
writeErr(w, 400, "bad task id")
|
||
return
|
||
}
|
||
ruleID, ok := pathInt(r, "rid")
|
||
if !ok || ruleID <= 0 {
|
||
writeErr(w, 400, "bad rule id")
|
||
return
|
||
}
|
||
var req struct {
|
||
Enabled bool `json:"enabled"`
|
||
}
|
||
if err := decode(r, &req); err != nil {
|
||
writeErr(w, 400, err.Error())
|
||
return
|
||
}
|
||
if err := pg.Assets().ToggleTaskInterceptRule(taskID, ruleID, req.Enabled); err != nil {
|
||
writeErr(w, 500, err.Error())
|
||
return
|
||
}
|
||
writeJSON(w, 200, map[string]any{"ok": true, "enabled": req.Enabled})
|
||
}
|