github.com/crowdsecurity/crowdsec@v1.6.1/pkg/acquisition/modules/appsec/appsec_test.go (about) 1 package appsecacquisition 2 3 import ( 4 "testing" 5 "time" 6 7 "github.com/crowdsecurity/crowdsec/pkg/appsec" 8 "github.com/crowdsecurity/crowdsec/pkg/appsec/appsec_rule" 9 "github.com/crowdsecurity/crowdsec/pkg/types" 10 "github.com/davecgh/go-spew/spew" 11 "github.com/google/uuid" 12 log "github.com/sirupsen/logrus" 13 ) 14 15 type appsecRuleTest struct { 16 name string 17 expected_load_ok bool 18 inband_rules []appsec_rule.CustomRule 19 outofband_rules []appsec_rule.CustomRule 20 on_load []appsec.Hook 21 pre_eval []appsec.Hook 22 post_eval []appsec.Hook 23 on_match []appsec.Hook 24 BouncerBlockedHTTPCode int 25 UserBlockedHTTPCode int 26 UserPassedHTTPCode int 27 DefaultRemediation string 28 DefaultPassAction string 29 input_request appsec.ParsedRequest 30 output_asserts func(events []types.Event, responses []appsec.AppsecTempResponse, appsecResponse appsec.BodyResponse, statusCode int) 31 } 32 33 func loadAppSecEngine(test appsecRuleTest, t *testing.T) { 34 if testing.Verbose() { 35 log.SetLevel(log.TraceLevel) 36 } else { 37 log.SetLevel(log.WarnLevel) 38 } 39 inbandRules := []string{} 40 outofbandRules := []string{} 41 InChan := make(chan appsec.ParsedRequest) 42 OutChan := make(chan types.Event) 43 44 logger := log.WithFields(log.Fields{"test": test.name}) 45 46 //build rules 47 for ridx, rule := range test.inband_rules { 48 strRule, _, err := rule.Convert(appsec_rule.ModsecurityRuleType, rule.Name) 49 if err != nil { 50 t.Fatalf("failed compilation of rule %d/%d of %s : %s", ridx, len(test.inband_rules), test.name, err) 51 } 52 inbandRules = append(inbandRules, strRule) 53 54 } 55 for ridx, rule := range test.outofband_rules { 56 strRule, _, err := rule.Convert(appsec_rule.ModsecurityRuleType, rule.Name) 57 if err != nil { 58 t.Fatalf("failed compilation of rule %d/%d of %s : %s", ridx, len(test.outofband_rules), test.name, err) 59 } 60 outofbandRules = append(outofbandRules, strRule) 61 } 62 63 appsecCfg := appsec.AppsecConfig{Logger: logger, 64 OnLoad: test.on_load, 65 PreEval: test.pre_eval, 66 PostEval: test.post_eval, 67 OnMatch: test.on_match, 68 BouncerBlockedHTTPCode: test.BouncerBlockedHTTPCode, 69 UserBlockedHTTPCode: test.UserBlockedHTTPCode, 70 UserPassedHTTPCode: test.UserPassedHTTPCode, 71 DefaultRemediation: test.DefaultRemediation, 72 DefaultPassAction: test.DefaultPassAction} 73 AppsecRuntime, err := appsecCfg.Build() 74 if err != nil { 75 t.Fatalf("unable to build appsec runtime : %s", err) 76 } 77 AppsecRuntime.InBandRules = []appsec.AppsecCollection{{Rules: inbandRules}} 78 AppsecRuntime.OutOfBandRules = []appsec.AppsecCollection{{Rules: outofbandRules}} 79 appsecRunnerUUID := uuid.New().String() 80 //we copy AppsecRutime for each runner 81 wrt := *AppsecRuntime 82 wrt.Logger = logger 83 runner := AppsecRunner{ 84 inChan: InChan, 85 UUID: appsecRunnerUUID, 86 logger: logger, 87 AppsecRuntime: &wrt, 88 Labels: map[string]string{"foo": "bar"}, 89 outChan: OutChan, 90 } 91 err = runner.Init("/tmp/") 92 if err != nil { 93 t.Fatalf("unable to initialize runner : %s", err) 94 } 95 96 input := test.input_request 97 input.ResponseChannel = make(chan appsec.AppsecTempResponse) 98 OutputEvents := make([]types.Event, 0) 99 OutputResponses := make([]appsec.AppsecTempResponse, 0) 100 go func() { 101 for { 102 //log.Printf("reading from %p", input.ResponseChannel) 103 out := <-input.ResponseChannel 104 OutputResponses = append(OutputResponses, out) 105 //log.Errorf("response -> %s", spew.Sdump(out)) 106 } 107 }() 108 go func() { 109 for { 110 out := <-OutChan 111 OutputEvents = append(OutputEvents, out) 112 //log.Errorf("outchan -> %s", spew.Sdump(out)) 113 } 114 }() 115 116 runner.handleRequest(&input) 117 time.Sleep(50 * time.Millisecond) 118 119 http_status, appsecResponse := AppsecRuntime.GenerateResponse(OutputResponses[0], logger) 120 log.Infof("events : %s", spew.Sdump(OutputEvents)) 121 log.Infof("responses : %s", spew.Sdump(OutputResponses)) 122 test.output_asserts(OutputEvents, OutputResponses, appsecResponse, http_status) 123 124 }