Skip to content

Commit

Permalink
Added SPOA errors
Browse files Browse the repository at this point in the history
  • Loading branch information
zc-devs committed Jul 23, 2023
1 parent aecf93d commit 04fa36d
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 14 deletions.
8 changes: 6 additions & 2 deletions docker/haproxy/haproxy.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ frontend test_frontend
bind *:443 ssl crt /usr/local/etc/haproxy/example.com.pem alpn h2,http/1.1
unique-id-format %[uuid()]
unique-id-header X-Unique-ID
log-format "%ci:%cp\ [%t]\ %ft\ %b/%s\ %Th/%Ti/%TR/%Tq/%Tw/%Tc/%Tr/%Tt\ %ST\ %B\ %CC\ %CS\ %tsc\ %ac/%fc/%bc/%sc/%rc\ %sq/%bq\ %hr\ %hs\ %{+Q}r\ %ID\ spoa-error:\ %[var(txn.coraza.error)]\ waf-hit:\ %[var(txn.coraza.fail)]"
log-format "%ci:%cp\ [%t]\ %ft\ %b/%s\ %Th/%Ti/%TR/%Tq/%Tw/%Tc/%Tr/%Tt\ %ST\ %B\ %CC\ %CS\ %tsc\ %ac/%fc/%bc/%sc/%rc\ %sq/%bq\ %hr\ %hs\ %{+Q}r\ %ID\ waf-hit:\ %[var(txn.coraza.fail)]\ spoe-error:\ %[var(txn.coraza.error)]\ spoa-error:\ %[var(txn.coraza.err_code)]\ %[var(txn.coraza.err_msg)]"

filter spoe engine coraza config /usr/local/etc/haproxy/coraza.cfg

Expand All @@ -40,10 +40,14 @@ frontend test_frontend
http-request silent-drop if { var(txn.coraza.action) -m str drop }
http-response silent-drop if { var(txn.coraza.action) -m str drop }

# Deny in case of an error, when processing with the Coraza SPOA
# Deny in case of an error, when processing with the Coraza SPOE
http-request deny deny_status 504 if { var(txn.coraza.error) -m int gt 0 }
http-response deny deny_status 504 if { var(txn.coraza.error) -m int gt 0 }

# Deny in case of an error, when processing with the Coraza SPOA
http-request deny deny_status 504 if { var(txn.coraza.err_code) -m int gt 0 }
http-response deny deny_status 504 if { var(txn.coraza.err_code) -m int gt 0 }

# Deprecated, use action instead of fail
#http-request deny deny_status 401 hdr waf-block "request" if { var(txn.coraza.fail) -m int eq 1 }
#http-response deny deny_status 401 hdr waf-block "response" if { var(txn.coraza.fail) -m int eq 1 }
Expand Down
61 changes: 49 additions & 12 deletions internal/spoa.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,39 @@ func (s *SPOA) message(code int) []spoe.Action {
}
}

func (s *SPOA) error(code int, err error) []spoe.Action {
return []spoe.Action{
spoe.ActionSetVar{
Name: "err_code",
Scope: spoe.VarScopeTransaction,
Value: code,
},
spoe.ActionSetVar{
Name: "err_msg",
Scope: spoe.VarScopeTransaction,
Value: err.Error(),
},
}
}

func (s *SPOA) badRequestError(err error) []spoe.Action {
log.Error().Err(err).Msg("Bad request")
return s.error(1, err)
}

func (s *SPOA) badResponseError(err error) []spoe.Action {
log.Error().Err(err).Msg("Bad response")
return s.error(2, err)
}

func (s *SPOA) processRequestError(err error) []spoe.Action {
return s.error(3, err)
}

func (s *SPOA) processResponseError(err error) []spoe.Action {
return s.error(4, err)
}

func (s *SPOA) readHeaders(headers string) (http.Header, error) {
h := http.Header{}
hs := strings.Split(headers, "\r\n")
Expand Down Expand Up @@ -224,12 +257,12 @@ func (s *SPOA) processRequest(spoeMsg *spoe.Message) ([]spoe.Action, error) {

req, err = NewRequest(spoeMsg)
if err != nil {
return nil, err
return s.badRequestError(err), nil
}

app, err = s.getApplication(req.app)
if err != nil {
return nil, err
return s.badRequestError(err), nil
}

tx = app.waf.NewTransactionWithID(req.id)
Expand All @@ -240,12 +273,12 @@ func (s *SPOA) processRequest(spoeMsg *spoe.Message) ([]spoe.Action, error) {

err = req.init()
if err != nil {
return nil, err
return s.badRequestError(err), nil
}

headers, err := s.readHeaders(req.headers)
if err != nil {
return nil, err
return s.badRequestError(err), nil
}
for key, values := range headers {
for _, v := range values {
Expand All @@ -255,7 +288,8 @@ func (s *SPOA) processRequest(spoeMsg *spoe.Message) ([]spoe.Action, error) {

it, _, err := tx.WriteRequestBody(req.body)
if err != nil {
return nil, err
tx.DebugLogger().Error().Err(err).Str("transaction_id", tx.ID()).Msg("Failed to write request body")
return s.processRequestError(err), nil
}
if it != nil {
return s.processInterruption(it, hit), nil
Expand All @@ -271,7 +305,8 @@ func (s *SPOA) processRequest(spoeMsg *spoe.Message) ([]spoe.Action, error) {

it, err = tx.ProcessRequestBody()
if err != nil {
return nil, err
tx.DebugLogger().Error().Err(err).Str("transaction_id", tx.ID()).Msg("Failed to process request body")
return s.processRequestError(err), nil
}
if it != nil {
return s.processInterruption(it, hit), nil
Expand All @@ -293,12 +328,12 @@ func (s *SPOA) processResponse(spoeMsg *spoe.Message) ([]spoe.Action, error) {

resp, err = NewResponse(spoeMsg)
if err != nil {
return nil, err
return s.badResponseError(err), nil
}

app, err = s.getApplication(resp.app)
if err != nil {
return nil, err
return s.badResponseError(err), nil
}

txInterface, err := app.cache.Get(resp.id)
Expand All @@ -312,12 +347,12 @@ func (s *SPOA) processResponse(spoeMsg *spoe.Message) ([]spoe.Action, error) {

err = resp.init()
if err != nil {
return nil, err
return s.badResponseError(err), nil
}

headers, err := s.readHeaders(resp.headers)
if err != nil {
return nil, err
return s.badResponseError(err), nil
}
for key, values := range headers {
for _, v := range values {
Expand All @@ -327,7 +362,8 @@ func (s *SPOA) processResponse(spoeMsg *spoe.Message) ([]spoe.Action, error) {

it, _, err := tx.WriteResponseBody(resp.body)
if err != nil {
return nil, err
tx.DebugLogger().Error().Err(err).Str("transaction_id", tx.ID()).Msg("Failed to write response body")
return s.processResponseError(err), nil
}
if it != nil {
return s.processInterruption(it, hit), nil
Expand All @@ -340,7 +376,8 @@ func (s *SPOA) processResponse(spoeMsg *spoe.Message) ([]spoe.Action, error) {

it, err = tx.ProcessResponseBody()
if err != nil {
return nil, err
tx.DebugLogger().Error().Err(err).Str("transaction_id", tx.ID()).Msg("Failed to process response body")
return s.processResponseError(err), nil
}
if it != nil {
return s.processInterruption(it, hit), nil
Expand Down

0 comments on commit 04fa36d

Please sign in to comment.