123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429 |
- package apiserver
- import (
- "testing"
- "github.com/stretchr/testify/assert"
- )
- func TestDeleteDecisionRange(t *testing.T) {
- lapi := SetupLAPITest(t)
- // Create Valid Alert
- lapi.InsertAlertFromFile("./tests/alert_minibulk.json")
- // delete by ip wrong
- w := lapi.RecordResponse("DELETE", "/v1/decisions?range=1.2.3.0/24", emptyBody)
- assert.Equal(t, 200, w.Code)
- assert.Equal(t, `{"nbDeleted":"0"}`, w.Body.String())
- // delete by range
- w = lapi.RecordResponse("DELETE", "/v1/decisions?range=91.121.79.0/24&contains=false", emptyBody)
- assert.Equal(t, 200, w.Code)
- assert.Equal(t, `{"nbDeleted":"2"}`, w.Body.String())
- // delete by range : ensure it was already deleted
- w = lapi.RecordResponse("DELETE", "/v1/decisions?range=91.121.79.0/24", emptyBody)
- assert.Equal(t, 200, w.Code)
- assert.Equal(t, `{"nbDeleted":"0"}`, w.Body.String())
- }
- func TestDeleteDecisionFilter(t *testing.T) {
- lapi := SetupLAPITest(t)
- // Create Valid Alert
- lapi.InsertAlertFromFile("./tests/alert_minibulk.json")
- // delete by ip wrong
- w := lapi.RecordResponse("DELETE", "/v1/decisions?ip=1.2.3.4", emptyBody)
- assert.Equal(t, 200, w.Code)
- assert.Equal(t, `{"nbDeleted":"0"}`, w.Body.String())
- // delete by ip good
- w = lapi.RecordResponse("DELETE", "/v1/decisions?ip=91.121.79.179", emptyBody)
- assert.Equal(t, 200, w.Code)
- assert.Equal(t, `{"nbDeleted":"1"}`, w.Body.String())
- // delete by scope/value
- w = lapi.RecordResponse("DELETE", "/v1/decisions?scopes=Ip&value=91.121.79.178", emptyBody)
- assert.Equal(t, 200, w.Code)
- assert.Equal(t, `{"nbDeleted":"1"}`, w.Body.String())
- }
- func TestGetDecisionFilters(t *testing.T) {
- lapi := SetupLAPITest(t)
- // Create Valid Alert
- lapi.InsertAlertFromFile("./tests/alert_minibulk.json")
- // Get Decision
- w := lapi.RecordResponse("GET", "/v1/decisions", emptyBody)
- assert.Equal(t, 200, w.Code)
- decisions, code, err := readDecisionsGetResp(w)
- assert.Nil(t, err)
- assert.Equal(t, 200, code)
- assert.Equal(t, 2, len(decisions))
- assert.Equal(t, "crowdsecurity/ssh-bf", *decisions[0].Scenario)
- assert.Equal(t, "91.121.79.179", *decisions[0].Value)
- assert.Equal(t, int64(1), decisions[0].ID)
- assert.Equal(t, "crowdsecurity/ssh-bf", *decisions[1].Scenario)
- assert.Equal(t, "91.121.79.178", *decisions[1].Value)
- assert.Equal(t, int64(2), decisions[1].ID)
- // Get Decision : type filter
- w = lapi.RecordResponse("GET", "/v1/decisions?type=ban", emptyBody)
- assert.Equal(t, 200, w.Code)
- decisions, code, err = readDecisionsGetResp(w)
- assert.Nil(t, err)
- assert.Equal(t, 200, code)
- assert.Equal(t, 2, len(decisions))
- assert.Equal(t, "crowdsecurity/ssh-bf", *decisions[0].Scenario)
- assert.Equal(t, "91.121.79.179", *decisions[0].Value)
- assert.Equal(t, int64(1), decisions[0].ID)
- assert.Equal(t, "crowdsecurity/ssh-bf", *decisions[1].Scenario)
- assert.Equal(t, "91.121.79.178", *decisions[1].Value)
- assert.Equal(t, int64(2), decisions[1].ID)
- // assert.Contains(t, w.Body.String(), `"id":1,"origin":"crowdsec","scenario":"crowdsecurity/ssh-bf","scope":"Ip","type":"ban","value":"91.121.79.179"`)
- // assert.Contains(t, w.Body.String(), `"id":2,"origin":"crowdsec","scenario":"crowdsecurity/ssh-bf","scope":"Ip","type":"ban","value":"91.121.79.178"`)
- // Get Decision : scope/value
- w = lapi.RecordResponse("GET", "/v1/decisions?scopes=Ip&value=91.121.79.179", emptyBody)
- assert.Equal(t, 200, w.Code)
- decisions, code, err = readDecisionsGetResp(w)
- assert.Nil(t, err)
- assert.Equal(t, 200, code)
- assert.Equal(t, 1, len(decisions))
- assert.Equal(t, "crowdsecurity/ssh-bf", *decisions[0].Scenario)
- assert.Equal(t, "91.121.79.179", *decisions[0].Value)
- assert.Equal(t, int64(1), decisions[0].ID)
- // assert.Contains(t, w.Body.String(), `"id":1,"origin":"crowdsec","scenario":"crowdsecurity/ssh-bf","scope":"Ip","type":"ban","value":"91.121.79.179"`)
- // assert.NotContains(t, w.Body.String(), `"id":2,"origin":"crowdsec","scenario":"crowdsecurity/ssh-bf","scope":"Ip","type":"ban","value":"91.121.79.178"`)
- // Get Decision : ip filter
- w = lapi.RecordResponse("GET", "/v1/decisions?ip=91.121.79.179", emptyBody)
- assert.Equal(t, 200, w.Code)
- decisions, code, err = readDecisionsGetResp(w)
- assert.Nil(t, err)
- assert.Equal(t, 200, code)
- assert.Equal(t, 1, len(decisions))
- assert.Equal(t, "crowdsecurity/ssh-bf", *decisions[0].Scenario)
- assert.Equal(t, "91.121.79.179", *decisions[0].Value)
- assert.Equal(t, int64(1), decisions[0].ID)
- // assert.Contains(t, w.Body.String(), `"id":1,"origin":"crowdsec","scenario":"crowdsecurity/ssh-bf","scope":"Ip","type":"ban","value":"91.121.79.179"`)
- // assert.NotContains(t, w.Body.String(), `"id":2,"origin":"crowdsec","scenario":"crowdsecurity/ssh-bf","scope":"Ip","type":"ban","value":"91.121.79.178"`)
- // Get decision : by range
- w = lapi.RecordResponse("GET", "/v1/decisions?range=91.121.79.0/24&contains=false", emptyBody)
- assert.Equal(t, 200, w.Code)
- decisions, code, err = readDecisionsGetResp(w)
- assert.Nil(t, err)
- assert.Equal(t, 200, code)
- assert.Equal(t, 2, len(decisions))
- assert.Contains(t, []string{*decisions[0].Value, *decisions[1].Value}, "91.121.79.179")
- assert.Contains(t, []string{*decisions[0].Value, *decisions[1].Value}, "91.121.79.178")
- }
- func TestGetDecision(t *testing.T) {
- lapi := SetupLAPITest(t)
- // Create Valid Alert
- lapi.InsertAlertFromFile("./tests/alert_sample.json")
- // Get Decision
- w := lapi.RecordResponse("GET", "/v1/decisions", emptyBody)
- assert.Equal(t, 200, w.Code)
- decisions, code, err := readDecisionsGetResp(w)
- assert.Nil(t, err)
- assert.Equal(t, 200, code)
- assert.Equal(t, 3, len(decisions))
- /*decisions get doesn't perform deduplication*/
- assert.Equal(t, "crowdsecurity/test", *decisions[0].Scenario)
- assert.Equal(t, "127.0.0.1", *decisions[0].Value)
- assert.Equal(t, int64(1), decisions[0].ID)
- assert.Equal(t, "crowdsecurity/test", *decisions[1].Scenario)
- assert.Equal(t, "127.0.0.1", *decisions[1].Value)
- assert.Equal(t, int64(2), decisions[1].ID)
- assert.Equal(t, "crowdsecurity/test", *decisions[2].Scenario)
- assert.Equal(t, "127.0.0.1", *decisions[2].Value)
- assert.Equal(t, int64(3), decisions[2].ID)
- // Get Decision with invalid filter. It should ignore this filter
- w = lapi.RecordResponse("GET", "/v1/decisions?test=test", emptyBody)
- assert.Equal(t, 200, w.Code)
- assert.Equal(t, 3, len(decisions))
- }
- func TestDeleteDecisionByID(t *testing.T) {
- lapi := SetupLAPITest(t)
- // Create Valid Alert
- lapi.InsertAlertFromFile("./tests/alert_sample.json")
- //Have one alerts
- w := lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true", emptyBody)
- decisions, code, err := readDecisionsStreamResp(w)
- assert.Equal(t, err, nil)
- assert.Equal(t, code, 200)
- assert.Equal(t, len(decisions["deleted"]), 0)
- assert.Equal(t, len(decisions["new"]), 1)
- // Delete alert with Invalid ID
- w = lapi.RecordResponse("DELETE", "/v1/decisions/test", emptyBody)
- assert.Equal(t, 400, w.Code)
- err_resp, _, err := readDecisionsErrorResp(w)
- assert.NoError(t, err)
- assert.Equal(t, err_resp["message"], "decision_id must be valid integer")
- // Delete alert with ID that not exist
- w = lapi.RecordResponse("DELETE", "/v1/decisions/100", emptyBody)
- assert.Equal(t, 500, w.Code)
- err_resp, _, err = readDecisionsErrorResp(w)
- assert.NoError(t, err)
- assert.Equal(t, err_resp["message"], "decision with id '100' doesn't exist: unable to delete")
- //Have one alerts
- w = lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true", emptyBody)
- decisions, code, err = readDecisionsStreamResp(w)
- assert.Equal(t, err, nil)
- assert.Equal(t, code, 200)
- assert.Equal(t, len(decisions["deleted"]), 0)
- assert.Equal(t, len(decisions["new"]), 1)
- // Delete alert with valid ID
- w = lapi.RecordResponse("DELETE", "/v1/decisions/1", emptyBody)
- assert.Equal(t, 200, w.Code)
- resp, _, err := readDecisionsDeleteResp(w)
- assert.NoError(t, err)
- assert.Equal(t, resp.NbDeleted, "1")
- //Have one alert (because we delete an alert that has dup targets)
- w = lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true", emptyBody)
- decisions, code, err = readDecisionsStreamResp(w)
- assert.Equal(t, err, nil)
- assert.Equal(t, code, 200)
- assert.Equal(t, len(decisions["deleted"]), 0)
- assert.Equal(t, len(decisions["new"]), 1)
- }
- func TestDeleteDecision(t *testing.T) {
- lapi := SetupLAPITest(t)
- // Create Valid Alert
- lapi.InsertAlertFromFile("./tests/alert_sample.json")
- // Delete alert with Invalid filter
- w := lapi.RecordResponse("DELETE", "/v1/decisions?test=test", emptyBody)
- assert.Equal(t, 500, w.Code)
- err_resp, _, err := readDecisionsErrorResp(w)
- assert.NoError(t, err)
- assert.Equal(t, err_resp["message"], "'test' doesn't exist: invalid filter")
- // Delete all alert
- w = lapi.RecordResponse("DELETE", "/v1/decisions", emptyBody)
- assert.Equal(t, 200, w.Code)
- resp, _, err := readDecisionsDeleteResp(w)
- assert.NoError(t, err)
- assert.Equal(t, resp.NbDeleted, "3")
- }
- func TestStreamStartDecisionDedup(t *testing.T) {
- //Ensure that at stream startup we only get the longest decision
- lapi := SetupLAPITest(t)
- // Create Valid Alert : 3 decisions for 127.0.0.1, longest has id=3
- lapi.InsertAlertFromFile("./tests/alert_sample.json")
- // Get Stream, we only get one decision (the longest one)
- w := lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true", emptyBody)
- decisions, code, err := readDecisionsStreamResp(w)
- assert.Equal(t, err, nil)
- assert.Equal(t, code, 200)
- assert.Equal(t, len(decisions["deleted"]), 0)
- assert.Equal(t, len(decisions["new"]), 1)
- assert.Equal(t, decisions["new"][0].ID, int64(3))
- assert.Equal(t, *decisions["new"][0].Origin, "test")
- assert.Equal(t, *decisions["new"][0].Value, "127.0.0.1")
- // id=3 decision is deleted, this won't affect `deleted`, because there are decisions on the same ip
- w = lapi.RecordResponse("DELETE", "/v1/decisions/3", emptyBody)
- assert.Equal(t, 200, w.Code)
- // Get Stream, we only get one decision (the longest one, id=2)
- w = lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true", emptyBody)
- decisions, code, err = readDecisionsStreamResp(w)
- assert.Equal(t, err, nil)
- assert.Equal(t, code, 200)
- assert.Equal(t, len(decisions["deleted"]), 0)
- assert.Equal(t, len(decisions["new"]), 1)
- assert.Equal(t, decisions["new"][0].ID, int64(2))
- assert.Equal(t, *decisions["new"][0].Origin, "test")
- assert.Equal(t, *decisions["new"][0].Value, "127.0.0.1")
- // We delete another decision, yet don't receive it in stream, since there's another decision on same IP
- w = lapi.RecordResponse("DELETE", "/v1/decisions/2", emptyBody)
- assert.Equal(t, 200, w.Code)
- // And get the remaining decision (1)
- w = lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true", emptyBody)
- decisions, code, err = readDecisionsStreamResp(w)
- assert.Equal(t, err, nil)
- assert.Equal(t, code, 200)
- assert.Equal(t, len(decisions["deleted"]), 0)
- assert.Equal(t, len(decisions["new"]), 1)
- assert.Equal(t, decisions["new"][0].ID, int64(1))
- assert.Equal(t, *decisions["new"][0].Origin, "test")
- assert.Equal(t, *decisions["new"][0].Value, "127.0.0.1")
- // We delete the last decision, we receive the delete order
- w = lapi.RecordResponse("DELETE", "/v1/decisions/1", emptyBody)
- assert.Equal(t, 200, w.Code)
- //and now we only get a deleted decision
- w = lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true", emptyBody)
- decisions, code, err = readDecisionsStreamResp(w)
- assert.Equal(t, err, nil)
- assert.Equal(t, code, 200)
- assert.Equal(t, len(decisions["deleted"]), 1)
- assert.Equal(t, decisions["deleted"][0].ID, int64(1))
- assert.Equal(t, *decisions["deleted"][0].Origin, "test")
- assert.Equal(t, *decisions["deleted"][0].Value, "127.0.0.1")
- assert.Equal(t, len(decisions["new"]), 0)
- }
- func TestStreamDecisionDedup(t *testing.T) {
- //Ensure that at stream startup we only get the longest decision
- lapi := SetupLAPITest(t)
- // Create Valid Alert : 3 decisions for 127.0.0.1, longest has id=3
- lapi.InsertAlertFromFile("./tests/alert_sample.json")
- // Get Stream, we only get one decision (the longest one)
- w := lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true", emptyBody)
- decisions, code, err := readDecisionsStreamResp(w)
- assert.Equal(t, err, nil)
- assert.Equal(t, code, 200)
- assert.Equal(t, len(decisions["deleted"]), 0)
- assert.Equal(t, len(decisions["new"]), 1)
- assert.Equal(t, decisions["new"][0].ID, int64(3))
- assert.Equal(t, *decisions["new"][0].Origin, "test")
- assert.Equal(t, *decisions["new"][0].Value, "127.0.0.1")
- // id=3 decision is deleted, this won't affect `deleted`, because there are decisions on the same ip
- w = lapi.RecordResponse("DELETE", "/v1/decisions/3", emptyBody)
- assert.Equal(t, 200, w.Code)
- w = lapi.RecordResponse("GET", "/v1/decisions/stream", emptyBody)
- assert.Equal(t, err, nil)
- decisions, code, err = readDecisionsStreamResp(w)
- assert.Equal(t, err, nil)
- assert.Equal(t, code, 200)
- assert.Equal(t, len(decisions["deleted"]), 0)
- assert.Equal(t, len(decisions["new"]), 0)
- // We delete another decision, yet don't receive it in stream, since there's another decision on same IP
- w = lapi.RecordResponse("DELETE", "/v1/decisions/2", emptyBody)
- assert.Equal(t, 200, w.Code)
- w = lapi.RecordResponse("GET", "/v1/decisions/stream", emptyBody)
- decisions, code, err = readDecisionsStreamResp(w)
- assert.Equal(t, err, nil)
- assert.Equal(t, code, 200)
- assert.Equal(t, len(decisions["deleted"]), 0)
- assert.Equal(t, len(decisions["new"]), 0)
- // We delete the last decision, we receive the delete order
- w = lapi.RecordResponse("DELETE", "/v1/decisions/1", emptyBody)
- assert.Equal(t, 200, w.Code)
- w = lapi.RecordResponse("GET", "/v1/decisions/stream", emptyBody)
- decisions, code, err = readDecisionsStreamResp(w)
- assert.Equal(t, err, nil)
- assert.Equal(t, code, 200)
- assert.Equal(t, len(decisions["deleted"]), 1)
- assert.Equal(t, decisions["deleted"][0].ID, int64(1))
- assert.Equal(t, *decisions["deleted"][0].Origin, "test")
- assert.Equal(t, *decisions["deleted"][0].Value, "127.0.0.1")
- assert.Equal(t, len(decisions["new"]), 0)
- }
- func TestStreamDecisionFilters(t *testing.T) {
- lapi := SetupLAPITest(t)
- // Create Valid Alert
- lapi.InsertAlertFromFile("./tests/alert_stream_fixture.json")
- w := lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true", emptyBody)
- decisions, code, err := readDecisionsStreamResp(w)
- assert.Equal(t, 200, code)
- assert.Equal(t, err, nil)
- assert.Equal(t, len(decisions["deleted"]), 0)
- assert.Equal(t, len(decisions["new"]), 3)
- assert.Equal(t, decisions["new"][0].ID, int64(1))
- assert.Equal(t, *decisions["new"][0].Origin, "test1")
- assert.Equal(t, *decisions["new"][0].Value, "127.0.0.1")
- assert.Equal(t, *decisions["new"][0].Scenario, "crowdsecurity/http_bf")
- assert.Equal(t, decisions["new"][1].ID, int64(2))
- assert.Equal(t, *decisions["new"][1].Origin, "test2")
- assert.Equal(t, *decisions["new"][1].Value, "127.0.0.1")
- assert.Equal(t, *decisions["new"][1].Scenario, "crowdsecurity/ssh_bf")
- assert.Equal(t, decisions["new"][2].ID, int64(3))
- assert.Equal(t, *decisions["new"][2].Origin, "test3")
- assert.Equal(t, *decisions["new"][2].Value, "127.0.0.1")
- assert.Equal(t, *decisions["new"][2].Scenario, "crowdsecurity/ddos")
- // test filter scenarios_not_containing
- w = lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true&scenarios_not_containing=http", emptyBody)
- decisions, code, err = readDecisionsStreamResp(w)
- assert.Equal(t, err, nil)
- assert.Equal(t, 200, code)
- assert.Equal(t, len(decisions["deleted"]), 0)
- assert.Equal(t, len(decisions["new"]), 2)
- assert.Equal(t, decisions["new"][0].ID, int64(2))
- assert.Equal(t, decisions["new"][1].ID, int64(3))
- // test filter scenarios_containing
- w = lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true&scenarios_containing=http", emptyBody)
- decisions, code, err = readDecisionsStreamResp(w)
- assert.Equal(t, err, nil)
- assert.Equal(t, 200, code)
- assert.Equal(t, len(decisions["deleted"]), 0)
- assert.Equal(t, len(decisions["new"]), 1)
- assert.Equal(t, decisions["new"][0].ID, int64(1))
- // test filters both by scenarios_not_containing and scenarios_containing
- w = lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true&scenarios_not_containing=ssh&scenarios_containing=ddos", emptyBody)
- decisions, code, err = readDecisionsStreamResp(w)
- assert.Equal(t, err, nil)
- assert.Equal(t, 200, code)
- assert.Equal(t, len(decisions["deleted"]), 0)
- assert.Equal(t, len(decisions["new"]), 1)
- assert.Equal(t, decisions["new"][0].ID, int64(3))
- // test filter by origin
- w = lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true&origins=test1,test2", emptyBody)
- decisions, code, err = readDecisionsStreamResp(w)
- assert.Equal(t, err, nil)
- assert.Equal(t, 200, code)
- assert.Equal(t, len(decisions["deleted"]), 0)
- assert.Equal(t, len(decisions["new"]), 2)
- assert.Equal(t, decisions["new"][0].ID, int64(1))
- assert.Equal(t, decisions["new"][1].ID, int64(2))
- }
|