2020-11-30 09:37:17 +00:00
package apiserver
import (
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"strings"
2021-08-25 09:43:29 +00:00
"sync"
2020-11-30 09:37:17 +00:00
"testing"
"github.com/gin-gonic/gin"
log "github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
2023-12-14 13:54:11 +00:00
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
"github.com/crowdsecurity/crowdsec/pkg/csplugin"
"github.com/crowdsecurity/crowdsec/pkg/models"
2020-11-30 09:37:17 +00:00
)
2022-03-29 12:20:26 +00:00
type LAPI struct {
router * gin . Engine
loginResp models . WatcherAuthResponse
bouncerKey string
t * testing . T
2022-06-22 08:29:02 +00:00
DBConfig * csconfig . DatabaseCfg
2022-03-29 12:20:26 +00:00
}
func SetupLAPITest ( t * testing . T ) LAPI {
t . Helper ( )
2023-05-25 13:32:32 +00:00
router , loginResp , config , err := InitMachineTest ( t )
2022-03-29 12:20:26 +00:00
if err != nil {
2022-06-22 13:53:53 +00:00
t . Fatal ( err )
2022-03-29 12:20:26 +00:00
}
2022-05-17 10:14:59 +00:00
APIKey , err := CreateTestBouncer ( config . API . Server . DbConfig )
2022-03-29 12:20:26 +00:00
if err != nil {
2022-06-22 13:53:53 +00:00
t . Fatal ( err )
2022-03-29 12:20:26 +00:00
}
2022-06-22 08:29:02 +00:00
2022-03-29 12:20:26 +00:00
return LAPI {
router : router ,
loginResp : loginResp ,
bouncerKey : APIKey ,
2022-06-22 08:29:02 +00:00
DBConfig : config . API . Server . DbConfig ,
2022-03-29 12:20:26 +00:00
}
}
func ( l * LAPI ) InsertAlertFromFile ( path string ) * httptest . ResponseRecorder {
alertReader := GetAlertReaderFromFile ( path )
2022-08-16 07:46:10 +00:00
return l . RecordResponse ( http . MethodPost , "/v1/alerts" , alertReader , "password" )
2022-03-29 12:20:26 +00:00
}
2022-06-08 14:05:52 +00:00
func ( l * LAPI ) RecordResponse ( verb string , url string , body * strings . Reader , authType string ) * httptest . ResponseRecorder {
2022-03-29 12:20:26 +00:00
w := httptest . NewRecorder ( )
req , err := http . NewRequest ( verb , url , body )
if err != nil {
l . t . Fatal ( err )
}
2023-12-14 13:54:11 +00:00
2022-06-08 14:05:52 +00:00
if authType == "apikey" {
req . Header . Add ( "X-Api-Key" , l . bouncerKey )
} else if authType == "password" {
AddAuthHeaders ( req , l . loginResp )
} else {
l . t . Fatal ( "auth type not supported" )
}
2023-12-14 13:54:11 +00:00
2022-03-29 12:20:26 +00:00
l . router . ServeHTTP ( w , req )
2023-12-14 13:54:11 +00:00
2022-03-29 12:20:26 +00:00
return w
}
2023-05-25 13:32:32 +00:00
func InitMachineTest ( t * testing . T ) ( * gin . Engine , models . WatcherAuthResponse , csconfig . Config , error ) {
router , config , err := NewAPITest ( t )
2020-11-30 09:37:17 +00:00
if err != nil {
2022-05-17 10:14:59 +00:00
return nil , models . WatcherAuthResponse { } , config , fmt . Errorf ( "unable to run local API: %s" , err )
2020-11-30 09:37:17 +00:00
}
2022-05-17 10:14:59 +00:00
loginResp , err := LoginToTestAPI ( router , config )
2020-11-30 09:37:17 +00:00
if err != nil {
2022-11-29 08:16:07 +00:00
return nil , models . WatcherAuthResponse { } , config , err
2020-11-30 09:37:17 +00:00
}
2023-12-14 13:54:11 +00:00
2022-05-17 10:14:59 +00:00
return router , loginResp , config , nil
2021-08-25 09:43:29 +00:00
}
2020-11-30 09:37:17 +00:00
2022-05-17 10:14:59 +00:00
func LoginToTestAPI ( router * gin . Engine , config csconfig . Config ) ( models . WatcherAuthResponse , error ) {
2021-08-25 09:43:29 +00:00
body , err := CreateTestMachine ( router )
if err != nil {
2022-11-29 08:16:07 +00:00
return models . WatcherAuthResponse { } , err
2021-08-25 09:43:29 +00:00
}
2022-05-17 10:14:59 +00:00
err = ValidateMachine ( "test" , config . API . Server . DbConfig )
2020-11-30 09:37:17 +00:00
if err != nil {
2022-06-22 13:53:53 +00:00
log . Fatalln ( err )
2020-11-30 09:37:17 +00:00
}
w := httptest . NewRecorder ( )
2022-08-16 07:46:10 +00:00
req , _ := http . NewRequest ( http . MethodPost , "/v1/watchers/login" , strings . NewReader ( body ) )
2020-11-30 09:37:17 +00:00
req . Header . Add ( "User-Agent" , UserAgent )
router . ServeHTTP ( w , req )
loginResp := models . WatcherAuthResponse { }
err = json . NewDecoder ( w . Body ) . Decode ( & loginResp )
if err != nil {
2022-11-29 08:16:07 +00:00
return models . WatcherAuthResponse { } , err
2020-11-30 09:37:17 +00:00
}
2022-06-08 14:05:52 +00:00
2021-08-25 09:43:29 +00:00
return loginResp , nil
}
2020-11-30 09:37:17 +00:00
2021-08-25 09:43:29 +00:00
func AddAuthHeaders ( request * http . Request , authResponse models . WatcherAuthResponse ) {
request . Header . Add ( "User-Agent" , UserAgent )
request . Header . Add ( "Authorization" , fmt . Sprintf ( "Bearer %s" , authResponse . Token ) )
2020-11-30 09:37:17 +00:00
}
func TestSimulatedAlert ( t * testing . T ) {
2022-03-29 12:20:26 +00:00
lapi := SetupLAPITest ( t )
lapi . InsertAlertFromFile ( "./tests/alert_minibulk+simul.json" )
alertContent := GetAlertReaderFromFile ( "./tests/alert_minibulk+simul.json" )
2020-11-30 09:37:17 +00:00
//exclude decision in simulation mode
2022-03-29 12:20:26 +00:00
2022-06-08 14:05:52 +00:00
w := lapi . RecordResponse ( "GET" , "/v1/alerts?simulated=false" , alertContent , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 200 , w . Code )
assert . Contains ( t , w . Body . String ( ) , ` "message":"Ip 91.121.79.178 performed crowdsecurity/ssh-bf (6 events over ` )
assert . NotContains ( t , w . Body . String ( ) , ` "message":"Ip 91.121.79.179 performed crowdsecurity/ssh-bf (6 events over ` )
//include decision in simulation mode
2022-03-29 12:20:26 +00:00
2022-06-08 14:05:52 +00:00
w = lapi . RecordResponse ( "GET" , "/v1/alerts?simulated=true" , alertContent , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 200 , w . Code )
assert . Contains ( t , w . Body . String ( ) , ` "message":"Ip 91.121.79.178 performed crowdsecurity/ssh-bf (6 events over ` )
assert . Contains ( t , w . Body . String ( ) , ` "message":"Ip 91.121.79.179 performed crowdsecurity/ssh-bf (6 events over ` )
}
func TestCreateAlert ( t * testing . T ) {
2022-03-29 12:20:26 +00:00
lapi := SetupLAPITest ( t )
2020-11-30 09:37:17 +00:00
// Create Alert with invalid format
2022-08-16 07:46:10 +00:00
w := lapi . RecordResponse ( http . MethodPost , "/v1/alerts" , strings . NewReader ( "test" ) , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 400 , w . Code )
assert . Equal ( t , "{\"message\":\"invalid character 'e' in literal true (expecting 'r')\"}" , w . Body . String ( ) )
// Create Alert with invalid input
2022-03-29 12:20:26 +00:00
alertContent := GetAlertReaderFromFile ( "./tests/invalidAlert_sample.json" )
2020-11-30 09:37:17 +00:00
2022-08-16 07:46:10 +00:00
w = lapi . RecordResponse ( http . MethodPost , "/v1/alerts" , alertContent , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 500 , w . Code )
2022-01-11 15:45:34 +00:00
assert . Equal ( t , "{\"message\":\"validation failure list:\\n0.scenario in body is required\\n0.scenario_hash in body is required\\n0.scenario_version in body is required\\n0.simulated in body is required\\n0.source in body is required\"}" , w . Body . String ( ) )
2020-11-30 09:37:17 +00:00
// Create Valid Alert
2022-03-29 12:20:26 +00:00
w = lapi . InsertAlertFromFile ( "./tests/alert_sample.json" )
2020-11-30 15:15:07 +00:00
assert . Equal ( t , 201 , w . Code )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , "[\"1\"]" , w . Body . String ( ) )
}
2021-08-25 09:43:29 +00:00
func TestCreateAlertChannels ( t * testing . T ) {
2023-05-25 13:32:32 +00:00
apiServer , config , err := NewAPIServer ( t )
2021-08-25 09:43:29 +00:00
if err != nil {
2022-06-22 13:53:53 +00:00
log . Fatalln ( err )
2021-08-25 09:43:29 +00:00
}
apiServer . controller . PluginChannel = make ( chan csplugin . ProfileAlert )
apiServer . InitController ( )
2022-05-17 10:14:59 +00:00
loginResp , err := LoginToTestAPI ( apiServer . router , config )
2021-08-25 09:43:29 +00:00
if err != nil {
2022-06-22 13:53:53 +00:00
log . Fatalln ( err )
2021-08-25 09:43:29 +00:00
}
2022-03-29 12:20:26 +00:00
lapi := LAPI { router : apiServer . router , loginResp : loginResp }
2021-08-25 09:43:29 +00:00
2023-12-14 13:54:11 +00:00
var (
pd csplugin . ProfileAlert
wg sync . WaitGroup
)
2021-08-25 09:43:29 +00:00
wg . Add ( 1 )
2023-12-14 13:54:11 +00:00
2021-08-25 09:43:29 +00:00
go func ( ) {
pd = <- apiServer . controller . PluginChannel
2023-12-14 13:54:11 +00:00
2021-08-25 09:43:29 +00:00
wg . Done ( )
} ( )
2022-03-29 12:20:26 +00:00
go lapi . InsertAlertFromFile ( "./tests/alert_ssh-bf.json" )
2021-08-25 09:43:29 +00:00
wg . Wait ( )
2023-12-14 13:54:11 +00:00
assert . Len ( t , pd . Alert . Decisions , 1 )
2021-08-25 09:43:29 +00:00
apiServer . Close ( )
}
2020-11-30 09:37:17 +00:00
func TestAlertListFilters ( t * testing . T ) {
2022-03-29 12:20:26 +00:00
lapi := SetupLAPITest ( t )
lapi . InsertAlertFromFile ( "./tests/alert_ssh-bf.json" )
alertContent := GetAlertReaderFromFile ( "./tests/alert_ssh-bf.json" )
2020-11-30 09:37:17 +00:00
//bad filter
2022-03-29 12:20:26 +00:00
2022-06-08 14:05:52 +00:00
w := lapi . RecordResponse ( "GET" , "/v1/alerts?test=test" , alertContent , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 500 , w . Code )
assert . Equal ( t , "{\"message\":\"Filter parameter 'test' is unknown (=test): invalid filter\"}" , w . Body . String ( ) )
//get without filters
2022-03-29 12:20:26 +00:00
2022-06-08 14:05:52 +00:00
w = lapi . RecordResponse ( "GET" , "/v1/alerts" , emptyBody , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 200 , w . Code )
//check alert and decision
assert . Contains ( t , w . Body . String ( ) , "Ip 91.121.79.195 performed 'crowdsecurity/ssh-bf' (6 events over " )
2021-01-14 15:27:45 +00:00
assert . Contains ( t , w . Body . String ( ) , ` scope":"Ip","simulated":false,"type":"ban","value":"91.121.79.195" ` )
2020-11-30 09:37:17 +00:00
//test decision_type filter (ok)
2022-03-29 12:20:26 +00:00
2022-06-08 14:05:52 +00:00
w = lapi . RecordResponse ( "GET" , "/v1/alerts?decision_type=ban" , emptyBody , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 200 , w . Code )
assert . Contains ( t , w . Body . String ( ) , "Ip 91.121.79.195 performed 'crowdsecurity/ssh-bf' (6 events over " )
2021-01-14 15:27:45 +00:00
assert . Contains ( t , w . Body . String ( ) , ` scope":"Ip","simulated":false,"type":"ban","value":"91.121.79.195" ` )
2020-11-30 09:37:17 +00:00
//test decision_type filter (bad value)
2022-03-29 12:20:26 +00:00
2022-06-08 14:05:52 +00:00
w = lapi . RecordResponse ( "GET" , "/v1/alerts?decision_type=ratata" , emptyBody , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 200 , w . Code )
assert . Equal ( t , "null" , w . Body . String ( ) )
//test scope (ok)
2022-03-29 12:20:26 +00:00
2022-06-08 14:05:52 +00:00
w = lapi . RecordResponse ( "GET" , "/v1/alerts?scope=Ip" , emptyBody , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 200 , w . Code )
assert . Contains ( t , w . Body . String ( ) , "Ip 91.121.79.195 performed 'crowdsecurity/ssh-bf' (6 events over " )
2021-01-14 15:27:45 +00:00
assert . Contains ( t , w . Body . String ( ) , ` scope":"Ip","simulated":false,"type":"ban","value":"91.121.79.195" ` )
2020-11-30 09:37:17 +00:00
//test scope (bad value)
2022-03-29 12:20:26 +00:00
2022-06-08 14:05:52 +00:00
w = lapi . RecordResponse ( "GET" , "/v1/alerts?scope=rarara" , emptyBody , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 200 , w . Code )
assert . Equal ( t , "null" , w . Body . String ( ) )
//test scenario (ok)
2022-03-29 12:20:26 +00:00
2022-06-08 14:05:52 +00:00
w = lapi . RecordResponse ( "GET" , "/v1/alerts?scenario=crowdsecurity/ssh-bf" , emptyBody , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 200 , w . Code )
assert . Contains ( t , w . Body . String ( ) , "Ip 91.121.79.195 performed 'crowdsecurity/ssh-bf' (6 events over " )
2021-01-14 15:27:45 +00:00
assert . Contains ( t , w . Body . String ( ) , ` scope":"Ip","simulated":false,"type":"ban","value":"91.121.79.195" ` )
2020-11-30 09:37:17 +00:00
//test scenario (bad value)
2022-03-29 12:20:26 +00:00
2022-06-08 14:05:52 +00:00
w = lapi . RecordResponse ( "GET" , "/v1/alerts?scenario=crowdsecurity/nope" , emptyBody , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 200 , w . Code )
assert . Equal ( t , "null" , w . Body . String ( ) )
//test ip (ok)
2022-03-29 12:20:26 +00:00
2022-06-08 14:05:52 +00:00
w = lapi . RecordResponse ( "GET" , "/v1/alerts?ip=91.121.79.195" , emptyBody , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 200 , w . Code )
assert . Contains ( t , w . Body . String ( ) , "Ip 91.121.79.195 performed 'crowdsecurity/ssh-bf' (6 events over " )
2021-01-14 15:27:45 +00:00
assert . Contains ( t , w . Body . String ( ) , ` scope":"Ip","simulated":false,"type":"ban","value":"91.121.79.195" ` )
2020-11-30 09:37:17 +00:00
//test ip (bad value)
2022-03-29 12:20:26 +00:00
2022-06-08 14:05:52 +00:00
w = lapi . RecordResponse ( "GET" , "/v1/alerts?ip=99.122.77.195" , emptyBody , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 200 , w . Code )
assert . Equal ( t , "null" , w . Body . String ( ) )
//test ip (invalid value)
2022-03-29 12:20:26 +00:00
2022-06-08 14:05:52 +00:00
w = lapi . RecordResponse ( "GET" , "/v1/alerts?ip=gruueq" , emptyBody , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 500 , w . Code )
2021-01-14 15:27:45 +00:00
assert . Equal ( t , ` { "message":"unable to convert 'gruueq' to int: invalid address: invalid ip address / range"} ` , w . Body . String ( ) )
2020-11-30 09:37:17 +00:00
//test range (ok)
2022-03-29 12:20:26 +00:00
2022-06-08 14:05:52 +00:00
w = lapi . RecordResponse ( "GET" , "/v1/alerts?range=91.121.79.0/24&contains=false" , emptyBody , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 200 , w . Code )
assert . Contains ( t , w . Body . String ( ) , "Ip 91.121.79.195 performed 'crowdsecurity/ssh-bf' (6 events over " )
2021-01-14 15:27:45 +00:00
assert . Contains ( t , w . Body . String ( ) , ` scope":"Ip","simulated":false,"type":"ban","value":"91.121.79.195" ` )
2020-11-30 09:37:17 +00:00
//test range
2022-03-29 12:20:26 +00:00
2022-06-08 14:05:52 +00:00
w = lapi . RecordResponse ( "GET" , "/v1/alerts?range=99.122.77.0/24&contains=false" , emptyBody , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 200 , w . Code )
assert . Equal ( t , "null" , w . Body . String ( ) )
//test range (invalid value)
2022-03-29 12:20:26 +00:00
2022-06-08 14:05:52 +00:00
w = lapi . RecordResponse ( "GET" , "/v1/alerts?range=ratata" , emptyBody , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 500 , w . Code )
2021-01-14 15:27:45 +00:00
assert . Equal ( t , ` { "message":"unable to convert 'ratata' to int: invalid address: invalid ip address / range"} ` , w . Body . String ( ) )
2020-11-30 09:37:17 +00:00
//test since (ok)
2022-03-29 12:20:26 +00:00
2022-06-08 14:05:52 +00:00
w = lapi . RecordResponse ( "GET" , "/v1/alerts?since=1h" , emptyBody , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 200 , w . Code )
assert . Contains ( t , w . Body . String ( ) , "Ip 91.121.79.195 performed 'crowdsecurity/ssh-bf' (6 events over " )
2021-01-14 15:27:45 +00:00
assert . Contains ( t , w . Body . String ( ) , ` scope":"Ip","simulated":false,"type":"ban","value":"91.121.79.195" ` )
2020-11-30 09:37:17 +00:00
2022-04-27 09:04:12 +00:00
//test since (ok but yields no results)
2022-03-29 12:20:26 +00:00
2022-06-08 14:05:52 +00:00
w = lapi . RecordResponse ( "GET" , "/v1/alerts?since=1ns" , emptyBody , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 200 , w . Code )
assert . Equal ( t , "null" , w . Body . String ( ) )
//test since (invalid value)
2022-03-29 12:20:26 +00:00
2022-06-08 14:05:52 +00:00
w = lapi . RecordResponse ( "GET" , "/v1/alerts?since=1zuzu" , emptyBody , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 500 , w . Code )
assert . Contains ( t , w . Body . String ( ) , ` { "message":"while parsing duration: time: unknown unit ` )
//test until (ok)
2022-03-29 12:20:26 +00:00
2022-06-08 14:05:52 +00:00
w = lapi . RecordResponse ( "GET" , "/v1/alerts?until=1ns" , emptyBody , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 200 , w . Code )
assert . Contains ( t , w . Body . String ( ) , "Ip 91.121.79.195 performed 'crowdsecurity/ssh-bf' (6 events over " )
2021-01-14 15:27:45 +00:00
assert . Contains ( t , w . Body . String ( ) , ` scope":"Ip","simulated":false,"type":"ban","value":"91.121.79.195" ` )
2020-11-30 09:37:17 +00:00
//test until (ok but no return)
2022-03-29 12:20:26 +00:00
2022-06-08 14:05:52 +00:00
w = lapi . RecordResponse ( "GET" , "/v1/alerts?until=1m" , emptyBody , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 200 , w . Code )
assert . Equal ( t , "null" , w . Body . String ( ) )
//test until (invalid value)
2022-03-29 12:20:26 +00:00
2022-06-08 14:05:52 +00:00
w = lapi . RecordResponse ( "GET" , "/v1/alerts?until=1zuzu" , emptyBody , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 500 , w . Code )
assert . Contains ( t , w . Body . String ( ) , ` { "message":"while parsing duration: time: unknown unit ` )
//test simulated (ok)
2022-03-29 12:20:26 +00:00
2022-06-08 14:05:52 +00:00
w = lapi . RecordResponse ( "GET" , "/v1/alerts?simulated=true" , emptyBody , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 200 , w . Code )
assert . Contains ( t , w . Body . String ( ) , "Ip 91.121.79.195 performed 'crowdsecurity/ssh-bf' (6 events over " )
2021-01-14 15:27:45 +00:00
assert . Contains ( t , w . Body . String ( ) , ` scope":"Ip","simulated":false,"type":"ban","value":"91.121.79.195" ` )
2020-11-30 09:37:17 +00:00
//test simulated (ok)
2022-03-29 12:20:26 +00:00
2022-06-08 14:05:52 +00:00
w = lapi . RecordResponse ( "GET" , "/v1/alerts?simulated=false" , emptyBody , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 200 , w . Code )
assert . Contains ( t , w . Body . String ( ) , "Ip 91.121.79.195 performed 'crowdsecurity/ssh-bf' (6 events over " )
2021-01-14 15:27:45 +00:00
assert . Contains ( t , w . Body . String ( ) , ` scope":"Ip","simulated":false,"type":"ban","value":"91.121.79.195" ` )
2020-11-30 09:37:17 +00:00
//test has active decision
2022-03-29 12:20:26 +00:00
2022-06-08 14:05:52 +00:00
w = lapi . RecordResponse ( "GET" , "/v1/alerts?has_active_decision=true" , emptyBody , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 200 , w . Code )
assert . Contains ( t , w . Body . String ( ) , "Ip 91.121.79.195 performed 'crowdsecurity/ssh-bf' (6 events over " )
2021-01-14 15:27:45 +00:00
assert . Contains ( t , w . Body . String ( ) , ` scope":"Ip","simulated":false,"type":"ban","value":"91.121.79.195" ` )
2020-11-30 09:37:17 +00:00
//test has active decision
2022-03-29 12:20:26 +00:00
2022-06-08 14:05:52 +00:00
w = lapi . RecordResponse ( "GET" , "/v1/alerts?has_active_decision=false" , emptyBody , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 200 , w . Code )
assert . Equal ( t , "null" , w . Body . String ( ) )
//test has active decision (invalid value)
2022-03-29 12:20:26 +00:00
2022-06-08 14:05:52 +00:00
w = lapi . RecordResponse ( "GET" , "/v1/alerts?has_active_decision=ratatqata" , emptyBody , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 500 , w . Code )
assert . Equal ( t , ` { "message":"'ratatqata' is not a boolean: strconv.ParseBool: parsing \"ratatqata\": invalid syntax: unable to parse type"} ` , w . Body . String ( ) )
}
func TestAlertBulkInsert ( t * testing . T ) {
2022-03-29 12:20:26 +00:00
lapi := SetupLAPITest ( t )
2020-11-30 09:37:17 +00:00
//insert a bulk of 20 alerts to trigger bulk insert
2022-03-29 12:20:26 +00:00
lapi . InsertAlertFromFile ( "./tests/alert_bulk.json" )
alertContent := GetAlertReaderFromFile ( "./tests/alert_bulk.json" )
2020-11-30 09:37:17 +00:00
2022-06-08 14:05:52 +00:00
w := lapi . RecordResponse ( "GET" , "/v1/alerts" , alertContent , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 200 , w . Code )
}
func TestListAlert ( t * testing . T ) {
2022-03-29 12:20:26 +00:00
lapi := SetupLAPITest ( t )
lapi . InsertAlertFromFile ( "./tests/alert_sample.json" )
2020-11-30 09:37:17 +00:00
// List Alert with invalid filter
2022-03-29 12:20:26 +00:00
2022-06-08 14:05:52 +00:00
w := lapi . RecordResponse ( "GET" , "/v1/alerts?test=test" , emptyBody , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 500 , w . Code )
assert . Equal ( t , "{\"message\":\"Filter parameter 'test' is unknown (=test): invalid filter\"}" , w . Body . String ( ) )
// List Alert
2022-06-08 14:05:52 +00:00
w = lapi . RecordResponse ( "GET" , "/v1/alerts" , emptyBody , "password" )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 200 , w . Code )
assert . Contains ( t , w . Body . String ( ) , "crowdsecurity/test" )
}
func TestCreateAlertErrors ( t * testing . T ) {
2022-03-29 12:20:26 +00:00
lapi := SetupLAPITest ( t )
alertContent := GetAlertReaderFromFile ( "./tests/alert_sample.json" )
2020-11-30 09:37:17 +00:00
//test invalid bearer
w := httptest . NewRecorder ( )
2022-08-16 07:46:10 +00:00
req , _ := http . NewRequest ( http . MethodPost , "/v1/alerts" , alertContent )
2020-11-30 09:37:17 +00:00
req . Header . Add ( "User-Agent" , UserAgent )
req . Header . Add ( "Authorization" , fmt . Sprintf ( "Bearer %s" , "ratata" ) )
2022-03-29 12:20:26 +00:00
lapi . router . ServeHTTP ( w , req )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 401 , w . Code )
//test invalid bearer
w = httptest . NewRecorder ( )
2022-08-16 07:46:10 +00:00
req , _ = http . NewRequest ( http . MethodPost , "/v1/alerts" , alertContent )
2020-11-30 09:37:17 +00:00
req . Header . Add ( "User-Agent" , UserAgent )
2022-03-29 12:20:26 +00:00
req . Header . Add ( "Authorization" , fmt . Sprintf ( "Bearer %s" , lapi . loginResp . Token + "s" ) )
lapi . router . ServeHTTP ( w , req )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 401 , w . Code )
}
func TestDeleteAlert ( t * testing . T ) {
2022-03-29 12:20:26 +00:00
lapi := SetupLAPITest ( t )
lapi . InsertAlertFromFile ( "./tests/alert_sample.json" )
2020-11-30 09:37:17 +00:00
// Fail Delete Alert
2022-03-29 12:20:26 +00:00
w := httptest . NewRecorder ( )
2022-08-16 07:46:10 +00:00
req , _ := http . NewRequest ( http . MethodDelete , "/v1/alerts" , strings . NewReader ( "" ) )
2022-03-29 12:20:26 +00:00
AddAuthHeaders ( req , lapi . loginResp )
2020-11-30 09:37:17 +00:00
req . RemoteAddr = "127.0.0.2:4242"
2022-03-29 12:20:26 +00:00
lapi . router . ServeHTTP ( w , req )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 403 , w . Code )
assert . Equal ( t , ` { "message":"access forbidden from this IP (127.0.0.2)"} ` , w . Body . String ( ) )
// Delete Alert
w = httptest . NewRecorder ( )
2022-08-16 07:46:10 +00:00
req , _ = http . NewRequest ( http . MethodDelete , "/v1/alerts" , strings . NewReader ( "" ) )
2022-03-29 12:20:26 +00:00
AddAuthHeaders ( req , lapi . loginResp )
2020-11-30 09:37:17 +00:00
req . RemoteAddr = "127.0.0.1:4242"
2022-10-19 12:37:27 +00:00
lapi . router . ServeHTTP ( w , req )
assert . Equal ( t , 200 , w . Code )
assert . Equal ( t , ` { "nbDeleted":"1"} ` , w . Body . String ( ) )
}
func TestDeleteAlertByID ( t * testing . T ) {
lapi := SetupLAPITest ( t )
lapi . InsertAlertFromFile ( "./tests/alert_sample.json" )
// Fail Delete Alert
w := httptest . NewRecorder ( )
req , _ := http . NewRequest ( http . MethodDelete , "/v1/alerts/1" , strings . NewReader ( "" ) )
AddAuthHeaders ( req , lapi . loginResp )
req . RemoteAddr = "127.0.0.2:4242"
lapi . router . ServeHTTP ( w , req )
assert . Equal ( t , 403 , w . Code )
assert . Equal ( t , ` { "message":"access forbidden from this IP (127.0.0.2)"} ` , w . Body . String ( ) )
// Delete Alert
w = httptest . NewRecorder ( )
req , _ = http . NewRequest ( http . MethodDelete , "/v1/alerts/1" , strings . NewReader ( "" ) )
AddAuthHeaders ( req , lapi . loginResp )
req . RemoteAddr = "127.0.0.1:4242"
2022-03-29 12:20:26 +00:00
lapi . router . ServeHTTP ( w , req )
2020-11-30 09:37:17 +00:00
assert . Equal ( t , 200 , w . Code )
2020-11-30 15:15:07 +00:00
assert . Equal ( t , ` { "nbDeleted":"1"} ` , w . Body . String ( ) )
2020-11-30 09:37:17 +00:00
}
2022-03-16 16:28:34 +00:00
func TestDeleteAlertTrustedIPS ( t * testing . T ) {
2023-05-25 13:32:32 +00:00
cfg := LoadTestConfig ( t )
2022-03-16 16:28:34 +00:00
// IPv6 mocking doesn't seem to work.
// cfg.API.Server.TrustedIPs = []string{"1.2.3.4", "1.2.4.0/24", "::"}
cfg . API . Server . TrustedIPs = [ ] string { "1.2.3.4" , "1.2.4.0/24" }
cfg . API . Server . ListenURI = "::8080"
server , err := NewServer ( cfg . API . Server )
if err != nil {
2022-06-22 13:53:53 +00:00
log . Fatal ( err )
2022-03-16 16:28:34 +00:00
}
err = server . InitController ( )
if err != nil {
2022-06-22 13:53:53 +00:00
log . Fatal ( err )
2022-03-16 16:28:34 +00:00
}
router , err := server . Router ( )
if err != nil {
2022-06-22 13:53:53 +00:00
log . Fatal ( err )
2022-03-16 16:28:34 +00:00
}
2022-05-17 10:14:59 +00:00
loginResp , err := LoginToTestAPI ( router , cfg )
2022-03-16 16:28:34 +00:00
if err != nil {
2022-06-22 13:53:53 +00:00
log . Fatal ( err )
2022-03-16 16:28:34 +00:00
}
2022-03-29 12:20:26 +00:00
lapi := LAPI {
router : router ,
loginResp : loginResp ,
t : t ,
2022-03-16 16:28:34 +00:00
}
assertAlertDeleteFailedFromIP := func ( ip string ) {
w := httptest . NewRecorder ( )
2022-08-16 07:46:10 +00:00
req , _ := http . NewRequest ( http . MethodDelete , "/v1/alerts" , strings . NewReader ( "" ) )
2022-03-16 16:28:34 +00:00
AddAuthHeaders ( req , loginResp )
req . RemoteAddr = ip + ":1234"
2022-03-29 12:20:26 +00:00
2022-03-16 16:28:34 +00:00
router . ServeHTTP ( w , req )
assert . Equal ( t , 403 , w . Code )
assert . Contains ( t , w . Body . String ( ) , fmt . Sprintf ( ` { "message":"access forbidden from this IP (%s)"} ` , ip ) )
}
assertAlertDeletedFromIP := func ( ip string ) {
w := httptest . NewRecorder ( )
2022-08-16 07:46:10 +00:00
req , _ := http . NewRequest ( http . MethodDelete , "/v1/alerts" , strings . NewReader ( "" ) )
2022-03-16 16:28:34 +00:00
AddAuthHeaders ( req , loginResp )
req . RemoteAddr = ip + ":1234"
2022-03-29 12:20:26 +00:00
2022-03-16 16:28:34 +00:00
router . ServeHTTP ( w , req )
assert . Equal ( t , 200 , w . Code )
assert . Equal ( t , ` { "nbDeleted":"1"} ` , w . Body . String ( ) )
}
2022-03-29 12:20:26 +00:00
lapi . InsertAlertFromFile ( "./tests/alert_sample.json" )
2022-03-16 16:28:34 +00:00
assertAlertDeleteFailedFromIP ( "4.3.2.1" )
assertAlertDeletedFromIP ( "1.2.3.4" )
2022-03-29 12:20:26 +00:00
lapi . InsertAlertFromFile ( "./tests/alert_sample.json" )
2022-03-16 16:28:34 +00:00
assertAlertDeletedFromIP ( "1.2.4.0" )
2022-03-29 12:20:26 +00:00
lapi . InsertAlertFromFile ( "./tests/alert_sample.json" )
2022-03-16 16:28:34 +00:00
assertAlertDeletedFromIP ( "1.2.4.1" )
2022-03-29 12:20:26 +00:00
lapi . InsertAlertFromFile ( "./tests/alert_sample.json" )
2022-03-16 16:28:34 +00:00
assertAlertDeletedFromIP ( "1.2.4.255" )
2022-03-29 12:20:26 +00:00
lapi . InsertAlertFromFile ( "./tests/alert_sample.json" )
2022-03-16 16:28:34 +00:00
assertAlertDeletedFromIP ( "127.0.0.1" )
}