request.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. package waf
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "net/http"
  6. "net/url"
  7. "github.com/crowdsecurity/coraza/v3/experimental"
  8. corazatypes "github.com/crowdsecurity/coraza/v3/types"
  9. "github.com/google/uuid"
  10. )
  11. const (
  12. URIHeaderName = "X-Crowdsec-Waf-Uri"
  13. VerbHeaderName = "X-Crowdsec-Waf-Verb"
  14. HostHeaderName = "X-Crowdsec-Waf-Host"
  15. IPHeaderName = "X-Crowdsec-Waf-Ip"
  16. )
  17. type ResponseRequest struct {
  18. UUID string
  19. Tx corazatypes.Transaction
  20. Interruption *corazatypes.Interruption
  21. Err error
  22. SendEvents bool
  23. }
  24. func NewResponseRequest(Tx experimental.FullTransaction, in *corazatypes.Interruption, UUID string, err error) ResponseRequest {
  25. return ResponseRequest{
  26. UUID: UUID,
  27. Tx: Tx,
  28. Interruption: in,
  29. Err: err,
  30. SendEvents: true,
  31. }
  32. }
  33. func (r *ResponseRequest) SetRemediation(remediation string) error {
  34. r.Interruption.Action = remediation
  35. return nil
  36. }
  37. func (r *ResponseRequest) SetRemediationByID(ID int, remediation string) error {
  38. if r.Interruption.RuleID == ID {
  39. r.Interruption.Action = remediation
  40. }
  41. return nil
  42. }
  43. func (r *ResponseRequest) CancelEvent() error {
  44. // true by default
  45. r.SendEvents = false
  46. return nil
  47. }
  48. type ParsedRequest struct {
  49. RemoteAddr string
  50. Host string
  51. ClientIP string
  52. URI string
  53. ClientHost string
  54. Headers http.Header
  55. URL *url.URL
  56. Method string
  57. Proto string
  58. Body []byte
  59. TransferEncoding []string
  60. UUID string
  61. Tx experimental.FullTransaction
  62. ResponseChannel chan ResponseRequest
  63. }
  64. func NewParsedRequestFromRequest(r *http.Request) (ParsedRequest, error) {
  65. var body []byte
  66. var err error
  67. if r.Body != nil {
  68. body = make([]byte, 0)
  69. body, err = ioutil.ReadAll(r.Body)
  70. if err != nil {
  71. return ParsedRequest{}, fmt.Errorf("unable to read body: %s", err)
  72. }
  73. }
  74. // the real source of the request is set in 'x-client-ip'
  75. clientIP := r.Header.Get(IPHeaderName)
  76. // the real target Host of the request is set in 'x-client-host'
  77. clientHost := r.Header.Get(HostHeaderName)
  78. // the real URI of the request is set in 'x-client-uri'
  79. clientURI := r.Header.Get(URIHeaderName)
  80. // the real VERB of the request is set in 'x-client-uri'
  81. clientMethod := r.Header.Get(VerbHeaderName)
  82. // delete those headers before coraza process the request
  83. delete(r.Header, IPHeaderName)
  84. delete(r.Header, HostHeaderName)
  85. delete(r.Header, URIHeaderName)
  86. delete(r.Header, VerbHeaderName)
  87. return ParsedRequest{
  88. RemoteAddr: r.RemoteAddr,
  89. UUID: uuid.New().String(),
  90. ClientHost: clientHost,
  91. ClientIP: clientIP,
  92. URI: clientURI,
  93. Method: clientMethod,
  94. Host: r.Host,
  95. Headers: r.Header,
  96. URL: r.URL,
  97. Proto: r.Proto,
  98. Body: body,
  99. TransferEncoding: r.TransferEncoding,
  100. ResponseChannel: make(chan ResponseRequest),
  101. }, nil
  102. }