github.com/crowdsecurity/crowdsec@v1.6.1/pkg/cticlient/cti_test.go (about) 1 package cticlient 2 3 // import ( 4 // "encoding/json" 5 // "net/http" 6 // "net/http/httptest" 7 // "net/url" 8 // "strings" 9 // "testing" 10 // "time" 11 12 // "github.com/stretchr/testify/assert" 13 // ) 14 15 // var sampledata = map[string]CTIResponse{ 16 // //1.2.3.4 is a known false positive 17 // "1.2.3.4": { 18 // Ip: "1.2.3.4", 19 // Classifications: CTIClassifications{ 20 // FalsePositives: []CTIClassification{ 21 // { 22 // Name: "example_false_positive", 23 // Label: "Example False Positive", 24 // }, 25 // }, 26 // }, 27 // }, 28 // //1.2.3.5 is a known bad-guy, and part of FIRE 29 // "1.2.3.5": { 30 // Ip: "1.2.3.5", 31 // Classifications: CTIClassifications{ 32 // Classifications: []CTIClassification{ 33 // { 34 // Name: "community-blocklist", 35 // Label: "CrowdSec Community Blocklist", 36 // Description: "IP belong to the CrowdSec Community Blocklist", 37 // }, 38 // }, 39 // }, 40 // }, 41 // //1.2.3.6 is a bad guy (high bg noise), but not in FIRE 42 // "1.2.3.6": { 43 // Ip: "1.2.3.6", 44 // BackgroundNoiseScore: new(int), 45 // Behaviors: []*CTIBehavior{ 46 // {Name: "ssh:bruteforce", Label: "SSH Bruteforce", Description: "SSH Bruteforce"}, 47 // }, 48 // AttackDetails: []*CTIAttackDetails{ 49 // {Name: "crowdsecurity/ssh-bf", Label: "Example Attack"}, 50 // {Name: "crowdsecurity/ssh-slow-bf", Label: "Example Attack"}, 51 // }, 52 // }, 53 // //1.2.3.7 is a ok guy, but part of a bad range 54 // "1.2.3.7": CTIResponse{}, 55 // } 56 57 // func EmptyCTIResponse(ip string) CTIResponse { 58 // return CTIResponse{ 59 // IpRangeScore: 0, 60 // Ip: ip, 61 // Location: CTILocationInfo{}, 62 // } 63 // } 64 65 // /* 66 // TBD : Simulate correctly quotas exhaustion 67 // */ 68 // func setup() (Router *http.ServeMux, serverURL string, teardown func()) { 69 70 // //set static values 71 // *sampledata["1.2.3.6"].BackgroundNoiseScore = 10 72 73 // // mux is the HTTP request multiplexer used with the test server. 74 // Router = http.NewServeMux() 75 // baseURLPath := "/v2" 76 77 // apiHandler := http.NewServeMux() 78 // apiHandler.Handle(baseURLPath+"/", http.StripPrefix(baseURLPath, Router)) 79 80 // // server is a test HTTP server used to provide mock API responses. 81 // server := httptest.NewServer(apiHandler) 82 83 // // let's mock the API endpoints 84 // Router.HandleFunc("/smoke/", func(w http.ResponseWriter, r *http.Request) { 85 // //testMethod(t, r, "GET") 86 // if r.Header.Get("X-Api-Key") != "EXAMPLE_API_KEY" { 87 // w.WriteHeader(http.StatusForbidden) 88 // w.Write([]byte(`{"message":"Forbidden"}`)) 89 // return 90 // } 91 92 // frags := strings.Split(r.RequestURI, "/") 93 // //[empty] [smoke] [v2] [actual_ip] 94 // if len(frags) != 4 { 95 // w.WriteHeader(http.StatusBadRequest) 96 // w.Write([]byte(`{"message":"Bad Request"}`)) 97 // return 98 // } 99 // ip := frags[3] 100 101 // if ip == "" { 102 // //to be fixed to stick w/ real behavior 103 // panic("empty ip") 104 105 // } 106 // // vars := mux.Vars(r) 107 // if v, ok := sampledata[ip]; ok { 108 // data, err := json.Marshal(v) 109 // if err != nil { 110 // panic("unable to marshal") 111 // } 112 // w.WriteHeader(http.StatusOK) 113 // w.Write(data) 114 // return 115 // } 116 // w.WriteHeader(http.StatusOK) 117 // data, err := json.Marshal(EmptyCTIResponse(ip)) 118 // if err != nil { 119 // panic("unable to marshal") 120 // } 121 // w.Write(data) 122 // return 123 // }) 124 // return Router, server.URL, server.Close 125 // } 126 127 // func TestCTIAuthKO(t *testing.T) { 128 129 // _, urlx, teardown := setup() 130 // apiURL, err := url.Parse(urlx + "/") 131 // if err != nil { 132 // t.Fatalf("parsing api url: %s", apiURL) 133 // } 134 135 // defer teardown() 136 // defer ShutdownCTI() 137 // CTIUrl = urlx 138 // key := "BAD_KEY" 139 // if err := InitCTI(&key, nil, nil); err != nil { 140 // t.Fatalf("InitCTI failed: %s", err) 141 // } 142 143 // ret := IpCTI("1.2.3.4") 144 // assert.Equal(t, false, ret.Ok(), "should be ko") 145 // assert.Equal(t, CTIResponse{}, ret, "auth failed, empty answer") 146 // assert.Equal(t, CTIApiEnabled, false, "auth failed, api disabled") 147 // //auth is disabled, we should always receive empty object 148 // ret = IpCTI("1.2.3.4") 149 // assert.Equal(t, false, ret.Ok(), "should be ko") 150 // assert.Equal(t, CTIResponse{}, ret, "auth failed, empty answer") 151 // } 152 153 // func TestCTINoKey(t *testing.T) { 154 155 // _, urlx, teardown := setup() 156 // apiURL, err := url.Parse(urlx + "/") 157 // if err != nil { 158 // t.Fatalf("parsing api url: %s", apiURL) 159 // } 160 161 // defer teardown() 162 // defer ShutdownCTI() 163 // CTIUrl = urlx 164 // //key := "" 165 // err = InitCTI(nil, nil, nil) 166 // assert.NotEqual(t, err, nil, "InitCTI should fail") 167 // ret := IpCTI("1.2.3.4") 168 // assert.Equal(t, false, ret.Ok(), "should be ko") 169 // assert.Equal(t, CTIResponse{}, ret, "auth failed, empty answer") 170 // assert.Equal(t, CTIApiEnabled, false, "auth failed, api disabled") 171 // } 172 173 // func TestCTIAuthOK(t *testing.T) { 174 175 // _, urlx, teardown := setup() 176 // apiURL, err := url.Parse(urlx + "/") 177 // if err != nil { 178 // t.Fatalf("parsing api url: %s", apiURL) 179 // } 180 181 // defer teardown() 182 // defer ShutdownCTI() 183 184 // CTIUrl = urlx 185 // key := "EXAMPLE_API_KEY" 186 // if err := InitCTI(&key, nil, nil); err != nil { 187 // t.Fatalf("InitCTI failed: %s", err) 188 // } 189 190 // ret := IpCTI("1.2.3.4") 191 // assert.Equal(t, true, ret.Ok(), "should be ok") 192 // assert.Equal(t, "1.2.3.4", ret.Ip, "auth failed, empty answer") 193 // assert.Equal(t, CTIApiEnabled, true, "auth failed, api disabled") 194 // } 195 // func TestCTIKnownFP(t *testing.T) { 196 // _, urlx, teardown := setup() 197 // apiURL, err := url.Parse(urlx + "/") 198 // if err != nil { 199 // t.Fatalf("parsing api url: %s", apiURL) 200 // } 201 202 // defer teardown() 203 // defer ShutdownCTI() 204 205 // CTIUrl = urlx 206 // key := "EXAMPLE_API_KEY" 207 // if err := InitCTI(&key, nil, nil); err != nil { 208 // t.Fatalf("InitCTI failed: %s", err) 209 // } 210 211 // ret := IpCTI("1.2.3.4") 212 // assert.Equal(t, true, ret.Ok(), "should be ok") 213 // assert.Equal(t, "1.2.3.4", ret.Ip, "auth failed, empty answer") 214 // assert.Equal(t, ret.IsFalsePositive(), true, "1.2.3.4 is a known false positive") 215 // } 216 217 // func TestCTIBelongsToFire(t *testing.T) { 218 // _, urlx, teardown := setup() 219 // apiURL, err := url.Parse(urlx + "/") 220 // if err != nil { 221 // t.Fatalf("parsing api url: %s", apiURL) 222 // } 223 224 // defer teardown() 225 // defer ShutdownCTI() 226 227 // CTIUrl = urlx 228 // key := "EXAMPLE_API_KEY" 229 // if err := InitCTI(&key, nil, nil); err != nil { 230 // t.Fatalf("InitCTI failed: %s", err) 231 // } 232 233 // ret := IpCTI("1.2.3.5") 234 // assert.Equal(t, true, ret.Ok(), "should be ok") 235 // assert.Equal(t, "1.2.3.5", ret.Ip, "auth failed, empty answer") 236 // assert.Equal(t, ret.IsPartOfCommunityBlocklist(), true, "1.2.3.5 is a known false positive") 237 // } 238 239 // func TestCTIBehaviors(t *testing.T) { 240 // _, urlx, teardown := setup() 241 // apiURL, err := url.Parse(urlx + "/") 242 // if err != nil { 243 // t.Fatalf("parsing api url: %s", apiURL) 244 // } 245 246 // defer teardown() 247 // defer ShutdownCTI() 248 249 // CTIUrl = urlx 250 // key := "EXAMPLE_API_KEY" 251 // if err := InitCTI(&key, nil, nil); err != nil { 252 // t.Fatalf("InitCTI failed: %s", err) 253 // } 254 255 // ret := IpCTI("1.2.3.6") 256 // assert.Equal(t, true, ret.Ok(), "should be ok") 257 // assert.Equal(t, ret.Ip, "1.2.3.6", "auth failed, empty answer") 258 // //ssh:bruteforce 259 // assert.Equal(t, []string{"ssh:bruteforce"}, ret.GetBehaviors(), "error matching behaviors") 260 // assert.Equal(t, []string{"crowdsecurity/ssh-bf", "crowdsecurity/ssh-slow-bf"}, ret.GetAttackDetails(), "error matching behaviors") 261 // assert.Equal(t, 10, ret.GetBackgroundNoiseScore(), "error matching bg noise") 262 // } 263 264 // func TestCacheFetch(t *testing.T) { 265 // _, urlx, teardown := setup() 266 // apiURL, err := url.Parse(urlx + "/") 267 // if err != nil { 268 // t.Fatalf("parsing api url: %s", apiURL) 269 // } 270 271 // defer teardown() 272 // defer ShutdownCTI() 273 274 // CTIUrl = urlx 275 // key := "EXAMPLE_API_KEY" 276 // ttl := 1 * time.Second 277 // if err := InitCTI(&key, &ttl, nil); err != nil { 278 // t.Fatalf("InitCTI failed: %s", err) 279 // } 280 281 // ret := IpCTI("1.2.3.6") 282 // assert.Equal(t, true, ret.Ok(), "should be ok") 283 // assert.Equal(t, "1.2.3.6", ret.Ip, "initial fetch : bad item") 284 // assert.Equal(t, 1, CTICache.Len(true), "initial fetch : bad cache size") 285 // assert.Equal(t, "1.2.3.6", CTICache.Keys(true)[0].(string), "initial fetch : bad cache keys") 286 // //get it a second time before it expires 287 // ret = IpCTI("1.2.3.6") 288 // assert.Equal(t, true, ret.Ok(), "should be ok") 289 // assert.Equal(t, "1.2.3.6", ret.Ip, "initial fetch : bad item") 290 // assert.Equal(t, 1, CTICache.Len(true), "initial fetch : bad cache size") 291 // assert.Equal(t, "1.2.3.6", CTICache.Keys(true)[0].(string), "initial fetch : bad cache keys") 292 // //let data expire 293 // time.Sleep(1 * time.Second) 294 // assert.Equal(t, 0, CTICache.Len(true), "after ttl : bad cache size") 295 // //fetch again 296 // ret = IpCTI("1.2.3.6") 297 // assert.Equal(t, true, ret.Ok(), "should be ok") 298 // assert.Equal(t, "1.2.3.6", ret.Ip, "second fetch : bad item") 299 // assert.Equal(t, 1, CTICache.Len(true), "second fetch : bad cache size") 300 // assert.Equal(t, "1.2.3.6", CTICache.Keys(true)[0].(string), "initial fetch : bad cache keys") 301 // } 302 303 // //GetMaliciousnessScore