123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- package csprofiles
- import (
- "fmt"
- "reflect"
- "testing"
- "github.com/stretchr/testify/require"
- "github.com/crowdsecurity/crowdsec/pkg/csconfig"
- "github.com/crowdsecurity/crowdsec/pkg/exprhelpers"
- "github.com/crowdsecurity/crowdsec/pkg/models"
- )
- var (
- scope = "Country"
- typ = "ban"
- boolFalse = false
- boolTrue = true
- duration = "1h"
- value = "CH"
- scenario = "ssh-bf"
- )
- func TestNewProfile(t *testing.T) {
- tests := []struct {
- name string
- profileCfg *csconfig.ProfileCfg
- expectedNbProfile int
- }{
- {
- name: "filter ok and duration_expr ok",
- profileCfg: &csconfig.ProfileCfg{
- Filters: []string{
- "1==1",
- },
- DurationExpr: "1==1",
- Debug: &boolFalse,
- Decisions: []models.Decision{
- {Type: &typ, Scope: &scope, Simulated: &boolTrue, Duration: &duration},
- },
- },
- expectedNbProfile: 1,
- },
- {
- name: "filter NOK and duration_expr ok",
- profileCfg: &csconfig.ProfileCfg{
- Filters: []string{
- "1==1",
- "unknownExprHelper() == 'foo'",
- },
- DurationExpr: "1==1",
- Debug: &boolFalse,
- Decisions: []models.Decision{
- {Type: &typ, Scope: &scope, Simulated: &boolFalse, Duration: &duration},
- },
- },
- expectedNbProfile: 0,
- },
- {
- name: "filter ok and duration_expr NOK",
- profileCfg: &csconfig.ProfileCfg{
- Filters: []string{
- "1==1",
- },
- DurationExpr: "unknownExprHelper() == 'foo'",
- Debug: &boolFalse,
- Decisions: []models.Decision{
- {Type: &typ, Scope: &scope, Simulated: &boolFalse, Duration: &duration},
- },
- },
- expectedNbProfile: 0,
- },
- {
- name: "filter ok and duration_expr ok + DEBUG",
- profileCfg: &csconfig.ProfileCfg{
- Filters: []string{
- "1==1",
- },
- DurationExpr: "1==1",
- Debug: &boolTrue,
- Decisions: []models.Decision{
- {Type: &typ, Scope: &scope, Simulated: &boolFalse, Duration: &duration},
- },
- },
- expectedNbProfile: 1,
- },
- {
- name: "filter ok and no duration",
- profileCfg: &csconfig.ProfileCfg{
- Filters: []string{
- "1==1",
- },
- Debug: &boolTrue,
- Decisions: []models.Decision{
- {Type: &typ, Scope: &scope, Simulated: &boolFalse},
- },
- },
- expectedNbProfile: 1,
- },
- }
- for _, test := range tests {
- test := test
- t.Run(test.name, func(t *testing.T) {
- profilesCfg := []*csconfig.ProfileCfg{
- test.profileCfg,
- }
- profile, _ := NewProfile(profilesCfg)
- fmt.Printf("expected : %+v | result : %+v", test.expectedNbProfile, len(profile))
- require.Len(t, profile, test.expectedNbProfile)
- })
- }
- }
- func TestEvaluateProfile(t *testing.T) {
- type args struct {
- profileCfg *csconfig.ProfileCfg
- Alert *models.Alert
- }
- exprhelpers.Init(nil)
- tests := []struct {
- name string
- args args
- expectedDecisionCount int // count of expected decisions
- expectedDuration string
- expectedMatchStatus bool
- }{
- {
- name: "simple pass single expr",
- args: args{
- profileCfg: &csconfig.ProfileCfg{
- Filters: []string{fmt.Sprintf("Alert.GetScenario() == \"%s\"", scenario)},
- Debug: &boolFalse,
- },
- Alert: &models.Alert{Remediation: true, Scenario: &scenario},
- },
- expectedDecisionCount: 0,
- expectedMatchStatus: true,
- },
- {
- name: "simple fail single expr",
- args: args{
- profileCfg: &csconfig.ProfileCfg{
- Filters: []string{"Alert.GetScenario() == \"Foo\""},
- },
- Alert: &models.Alert{Remediation: true},
- },
- expectedDecisionCount: 0,
- expectedMatchStatus: false,
- },
- {
- name: "1 expr fail 1 expr pass should still eval to match",
- args: args{
- profileCfg: &csconfig.ProfileCfg{
- Filters: []string{"1==1", "1!=1"},
- },
- Alert: &models.Alert{Remediation: true},
- },
- expectedDecisionCount: 0,
- expectedMatchStatus: true,
- },
- {
- name: "simple filter with 2 decision",
- args: args{
- profileCfg: &csconfig.ProfileCfg{
- Filters: []string{"1==1"},
- Decisions: []models.Decision{
- {Type: &typ, Scope: &scope, Simulated: &boolTrue, Duration: &duration},
- {Type: &typ, Scope: &scope, Simulated: &boolFalse, Duration: &duration},
- },
- },
- Alert: &models.Alert{Remediation: true, Scenario: &scenario, Source: &models.Source{Value: &value}},
- },
- expectedDecisionCount: 2,
- expectedMatchStatus: true,
- },
- {
- name: "simple filter with decision_expr",
- args: args{
- profileCfg: &csconfig.ProfileCfg{
- Filters: []string{"1==1"},
- Decisions: []models.Decision{
- {Type: &typ, Scope: &scope, Simulated: &boolFalse},
- },
- DurationExpr: "Sprintf('%dh', 4*4)",
- },
- Alert: &models.Alert{Remediation: true, Scenario: &scenario, Source: &models.Source{Value: &value}},
- },
- expectedDecisionCount: 1,
- expectedDuration: "16h",
- expectedMatchStatus: true,
- },
- }
- for _, tt := range tests {
- tt := tt
- t.Run(tt.name, func(t *testing.T) {
- profilesCfg := []*csconfig.ProfileCfg{
- tt.args.profileCfg,
- }
- profile, err := NewProfile(profilesCfg)
- if err != nil {
- t.Errorf("failed to get newProfile : %+v", err)
- }
- got, got1, _ := profile[0].EvaluateProfile(tt.args.Alert)
- if !reflect.DeepEqual(len(got), tt.expectedDecisionCount) {
- t.Errorf("EvaluateProfile() got = %+v, want %+v", got, tt.expectedDecisionCount)
- }
- if got1 != tt.expectedMatchStatus {
- t.Errorf("EvaluateProfile() got1 = %v, want %v", got1, tt.expectedMatchStatus)
- }
- if tt.expectedDuration != "" {
- require.Equal(t, tt.expectedDuration, *got[0].Duration, "The two durations should be the same")
- }
- })
- }
- }
|