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  }