github.com/fastly/go-fastly@v1.18.0/fastly/waf_test.go (about) 1 package fastly 2 3 import ( 4 "bytes" 5 "io/ioutil" 6 "testing" 7 ) 8 9 func TestClient_WAFs(t *testing.T) { 10 t.Parallel() 11 12 var err error 13 var tv *Version 14 record(t, "wafs/version", func(c *Client) { 15 tv = testVersion(t, c) 16 }) 17 18 // Enable logging on the service - we cannot create wafs without logging 19 // enabled 20 record(t, "wafs/logging/create", func(c *Client) { 21 _, err = c.CreateSyslog(&CreateSyslogInput{ 22 Service: testServiceID, 23 Version: tv.Number, 24 Name: "test-syslog", 25 Address: "example.com", 26 Hostname: "example.com", 27 Port: 1234, 28 Token: "abcd1234", 29 Format: "format", 30 FormatVersion: 2, 31 MessageType: "classic", 32 }) 33 }) 34 if err != nil { 35 t.Fatal(err) 36 } 37 defer func() { 38 record(t, "wafs/logging/cleanup", func(c *Client) { 39 c.DeleteSyslog(&DeleteSyslogInput{ 40 Service: testServiceID, 41 Version: tv.Number, 42 Name: "test-syslog", 43 }) 44 }) 45 }() 46 47 // Create a condition - we cannot create a waf without attaching a condition 48 var condition *Condition 49 record(t, "wafs/condition/create", func(c *Client) { 50 condition, err = c.CreateCondition(&CreateConditionInput{ 51 Service: testServiceID, 52 Version: tv.Number, 53 Name: "test-waf-condition", 54 Statement: "req.url~+\"index.html\"", 55 Type: "PREFETCH", // This must be a prefetch condition 56 Priority: 1, 57 }) 58 }) 59 if err != nil { 60 t.Fatal(err) 61 } 62 defer func() { 63 record(t, "wafs/condition/cleanup", func(c *Client) { 64 c.DeleteCondition(&DeleteConditionInput{ 65 Service: testServiceID, 66 Version: tv.Number, 67 Name: "test-waf-condition", 68 }) 69 }) 70 }() 71 72 // Create a response object 73 var ro *ResponseObject 74 record(t, "wafs/response_object/create", func(c *Client) { 75 ro, err = c.CreateResponseObject(&CreateResponseObjectInput{ 76 Service: testServiceID, 77 Version: tv.Number, 78 Name: "test-response-object", 79 Status: 200, 80 Response: "Ok", 81 Content: "abcd", 82 ContentType: "text/plain", 83 }) 84 }) 85 if err != nil { 86 t.Fatal(err) 87 } 88 defer func() { 89 record(t, "wafs/response_object/cleanup", func(c *Client) { 90 c.DeleteResponseObject(&DeleteResponseObjectInput{ 91 Service: testServiceID, 92 Version: tv.Number, 93 Name: ro.Name, 94 }) 95 }) 96 }() 97 98 // Create 99 var waf *WAF 100 record(t, "wafs/create", func(c *Client) { 101 waf, err = c.CreateWAF(&CreateWAFInput{ 102 Service: testServiceID, 103 Version: tv.Number, 104 PrefetchCondition: condition.Name, 105 Response: ro.Name, 106 }) 107 }) 108 if err != nil { 109 t.Fatal(err) 110 } 111 112 // List 113 var wafs []*WAF 114 record(t, "wafs/list", func(c *Client) { 115 wafs, err = c.ListWAFs(&ListWAFsInput{ 116 Service: testServiceID, 117 Version: tv.Number, 118 }) 119 }) 120 if err != nil { 121 t.Fatal(err) 122 } 123 if len(wafs) < 1 { 124 t.Errorf("bad wafs: %v", wafs) 125 } 126 127 // Ensure deleted 128 defer func() { 129 record(t, "wafs/cleanup", func(c *Client) { 130 c.DeleteWAF(&DeleteWAFInput{ 131 Service: testServiceID, 132 Version: tv.Number, 133 ID: waf.ID, 134 }) 135 }) 136 }() 137 138 // Get 139 var nwaf *WAF 140 record(t, "wafs/get", func(c *Client) { 141 nwaf, err = c.GetWAF(&GetWAFInput{ 142 Service: testServiceID, 143 Version: tv.Number, 144 ID: waf.ID, 145 }) 146 }) 147 if err != nil { 148 t.Fatal(err) 149 } 150 if nwaf.ID != waf.ID { 151 t.Errorf("expected %q to be %q", nwaf.ID, waf.ID) 152 } 153 154 // Get the WAF ruleset 155 var ruleset *Ruleset 156 record(t, "wafs/ruleset/get", func(c *Client) { 157 ruleset, err = c.GetWAFRuleRuleSets(&GetWAFRuleRuleSetsInput{ 158 Service: testServiceID, 159 ID: waf.ID, 160 }) 161 }) 162 if err != nil { 163 t.Fatal(err) 164 } 165 if ruleset.ID != waf.ID { 166 t.Errorf("expected %q to be %q", ruleset.ID, waf.ID) 167 } 168 if ruleset.VCL == "" { 169 t.Error("bad vcl") 170 } 171 if ruleset.LastPush != waf.LastPush { 172 t.Errorf("expected %q to be %q", ruleset.LastPush, waf.LastPush) 173 } 174 if ruleset.Link != "" { 175 t.Error("bad link") 176 } 177 178 // Update 179 // Create a new response object to attach 180 var nro *ResponseObject 181 record(t, "wafs/response_object/create_another", func(c *Client) { 182 nro, err = c.CreateResponseObject(&CreateResponseObjectInput{ 183 Service: testServiceID, 184 Version: tv.Number, 185 Name: "test-response-object-2", 186 Status: 200, 187 Response: "Ok", 188 Content: "efgh", 189 ContentType: "text/plain", 190 }) 191 }) 192 if err != nil { 193 t.Fatal(err) 194 } 195 defer func() { 196 record(t, "wafs/response_object/cleanup_another", func(c *Client) { 197 c.DeleteResponseObject(&DeleteResponseObjectInput{ 198 Service: testServiceID, 199 Version: tv.Number, 200 Name: nro.Name, 201 }) 202 }) 203 }() 204 var uwaf *WAF 205 record(t, "wafs/update", func(c *Client) { 206 uwaf, err = c.UpdateWAF(&UpdateWAFInput{ 207 Service: testServiceID, 208 Version: tv.Number, 209 ID: waf.ID, 210 Response: nro.Name, 211 }) 212 }) 213 if err != nil { 214 t.Fatal(err) 215 } 216 if uwaf.Response != "test-response-object-2" { 217 t.Errorf("bad name: %q", uwaf.Response) 218 } 219 220 // Update the WAF ruleset 221 var uRuleset *Ruleset 222 record(t, "wafs/ruleset/patch", func(c *Client) { 223 uRuleset, err = c.UpdateWAFRuleSets(&UpdateWAFRuleRuleSetsInput{ 224 Service: testServiceID, 225 ID: uwaf.ID, 226 }) 227 }) 228 if err != nil { 229 t.Fatal(err) 230 } 231 if uRuleset.ID != uwaf.ID { 232 t.Errorf("expected %q to be %q", uRuleset.ID, uwaf.ID) 233 } 234 if uRuleset.VCL != "" { 235 t.Error("bad vcl") 236 } 237 if uRuleset.LastPush != nil { 238 t.Error("bad last_push") 239 } 240 if uRuleset.Link == "" { 241 t.Error("bad link") 242 } 243 244 // Delete 245 record(t, "wafs/delete", func(c *Client) { 246 err = c.DeleteWAF(&DeleteWAFInput{ 247 Service: testServiceID, 248 Version: tv.Number, 249 ID: waf.ID, 250 }) 251 }) 252 if err != nil { 253 t.Fatal(err) 254 } 255 256 } 257 258 func TestClient_ListWAFs_validation(t *testing.T) { 259 var err error 260 _, err = testClient.ListWAFs(&ListWAFsInput{ 261 Service: "", 262 }) 263 if err != ErrMissingService { 264 t.Errorf("bad error: %s", err) 265 } 266 267 _, err = testClient.ListWAFs(&ListWAFsInput{ 268 Service: "foo", 269 Version: 0, 270 }) 271 if err != ErrMissingVersion { 272 t.Errorf("bad error: %s", err) 273 } 274 } 275 276 func TestClient_CreateWAF_validation(t *testing.T) { 277 var err error 278 _, err = testClient.CreateWAF(&CreateWAFInput{ 279 Service: "", 280 }) 281 if err != ErrMissingService { 282 t.Errorf("bad error: %s", err) 283 } 284 285 _, err = testClient.CreateWAF(&CreateWAFInput{ 286 Service: "foo", 287 Version: 0, 288 }) 289 if err != ErrMissingVersion { 290 t.Errorf("bad error: %s", err) 291 } 292 } 293 294 func TestClient_GetWAF_validation(t *testing.T) { 295 var err error 296 _, err = testClient.GetWAF(&GetWAFInput{ 297 Service: "", 298 }) 299 if err != ErrMissingService { 300 t.Errorf("bad error: %s", err) 301 } 302 303 _, err = testClient.GetWAF(&GetWAFInput{ 304 Service: "foo", 305 Version: 0, 306 }) 307 if err != ErrMissingVersion { 308 t.Errorf("bad error: %s", err) 309 } 310 311 _, err = testClient.GetWAF(&GetWAFInput{ 312 Service: "foo", 313 Version: 1, 314 ID: "", 315 }) 316 if err != ErrMissingWAFID { 317 t.Errorf("bad error: %s", err) 318 } 319 } 320 321 // 322 // func TestClient_UpdateWAF_validation(t *testing.T) { 323 // var err error 324 // _, err = testClient.UpdateWAF(&UpdateWAFInput{ 325 // Service: "", 326 // }) 327 // if err != ErrMissingService { 328 // t.Errorf("bad error: %s", err) 329 // } 330 // 331 // _, err = testClient.UpdateWAF(&UpdateWAFInput{ 332 // Service: "foo", 333 // Version: 0, 334 // }) 335 // if err != ErrMissingVersion { 336 // t.Errorf("bad error: %s", err) 337 // } 338 // 339 // _, err = testClient.UpdateWAF(&UpdateWAFInput{ 340 // Service: "foo", 341 // Version: 1, 342 // WAFID: "", 343 // }) 344 // if err != ErrMissingWAFID { 345 // t.Errorf("bad error: %s", err) 346 // } 347 // } 348 // 349 // func TestClient_DeleteWAF_validation(t *testing.T) { 350 // var err error 351 // err = testClient.DeleteWAF(&DeleteWAFInput{ 352 // Service: "", 353 // }) 354 // if err != ErrMissingService { 355 // t.Errorf("bad error: %s", err) 356 // } 357 // 358 // err = testClient.DeleteWAF(&DeleteWAFInput{ 359 // Service: "foo", 360 // Version: 0, 361 // }) 362 // if err != ErrMissingVersion { 363 // t.Errorf("bad error: %s", err) 364 // } 365 // 366 // err = testClient.DeleteWAF(&DeleteWAFInput{ 367 // Service: "foo", 368 // Version: 1, 369 // WAFID: "", 370 // }) 371 // if err != ErrMissingWAFID { 372 // t.Errorf("bad error: %s", err) 373 // } 374 // } 375 376 func TestUpdateWAFRuleStatusesInput_validate(t *testing.T) { 377 tests := []struct { 378 description string 379 input UpdateWAFRuleStatusInput 380 expected error 381 }{ 382 { 383 description: "Accepts valid input", 384 input: UpdateWAFRuleStatusInput{ 385 ID: "as098k-8104", 386 RuleID: 8104, 387 Service: "108asj1", 388 WAF: "as098k", 389 Status: "block", 390 }, 391 expected: nil, 392 }, 393 { 394 description: "Rejects input with missing int field", 395 input: UpdateWAFRuleStatusInput{ 396 ID: "as098k-8104", 397 Service: "108asj1", 398 WAF: "as098k", 399 Status: "block", 400 }, 401 expected: ErrMissingRuleID, 402 }, 403 { 404 description: "Rejects input with missing string field", 405 input: UpdateWAFRuleStatusInput{ 406 ID: "as098k-8104", 407 RuleID: 8104, 408 WAF: "as098k", 409 Status: "block", 410 }, 411 expected: ErrMissingService, 412 }, 413 } 414 for _, testcase := range tests { 415 err := testcase.input.validate() 416 if err != testcase.expected { 417 t.Errorf("In test %s: Expected %v,got %v", testcase.description, testcase.expected, err) 418 } 419 } 420 } 421 422 func TestUpdateWAFRuleTagStatusInput_validate(t *testing.T) { 423 tests := []struct { 424 description string 425 input UpdateWAFRuleTagStatusInput 426 expected error 427 }{ 428 { 429 description: "Accepts valid input", 430 input: UpdateWAFRuleTagStatusInput{ 431 Tag: "lala tag la", 432 Service: "108asj1", 433 WAF: "as098k", 434 Status: "block", 435 }, 436 expected: nil, 437 }, 438 { 439 description: "Rejects input with missing string field", 440 input: UpdateWAFRuleTagStatusInput{ 441 Service: "108asj1", 442 WAF: "as098k", 443 Status: "block", 444 }, 445 expected: ErrMissingTag, 446 }, 447 } 448 for _, testcase := range tests { 449 err := testcase.input.validate() 450 if err != testcase.expected { 451 t.Errorf("In test %s: Expected %v,got %v", testcase.description, testcase.expected, err) 452 } 453 } 454 } 455 456 func TestGetWAFRuleStatusesInput_formatFilters(t *testing.T) { 457 tests := []struct { 458 description string 459 filters GetWAFRuleStatusesFilters 460 expected map[string]string 461 }{ 462 { 463 description: "converts both strings and ints to strings", 464 filters: GetWAFRuleStatusesFilters{ 465 Status: "log", 466 Accuracy: 10, 467 Version: "180ad", 468 }, 469 expected: map[string]string{ 470 "filter[status]": "log", 471 "filter[rule][accuracy]": "10", 472 "filter[rule][version]": "180ad", 473 }, 474 }, 475 { 476 description: "converts arrays to strings", 477 filters: GetWAFRuleStatusesFilters{ 478 Status: "log", 479 Version: "181ad", 480 Tags: []int{18, 1, 1093, 86308}, 481 }, 482 expected: map[string]string{ 483 "filter[status]": "log", 484 "filter[rule][version]": "181ad", 485 "include": "18,1,1093,86308", 486 }, 487 }, 488 } 489 for _, testcase := range tests { 490 input := GetWAFRuleStatusesInput{ 491 Filters: testcase.filters, 492 } 493 answer := input.formatFilters() 494 if len(answer) != len(testcase.expected) { 495 t.Errorf("In test %s: Expected map with %d entries,got one with %d", testcase.description, len(testcase.expected), len(answer)) 496 } 497 for key, value := range testcase.expected { 498 if answer[key] != value { 499 t.Errorf("In test %s: Expected %s key to have value %s, got %s", testcase.description, key, value, answer[key]) 500 } 501 } 502 } 503 } 504 505 func TestGetPages(t *testing.T) { 506 tests := []struct { 507 description string 508 input string 509 expectedPages paginationInfo 510 expectedErr error 511 }{ 512 { 513 description: "returns the next page", 514 input: `{"links": {"next": "https://google.com/2"}, "data": []}`, 515 expectedPages: paginationInfo{ 516 Next: "https://google.com/2", 517 }, 518 }, 519 { 520 description: "returns multiple pages", 521 input: `{"links": {"next": "https://google.com/2", "first": "https://google.com/1"}, "data": []}`, 522 expectedPages: paginationInfo{ 523 First: "https://google.com/1", 524 Next: "https://google.com/2", 525 }, 526 }, 527 { 528 description: "returns no pages", 529 input: `{"data": []}`, 530 expectedPages: paginationInfo{}, 531 }, 532 } 533 for _, testcase := range tests { 534 pages, reader, err := getPages(bytes.NewReader([]byte(testcase.input))) 535 if pages != testcase.expectedPages { 536 t.Errorf("Test %s: Expected pages %+v, got %+v", testcase.description, testcase.expectedPages, pages) 537 } 538 539 // we expect to be able to get the original input out again 540 resultBytes, _ := ioutil.ReadAll(reader) 541 if string(resultBytes) != testcase.input { 542 t.Errorf("Test %s: Expected body %s, got %s", testcase.description, testcase.input, string(resultBytes)) 543 } 544 if err != testcase.expectedErr { 545 t.Errorf("Test %s: Expected error %v, got %v", testcase.description, testcase.expectedErr, err) 546 } 547 } 548 } 549 550 func TestUpdateWAFConfigSetInput_validate(t *testing.T) { 551 tests := []struct { 552 description string 553 input UpdateWAFConfigSetInput 554 expected error 555 }{ 556 { 557 description: "Accepts valid input", 558 input: UpdateWAFConfigSetInput{ 559 WAFList: []ConfigSetWAFs{{ID: "derpID"}}, 560 ConfigSetID: "derpConfigSet", 561 }, 562 expected: nil, 563 }, 564 } 565 for _, testcase := range tests { 566 err := testcase.input.validate() 567 if err != testcase.expected { 568 t.Errorf("In test %s: Expected %v,got %v", testcase.description, testcase.expected, err) 569 } 570 } 571 }