appsec.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  1. package appsec
  2. import (
  3. "fmt"
  4. "os"
  5. "regexp"
  6. "github.com/antonmedv/expr"
  7. "github.com/antonmedv/expr/vm"
  8. "github.com/crowdsecurity/crowdsec/pkg/cwhub"
  9. "github.com/crowdsecurity/crowdsec/pkg/exprhelpers"
  10. "github.com/crowdsecurity/crowdsec/pkg/types"
  11. log "github.com/sirupsen/logrus"
  12. "gopkg.in/yaml.v2"
  13. )
  14. type Hook struct {
  15. Filter string `yaml:"filter"`
  16. FilterExpr *vm.Program `yaml:"-"`
  17. OnSuccess string `yaml:"on_success"`
  18. Apply []string `yaml:"apply"`
  19. ApplyExpr []*vm.Program `yaml:"-"`
  20. }
  21. const (
  22. hookOnLoad = iota
  23. hookPreEval
  24. hookPostEval
  25. hookOnMatch
  26. )
  27. func (h *Hook) Build(hookStage int) error {
  28. ctx := map[string]interface{}{}
  29. switch hookStage {
  30. case hookOnLoad:
  31. ctx = GetOnLoadEnv(&AppsecRuntimeConfig{})
  32. case hookPreEval:
  33. ctx = GetPreEvalEnv(&AppsecRuntimeConfig{}, &ParsedRequest{})
  34. case hookPostEval:
  35. ctx = GetPostEvalEnv(&AppsecRuntimeConfig{}, &ParsedRequest{})
  36. case hookOnMatch:
  37. ctx = GetOnMatchEnv(&AppsecRuntimeConfig{}, &ParsedRequest{}, types.Event{})
  38. }
  39. opts := exprhelpers.GetExprOptions(ctx)
  40. if h.Filter != "" {
  41. program, err := expr.Compile(h.Filter, opts...) //FIXME: opts
  42. if err != nil {
  43. return fmt.Errorf("unable to compile filter %s : %w", h.Filter, err)
  44. }
  45. h.FilterExpr = program
  46. }
  47. for _, apply := range h.Apply {
  48. program, err := expr.Compile(apply, opts...)
  49. if err != nil {
  50. return fmt.Errorf("unable to compile apply %s : %w", apply, err)
  51. }
  52. h.ApplyExpr = append(h.ApplyExpr, program)
  53. }
  54. return nil
  55. }
  56. type AppsecTempResponse struct {
  57. InBandInterrupt bool
  58. OutOfBandInterrupt bool
  59. Action string //allow, deny, captcha, log
  60. HTTPResponseCode int
  61. SendEvent bool //do we send an internal event on rule match
  62. SendAlert bool //do we send an alert on rule match
  63. }
  64. type AppsecSubEngineOpts struct {
  65. DisableBodyInspection bool `yaml:"disable_body_inspection"`
  66. RequestBodyInMemoryLimit *int `yaml:"request_body_in_memory_limit"`
  67. }
  68. // runtime version of AppsecConfig
  69. type AppsecRuntimeConfig struct {
  70. Name string
  71. OutOfBandRules []AppsecCollection
  72. InBandRules []AppsecCollection
  73. DefaultRemediation string
  74. RemediationByTag map[string]string //Also used for ByName, as the name (for modsec rules) is a tag crowdsec-NAME
  75. RemediationById map[int]string
  76. CompiledOnLoad []Hook
  77. CompiledPreEval []Hook
  78. CompiledPostEval []Hook
  79. CompiledOnMatch []Hook
  80. CompiledVariablesTracking []*regexp.Regexp
  81. Config *AppsecConfig
  82. //CorazaLogger debuglog.Logger
  83. //those are ephemeral, created/destroyed with every req
  84. OutOfBandTx ExtendedTransaction //is it a good idea ?
  85. InBandTx ExtendedTransaction //is it a good idea ?
  86. Response AppsecTempResponse
  87. //should we store matched rules here ?
  88. Logger *log.Entry
  89. //Set by on_load to ignore some rules on loading
  90. DisabledInBandRuleIds []int
  91. DisabledInBandRulesTags []string //Also used for ByName, as the name (for modsec rules) is a tag crowdsec-NAME
  92. DisabledOutOfBandRuleIds []int
  93. DisabledOutOfBandRulesTags []string //Also used for ByName, as the name (for modsec rules) is a tag crowdsec-NAME
  94. }
  95. type AppsecConfig struct {
  96. Name string `yaml:"name"`
  97. OutOfBandRules []string `yaml:"outofband_rules"`
  98. InBandRules []string `yaml:"inband_rules"`
  99. DefaultRemediation string `yaml:"default_remediation"`
  100. DefaultPassAction string `yaml:"default_pass_action"`
  101. BlockedHTTPCode int `yaml:"blocked_http_code"`
  102. PassedHTTPCode int `yaml:"passed_http_code"`
  103. OnLoad []Hook `yaml:"on_load"`
  104. PreEval []Hook `yaml:"pre_eval"`
  105. PostEval []Hook `yaml:"post_eval"`
  106. OnMatch []Hook `yaml:"on_match"`
  107. VariablesTracking []string `yaml:"variables_tracking"`
  108. InbandOptions AppsecSubEngineOpts `yaml:"inband_options"`
  109. OutOfBandOptions AppsecSubEngineOpts `yaml:"outofband_options"`
  110. LogLevel *log.Level `yaml:"log_level"`
  111. Logger *log.Entry `yaml:"-"`
  112. }
  113. func (w *AppsecRuntimeConfig) ClearResponse() {
  114. w.Logger.Debugf("#-> %p", w)
  115. w.Response = AppsecTempResponse{}
  116. w.Logger.Debugf("-> %p", w.Config)
  117. w.Response.Action = w.Config.DefaultPassAction
  118. w.Response.HTTPResponseCode = w.Config.PassedHTTPCode
  119. w.Response.SendEvent = true
  120. w.Response.SendAlert = true
  121. }
  122. func (wc *AppsecConfig) LoadByPath(file string) error {
  123. wc.Logger.Debugf("loading config %s", file)
  124. yamlFile, err := os.ReadFile(file)
  125. if err != nil {
  126. return fmt.Errorf("unable to read file %s : %s", file, err)
  127. }
  128. err = yaml.UnmarshalStrict(yamlFile, wc)
  129. if err != nil {
  130. return fmt.Errorf("unable to parse yaml file %s : %s", file, err)
  131. }
  132. if wc.Name == "" {
  133. return fmt.Errorf("name cannot be empty")
  134. }
  135. if wc.LogLevel == nil {
  136. lvl := wc.Logger.Logger.GetLevel()
  137. wc.LogLevel = &lvl
  138. }
  139. wc.Logger = wc.Logger.Dup().WithField("name", wc.Name)
  140. wc.Logger.Logger.SetLevel(*wc.LogLevel)
  141. return nil
  142. }
  143. func (wc *AppsecConfig) Load(configName string) error {
  144. appsecConfigs := hub.GetItemMap(cwhub.APPSEC_CONFIGS)
  145. for _, hubAppsecConfigItem := range appsecConfigs {
  146. if !hubAppsecConfigItem.State.Installed {
  147. continue
  148. }
  149. if hubAppsecConfigItem.Name != configName {
  150. continue
  151. }
  152. wc.Logger.Infof("loading %s", hubAppsecConfigItem.State.LocalPath)
  153. err := wc.LoadByPath(hubAppsecConfigItem.State.LocalPath)
  154. if err != nil {
  155. return fmt.Errorf("unable to load appsec-config %s : %s", hubAppsecConfigItem.State.LocalPath, err)
  156. }
  157. return nil
  158. }
  159. return fmt.Errorf("no appsec-config found for %s", configName)
  160. }
  161. func (wc *AppsecConfig) GetDataDir() string {
  162. return hub.GetDataDir()
  163. }
  164. func (wc *AppsecConfig) Build() (*AppsecRuntimeConfig, error) {
  165. ret := &AppsecRuntimeConfig{Logger: wc.Logger.WithField("component", "appsec_runtime_config")}
  166. //set the defaults
  167. switch wc.DefaultRemediation {
  168. case "":
  169. wc.DefaultRemediation = "ban"
  170. case "ban", "captcha", "log":
  171. //those are the officially supported remediation(s)
  172. default:
  173. wc.Logger.Warningf("default '%s' remediation of %s is none of [ban,captcha,log] ensure bouncer compatbility!", wc.DefaultRemediation, wc.Name)
  174. }
  175. if wc.BlockedHTTPCode == 0 {
  176. wc.BlockedHTTPCode = 403
  177. }
  178. if wc.PassedHTTPCode == 0 {
  179. wc.PassedHTTPCode = 200
  180. }
  181. if wc.DefaultPassAction == "" {
  182. wc.DefaultPassAction = "allow"
  183. }
  184. ret.Name = wc.Name
  185. ret.Config = wc
  186. ret.DefaultRemediation = wc.DefaultRemediation
  187. wc.Logger.Tracef("Loading config %+v", wc)
  188. //load rules
  189. for _, rule := range wc.OutOfBandRules {
  190. wc.Logger.Infof("loading outofband rule %s", rule)
  191. collections, err := LoadCollection(rule, wc.Logger.WithField("component", "appsec_collection_loader"))
  192. if err != nil {
  193. return nil, fmt.Errorf("unable to load outofband rule %s : %s", rule, err)
  194. }
  195. ret.OutOfBandRules = append(ret.OutOfBandRules, collections...)
  196. }
  197. wc.Logger.Infof("Loaded %d outofband rules", len(ret.OutOfBandRules))
  198. for _, rule := range wc.InBandRules {
  199. wc.Logger.Infof("loading inband rule %s", rule)
  200. collections, err := LoadCollection(rule, wc.Logger.WithField("component", "appsec_collection_loader"))
  201. if err != nil {
  202. return nil, fmt.Errorf("unable to load inband rule %s : %s", rule, err)
  203. }
  204. ret.InBandRules = append(ret.InBandRules, collections...)
  205. }
  206. wc.Logger.Infof("Loaded %d inband rules", len(ret.InBandRules))
  207. //load hooks
  208. for _, hook := range wc.OnLoad {
  209. err := hook.Build(hookOnLoad)
  210. if err != nil {
  211. return nil, fmt.Errorf("unable to build on_load hook : %s", err)
  212. }
  213. ret.CompiledOnLoad = append(ret.CompiledOnLoad, hook)
  214. }
  215. for _, hook := range wc.PreEval {
  216. err := hook.Build(hookPreEval)
  217. if err != nil {
  218. return nil, fmt.Errorf("unable to build pre_eval hook : %s", err)
  219. }
  220. ret.CompiledPreEval = append(ret.CompiledPreEval, hook)
  221. }
  222. for _, hook := range wc.PostEval {
  223. err := hook.Build(hookPostEval)
  224. if err != nil {
  225. return nil, fmt.Errorf("unable to build post_eval hook : %s", err)
  226. }
  227. ret.CompiledPostEval = append(ret.CompiledPostEval, hook)
  228. }
  229. for _, hook := range wc.OnMatch {
  230. err := hook.Build(hookOnMatch)
  231. if err != nil {
  232. return nil, fmt.Errorf("unable to build on_match hook : %s", err)
  233. }
  234. ret.CompiledOnMatch = append(ret.CompiledOnMatch, hook)
  235. }
  236. //variable tracking
  237. for _, variable := range wc.VariablesTracking {
  238. compiledVariableRule, err := regexp.Compile(variable)
  239. if err != nil {
  240. return nil, fmt.Errorf("cannot compile variable regexp %s: %w", variable, err)
  241. }
  242. ret.CompiledVariablesTracking = append(ret.CompiledVariablesTracking, compiledVariableRule)
  243. }
  244. return ret, nil
  245. }
  246. func (w *AppsecRuntimeConfig) ProcessOnLoadRules() error {
  247. for _, rule := range w.CompiledOnLoad {
  248. if rule.FilterExpr != nil {
  249. output, err := exprhelpers.Run(rule.FilterExpr, GetOnLoadEnv(w), w.Logger, w.Logger.Level >= log.DebugLevel)
  250. if err != nil {
  251. return fmt.Errorf("unable to run appsec on_load filter %s : %w", rule.Filter, err)
  252. }
  253. switch t := output.(type) {
  254. case bool:
  255. if !t {
  256. w.Logger.Debugf("filter didnt match")
  257. continue
  258. }
  259. default:
  260. w.Logger.Errorf("Filter must return a boolean, can't filter")
  261. continue
  262. }
  263. }
  264. for _, applyExpr := range rule.ApplyExpr {
  265. o, err := exprhelpers.Run(applyExpr, GetOnLoadEnv(w), w.Logger, w.Logger.Level >= log.DebugLevel)
  266. if err != nil {
  267. w.Logger.Errorf("unable to apply appsec on_load expr: %s", err)
  268. continue
  269. }
  270. switch t := o.(type) {
  271. case error:
  272. w.Logger.Errorf("unable to apply appsec on_load expr: %s", t)
  273. continue
  274. default:
  275. }
  276. }
  277. }
  278. return nil
  279. }
  280. func (w *AppsecRuntimeConfig) ProcessOnMatchRules(request *ParsedRequest, evt types.Event) error {
  281. for _, rule := range w.CompiledOnMatch {
  282. if rule.FilterExpr != nil {
  283. output, err := exprhelpers.Run(rule.FilterExpr, GetOnMatchEnv(w, request, evt), w.Logger, w.Logger.Level >= log.DebugLevel)
  284. if err != nil {
  285. return fmt.Errorf("unable to run appsec on_match filter %s : %w", rule.Filter, err)
  286. }
  287. switch t := output.(type) {
  288. case bool:
  289. if !t {
  290. w.Logger.Debugf("filter didnt match")
  291. continue
  292. }
  293. default:
  294. w.Logger.Errorf("Filter must return a boolean, can't filter")
  295. continue
  296. }
  297. }
  298. for _, applyExpr := range rule.ApplyExpr {
  299. o, err := exprhelpers.Run(applyExpr, GetOnMatchEnv(w, request, evt), w.Logger, w.Logger.Level >= log.DebugLevel)
  300. if err != nil {
  301. w.Logger.Errorf("unable to apply appsec on_match expr: %s", err)
  302. continue
  303. }
  304. switch t := o.(type) {
  305. case error:
  306. w.Logger.Errorf("unable to apply appsec on_match expr: %s", t)
  307. continue
  308. default:
  309. }
  310. }
  311. }
  312. return nil
  313. }
  314. func (w *AppsecRuntimeConfig) ProcessPreEvalRules(request *ParsedRequest) error {
  315. w.Logger.Debugf("processing %d pre_eval rules", len(w.CompiledPreEval))
  316. for _, rule := range w.CompiledPreEval {
  317. if rule.FilterExpr != nil {
  318. output, err := exprhelpers.Run(rule.FilterExpr, GetPreEvalEnv(w, request), w.Logger, w.Logger.Level >= log.DebugLevel)
  319. if err != nil {
  320. return fmt.Errorf("unable to run appsec pre_eval filter %s : %w", rule.Filter, err)
  321. }
  322. switch t := output.(type) {
  323. case bool:
  324. if !t {
  325. w.Logger.Debugf("filter didnt match")
  326. continue
  327. }
  328. default:
  329. w.Logger.Errorf("Filter must return a boolean, can't filter")
  330. continue
  331. }
  332. }
  333. // here means there is no filter or the filter matched
  334. for _, applyExpr := range rule.ApplyExpr {
  335. o, err := exprhelpers.Run(applyExpr, GetPreEvalEnv(w, request), w.Logger, w.Logger.Level >= log.DebugLevel)
  336. if err != nil {
  337. w.Logger.Errorf("unable to apply appsec pre_eval expr: %s", err)
  338. continue
  339. }
  340. switch t := o.(type) {
  341. case error:
  342. w.Logger.Errorf("unable to apply appsec pre_eval expr: %s", t)
  343. continue
  344. default:
  345. }
  346. }
  347. }
  348. return nil
  349. }
  350. func (w *AppsecRuntimeConfig) ProcessPostEvalRules(request *ParsedRequest) error {
  351. for _, rule := range w.CompiledPostEval {
  352. if rule.FilterExpr != nil {
  353. output, err := exprhelpers.Run(rule.FilterExpr, GetPostEvalEnv(w, request), w.Logger, w.Logger.Level >= log.DebugLevel)
  354. if err != nil {
  355. return fmt.Errorf("unable to run appsec post_eval filter %s : %w", rule.Filter, err)
  356. }
  357. switch t := output.(type) {
  358. case bool:
  359. if !t {
  360. w.Logger.Debugf("filter didnt match")
  361. continue
  362. }
  363. default:
  364. w.Logger.Errorf("Filter must return a boolean, can't filter")
  365. continue
  366. }
  367. }
  368. // here means there is no filter or the filter matched
  369. for _, applyExpr := range rule.ApplyExpr {
  370. o, err := exprhelpers.Run(applyExpr, GetPostEvalEnv(w, request), w.Logger, w.Logger.Level >= log.DebugLevel)
  371. if err != nil {
  372. w.Logger.Errorf("unable to apply appsec post_eval expr: %s", err)
  373. continue
  374. }
  375. switch t := o.(type) {
  376. case error:
  377. w.Logger.Errorf("unable to apply appsec post_eval expr: %s", t)
  378. continue
  379. default:
  380. }
  381. }
  382. }
  383. return nil
  384. }
  385. func (w *AppsecRuntimeConfig) RemoveInbandRuleByID(id int) error {
  386. w.Logger.Debugf("removing inband rule %d", id)
  387. return w.InBandTx.RemoveRuleByIDWithError(id)
  388. }
  389. func (w *AppsecRuntimeConfig) RemoveOutbandRuleByID(id int) error {
  390. w.Logger.Debugf("removing outband rule %d", id)
  391. return w.OutOfBandTx.RemoveRuleByIDWithError(id)
  392. }
  393. func (w *AppsecRuntimeConfig) RemoveInbandRuleByTag(tag string) error {
  394. w.Logger.Debugf("removing inband rule with tag %s", tag)
  395. return w.InBandTx.RemoveRuleByTagWithError(tag)
  396. }
  397. func (w *AppsecRuntimeConfig) RemoveOutbandRuleByTag(tag string) error {
  398. w.Logger.Debugf("removing outband rule with tag %s", tag)
  399. return w.OutOfBandTx.RemoveRuleByTagWithError(tag)
  400. }
  401. func (w *AppsecRuntimeConfig) RemoveInbandRuleByName(name string) error {
  402. tag := fmt.Sprintf("crowdsec-%s", name)
  403. w.Logger.Debugf("removing inband rule %s", tag)
  404. return w.InBandTx.RemoveRuleByTagWithError(tag)
  405. }
  406. func (w *AppsecRuntimeConfig) RemoveOutbandRuleByName(name string) error {
  407. tag := fmt.Sprintf("crowdsec-%s", name)
  408. w.Logger.Debugf("removing outband rule %s", tag)
  409. return w.OutOfBandTx.RemoveRuleByTagWithError(tag)
  410. }
  411. func (w *AppsecRuntimeConfig) CancelEvent() error {
  412. w.Logger.Debugf("canceling event")
  413. w.Response.SendEvent = false
  414. return nil
  415. }
  416. // Disable a rule at load time, meaning it will not run for any request
  417. func (w *AppsecRuntimeConfig) DisableInBandRuleByID(id int) error {
  418. w.DisabledInBandRuleIds = append(w.DisabledInBandRuleIds, id)
  419. return nil
  420. }
  421. // Disable a rule at load time, meaning it will not run for any request
  422. func (w *AppsecRuntimeConfig) DisableInBandRuleByName(name string) error {
  423. tagValue := fmt.Sprintf("crowdsec-%s", name)
  424. w.DisabledInBandRulesTags = append(w.DisabledInBandRulesTags, tagValue)
  425. return nil
  426. }
  427. // Disable a rule at load time, meaning it will not run for any request
  428. func (w *AppsecRuntimeConfig) DisableInBandRuleByTag(tag string) error {
  429. w.DisabledInBandRulesTags = append(w.DisabledInBandRulesTags, tag)
  430. return nil
  431. }
  432. // Disable a rule at load time, meaning it will not run for any request
  433. func (w *AppsecRuntimeConfig) DisableOutBandRuleByID(id int) error {
  434. w.DisabledOutOfBandRuleIds = append(w.DisabledOutOfBandRuleIds, id)
  435. return nil
  436. }
  437. // Disable a rule at load time, meaning it will not run for any request
  438. func (w *AppsecRuntimeConfig) DisableOutBandRuleByName(name string) error {
  439. tagValue := fmt.Sprintf("crowdsec-%s", name)
  440. w.DisabledOutOfBandRulesTags = append(w.DisabledOutOfBandRulesTags, tagValue)
  441. return nil
  442. }
  443. // Disable a rule at load time, meaning it will not run for any request
  444. func (w *AppsecRuntimeConfig) DisableOutBandRuleByTag(tag string) error {
  445. w.DisabledOutOfBandRulesTags = append(w.DisabledOutOfBandRulesTags, tag)
  446. return nil
  447. }
  448. func (w *AppsecRuntimeConfig) SendEvent() error {
  449. w.Logger.Debugf("sending event")
  450. w.Response.SendEvent = true
  451. return nil
  452. }
  453. func (w *AppsecRuntimeConfig) SendAlert() error {
  454. w.Logger.Debugf("sending alert")
  455. w.Response.SendAlert = true
  456. return nil
  457. }
  458. func (w *AppsecRuntimeConfig) CancelAlert() error {
  459. w.Logger.Debugf("canceling alert")
  460. w.Response.SendAlert = false
  461. return nil
  462. }
  463. func (w *AppsecRuntimeConfig) SetActionByTag(tag string, action string) error {
  464. if w.RemediationByTag == nil {
  465. w.RemediationByTag = make(map[string]string)
  466. }
  467. w.Logger.Debugf("setting action of %s to %s", tag, action)
  468. w.RemediationByTag[tag] = action
  469. return nil
  470. }
  471. func (w *AppsecRuntimeConfig) SetActionByID(id int, action string) error {
  472. if w.RemediationById == nil {
  473. w.RemediationById = make(map[int]string)
  474. }
  475. w.Logger.Debugf("setting action of %d to %s", id, action)
  476. w.RemediationById[id] = action
  477. return nil
  478. }
  479. func (w *AppsecRuntimeConfig) SetActionByName(name string, action string) error {
  480. if w.RemediationByTag == nil {
  481. w.RemediationByTag = make(map[string]string)
  482. }
  483. tag := fmt.Sprintf("crowdsec-%s", name)
  484. w.Logger.Debugf("setting action of %s to %s", tag, action)
  485. w.RemediationByTag[tag] = action
  486. return nil
  487. }
  488. func (w *AppsecRuntimeConfig) SetAction(action string) error {
  489. //log.Infof("setting to %s", action)
  490. w.Logger.Debugf("setting action to %s", action)
  491. switch action {
  492. case "allow":
  493. w.Response.Action = action
  494. w.Response.HTTPResponseCode = w.Config.PassedHTTPCode
  495. //@tko how should we handle this ? it seems bouncer only understand bans, but it might be misleading ?
  496. case "deny", "ban", "block":
  497. w.Response.Action = "ban"
  498. case "log":
  499. w.Response.Action = action
  500. w.Response.HTTPResponseCode = w.Config.PassedHTTPCode
  501. case "captcha":
  502. w.Response.Action = action
  503. default:
  504. w.Response.Action = action
  505. }
  506. return nil
  507. }
  508. func (w *AppsecRuntimeConfig) SetHTTPCode(code int) error {
  509. w.Logger.Debugf("setting http code to %d", code)
  510. w.Response.HTTPResponseCode = code
  511. return nil
  512. }
  513. type BodyResponse struct {
  514. Action string `json:"action"`
  515. HTTPStatus int `json:"http_status"`
  516. }
  517. func (w *AppsecRuntimeConfig) GenerateResponse(response AppsecTempResponse, logger *log.Entry) BodyResponse {
  518. resp := BodyResponse{}
  519. //if there is no interrupt, we should allow with default code
  520. if !response.InBandInterrupt {
  521. resp.Action = w.Config.DefaultPassAction
  522. resp.HTTPStatus = w.Config.PassedHTTPCode
  523. return resp
  524. }
  525. resp.Action = response.Action
  526. if resp.Action == "" {
  527. resp.Action = w.Config.DefaultRemediation
  528. }
  529. logger.Debugf("action is %s", resp.Action)
  530. resp.HTTPStatus = response.HTTPResponseCode
  531. if resp.HTTPStatus == 0 {
  532. resp.HTTPStatus = w.Config.BlockedHTTPCode
  533. }
  534. logger.Debugf("http status is %d", resp.HTTPStatus)
  535. return resp
  536. }