@@ -132,66 +132,66 @@ func (r *AppsecRunner) Init(datadir string) error {
132132 return nil
133133}
134134
135- func (r * AppsecRunner ) processRequest (tx appsec.ExtendedTransaction , request * appsec.ParsedRequest ) error {
135+ func (r * AppsecRunner ) processRequest (state * appsec.AppsecRequestState , request * appsec.ParsedRequest ) error {
136136 var in * corazatypes.Interruption
137137 var err error
138138
139- if request .Tx .IsRuleEngineOff () {
139+ if state .Tx .IsRuleEngineOff () {
140140 r .logger .Debugf ("rule engine is off, skipping" )
141141 return nil
142142 }
143143
144144 defer func () {
145- request .Tx .ProcessLogging ()
145+ state .Tx .ProcessLogging ()
146146 //We don't close the transaction here, as it will reset coraza internal state and break variable tracking
147147
148- err := r .AppsecRuntime .ProcessPostEvalRules (request )
148+ err := r .AppsecRuntime .ProcessPostEvalRules (state , request )
149149 if err != nil {
150150 r .logger .Errorf ("unable to process PostEval rules: %s" , err )
151151 }
152152 }()
153153
154154 //pre eval (expr) rules
155- err = r .AppsecRuntime .ProcessPreEvalRules (request )
155+ err = r .AppsecRuntime .ProcessPreEvalRules (state , request )
156156 if err != nil {
157157 r .logger .Errorf ("unable to process PreEval rules: %s" , err )
158158 //FIXME: should we abort here ?
159159 }
160160
161- request .Tx .ProcessConnection (request .ClientIP , 0 , "" , 0 )
161+ state .Tx .ProcessConnection (request .ClientIP , 0 , "" , 0 )
162162
163163 for k , v := range request .Args {
164164 for _ , vv := range v {
165- request .Tx .AddGetRequestArgument (k , vv )
165+ state .Tx .AddGetRequestArgument (k , vv )
166166 }
167167 }
168168
169- request .Tx .ProcessURI (request .URI , request .Method , request .Proto )
169+ state .Tx .ProcessURI (request .URI , request .Method , request .Proto )
170170
171171 for k , vr := range request .Headers {
172172 for _ , v := range vr {
173- request .Tx .AddRequestHeader (k , v )
173+ state .Tx .AddRequestHeader (k , v )
174174 }
175175 }
176176
177177 if request .ClientHost != "" {
178- request .Tx .AddRequestHeader ("Host" , request .ClientHost )
179- request .Tx .SetServerName (request .ClientHost )
178+ state .Tx .AddRequestHeader ("Host" , request .ClientHost )
179+ state .Tx .SetServerName (request .ClientHost )
180180 }
181181
182182 if request .TransferEncoding != nil {
183- request .Tx .AddRequestHeader ("Transfer-Encoding" , request .TransferEncoding [0 ])
183+ state .Tx .AddRequestHeader ("Transfer-Encoding" , request .TransferEncoding [0 ])
184184 }
185185
186- in = request .Tx .ProcessRequestHeaders ()
186+ in = state .Tx .ProcessRequestHeaders ()
187187
188188 if in != nil {
189189 r .logger .Infof ("inband rules matched for headers : %s" , in .Action )
190190 return nil
191191 }
192192
193193 if len (request .Body ) > 0 {
194- in , _ , err = request .Tx .WriteRequestBody (request .Body )
194+ in , _ , err = state .Tx .WriteRequestBody (request .Body )
195195 if err != nil {
196196 r .logger .Errorf ("unable to write request body : %s" , err )
197197 return err
@@ -201,7 +201,7 @@ func (r *AppsecRunner) processRequest(tx appsec.ExtendedTransaction, request *ap
201201 }
202202 }
203203
204- in , err = request .Tx .ProcessRequestBody ()
204+ in , err = state .Tx .ProcessRequestBody ()
205205 if err != nil {
206206 r .logger .Errorf ("unable to process request body : %s" , err )
207207 return err
@@ -214,70 +214,67 @@ func (r *AppsecRunner) processRequest(tx appsec.ExtendedTransaction, request *ap
214214 return nil
215215}
216216
217- func (r * AppsecRunner ) ProcessInBandRules (request * appsec.ParsedRequest ) error {
217+ func (r * AppsecRunner ) ProcessInBandRules (state * appsec. AppsecRequestState , request * appsec.ParsedRequest ) error {
218218 tx := appsec .NewExtendedTransaction (r .AppsecInbandEngine , request .UUID )
219- r .AppsecRuntime .InBandTx = tx
220- request .Tx = tx
219+ state .Tx = tx
221220 if len (r .AppsecRuntime .InBandRules ) == 0 {
222221 return nil
223222 }
224- err := r .processRequest (tx , request )
223+ err := r .processRequest (state , request )
225224 return err
226225}
227226
228- func (r * AppsecRunner ) ProcessOutOfBandRules (request * appsec.ParsedRequest ) error {
227+ func (r * AppsecRunner ) ProcessOutOfBandRules (state * appsec. AppsecRequestState , request * appsec.ParsedRequest ) error {
229228 tx := appsec .NewExtendedTransaction (r .AppsecOutbandEngine , request .UUID )
230- r .AppsecRuntime .OutOfBandTx = tx
231- request .Tx = tx
229+ state .Tx = tx
232230 if len (r .AppsecRuntime .OutOfBandRules ) == 0 {
233231 return nil
234232 }
235- err := r .processRequest (tx , request )
233+ err := r .processRequest (state , request )
236234 return err
237235}
238236
239- func (r * AppsecRunner ) handleInBandInterrupt (request * appsec.ParsedRequest ) {
237+ func (r * AppsecRunner ) handleInBandInterrupt (state * appsec. AppsecRequestState , request * appsec.ParsedRequest ) {
240238
241239 if allowed , reason := r .appsecAllowlistsClient .IsAllowlisted (request .ClientIP ); allowed {
242240 r .logger .Infof ("%s is allowlisted by %s, skipping" , request .ClientIP , reason )
243241 return
244242 }
245243
246244 //create the associated event for crowdsec itself
247- evt , err := EventFromRequest (request , r .Labels )
245+ evt , err := EventFromRequest (request , r .Labels , state . Tx . ID () )
248246 if err != nil {
249247 //let's not interrupt the pipeline for this
250248 r .logger .Errorf ("unable to create event from request : %s" , err )
251249 }
252- err = r .AccumulateTxToEvent (& evt , request )
253- if err != nil {
254- r .logger .Errorf ("unable to accumulate tx to event : %s" , err )
255- }
256- if in := request .Tx .Interruption (); in != nil {
250+
251+ r .AccumulateTxToEvent (& evt , state , request )
252+
253+ if in := state .Tx .Interruption (); in != nil {
257254 r .logger .Debugf ("inband rules matched : %d" , in .RuleID )
258- r . AppsecRuntime .Response .InBandInterrupt = true
259- r . AppsecRuntime .Response .BouncerHTTPResponseCode = r .AppsecRuntime .Config .BouncerBlockedHTTPCode
260- r . AppsecRuntime .Response .UserHTTPResponseCode = r .AppsecRuntime .Config .UserBlockedHTTPCode
261- r . AppsecRuntime .Response .Action = r .AppsecRuntime .DefaultRemediation
255+ state .Response .InBandInterrupt = true
256+ state .Response .BouncerHTTPResponseCode = r .AppsecRuntime .Config .BouncerBlockedHTTPCode
257+ state .Response .UserHTTPResponseCode = r .AppsecRuntime .Config .UserBlockedHTTPCode
258+ state .Response .Action = r .AppsecRuntime .DefaultRemediation
262259
263260 if _ , ok := r .AppsecRuntime .RemediationById [in .RuleID ]; ok {
264- r . AppsecRuntime .Response .Action = r .AppsecRuntime .RemediationById [in .RuleID ]
261+ state .Response .Action = r .AppsecRuntime .RemediationById [in .RuleID ]
265262 }
266263
267264 for tag , remediation := range r .AppsecRuntime .RemediationByTag {
268265 if slices .Contains (in .Tags , tag ) {
269- r . AppsecRuntime .Response .Action = remediation
266+ state .Response .Action = remediation
270267 }
271268 }
272269
273- err = r .AppsecRuntime .ProcessOnMatchRules (request , evt )
270+ err = r .AppsecRuntime .ProcessOnMatchRules (state , request , evt )
274271 if err != nil {
275272 r .logger .Errorf ("unable to process OnMatch rules: %s" , err )
276273 return
277274 }
278275
279276 // Should the in band match trigger an overflow ?
280- if r . AppsecRuntime .Response .SendAlert {
277+ if state .Response .SendAlert {
281278 appsecOvlfw , err := AppsecEventGeneration (evt , request .HTTPRequest )
282279 if err != nil {
283280 r .logger .Errorf ("unable to generate appsec event : %s" , err )
@@ -288,34 +285,33 @@ func (r *AppsecRunner) handleInBandInterrupt(request *appsec.ParsedRequest) {
288285 }
289286 }
290287 // Should the in band match trigger an event ?
291- if r . AppsecRuntime .Response .SendEvent {
288+ if state .Response .SendEvent {
292289 r .outChan <- evt
293290 }
294291
295292 }
296293}
297294
298- func (r * AppsecRunner ) handleOutBandInterrupt (request * appsec.ParsedRequest ) {
295+ func (r * AppsecRunner ) handleOutBandInterrupt (state * appsec. AppsecRequestState , request * appsec.ParsedRequest ) {
299296
300297 if allowed , reason := r .appsecAllowlistsClient .IsAllowlisted (request .ClientIP ); allowed {
301298 r .logger .Infof ("%s is allowlisted by %s, skipping" , request .ClientIP , reason )
302299 return
303300 }
304301
305- evt , err := EventFromRequest (request , r .Labels )
302+ evt , err := EventFromRequest (request , r .Labels , state . Tx . ID () )
306303 if err != nil {
307304 //let's not interrupt the pipeline for this
308305 r .logger .Errorf ("unable to create event from request : %s" , err )
309306 }
310- err = r .AccumulateTxToEvent (& evt , request )
311- if err != nil {
312- r .logger .Errorf ("unable to accumulate tx to event : %s" , err )
313- }
314- if in := request .Tx .Interruption (); in != nil {
307+
308+ r .AccumulateTxToEvent (& evt , state , request )
309+
310+ if in := state .Tx .Interruption (); in != nil {
315311 r .logger .Debugf ("outband rules matched : %d" , in .RuleID )
316- r . AppsecRuntime .Response .OutOfBandInterrupt = true
312+ state .Response .OutOfBandInterrupt = true
317313
318- err = r .AppsecRuntime .ProcessOnMatchRules (request , evt )
314+ err = r .AppsecRuntime .ProcessOnMatchRules (state , request , evt )
319315 if err != nil {
320316 r .logger .Errorf ("unable to process OnMatch rules: %s" , err )
321317 return
@@ -325,7 +321,7 @@ func (r *AppsecRunner) handleOutBandInterrupt(request *appsec.ParsedRequest) {
325321 // The event and the alert share the same internal map (parsed, meta, ...)
326322 // The event can be modified by the parsers, which might cause a concurrent map read/write
327323 // Should the match trigger an overflow ?
328- if r . AppsecRuntime .Response .SendAlert {
324+ if state .Response .SendAlert {
329325 appsecOvlfw , err := AppsecEventGeneration (evt , request .HTTPRequest )
330326 if err != nil {
331327 r .logger .Errorf ("unable to generate appsec event : %s" , err )
@@ -337,17 +333,19 @@ func (r *AppsecRunner) handleOutBandInterrupt(request *appsec.ParsedRequest) {
337333 }
338334
339335 // Should the match trigger an event ?
340- if r . AppsecRuntime .Response .SendEvent {
336+ if state .Response .SendEvent {
341337 r .outChan <- evt
342338 }
343339 }
344340}
345341
346342func (r * AppsecRunner ) handleRequest (request * appsec.ParsedRequest ) {
347- r .AppsecRuntime .Logger = r .AppsecRuntime .Logger .WithField ("request_uuid" , request .UUID )
343+ state := r .AppsecRuntime .NewRequestState ()
344+ stateLogger := r .AppsecRuntime .Logger .WithField ("request_uuid" , request .UUID )
345+ r .AppsecRuntime .Logger = stateLogger
348346 logger := r .logger .WithField ("request_uuid" , request .UUID )
349347 logger .Debug ("Request received in runner" )
350- r .AppsecRuntime .ClearResponse ()
348+ r .AppsecRuntime .ClearResponse (& state )
351349
352350 request .IsInBand = true
353351 request .IsOutBand = false
@@ -356,11 +354,13 @@ func (r *AppsecRunner) handleRequest(request *appsec.ParsedRequest) {
356354 startInBandParsing := time .Now ()
357355 startGlobalParsing := time .Now ()
358356
357+ state .CurrentPhase = appsec .PhaseInBand
358+
359359 //inband appsec rules
360- err := r .ProcessInBandRules (request )
360+ err := r .ProcessInBandRules (& state , request )
361361 if err != nil {
362362 logger .Errorf ("unable to process InBand rules: %s" , err )
363- err = request .Tx .Close ()
363+ err = state .Tx .Close ()
364364 if err != nil {
365365 logger .Errorf ("unable to close inband transaction: %s" , err )
366366 }
@@ -371,35 +371,36 @@ func (r *AppsecRunner) handleRequest(request *appsec.ParsedRequest) {
371371 inBandParsingElapsed := time .Since (startInBandParsing )
372372 metrics .AppsecInbandParsingHistogram .With (prometheus.Labels {"source" : request .RemoteAddrNormalized , "appsec_engine" : request .AppsecEngine }).Observe (inBandParsingElapsed .Seconds ())
373373
374- if request .Tx .IsInterrupted () {
375- r .handleInBandInterrupt (request )
374+ if state .Tx .IsInterrupted () {
375+ r .handleInBandInterrupt (& state , request )
376376 }
377377
378- err = request .Tx .Close ()
378+ err = state .Tx .Close ()
379379 if err != nil {
380380 r .logger .Errorf ("unable to close inband transaction: %s" , err )
381381 }
382382
383383 // send back the result to the HTTP handler for the InBand part
384- request .ResponseChannel <- r . AppsecRuntime .Response
384+ request .ResponseChannel <- state .Response
385385
386386 //Now let's process the out of band rules
387387
388388 request .IsInBand = false
389389 request .IsOutBand = true
390- r .AppsecRuntime .Response .SendAlert = false
391- r .AppsecRuntime .Response .SendEvent = true
390+ state .Response .SendAlert = false
391+ state .Response .SendEvent = true
392+ state .CurrentPhase = appsec .PhaseOutOfBand
392393
393394 //FIXME: This is a bit of a hack to avoid confusion with the transaction if we do not have any inband rules.
394395 //We should probably have different transaction (or even different request object) for inband and out of band rules
395396 if len (r .AppsecRuntime .OutOfBandRules ) > 0 {
396397 //to measure the time spent in the Application Security Engine for OutOfBand rules
397398 startOutOfBandParsing := time .Now ()
398399
399- err = r .ProcessOutOfBandRules (request )
400+ err = r .ProcessOutOfBandRules (& state , request )
400401 if err != nil {
401402 logger .Errorf ("unable to process OutOfBand rules: %s" , err )
402- err = request .Tx .Close ()
403+ err = state .Tx .Close ()
403404 if err != nil {
404405 logger .Errorf ("unable to close outband transaction: %s" , err )
405406 }
@@ -409,11 +410,11 @@ func (r *AppsecRunner) handleRequest(request *appsec.ParsedRequest) {
409410 // time spent to process out of band rules
410411 outOfBandParsingElapsed := time .Since (startOutOfBandParsing )
411412 metrics .AppsecOutbandParsingHistogram .With (prometheus.Labels {"source" : request .RemoteAddrNormalized , "appsec_engine" : request .AppsecEngine }).Observe (outOfBandParsingElapsed .Seconds ())
412- if request .Tx .IsInterrupted () {
413- r .handleOutBandInterrupt (request )
413+ if state .Tx .IsInterrupted () {
414+ r .handleOutBandInterrupt (& state , request )
414415 }
415416 }
416- err = request .Tx .Close ()
417+ err = state .Tx .Close ()
417418 if err != nil {
418419 r .logger .Errorf ("unable to close outband transaction: %s" , err )
419420 }
0 commit comments