bitbucket.org/Aishee/synsec@v0.0.0-20210414005726-236fc01a153d/pkg/apiclient/alerts_service_test.go (about) 1 package apiclient 2 3 import ( 4 "context" 5 "fmt" 6 "net/http" 7 "net/url" 8 "reflect" 9 "testing" 10 11 "bitbucket.org/Aishee/synsec/pkg/cwversion" 12 "bitbucket.org/Aishee/synsec/pkg/models" 13 log "github.com/sirupsen/logrus" 14 "github.com/stretchr/testify/assert" 15 "github.com/stretchr/testify/require" 16 ) 17 18 func TestAlertsListAsMachine(t *testing.T) { 19 log.SetLevel(log.DebugLevel) 20 21 mux, urlx, teardown := setup() 22 mux.HandleFunc("/watchers/login", func(w http.ResponseWriter, r *http.Request) { 23 w.WriteHeader(http.StatusOK) 24 w.Write([]byte(`{"code": 200, "expire": "2030-01-02T15:04:05Z", "token": "oklol"}`)) 25 }) 26 log.Printf("URL is %s", urlx) 27 apiURL, err := url.Parse(urlx + "/") 28 if err != nil { 29 log.Fatalf("parsing api url: %s", apiURL) 30 } 31 client, err := NewClient(&Config{ 32 MachineID: "test_login", 33 Password: "test_password", 34 UserAgent: fmt.Sprintf("synsec/%s", cwversion.VersionStr()), 35 URL: apiURL, 36 VersionPrefix: "v1", 37 }) 38 39 if err != nil { 40 log.Fatalf("new api client: %s", err.Error()) 41 } 42 43 defer teardown() 44 45 mux.HandleFunc("/alerts", func(w http.ResponseWriter, r *http.Request) { 46 47 if r.URL.RawQuery == "ip=1.2.3.4" { 48 testMethod(t, r, "GET") 49 w.WriteHeader(http.StatusOK) 50 fmt.Fprintf(w, `null`) 51 return 52 } 53 54 testMethod(t, r, "GET") 55 w.WriteHeader(http.StatusOK) 56 fmt.Fprint(w, `[ 57 {"capacity":5,"created_at":"2020-11-28T10:20:47+01:00", 58 "decisions":[ 59 {"duration":"59m49.264032632s", 60 "id":1, 61 "origin":"synsec", 62 "scenario":"breakteam/ssh-bf", 63 "scope":"Ip", 64 "simulated":false, 65 "type":"ban", 66 "value":"1.1.1.172"} 67 ], 68 "events":[ 69 {"meta":[ 70 {"key":"target_user","value":"netflix"}, 71 {"key":"service","value":"ssh"} 72 ], 73 "timestamp":"2020-11-28 10:20:46 +0000 UTC"}, 74 {"meta":[ 75 {"key":"target_user","value":"netflix"}, 76 {"key":"service","value":"ssh"} 77 ], 78 "timestamp":"2020-11-28 10:20:46 +0000 UTC"} 79 ], 80 "events_count":6, 81 "id":1, 82 "labels":null, 83 "leakspeed":"10s", 84 "machine_id":"test", 85 "message":"Ip 1.1.1.172 performed 'breakteam/ssh-bf' (6 events over 2.920062ms) at 2020-11-28 10:20:46.845619968 +0100 CET m=+5.903899761", 86 "scenario":"breakteam/ssh-bf", 87 "scenario_hash":"4441dcff07020f6690d998b7101e642359ba405c2abb83565bbbdcee36de280f", 88 "scenario_version":"0.1", 89 "simulated":false, 90 "source":{ 91 "as_name":"Cloudflare Inc", 92 "cn":"AU", 93 "ip":"1.1.1.172", 94 "latitude":-37.7, 95 "longitude":145.1833, 96 "range":"1.1.1.0/24", 97 "scope":"Ip", 98 "value":"1.1.1.172" 99 }, 100 "start_at":"2020-11-28 10:20:46.842701127 +0100 +0100", 101 "stop_at":"2020-11-28 10:20:46.845621385 +0100 +0100" 102 } 103 ]`) 104 }) 105 106 tcapacity := int32(5) 107 tduration := "59m49.264032632s" 108 torigin := "synsec" 109 tscenario := "breakteam/ssh-bf" 110 tscope := "Ip" 111 ttype := "ban" 112 tvalue := "1.1.1.172" 113 ttimestamp := "2020-11-28 10:20:46 +0000 UTC" 114 teventscount := int32(6) 115 tleakspeed := "10s" 116 tmessage := "Ip 1.1.1.172 performed 'breakteam/ssh-bf' (6 events over 2.920062ms) at 2020-11-28 10:20:46.845619968 +0100 CET m=+5.903899761" 117 tscenariohash := "4441dcff07020f6690d998b7101e642359ba405c2abb83565bbbdcee36de280f" 118 tscenarioversion := "0.1" 119 tstartat := "2020-11-28 10:20:46.842701127 +0100 +0100" 120 tstopat := "2020-11-28 10:20:46.845621385 +0100 +0100" 121 122 expected := models.GetAlertsResponse{ 123 &models.Alert{ 124 Capacity: &tcapacity, 125 CreatedAt: "2020-11-28T10:20:47+01:00", 126 Decisions: []*models.Decision{ 127 &models.Decision{ 128 Duration: &tduration, 129 ID: 1, 130 Origin: &torigin, 131 Scenario: &tscenario, 132 133 Scope: &tscope, 134 Simulated: new(bool), //false, 135 Type: &ttype, 136 Value: &tvalue, 137 }, 138 }, 139 Events: []*models.Event{ 140 &models.Event{ 141 Meta: models.Meta{ 142 &models.MetaItems0{ 143 Key: "target_user", 144 Value: "netflix", 145 }, 146 &models.MetaItems0{ 147 Key: "service", 148 Value: "ssh", 149 }, 150 }, 151 Timestamp: &ttimestamp, 152 }, 153 &models.Event{ 154 Meta: models.Meta{ 155 &models.MetaItems0{ 156 Key: "target_user", 157 Value: "netflix", 158 }, 159 &models.MetaItems0{ 160 Key: "service", 161 Value: "ssh", 162 }, 163 }, 164 Timestamp: &ttimestamp, 165 }, 166 }, 167 EventsCount: &teventscount, 168 ID: 1, 169 Leakspeed: &tleakspeed, 170 MachineID: "test", 171 Message: &tmessage, 172 Remediation: false, 173 Scenario: &tscenario, 174 ScenarioHash: &tscenariohash, 175 ScenarioVersion: &tscenarioversion, 176 Simulated: new(bool), //(false), 177 Source: &models.Source{ 178 AsName: "Cloudflare Inc", 179 AsNumber: "", 180 Cn: "AU", 181 IP: "1.1.1.172", 182 Latitude: -37.7, 183 Longitude: 145.1833, 184 Range: "1.1.1.0/24", 185 Scope: &tscope, 186 Value: &tvalue, 187 }, 188 StartAt: &tstartat, 189 StopAt: &tstopat, 190 }, 191 } 192 193 //log.Debugf("data : -> %s", spew.Sdump(alerts)) 194 //log.Debugf("resp : -> %s", spew.Sdump(resp)) 195 //log.Debugf("expected : -> %s", spew.Sdump(expected)) 196 //first one returns data 197 alerts, resp, err := client.Alerts.List(context.Background(), AlertsListOpts{}) 198 if err != nil { 199 log.Errorf("test Unable to list alerts : %+v", err) 200 } 201 if resp.Response.StatusCode != http.StatusOK { 202 t.Errorf("Alerts.List returned status: %d, want %d", resp.Response.StatusCode, http.StatusOK) 203 } 204 205 if !reflect.DeepEqual(*alerts, expected) { 206 t.Errorf("client.Alerts.List returned %+v, want %+v", resp, expected) 207 } 208 //this one doesn't 209 filter := AlertsListOpts{IPEquals: new(string)} 210 *filter.IPEquals = "1.2.3.4" 211 alerts, resp, err = client.Alerts.List(context.Background(), filter) 212 if err != nil { 213 log.Errorf("test Unable to list alerts : %+v", err) 214 } 215 if resp.Response.StatusCode != http.StatusOK { 216 t.Errorf("Alerts.List returned status: %d, want %d", resp.Response.StatusCode, http.StatusOK) 217 } 218 assert.Equal(t, 0, len(*alerts)) 219 } 220 221 func TestAlertsGetAsMachine(t *testing.T) { 222 log.SetLevel(log.DebugLevel) 223 224 mux, urlx, teardown := setup() 225 mux.HandleFunc("/watchers/login", func(w http.ResponseWriter, r *http.Request) { 226 w.WriteHeader(http.StatusOK) 227 w.Write([]byte(`{"code": 200, "expire": "2030-01-02T15:04:05Z", "token": "oklol"}`)) 228 }) 229 log.Printf("URL is %s", urlx) 230 apiURL, err := url.Parse(urlx + "/") 231 if err != nil { 232 log.Fatalf("parsing api url: %s", apiURL) 233 } 234 client, err := NewClient(&Config{ 235 MachineID: "test_login", 236 Password: "test_password", 237 UserAgent: fmt.Sprintf("synsec/%s", cwversion.VersionStr()), 238 URL: apiURL, 239 VersionPrefix: "v1", 240 }) 241 242 if err != nil { 243 log.Fatalf("new api client: %s", err.Error()) 244 } 245 246 defer teardown() 247 mux.HandleFunc("/alerts/2", func(w http.ResponseWriter, r *http.Request) { 248 testMethod(t, r, "GET") 249 w.WriteHeader(http.StatusNotFound) 250 fmt.Fprintf(w, `{"message":"object not found"}`) 251 }) 252 253 mux.HandleFunc("/alerts/1", func(w http.ResponseWriter, r *http.Request) { 254 testMethod(t, r, "GET") 255 w.WriteHeader(http.StatusOK) 256 fmt.Fprint(w, `{"capacity":5,"created_at":"2020-11-28T10:20:47+01:00", 257 "decisions":[ 258 {"duration":"59m49.264032632s", 259 "end_ip":16843180, 260 "id":1, 261 "origin":"synsec", 262 "scenario":"breakteam/ssh-bf", 263 "scope":"Ip", 264 "simulated":false, 265 "start_ip":16843180, 266 "type":"ban", 267 "value":"1.1.1.172"} 268 ], 269 "events":[ 270 {"meta":[ 271 {"key":"target_user","value":"netflix"}, 272 {"key":"service","value":"ssh"} 273 ], 274 "timestamp":"2020-11-28 10:20:46 +0000 UTC"}, 275 {"meta":[ 276 {"key":"target_user","value":"netflix"}, 277 {"key":"service","value":"ssh"} 278 ], 279 "timestamp":"2020-11-28 10:20:46 +0000 UTC"} 280 ], 281 "events_count":6, 282 "id":1, 283 "labels":null, 284 "leakspeed":"10s", 285 "machine_id":"test", 286 "message":"Ip 1.1.1.172 performed 'breakteam/ssh-bf' (6 events over 2.920062ms) at 2020-11-28 10:20:46.845619968 +0100 CET m=+5.903899761", 287 "scenario":"breakteam/ssh-bf", 288 "scenario_hash":"4441dcff07020f6690d998b7101e642359ba405c2abb83565bbbdcee36de280f", 289 "scenario_version":"0.1", 290 "simulated":false, 291 "source":{ 292 "as_name":"Cloudflare Inc", 293 "cn":"AU", 294 "ip":"1.1.1.172", 295 "latitude":-37.7, 296 "longitude":145.1833, 297 "range":"1.1.1.0/24", 298 "scope":"Ip", 299 "value":"1.1.1.172" 300 }, 301 "start_at":"2020-11-28 10:20:46.842701127 +0100 +0100", 302 "stop_at":"2020-11-28 10:20:46.845621385 +0100 +0100" 303 }`) 304 }) 305 306 tcapacity := int32(5) 307 tduration := "59m49.264032632s" 308 torigin := "synsec" 309 tscenario := "breakteam/ssh-bf" 310 tscope := "Ip" 311 ttype := "ban" 312 tvalue := "1.1.1.172" 313 ttimestamp := "2020-11-28 10:20:46 +0000 UTC" 314 teventscount := int32(6) 315 tleakspeed := "10s" 316 tmessage := "Ip 1.1.1.172 performed 'breakteam/ssh-bf' (6 events over 2.920062ms) at 2020-11-28 10:20:46.845619968 +0100 CET m=+5.903899761" 317 tscenariohash := "4441dcff07020f6690d998b7101e642359ba405c2abb83565bbbdcee36de280f" 318 tscenarioversion := "0.1" 319 tstartat := "2020-11-28 10:20:46.842701127 +0100 +0100" 320 tstopat := "2020-11-28 10:20:46.845621385 +0100 +0100" 321 322 expected := &models.Alert{ 323 Capacity: &tcapacity, 324 CreatedAt: "2020-11-28T10:20:47+01:00", 325 Decisions: []*models.Decision{ 326 &models.Decision{ 327 Duration: &tduration, 328 ID: 1, 329 Origin: &torigin, 330 Scenario: &tscenario, 331 332 Scope: &tscope, 333 Simulated: new(bool), //false, 334 Type: &ttype, 335 Value: &tvalue, 336 }, 337 }, 338 Events: []*models.Event{ 339 &models.Event{ 340 Meta: models.Meta{ 341 &models.MetaItems0{ 342 Key: "target_user", 343 Value: "netflix", 344 }, 345 &models.MetaItems0{ 346 Key: "service", 347 Value: "ssh", 348 }, 349 }, 350 Timestamp: &ttimestamp, 351 }, 352 &models.Event{ 353 Meta: models.Meta{ 354 &models.MetaItems0{ 355 Key: "target_user", 356 Value: "netflix", 357 }, 358 &models.MetaItems0{ 359 Key: "service", 360 Value: "ssh", 361 }, 362 }, 363 Timestamp: &ttimestamp, 364 }, 365 }, 366 EventsCount: &teventscount, 367 ID: 1, 368 Leakspeed: &tleakspeed, 369 MachineID: "test", 370 Message: &tmessage, 371 Remediation: false, 372 Scenario: &tscenario, 373 ScenarioHash: &tscenariohash, 374 ScenarioVersion: &tscenarioversion, 375 Simulated: new(bool), //(false), 376 Source: &models.Source{ 377 AsName: "Cloudflare Inc", 378 AsNumber: "", 379 Cn: "AU", 380 IP: "1.1.1.172", 381 Latitude: -37.7, 382 Longitude: 145.1833, 383 Range: "1.1.1.0/24", 384 Scope: &tscope, 385 Value: &tvalue, 386 }, 387 StartAt: &tstartat, 388 StopAt: &tstopat, 389 } 390 391 alerts, resp, err := client.Alerts.GetByID(context.Background(), 1) 392 require.NoError(t, err) 393 if resp.Response.StatusCode != http.StatusOK { 394 t.Errorf("Alerts.List returned status: %d, want %d", resp.Response.StatusCode, http.StatusOK) 395 } 396 397 if !reflect.DeepEqual(*alerts, *expected) { 398 t.Errorf("client.Alerts.List returned %+v, want %+v", resp, expected) 399 } 400 401 //fail 402 alerts, resp, err = client.Alerts.GetByID(context.Background(), 2) 403 assert.Contains(t, fmt.Sprintf("%s", err), "API error: object not found") 404 405 } 406 407 func TestAlertsCreateAsMachine(t *testing.T) { 408 log.SetLevel(log.DebugLevel) 409 410 mux, urlx, teardown := setup() 411 mux.HandleFunc("/watchers/login", func(w http.ResponseWriter, r *http.Request) { 412 w.WriteHeader(http.StatusOK) 413 w.Write([]byte(`{"code": 200, "expire": "2030-01-02T15:04:05Z", "token": "oklol"}`)) 414 }) 415 mux.HandleFunc("/alerts", func(w http.ResponseWriter, r *http.Request) { 416 testMethod(t, r, "POST") 417 w.WriteHeader(http.StatusOK) 418 w.Write([]byte(`["3"]`)) 419 }) 420 log.Printf("URL is %s", urlx) 421 apiURL, err := url.Parse(urlx + "/") 422 if err != nil { 423 log.Fatalf("parsing api url: %s", apiURL) 424 } 425 client, err := NewClient(&Config{ 426 MachineID: "test_login", 427 Password: "test_password", 428 UserAgent: fmt.Sprintf("synsec/%s", cwversion.VersionStr()), 429 URL: apiURL, 430 VersionPrefix: "v1", 431 }) 432 433 if err != nil { 434 log.Fatalf("new api client: %s", err.Error()) 435 } 436 437 defer teardown() 438 alert := models.AddAlertsRequest{} 439 alerts, resp, err := client.Alerts.Add(context.Background(), alert) 440 require.NoError(t, err) 441 expected := &models.AddAlertsResponse{"3"} 442 if resp.Response.StatusCode != http.StatusOK { 443 t.Errorf("Alerts.List returned status: %d, want %d", resp.Response.StatusCode, http.StatusOK) 444 } 445 if !reflect.DeepEqual(*alerts, *expected) { 446 t.Errorf("client.Alerts.List returned %+v, want %+v", resp, expected) 447 } 448 } 449 450 func TestAlertsDeleteAsMachine(t *testing.T) { 451 log.SetLevel(log.DebugLevel) 452 453 mux, urlx, teardown := setup() 454 mux.HandleFunc("/watchers/login", func(w http.ResponseWriter, r *http.Request) { 455 w.WriteHeader(http.StatusOK) 456 w.Write([]byte(`{"code": 200, "expire": "2030-01-02T15:04:05Z", "token": "oklol"}`)) 457 }) 458 mux.HandleFunc("/alerts", func(w http.ResponseWriter, r *http.Request) { 459 testMethod(t, r, "DELETE") 460 assert.Equal(t, r.URL.RawQuery, "ip=1.2.3.4") 461 w.WriteHeader(http.StatusOK) 462 w.Write([]byte(`{"message":"0 deleted alerts"}`)) 463 }) 464 log.Printf("URL is %s", urlx) 465 apiURL, err := url.Parse(urlx + "/") 466 if err != nil { 467 log.Fatalf("parsing api url: %s", apiURL) 468 } 469 client, err := NewClient(&Config{ 470 MachineID: "test_login", 471 Password: "test_password", 472 UserAgent: fmt.Sprintf("synsec/%s", cwversion.VersionStr()), 473 URL: apiURL, 474 VersionPrefix: "v1", 475 }) 476 477 if err != nil { 478 log.Fatalf("new api client: %s", err.Error()) 479 } 480 481 defer teardown() 482 alert := AlertsDeleteOpts{IPEquals: new(string)} 483 *alert.IPEquals = "1.2.3.4" 484 alerts, resp, err := client.Alerts.Delete(context.Background(), alert) 485 require.NoError(t, err) 486 487 expected := &models.DeleteAlertsResponse{""} 488 if resp.Response.StatusCode != http.StatusOK { 489 t.Errorf("Alerts.List returned status: %d, want %d", resp.Response.StatusCode, http.StatusOK) 490 } 491 if !reflect.DeepEqual(*alerts, *expected) { 492 t.Errorf("client.Alerts.List returned %+v, want %+v", resp, expected) 493 } 494 }