github.com/nginxinc/kubernetes-ingress@v1.12.5/internal/k8s/appprotect/app_protect_configuration_test.go (about) 1 package appprotect 2 3 import ( 4 "testing" 5 "time" 6 7 "github.com/google/go-cmp/cmp" 8 "github.com/google/go-cmp/cmp/cmpopts" 9 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 10 ) 11 12 func parseTime(value string) *time.Time { 13 t, err := time.Parse(timeLayout, value) 14 if err != nil { 15 panic(err) 16 } 17 18 return &t 19 } 20 21 func sliceCmpFunc(x, y *unstructured.Unstructured) bool { 22 return x.GetUID() > y.GetUID() 23 } 24 25 var unstructuredSliceCmpOpts = cmpopts.SortSlices(sliceCmpFunc) 26 27 func TestCreateAppProtectPolicyEx(t *testing.T) { 28 tests := []struct { 29 policy *unstructured.Unstructured 30 expectedPolicyEx *PolicyEx 31 wantErr bool 32 msg string 33 }{ 34 { 35 policy: &unstructured.Unstructured{ 36 Object: map[string]interface{}{ 37 "metadata": map[string]interface{}{ 38 "uid": "1", 39 }, 40 "spec": map[string]interface{}{ 41 "policy": map[string]interface{}{ 42 "name": "TestPolicy", 43 "signature-requirements": []interface{}{ 44 map[string]interface{}{ 45 "maxRevisionDatetime": "2020-01-23T18:32:02Z", 46 "minRevisionDatetime": "2020-01-21T18:32:02Z", 47 "tag": "MinMax", 48 }, 49 map[string]interface{}{ 50 "maxRevisionDatetime": "2020-01-23T18:32:02Z", 51 "tag": "Max", 52 }, 53 map[string]interface{}{ 54 "minRevisionDatetime": "2020-01-23T18:32:02Z", 55 "tag": "Min", 56 }, 57 }, 58 }, 59 }, 60 }, 61 }, 62 expectedPolicyEx: &PolicyEx{ 63 SignatureReqs: []SignatureReq{ 64 { 65 Tag: "MinMax", 66 RevTimes: &RevTimes{ 67 MinRevTime: parseTime("2020-01-21T18:32:02Z"), 68 MaxRevTime: parseTime("2020-01-23T18:32:02Z"), 69 }, 70 }, 71 { 72 Tag: "Max", 73 RevTimes: &RevTimes{ 74 MaxRevTime: parseTime("2020-01-23T18:32:02Z"), 75 }, 76 }, 77 { 78 Tag: "Min", 79 RevTimes: &RevTimes{ 80 MinRevTime: parseTime("2020-01-23T18:32:02Z"), 81 }, 82 }, 83 }, 84 IsValid: true, 85 ErrorMsg: "", 86 }, 87 wantErr: false, 88 msg: "valid policy", 89 }, 90 { 91 policy: &unstructured.Unstructured{ 92 Object: map[string]interface{}{ 93 "spec": map[string]interface{}{ 94 "policy": map[string]interface{}{ 95 "name": "TestPolicy", 96 "signature-requirements": []interface{}{ 97 map[string]interface{}{ 98 "minRevisionDatetime": "time", 99 "tag": "MinMax", 100 }, 101 }, 102 }, 103 }, 104 }, 105 }, 106 expectedPolicyEx: &PolicyEx{ 107 SignatureReqs: nil, 108 IsValid: false, 109 ErrorMsg: "Invalid timestamp", 110 }, 111 wantErr: true, 112 msg: "policy with invalid min timestamp", 113 }, 114 { 115 policy: &unstructured.Unstructured{ 116 Object: map[string]interface{}{ 117 "spec": map[string]interface{}{ 118 "policy": map[string]interface{}{ 119 "name": "TestPolicy", 120 "signature-requirements": []interface{}{ 121 map[string]interface{}{ 122 "maxRevisionDatetime": "time", 123 "tag": "MinMax", 124 }, 125 }, 126 }, 127 }, 128 }, 129 }, 130 expectedPolicyEx: &PolicyEx{ 131 SignatureReqs: nil, 132 IsValid: false, 133 ErrorMsg: "Invalid timestamp", 134 }, 135 wantErr: true, 136 msg: "policy with invalid max timestamp", 137 }, 138 { 139 policy: &unstructured.Unstructured{ 140 Object: map[string]interface{}{ 141 "spec": map[string]interface{}{}, 142 }, 143 }, 144 expectedPolicyEx: &PolicyEx{ 145 SignatureReqs: nil, 146 IsValid: false, 147 ErrorMsg: "Validation Failed", 148 }, 149 wantErr: true, 150 msg: "policy empty spec", 151 }, 152 { 153 policy: &unstructured.Unstructured{ 154 Object: map[string]interface{}{ 155 "spec": map[string]interface{}{ 156 "policy": map[string]interface{}{ 157 "name": "TestPolicy", 158 "signature-requirements": map[string]interface{}{ 159 "invalid": map[string]interface{}{ 160 "maxRevisionDatetime": "time", 161 "tag": "MinMax", 162 }, 163 }, 164 }, 165 }, 166 }, 167 }, 168 expectedPolicyEx: &PolicyEx{ 169 SignatureReqs: nil, 170 IsValid: false, 171 ErrorMsg: failedValidationErrorMsg, 172 }, 173 wantErr: true, 174 msg: "policy with incorrect structure", 175 }, 176 } 177 178 for _, test := range tests { 179 test.expectedPolicyEx.Obj = test.policy 180 181 policyEx, err := createAppProtectPolicyEx(test.policy) 182 if (err != nil) != test.wantErr { 183 t.Errorf("createAppProtectPolicyEx() returned %v, for the case of %s", err, test.msg) 184 } 185 if diff := cmp.Diff(test.expectedPolicyEx, policyEx); diff != "" { 186 t.Errorf("createAppProtectPolicyEx() %q returned unexpected result (-want +got):\n%s", test.msg, diff) 187 } 188 } 189 } 190 191 func TestCreateAppProtectLogConfEx(t *testing.T) { 192 tests := []struct { 193 logConf *unstructured.Unstructured 194 expectedLogConfEx *LogConfEx 195 wantErr bool 196 msg string 197 }{ 198 { 199 logConf: &unstructured.Unstructured{ 200 Object: map[string]interface{}{ 201 "spec": map[string]interface{}{ 202 "content": map[string]interface{}{}, 203 "filter": map[string]interface{}{}, 204 }, 205 }, 206 }, 207 expectedLogConfEx: &LogConfEx{ 208 IsValid: true, 209 ErrorMsg: "", 210 }, 211 wantErr: false, 212 msg: "Valid LogConf", 213 }, 214 { 215 logConf: &unstructured.Unstructured{ 216 Object: map[string]interface{}{ 217 "spec": map[string]interface{}{ 218 "content": map[string]interface{}{}, 219 }, 220 }, 221 }, 222 expectedLogConfEx: &LogConfEx{ 223 IsValid: false, 224 ErrorMsg: failedValidationErrorMsg, 225 }, 226 wantErr: true, 227 msg: "Invalid LogConf", 228 }, 229 } 230 231 for _, test := range tests { 232 test.expectedLogConfEx.Obj = test.logConf 233 234 policyEx, err := createAppProtectLogConfEx(test.logConf) 235 if (err != nil) != test.wantErr { 236 t.Errorf("createAppProtectLogConfEx() returned %v, for the case of %s", err, test.msg) 237 } 238 if diff := cmp.Diff(test.expectedLogConfEx, policyEx); diff != "" { 239 t.Errorf("createAppProtectLogConfEx() %q returned unexpected result (-want +got):\n%s", test.msg, diff) 240 } 241 } 242 } 243 244 func TestCreateAppProtectUserSigEx(t *testing.T) { 245 tests := []struct { 246 userSig *unstructured.Unstructured 247 expectedUserSigEx *UserSigEx 248 wantErr bool 249 msg string 250 }{ 251 { 252 userSig: &unstructured.Unstructured{ 253 Object: map[string]interface{}{ 254 "spec": map[string]interface{}{ 255 "revisionDatetime": "2020-01-23T18:32:02Z", 256 "signatures": []interface{}{ 257 map[string]interface{}{}, 258 }, 259 "tag": "test", 260 }, 261 }, 262 }, 263 expectedUserSigEx: &UserSigEx{ 264 RevTime: parseTime("2020-01-23T18:32:02Z"), 265 IsValid: true, 266 ErrorMsg: "", 267 Tag: "test", 268 }, 269 wantErr: false, 270 msg: "Valid UserSig", 271 }, 272 { 273 userSig: &unstructured.Unstructured{ 274 Object: map[string]interface{}{ 275 "spec": map[string]interface{}{ 276 "signatures": []interface{}{ 277 map[string]interface{}{}, 278 }, 279 "tag": "test", 280 }, 281 }, 282 }, 283 expectedUserSigEx: &UserSigEx{ 284 IsValid: true, 285 ErrorMsg: "", 286 Tag: "test", 287 }, 288 wantErr: false, 289 msg: "Valid UserSig, no revDateTime", 290 }, 291 { 292 userSig: &unstructured.Unstructured{ 293 Object: map[string]interface{}{ 294 "spec": map[string]interface{}{ 295 "revisionDatetime": "time", 296 "signatures": []interface{}{ 297 map[string]interface{}{}, 298 }, 299 "tag": "test", 300 }, 301 }, 302 }, 303 expectedUserSigEx: &UserSigEx{ 304 IsValid: false, 305 ErrorMsg: invalidTimestampErrorMsg, 306 Tag: "", 307 }, 308 wantErr: true, 309 msg: "Invalid timestamp", 310 }, 311 } 312 313 for _, test := range tests { 314 test.expectedUserSigEx.Obj = test.userSig 315 316 userSigEx, err := createAppProtectUserSigEx(test.userSig) 317 if (err != nil) != test.wantErr { 318 t.Errorf("createAppProtectUserSigEx() returned %v, for the case of %s", err, test.msg) 319 } 320 if diff := cmp.Diff(test.expectedUserSigEx, userSigEx); diff != "" { 321 t.Errorf("createAppProtectUserSigEx() %q returned unexpected result (-want +got):\n%s", test.msg, diff) 322 } 323 } 324 } 325 326 func TestIsReqSatisfiedByUserSig(t *testing.T) { 327 userSigEx := &UserSigEx{Tag: "test", RevTime: parseTime("2020-06-16T18:32:01Z")} 328 userSigExNoRevTime := &UserSigEx{Tag: "test"} 329 tests := []struct { 330 sigReq SignatureReq 331 sigEx *UserSigEx 332 msg string 333 expected bool 334 }{ 335 { 336 sigReq: SignatureReq{ 337 Tag: "test", 338 RevTimes: &RevTimes{ 339 MinRevTime: parseTime("2020-01-21T18:32:02Z"), 340 MaxRevTime: parseTime("2020-10-23T18:32:02Z"), 341 }, 342 }, 343 sigEx: userSigEx, 344 msg: "Valid, Basic case", 345 expected: true, 346 }, 347 { 348 sigReq: SignatureReq{ 349 Tag: "test", 350 RevTimes: &RevTimes{ 351 MinRevTime: parseTime("2021-01-21T18:32:02Z"), 352 MaxRevTime: parseTime("2022-01-23T18:32:02Z"), 353 }, 354 }, 355 sigEx: userSigEx, 356 msg: "Invalid, rev not in Required period", 357 expected: false, 358 }, 359 { 360 sigReq: SignatureReq{ 361 Tag: "test", 362 RevTimes: &RevTimes{ 363 MaxRevTime: parseTime("2022-01-23T18:32:02Z"), 364 }, 365 }, 366 sigEx: userSigEx, 367 msg: "Valid, max rev time only", 368 expected: true, 369 }, 370 { 371 sigReq: SignatureReq{ 372 Tag: "test", 373 RevTimes: &RevTimes{ 374 MaxRevTime: parseTime("2019-01-23T18:32:02Z"), 375 }, 376 }, 377 sigEx: userSigEx, 378 msg: "Invalid, max rev time only", 379 expected: false, 380 }, 381 { 382 sigReq: SignatureReq{ 383 Tag: "test", 384 RevTimes: &RevTimes{ 385 MinRevTime: parseTime("2019-01-23T18:32:02Z"), 386 }, 387 }, 388 sigEx: userSigEx, 389 msg: "Valid, min rev time only", 390 expected: true, 391 }, 392 { 393 sigReq: SignatureReq{ 394 Tag: "test", 395 RevTimes: &RevTimes{ 396 MinRevTime: parseTime("2022-01-23T18:32:02Z"), 397 }, 398 }, 399 sigEx: userSigEx, 400 msg: "Invalid, min rev time only", 401 expected: false, 402 }, 403 { 404 sigReq: SignatureReq{ 405 Tag: "testing", 406 RevTimes: &RevTimes{ 407 MinRevTime: parseTime("2022-01-23T18:32:02Z"), 408 }, 409 }, 410 sigEx: userSigEx, 411 msg: "Invalid, different tag", 412 expected: false, 413 }, 414 { 415 sigReq: SignatureReq{ 416 Tag: "testing", 417 RevTimes: &RevTimes{}, 418 }, 419 sigEx: userSigEx, 420 msg: "Invalid, different tag, no revTimes", 421 expected: false, 422 }, 423 { 424 sigReq: SignatureReq{ 425 Tag: "test", 426 }, 427 sigEx: userSigEx, 428 msg: "Valid, matching tag, no revTimes", 429 expected: true, 430 }, 431 { 432 sigReq: SignatureReq{ 433 Tag: "test", 434 RevTimes: &RevTimes{ 435 MinRevTime: parseTime("2019-01-23T18:32:02Z"), 436 }, 437 }, 438 sigEx: userSigExNoRevTime, 439 msg: "Valid, no RevDateTime", 440 expected: true, 441 }, 442 } 443 444 for _, test := range tests { 445 result := isReqSatisfiedByUserSig(test.sigReq, test.sigEx) 446 if result != test.expected { 447 t.Errorf("Unexpected result in test case %s: got %v, expected: %v", test.msg, result, test.expected) 448 } 449 } 450 } 451 452 func TestAddOrUpdatePolicy(t *testing.T) { 453 basicTestPolicy := &unstructured.Unstructured{ 454 Object: map[string]interface{}{ 455 "metadata": map[string]interface{}{ 456 "namespace": "testing", 457 }, 458 "spec": map[string]interface{}{ 459 "policy": map[string]interface{}{ 460 "name": "TestPolicy", 461 "signature-requirements": []interface{}{ 462 map[string]interface{}{ 463 "maxRevisionDatetime": "2019-04-01T18:32:02Z", 464 "tag": "test", 465 }, 466 }, 467 }, 468 }, 469 }, 470 } 471 basicTestPolicyNoReqs := &unstructured.Unstructured{ 472 Object: map[string]interface{}{ 473 "metadata": map[string]interface{}{ 474 "namespace": "testing", 475 }, 476 "spec": map[string]interface{}{ 477 "policy": map[string]interface{}{ 478 "name": "TestPolicy", 479 }, 480 }, 481 }, 482 } 483 invalidTestPolicy := &unstructured.Unstructured{ 484 Object: map[string]interface{}{ 485 "metadata": map[string]interface{}{ 486 "namespace": "testing", 487 }, 488 "spec": map[string]interface{}{}, 489 }, 490 } 491 testPolicyUnsatisfied := &unstructured.Unstructured{ 492 Object: map[string]interface{}{ 493 "metadata": map[string]interface{}{ 494 "namespace": "testing", 495 }, 496 "spec": map[string]interface{}{ 497 "policy": map[string]interface{}{ 498 "name": "TestPolicy", 499 "signature-requirements": []interface{}{ 500 map[string]interface{}{ 501 "minRevisionDatetime": "2021-04-01T18:32:02Z", 502 "tag": "test", 503 }, 504 }, 505 }, 506 }, 507 }, 508 } 509 apc := newConfigurationImpl() 510 apc.UserSigs["testing/TestUsersig"] = &UserSigEx{Tag: "test", RevTime: parseTime("2019-01-01T18:32:02Z"), IsValid: true} 511 tests := []struct { 512 policy *unstructured.Unstructured 513 expectedChanges []Change 514 expectedProblems []Problem 515 msg string 516 }{ 517 { 518 policy: basicTestPolicy, 519 expectedChanges: []Change{ 520 {Resource: &PolicyEx{ 521 Obj: basicTestPolicy, 522 IsValid: true, 523 SignatureReqs: []SignatureReq{ 524 {Tag: "test", 525 RevTimes: &RevTimes{ 526 MaxRevTime: parseTime("2019-04-01T18:32:02Z"), 527 }, 528 }, 529 }, 530 }, 531 Op: AddOrUpdate, 532 }, 533 }, 534 expectedProblems: nil, 535 msg: "Basic Case with sig reqs", 536 }, 537 { 538 policy: basicTestPolicyNoReqs, 539 expectedChanges: []Change{ 540 {Resource: &PolicyEx{ 541 Obj: basicTestPolicyNoReqs, 542 IsValid: true, 543 SignatureReqs: []SignatureReq{}, 544 }, 545 Op: AddOrUpdate, 546 }, 547 }, 548 expectedProblems: nil, 549 msg: "basic case no sig reqs", 550 }, 551 { 552 policy: invalidTestPolicy, 553 expectedChanges: []Change{ 554 {Resource: &PolicyEx{ 555 Obj: invalidTestPolicy, 556 IsValid: false, 557 ErrorMsg: "Validation Failed", 558 }, 559 Op: Delete, 560 }, 561 }, 562 expectedProblems: []Problem{ 563 { 564 Object: invalidTestPolicy, 565 Reason: "Rejected", 566 Message: "Error validating policy : Error validating App Protect Policy : Required field map[] not found", 567 }, 568 }, 569 msg: "validation failed", 570 }, 571 { 572 policy: testPolicyUnsatisfied, 573 expectedChanges: []Change{ 574 {Resource: &PolicyEx{ 575 Obj: testPolicyUnsatisfied, 576 IsValid: false, 577 ErrorMsg: "Policy has unsatisfied signature requirements", 578 SignatureReqs: []SignatureReq{ 579 {Tag: "test", 580 RevTimes: &RevTimes{ 581 MinRevTime: parseTime("2021-04-01T18:32:02Z"), 582 }, 583 }, 584 }, 585 }, 586 Op: Delete, 587 }, 588 }, 589 expectedProblems: []Problem{ 590 { 591 Object: testPolicyUnsatisfied, 592 Reason: "Rejected", 593 Message: "Policy has unsatisfied signature requirements", 594 }, 595 }, 596 msg: "Missing sig reqs", 597 }, 598 } 599 for _, test := range tests { 600 aPChans, aPProbs := apc.AddOrUpdatePolicy(test.policy) 601 if diff := cmp.Diff(test.expectedChanges, aPChans); diff != "" { 602 t.Errorf("AddOrUpdatePolicy() %q changes returned unexpected result (-want +got):\n%s", test.msg, diff) 603 } 604 if diff := cmp.Diff(test.expectedProblems, aPProbs); diff != "" { 605 t.Errorf("AddOrUpdatePolicy() %q problems returned unexpected result (-want +got):\n%s", test.msg, diff) 606 } 607 } 608 } 609 610 func TestAddOrUpdateLogConf(t *testing.T) { 611 validLogConf := &unstructured.Unstructured{ 612 Object: map[string]interface{}{ 613 "metadata": map[string]interface{}{ 614 "namespace": "testing", 615 "name": "testlogconf", 616 }, 617 "spec": map[string]interface{}{ 618 "content": map[string]interface{}{}, 619 "filter": map[string]interface{}{}, 620 }, 621 }, 622 } 623 invalidLogConf := &unstructured.Unstructured{ 624 Object: map[string]interface{}{ 625 "metadata": map[string]interface{}{ 626 "namespace": "testing", 627 "name": "testlogconf", 628 }, 629 "spec": map[string]interface{}{ 630 "content": map[string]interface{}{}, 631 }, 632 }, 633 } 634 apc := NewConfiguration() 635 tests := []struct { 636 logconf *unstructured.Unstructured 637 expectedChanges []Change 638 expectedProblems []Problem 639 msg string 640 }{ 641 { 642 logconf: validLogConf, 643 expectedChanges: []Change{ 644 {Resource: &LogConfEx{ 645 Obj: validLogConf, 646 IsValid: true, 647 }, 648 Op: AddOrUpdate, 649 }, 650 }, 651 expectedProblems: nil, 652 msg: "Basic Case", 653 }, 654 { 655 logconf: invalidLogConf, 656 expectedChanges: []Change{ 657 {Resource: &LogConfEx{ 658 Obj: invalidLogConf, 659 IsValid: false, 660 ErrorMsg: "Validation Failed", 661 }, 662 Op: Delete, 663 }, 664 }, 665 expectedProblems: []Problem{ 666 { 667 Object: invalidLogConf, 668 Reason: "Rejected", 669 Message: "Error validating App Protect Log Configuration testlogconf: Required field map[] not found", 670 }, 671 }, 672 msg: "validation failed", 673 }, 674 } 675 for _, test := range tests { 676 aPChans, aPProbs := apc.AddOrUpdateLogConf(test.logconf) 677 if diff := cmp.Diff(test.expectedChanges, aPChans); diff != "" { 678 t.Errorf("AddOrUpdateLogConf() %q changes returned unexpected result (-want +got):\n%s", test.msg, diff) 679 } 680 if diff := cmp.Diff(test.expectedProblems, aPProbs); diff != "" { 681 t.Errorf("AddOrUpdateLogConf() %q problems returned unexpected result (-want +got):\n%s", test.msg, diff) 682 } 683 } 684 } 685 686 func TestAddOrUpdateUserSig(t *testing.T) { 687 testUserSig1 := &unstructured.Unstructured{ 688 Object: map[string]interface{}{ 689 "metadata": map[string]interface{}{ 690 "namespace": "testing", 691 "name": "test1", 692 "uid": "1", 693 "creationTimestamp": "2020-01-23T18:32:02Z", 694 }, 695 "spec": map[string]interface{}{ 696 "signatures": []interface{}{ 697 map[string]interface{}{}, 698 }, 699 "revisionDatetime": "2020-01-23T18:32:02Z", 700 "tag": "test1", 701 }, 702 }, 703 } 704 testUserSig2 := &unstructured.Unstructured{ 705 Object: map[string]interface{}{ 706 "metadata": map[string]interface{}{ 707 "namespace": "testing", 708 "name": "test2", 709 "uid": "2", 710 "creationTimestamp": "2020-01-23T18:32:02Z", 711 }, 712 "spec": map[string]interface{}{ 713 "signatures": []interface{}{ 714 map[string]interface{}{}, 715 }, 716 "revisionDatetime": "2020-01-23T18:32:02Z", 717 "tag": "test2", 718 }, 719 }, 720 } 721 invalidTestUserSig2 := &unstructured.Unstructured{ 722 Object: map[string]interface{}{ 723 "metadata": map[string]interface{}{ 724 "namespace": "testing", 725 "name": "test2", 726 "uid": "3", 727 "creationTimestamp": "2020-01-23T18:32:02Z", 728 }, 729 "spec": map[string]interface{}{ 730 "revisionDatetime": "2020-01-23T18:32:02Z", 731 "tag": "test2", 732 }, 733 }, 734 } 735 testUserSigDupTag := &unstructured.Unstructured{ 736 Object: map[string]interface{}{ 737 "metadata": map[string]interface{}{ 738 "namespace": "testing", 739 "name": "test2", 740 "uid": "4", 741 "creationTimestamp": "2020-01-25T18:32:02Z", 742 }, 743 "spec": map[string]interface{}{ 744 "signatures": []interface{}{ 745 map[string]interface{}{}, 746 }, 747 "revisionDatetime": "2020-01-23T18:32:02Z", 748 "tag": "test1", 749 }, 750 }, 751 } 752 testUserSig1Invalid := &unstructured.Unstructured{ 753 Object: map[string]interface{}{ 754 "metadata": map[string]interface{}{ 755 "namespace": "testing", 756 "name": "test1", 757 "uid": "1", 758 "creationTimestamp": "2020-01-23T18:32:02Z", 759 }, 760 }, 761 } 762 testUserSig3 := &unstructured.Unstructured{ 763 Object: map[string]interface{}{ 764 "metadata": map[string]interface{}{ 765 "namespace": "testing", 766 "name": "test3", 767 "uid": "5", 768 "creationTimestamp": "2020-01-23T18:32:02Z", 769 }, 770 "spec": map[string]interface{}{ 771 "signatures": []interface{}{ 772 map[string]interface{}{}, 773 }, 774 "revisionDatetime": "2020-01-23T18:32:02Z", 775 "tag": "test3", 776 }, 777 }, 778 } 779 780 appProtectConfiguration := newConfigurationImpl() 781 appProtectConfiguration.UserSigs["testing/test1"] = &UserSigEx{ 782 Obj: testUserSig1, 783 Tag: "test1", 784 IsValid: true, 785 ErrorMsg: "", 786 } 787 appProtectConfiguration.Policies["testing/testpolicy"] = &PolicyEx{ 788 Obj: &unstructured.Unstructured{Object: map[string]interface{}{}}, 789 IsValid: false, 790 ErrorMsg: "Policy has unsatisfied signature requirements", 791 SignatureReqs: []SignatureReq{ 792 { 793 Tag: "test3", 794 RevTimes: &RevTimes{ 795 MinRevTime: parseTime("2010-01-23T18:32:02Z"), 796 }, 797 }, 798 }, 799 } 800 tests := []struct { 801 usersig *unstructured.Unstructured 802 expectedUserSigChange UserSigChange 803 expectedProblems []Problem 804 msg string 805 }{ 806 { 807 usersig: testUserSig2, 808 expectedUserSigChange: UserSigChange{ 809 UserSigs: []*unstructured.Unstructured{ 810 testUserSig1, 811 testUserSig2, 812 }, 813 }, 814 msg: "Basic case", 815 }, 816 { 817 usersig: invalidTestUserSig2, 818 expectedUserSigChange: UserSigChange{ 819 UserSigs: []*unstructured.Unstructured{ 820 testUserSig1, 821 }, 822 }, 823 expectedProblems: []Problem{ 824 { 825 Object: invalidTestUserSig2, 826 Reason: "Rejected", 827 Message: "Validation Failed", 828 }, 829 }, 830 msg: "validation failed", 831 }, 832 { 833 usersig: testUserSigDupTag, 834 expectedUserSigChange: UserSigChange{ 835 UserSigs: []*unstructured.Unstructured{ 836 testUserSig1, 837 }, 838 }, 839 expectedProblems: []Problem{ 840 { 841 Object: testUserSigDupTag, 842 Message: "Duplicate tag set", 843 Reason: "Rejected", 844 }, 845 }, 846 msg: "Duplicate tags", 847 }, 848 { 849 usersig: testUserSig1Invalid, 850 expectedUserSigChange: UserSigChange{ 851 UserSigs: []*unstructured.Unstructured{ 852 testUserSigDupTag, 853 }, 854 }, 855 expectedProblems: []Problem{ 856 { 857 Object: testUserSig1Invalid, 858 Message: "Validation Failed", 859 Reason: "Rejected", 860 }, 861 }, 862 msg: "UserSig becomes valid after previous tag holder became invalid", 863 }, 864 { 865 usersig: testUserSig3, 866 expectedUserSigChange: UserSigChange{ 867 PolicyAddsOrUpdates: []*unstructured.Unstructured{ 868 { 869 Object: map[string]interface{}{}, 870 }, 871 }, 872 UserSigs: []*unstructured.Unstructured{ 873 testUserSigDupTag, 874 testUserSig3, 875 }, 876 }, 877 msg: "Policy becomes valid after a UserSig with the right tag was added", 878 }, 879 } 880 881 for _, test := range tests { 882 apUserSigChan, apProbs := appProtectConfiguration.AddOrUpdateUserSig(test.usersig) 883 if diff := cmp.Diff(test.expectedUserSigChange, apUserSigChan, unstructuredSliceCmpOpts); diff != "" { 884 t.Errorf("AddOrUpdateUserSig() %q changes returned unexpected result (-want +got):\n%s", test.msg, diff) 885 } 886 if diff := cmp.Diff(test.expectedProblems, apProbs); diff != "" { 887 t.Errorf("AddOrUpdateUserSig() %q problems returned unexpected result (-want +got):\n%s", test.msg, diff) 888 } 889 } 890 } 891 892 func TestDeletePolicy(t *testing.T) { 893 appProtectConfiguration := newConfigurationImpl() 894 appProtectConfiguration.Policies["testing/test"] = &PolicyEx{} 895 tests := []struct { 896 key string 897 expectedChanges []Change 898 expectedProblems []Problem 899 msg string 900 }{ 901 { 902 key: "testing/test", 903 expectedChanges: []Change{ 904 { 905 Op: Delete, 906 Resource: &PolicyEx{}, 907 }, 908 }, 909 expectedProblems: nil, 910 msg: "Positive", 911 }, 912 { 913 key: "testing/notpresent", 914 expectedChanges: nil, 915 expectedProblems: nil, 916 msg: "Negative", 917 }, 918 } 919 for _, test := range tests { 920 apChan, apProbs := appProtectConfiguration.DeletePolicy(test.key) 921 if diff := cmp.Diff(test.expectedChanges, apChan); diff != "" { 922 t.Errorf("DeletePolicy() %q changes returned unexpected result (-want +got):\n%s", test.msg, diff) 923 } 924 if diff := cmp.Diff(test.expectedProblems, apProbs); diff != "" { 925 t.Errorf("DeletePolicy() %q problems returned unexpected result (-want +got):\n%s", test.msg, diff) 926 } 927 } 928 } 929 930 func TestDeleteLogConf(t *testing.T) { 931 appProtectConfiguration := newConfigurationImpl() 932 appProtectConfiguration.LogConfs["testing/test"] = &LogConfEx{} 933 tests := []struct { 934 key string 935 expectedChanges []Change 936 expectedProblems []Problem 937 msg string 938 }{ 939 { 940 key: "testing/test", 941 expectedChanges: []Change{ 942 { 943 Op: Delete, 944 Resource: &LogConfEx{}, 945 }, 946 }, 947 expectedProblems: nil, 948 msg: "Positive", 949 }, 950 { 951 key: "testing/notpresent", 952 expectedChanges: nil, 953 expectedProblems: nil, 954 msg: "Negative", 955 }, 956 } 957 for _, test := range tests { 958 apChan, apProbs := appProtectConfiguration.DeleteLogConf(test.key) 959 if diff := cmp.Diff(test.expectedChanges, apChan); diff != "" { 960 t.Errorf("DeleteLogConf() %q changes returned unexpected result (-want +got):\n%s", test.msg, diff) 961 } 962 if diff := cmp.Diff(test.expectedProblems, apProbs); diff != "" { 963 t.Errorf("DeleteLogConf() %q problems returned unexpected result (-want +got):\n%s", test.msg, diff) 964 } 965 } 966 } 967 968 func TestDeleteUserSig(t *testing.T) { 969 testUserSig1 := &unstructured.Unstructured{ 970 Object: map[string]interface{}{ 971 "metadata": map[string]interface{}{ 972 "namespace": "testing", 973 "name": "test1", 974 "uid": "1", 975 "creationTimestamp": "2020-01-23T18:32:02Z", 976 }, 977 "spec": map[string]interface{}{ 978 "signatures": []interface{}{ 979 map[string]interface{}{}, 980 }, 981 "revisionDatetime": "2020-01-23T18:32:02Z", 982 "tag": "test1", 983 }, 984 }, 985 } 986 testUserSig2 := &unstructured.Unstructured{ 987 Object: map[string]interface{}{ 988 "metadata": map[string]interface{}{ 989 "namespace": "testing", 990 "name": "test2", 991 "uid": "2", 992 "creationTimestamp": "2020-01-23T18:32:02Z", 993 }, 994 "spec": map[string]interface{}{ 995 "signatures": []interface{}{ 996 map[string]interface{}{}, 997 }, 998 "revisionDatetime": "2020-01-23T18:32:02Z", 999 "tag": "test2", 1000 }, 1001 }, 1002 } 1003 appProtectConfiguration := newConfigurationImpl() 1004 appProtectConfiguration.UserSigs["testing/test1"] = &UserSigEx{ 1005 IsValid: true, 1006 Obj: testUserSig1, 1007 } 1008 appProtectConfiguration.UserSigs["testing/test2"] = &UserSigEx{ 1009 IsValid: true, 1010 Obj: testUserSig2, 1011 } 1012 appProtectConfiguration.Policies["testing/testpolicy"] = &PolicyEx{ 1013 Obj: &unstructured.Unstructured{Object: map[string]interface{}{}}, 1014 IsValid: true, 1015 ErrorMsg: "", 1016 SignatureReqs: []SignatureReq{ 1017 { 1018 Tag: "test1", 1019 RevTimes: &RevTimes{ 1020 MinRevTime: parseTime("2010-01-23T18:32:02Z"), 1021 }, 1022 }, 1023 }, 1024 } 1025 tests := []struct { 1026 key string 1027 expectedChange UserSigChange 1028 expectedProblems []Problem 1029 msg string 1030 }{ 1031 { 1032 key: "testing/test1", 1033 expectedChange: UserSigChange{ 1034 PolicyDeletions: []*unstructured.Unstructured{ 1035 { 1036 Object: map[string]interface{}{}, 1037 }, 1038 }, 1039 UserSigs: []*unstructured.Unstructured{ 1040 testUserSig2, 1041 }, 1042 }, 1043 expectedProblems: []Problem{ 1044 { 1045 Reason: "Rejected", 1046 Message: "Policy has unsatisfied signature requirements", 1047 Object: &unstructured.Unstructured{ 1048 Object: map[string]interface{}{}, 1049 }, 1050 }, 1051 }, 1052 msg: "Positive, policy gets set to invalid", 1053 }, 1054 { 1055 key: "testing/test3", 1056 expectedChange: UserSigChange{}, 1057 expectedProblems: nil, 1058 msg: "Negative", 1059 }, 1060 } 1061 1062 for _, test := range tests { 1063 apChan, apProbs := appProtectConfiguration.DeleteUserSig(test.key) 1064 if diff := cmp.Diff(test.expectedChange, apChan, unstructuredSliceCmpOpts); diff != "" { 1065 t.Errorf("DeleteUserSig() %q changes returned unexpected result (-want +got):\n%s", test.msg, diff) 1066 } 1067 if diff := cmp.Diff(test.expectedProblems, apProbs); diff != "" { 1068 t.Errorf("DeleteUserSig() %q problems returned unexpected result (-want +got):\n%s", test.msg, diff) 1069 } 1070 } 1071 } 1072 1073 func TestGetAppProtectResource(t *testing.T) { 1074 tests := []struct { 1075 kind string 1076 key string 1077 wantErr bool 1078 errMsg string 1079 msg string 1080 }{ 1081 { 1082 kind: "APPolicy", 1083 key: "testing/test1", 1084 wantErr: false, 1085 msg: "Policy, positive", 1086 }, 1087 { 1088 kind: "APPolicy", 1089 key: "testing/test2", 1090 wantErr: true, 1091 errMsg: "Validation Failed", 1092 msg: "Policy, Negative, invalid object", 1093 }, 1094 { 1095 kind: "APPolicy", 1096 key: "testing/test3", 1097 wantErr: true, 1098 errMsg: "App Protect Policy testing/test3 not found", 1099 msg: "Policy, Negative, Object Does not exist", 1100 }, 1101 { 1102 kind: "APLogConf", 1103 key: "testing/test1", 1104 wantErr: false, 1105 msg: "LogConf, positive", 1106 }, 1107 { 1108 kind: "APLogConf", 1109 key: "testing/test2", 1110 wantErr: true, 1111 errMsg: "Validation Failed", 1112 msg: "LogConf, Negative, invalid object", 1113 }, 1114 { 1115 kind: "APLogConf", 1116 key: "testing/test3", 1117 wantErr: true, 1118 errMsg: "App Protect LogConf testing/test3 not found", 1119 msg: "LogConf, Negative, Object Does not exist", 1120 }, 1121 { 1122 kind: "APUserSig", 1123 key: "testing/test1", 1124 wantErr: false, 1125 msg: "UserSig, positive", 1126 }, 1127 { 1128 kind: "APUserSig", 1129 key: "testing/test2", 1130 wantErr: true, 1131 errMsg: "Validation Failed", 1132 msg: "UserSig, Negative, invalid object", 1133 }, 1134 { 1135 kind: "APUserSig", 1136 key: "testing/test3", 1137 wantErr: true, 1138 errMsg: "App Protect UserSig testing/test3 not found", 1139 msg: "UserSig, Negative, Object Does not exist", 1140 }, 1141 { 1142 kind: "Notreal", 1143 key: "testing/test3", 1144 wantErr: true, 1145 errMsg: "Unknown App Protect resource kind Notreal", 1146 msg: "Ivalid kind, Negative", 1147 }, 1148 } 1149 appProtectConfiguration := newConfigurationImpl() 1150 appProtectConfiguration.Policies["testing/test1"] = &PolicyEx{IsValid: true, Obj: &unstructured.Unstructured{}} 1151 appProtectConfiguration.Policies["testing/test2"] = &PolicyEx{IsValid: false, Obj: &unstructured.Unstructured{}, ErrorMsg: "Validation Failed"} 1152 appProtectConfiguration.LogConfs["testing/test1"] = &LogConfEx{IsValid: true, Obj: &unstructured.Unstructured{}} 1153 appProtectConfiguration.LogConfs["testing/test2"] = &LogConfEx{IsValid: false, Obj: &unstructured.Unstructured{}, ErrorMsg: "Validation Failed"} 1154 appProtectConfiguration.UserSigs["testing/test1"] = &UserSigEx{IsValid: true, Obj: &unstructured.Unstructured{}} 1155 appProtectConfiguration.UserSigs["testing/test2"] = &UserSigEx{IsValid: false, Obj: &unstructured.Unstructured{}, ErrorMsg: "Validation Failed"} 1156 1157 for _, test := range tests { 1158 _, err := appProtectConfiguration.GetAppResource(test.kind, test.key) 1159 if (err != nil) != test.wantErr { 1160 t.Errorf("GetAppResource() returned %v on case %s", err, test.msg) 1161 } 1162 if test.wantErr || err != nil { 1163 if test.errMsg != err.Error() { 1164 t.Errorf("GetAppResource() returned error message %s on case %s (expected %s)", err.Error(), test.msg, test.errMsg) 1165 } 1166 } 1167 } 1168 }