github.com/DataDog/datadog-agent/pkg/security/secl@v0.55.0-devel.0.20240517055856-10c4965fea94/rules/policy_test.go (about) 1 // Unless explicitly stated otherwise all files in this repository are licensed 2 // under the Apache License Version 2.0. 3 // This product includes software developed at Datadog (https://www.datadoghq.com/). 4 // Copyright 2016-present Datadog, Inc. 5 6 //go:build linux 7 8 // Package rules holds rules related files 9 package rules 10 11 import ( 12 "fmt" 13 "os" 14 "path/filepath" 15 "strings" 16 "syscall" 17 "testing" 18 19 "github.com/google/go-cmp/cmp" 20 "github.com/google/go-cmp/cmp/cmpopts" 21 22 "github.com/Masterminds/semver/v3" 23 "github.com/hashicorp/go-multierror" 24 "github.com/stretchr/testify/assert" 25 "gopkg.in/yaml.v3" 26 27 "github.com/DataDog/datadog-agent/pkg/security/secl/compiler/eval" 28 "github.com/DataDog/datadog-agent/pkg/security/secl/model" 29 ) 30 31 func savePolicy(filename string, testPolicy *PolicyDef) error { 32 yamlBytes, err := yaml.Marshal(testPolicy) 33 if err != nil { 34 return err 35 } 36 37 return os.WriteFile(filename, yamlBytes, 0700) 38 } 39 40 func TestMacroMerge(t *testing.T) { 41 testPolicy := &PolicyDef{ 42 Rules: []*RuleDefinition{{ 43 ID: "test_rule", 44 Expression: `open.file.path == "/tmp/test" && process.name == "/usr/bin/vim"`, 45 }}, 46 Macros: []*MacroDefinition{{ 47 ID: "test_macro", 48 Values: []string{"/usr/bin/vi"}, 49 }}, 50 } 51 52 testPolicy2 := &PolicyDef{ 53 Macros: []*MacroDefinition{{ 54 ID: "test_macro", 55 Values: []string{"/usr/bin/vim"}, 56 Combine: MergePolicy, 57 }}, 58 } 59 60 tmpDir := t.TempDir() 61 62 if err := savePolicy(filepath.Join(tmpDir, "test.policy"), testPolicy); err != nil { 63 t.Fatal(err) 64 } 65 66 if err := savePolicy(filepath.Join(tmpDir, "test2.policy"), testPolicy2); err != nil { 67 t.Fatal(err) 68 } 69 70 event := model.NewFakeEvent() 71 event.SetFieldValue("open.file.path", "/tmp/test") 72 event.SetFieldValue("process.comm", "/usr/bin/vi") 73 74 provider, err := NewPoliciesDirProvider(tmpDir, false) 75 if err != nil { 76 t.Fatal(err) 77 } 78 loader := NewPolicyLoader(provider) 79 80 evaluationSet, _ := newTestEvaluationSet([]eval.RuleSetTagValue{DefaultRuleSetTagValue}) 81 if errs := evaluationSet.LoadPolicies(loader, PolicyLoaderOpts{}); errs.ErrorOrNil() != nil { 82 t.Error(err) 83 } 84 85 macro := evaluationSet.RuleSets[DefaultRuleSetTagValue].evalOpts.MacroStore.Get("test_macro") 86 if macro == nil { 87 t.Fatalf("failed to find test_macro in ruleset: %+v", evaluationSet.RuleSets[DefaultRuleSetTagValue].evalOpts.MacroStore.List()) 88 } 89 90 testPolicy2.Macros[0].Combine = "" 91 92 if err := savePolicy(filepath.Join(tmpDir, "test2.policy"), testPolicy2); err != nil { 93 t.Fatal(err) 94 } 95 96 if err := evaluationSet.LoadPolicies(loader, PolicyLoaderOpts{}); err == nil { 97 t.Error("expected macro ID conflict") 98 } 99 } 100 101 func TestRuleMerge(t *testing.T) { 102 testPolicy := &PolicyDef{ 103 Rules: []*RuleDefinition{{ 104 ID: "test_rule", 105 Expression: `open.file.path == "/tmp/test"`, 106 }}, 107 } 108 109 testPolicy2 := &PolicyDef{ 110 Rules: []*RuleDefinition{{ 111 ID: "test_rule", 112 Expression: `open.file.path == "/tmp/test"`, 113 Combine: OverridePolicy, 114 }}, 115 } 116 117 tmpDir := t.TempDir() 118 119 if err := savePolicy(filepath.Join(tmpDir, "test.policy"), testPolicy); err != nil { 120 t.Fatal(err) 121 } 122 123 if err := savePolicy(filepath.Join(tmpDir, "test2.policy"), testPolicy2); err != nil { 124 t.Fatal(err) 125 } 126 127 provider, err := NewPoliciesDirProvider(tmpDir, false) 128 if err != nil { 129 t.Fatal(err) 130 } 131 loader := NewPolicyLoader(provider) 132 133 evaluationSet, _ := newTestEvaluationSet([]eval.RuleSetTagValue{DefaultRuleSetTagValue}) 134 if errs := evaluationSet.LoadPolicies(loader, PolicyLoaderOpts{}); errs.ErrorOrNil() != nil { 135 t.Error(err) 136 } 137 138 rule := evaluationSet.RuleSets[DefaultRuleSetTagValue].GetRules()["test_rule"] 139 if rule == nil { 140 t.Fatal("failed to find test_rule in ruleset") 141 } 142 143 testPolicy2.Rules[0].Combine = "" 144 145 if err := savePolicy(filepath.Join(tmpDir, "test2.policy"), testPolicy2); err != nil { 146 t.Fatal(err) 147 } 148 149 if err := evaluationSet.LoadPolicies(loader, PolicyLoaderOpts{}); err == nil { 150 t.Error("expected rule ID conflict") 151 } 152 } 153 154 func TestActionSetVariable(t *testing.T) { 155 testPolicy := &PolicyDef{ 156 Rules: []*RuleDefinition{{ 157 ID: "test_rule", 158 Expression: `open.file.path == "/tmp/test"`, 159 Actions: []*ActionDefinition{{ 160 Set: &SetDefinition{ 161 Name: "var1", 162 Value: true, 163 }, 164 }, { 165 Set: &SetDefinition{ 166 Name: "var2", 167 Value: "value", 168 }, 169 }, { 170 Set: &SetDefinition{ 171 Name: "var3", 172 Value: 123, 173 }, 174 }, { 175 Set: &SetDefinition{ 176 Name: "var4", 177 Value: 123, 178 Scope: "process", 179 }, 180 }, { 181 Set: &SetDefinition{ 182 Name: "var5", 183 Value: []string{ 184 "val1", 185 }, 186 }, 187 }, { 188 Set: &SetDefinition{ 189 Name: "var6", 190 Value: []int{ 191 123, 192 }, 193 }, 194 }, { 195 Set: &SetDefinition{ 196 Name: "var7", 197 Append: true, 198 Value: []string{ 199 "aaa", 200 }, 201 }, 202 }, { 203 Set: &SetDefinition{ 204 Name: "var8", 205 Append: true, 206 Value: []int{ 207 123, 208 }, 209 }, 210 }, { 211 Set: &SetDefinition{ 212 Name: "var9", 213 Field: "open.file.path", 214 }, 215 }, { 216 Set: &SetDefinition{ 217 Name: "var10", 218 Field: "open.file.path", 219 Append: true, 220 }, 221 }}, 222 }, { 223 ID: "test_rule2", 224 Expression: `open.file.path == "/tmp/test2" && ` + 225 `${var1} == true && ` + 226 `"${var2}" == "value" && ` + 227 `${var2} == "value" && ` + 228 `${var3} == 123 && ` + 229 `${process.var4} == 123 && ` + 230 `"val1" in ${var5} && ` + 231 `123 in ${var6} && ` + 232 `"aaa" in ${var7} && ` + 233 `123 in ${var8} && ` + 234 `${var9} == "/tmp/test" && ` + 235 `"/tmp/test" in ${var10}`, 236 }}, 237 } 238 239 tmpDir := t.TempDir() 240 241 if err := savePolicy(filepath.Join(tmpDir, "test.policy"), testPolicy); err != nil { 242 t.Fatal(err) 243 } 244 245 provider, err := NewPoliciesDirProvider(tmpDir, false) 246 if err != nil { 247 t.Fatal(err) 248 } 249 loader := NewPolicyLoader(provider) 250 251 evaluationSet, _ := newTestEvaluationSet([]eval.RuleSetTagValue{DefaultRuleSetTagValue}) 252 if errs := evaluationSet.LoadPolicies(loader, PolicyLoaderOpts{}); errs.ErrorOrNil() != nil { 253 t.Error(err) 254 } 255 256 rule := evaluationSet.RuleSets[DefaultRuleSetTagValue].GetRules()["test_rule"] 257 if rule == nil { 258 t.Fatal("failed to find test_rule in ruleset") 259 } 260 261 event := model.NewFakeEvent() 262 event.Type = uint32(model.FileOpenEventType) 263 processCacheEntry := &model.ProcessCacheEntry{} 264 processCacheEntry.Retain() 265 event.ProcessCacheEntry = processCacheEntry 266 event.SetFieldValue("open.file.path", "/tmp/test2") 267 event.SetFieldValue("open.flags", syscall.O_RDONLY) 268 269 if evaluationSet.RuleSets[DefaultRuleSetTagValue].Evaluate(event) { 270 t.Errorf("Expected event to match no rule") 271 } 272 273 event.SetFieldValue("open.file.path", "/tmp/test") 274 275 if !evaluationSet.RuleSets[DefaultRuleSetTagValue].Evaluate(event) { 276 t.Errorf("Expected event to match rule") 277 } 278 279 event.SetFieldValue("open.file.path", "/tmp/test2") 280 if !evaluationSet.RuleSets[DefaultRuleSetTagValue].Evaluate(event) { 281 t.Errorf("Expected event to match rule") 282 } 283 284 scopedVariables := evaluationSet.RuleSets[DefaultRuleSetTagValue].scopedVariables["process"].(*eval.ScopedVariables) 285 286 assert.Equal(t, scopedVariables.Len(), 1) 287 event.ProcessCacheEntry.Release() 288 assert.Equal(t, scopedVariables.Len(), 0) 289 } 290 291 func TestActionSetVariableConflict(t *testing.T) { 292 testPolicy := &PolicyDef{ 293 Rules: []*RuleDefinition{{ 294 ID: "test_rule", 295 Expression: `open.file.path == "/tmp/test"`, 296 Actions: []*ActionDefinition{{ 297 Set: &SetDefinition{ 298 Name: "var1", 299 Value: true, 300 }, 301 }, { 302 Set: &SetDefinition{ 303 Name: "var1", 304 Value: "value", 305 }, 306 }}, 307 }, { 308 ID: "test_rule2", 309 Expression: `open.file.path == "/tmp/test2" && ` + 310 `${var1} == true`, 311 }}, 312 } 313 314 tmpDir := t.TempDir() 315 316 if err := savePolicy(filepath.Join(tmpDir, "test.policy"), testPolicy); err != nil { 317 t.Fatal(err) 318 } 319 320 provider, err := NewPoliciesDirProvider(tmpDir, false) 321 if err != nil { 322 t.Fatal(err) 323 } 324 loader := NewPolicyLoader(provider) 325 326 evaluationSet, _ := newTestEvaluationSet([]eval.RuleSetTagValue{DefaultRuleSetTagValue}) 327 if errs := evaluationSet.LoadPolicies(loader, PolicyLoaderOpts{}); errs.ErrorOrNil() == nil { 328 t.Error("expected policy to fail to load") 329 } 330 } 331 332 func TestRuleErrorLoading(t *testing.T) { 333 testPolicy := &PolicyDef{ 334 Rules: []*RuleDefinition{ 335 { 336 ID: "testA", 337 Expression: `open.file.path == "/tmp/test"`, 338 }, 339 { 340 ID: "testB", 341 Expression: `open.file.path =-= "/tmp/test"`, 342 }, 343 { 344 ID: "testA", 345 Expression: `open.file.path == "/tmp/toto"`, 346 }, 347 }, 348 } 349 350 es, err := loadPolicyIntoProbeEvaluationRuleSet(t, testPolicy, PolicyLoaderOpts{}) 351 rs := es.RuleSets[DefaultRuleSetTagValue] 352 assert.NotNil(t, err) 353 assert.Len(t, err.Errors, 2) 354 assert.ErrorContains(t, err.Errors[0], "rule `testA` error: multiple definition with the same ID") 355 assert.ErrorContains(t, err.Errors[1], "rule `testB` error: syntax error `1:17: unexpected token \"-\" (expected \"~\")`") 356 357 assert.Contains(t, rs.rules, "testA") 358 assert.NotContains(t, rs.rules, "testB") 359 } 360 361 func TestRuleAgentConstraint(t *testing.T) { 362 testPolicy := &PolicyDef{ 363 Macros: []*MacroDefinition{ 364 { 365 ID: "macro1", 366 Expression: `[1, 2]`, 367 }, 368 { 369 ID: "macro2", 370 Expression: `[3, 4]`, 371 AgentVersionConstraint: ">= 7.37, < 7.38", 372 }, 373 { 374 ID: "macro2", 375 Expression: `[3, 4, 5]`, 376 AgentVersionConstraint: ">= 7.38", 377 }, 378 }, 379 Rules: []*RuleDefinition{ 380 { 381 ID: "no_constraint", 382 Expression: `open.file.path == "/tmp/test"`, 383 }, 384 { 385 ID: "conflict", 386 Expression: `open.file.path == "/tmp/test1"`, 387 AgentVersionConstraint: "< 7.37", 388 }, 389 { 390 ID: "conflict", 391 Expression: `open.file.path == "/tmp/test2"`, 392 AgentVersionConstraint: ">= 7.37", 393 }, 394 { 395 ID: "basic", 396 Expression: `open.file.path == "/tmp/test"`, 397 AgentVersionConstraint: "< 7.37", 398 }, 399 { 400 ID: "basic2", 401 Expression: `open.file.path == "/tmp/test"`, 402 AgentVersionConstraint: "> 7.37", 403 }, 404 { 405 ID: "range", 406 Expression: `open.file.path == "/tmp/test"`, 407 AgentVersionConstraint: ">= 7.30, < 7.39", 408 }, 409 { 410 ID: "range_not", 411 Expression: `open.file.path == "/tmp/test"`, 412 AgentVersionConstraint: ">= 7.30, < 7.39, != 7.38", 413 }, 414 { 415 ID: "rc_prerelease", 416 Expression: `open.file.path == "/tmp/test"`, 417 AgentVersionConstraint: ">= 7.38", 418 }, 419 { 420 ID: "with_macro1", 421 Expression: `open.file.path == "/tmp/test" && open.mode in macro1`, 422 AgentVersionConstraint: ">= 7.38", 423 }, 424 { 425 ID: "with_macro2", 426 Expression: `open.file.path == "/tmp/test" && open.mode in macro2`, 427 AgentVersionConstraint: ">= 7.38", 428 }, 429 }, 430 } 431 432 expected := []struct { 433 ruleID string 434 expectedLoad bool 435 }{ 436 { 437 ruleID: "no_constraint", 438 expectedLoad: true, 439 }, 440 { 441 ruleID: "conflict", 442 expectedLoad: true, 443 }, 444 { 445 ruleID: "basic", 446 expectedLoad: false, 447 }, 448 { 449 ruleID: "basic2", 450 expectedLoad: true, 451 }, 452 { 453 ruleID: "range", 454 expectedLoad: true, 455 }, 456 { 457 ruleID: "range_not", 458 expectedLoad: false, 459 }, 460 { 461 ruleID: "rc_prerelease", 462 expectedLoad: true, 463 }, 464 { 465 ruleID: "with_macro1", 466 expectedLoad: true, 467 }, 468 { 469 ruleID: "with_macro2", 470 expectedLoad: true, 471 }, 472 } 473 474 agentVersion, err := semver.NewVersion("7.38") 475 assert.NoError(t, err) 476 477 agentVersionFilter, err := NewAgentVersionFilter(agentVersion) 478 assert.NoError(t, err) 479 480 policyOpts := PolicyLoaderOpts{ 481 MacroFilters: []MacroFilter{ 482 agentVersionFilter, 483 }, 484 RuleFilters: []RuleFilter{ 485 agentVersionFilter, 486 }, 487 } 488 489 es, err := loadPolicyIntoProbeEvaluationRuleSet(t, testPolicy, policyOpts) 490 rs := es.RuleSets[DefaultRuleSetTagValue] 491 492 for _, err := range err.(*multierror.Error).Errors { 493 if rerr, ok := err.(*ErrRuleLoad); ok { 494 if rerr.Definition.ID != "basic" && rerr.Definition.ID != "range_not" { 495 t.Errorf("unexpected error: %v", rerr) 496 } 497 } 498 } 499 500 for _, exp := range expected { 501 t.Run(exp.ruleID, func(t *testing.T) { 502 if exp.expectedLoad { 503 assert.Contains(t, rs.rules, exp.ruleID) 504 } else { 505 assert.NotContains(t, rs.rules, exp.ruleID) 506 } 507 }) 508 } 509 } 510 511 func TestActionSetVariableInvalid(t *testing.T) { 512 t.Run("both-field-and-value", func(t *testing.T) { 513 testPolicy := &PolicyDef{ 514 Rules: []*RuleDefinition{{ 515 ID: "test_rule", 516 Expression: `open.file.path == "/tmp/test"`, 517 Actions: []*ActionDefinition{{ 518 Set: &SetDefinition{ 519 Name: "var1", 520 Value: []string{"abc"}, 521 Field: "open.file.path", 522 }, 523 }}, 524 }}, 525 } 526 527 if _, err := loadPolicyIntoProbeEvaluationRuleSet(t, testPolicy, PolicyLoaderOpts{}); err == nil { 528 t.Error("policy should fail to load") 529 } else { 530 t.Log(err) 531 } 532 }) 533 534 t.Run("bool-array", func(t *testing.T) { 535 testPolicy := &PolicyDef{ 536 Rules: []*RuleDefinition{{ 537 ID: "test_rule", 538 Expression: `open.file.path == "/tmp/test"`, 539 Actions: []*ActionDefinition{{ 540 Set: &SetDefinition{ 541 Name: "var1", 542 Value: []bool{true}, 543 }, 544 }}, 545 }, { 546 ID: "test_rule2", 547 Expression: `open.file.path == "/tmp/test2" && ` + 548 `${var1} == true`, 549 }}, 550 } 551 552 if _, err := loadPolicyIntoProbeEvaluationRuleSet(t, testPolicy, PolicyLoaderOpts{}); err == nil { 553 t.Error("expected policy to fail to load") 554 } else { 555 t.Log(err) 556 } 557 }) 558 559 t.Run("heterogeneous-array", func(t *testing.T) { 560 testPolicy := &PolicyDef{ 561 Rules: []*RuleDefinition{{ 562 ID: "test_rule", 563 Expression: `open.file.path == "/tmp/test"`, 564 Actions: []*ActionDefinition{{ 565 Set: &SetDefinition{ 566 Name: "var1", 567 Value: []interface{}{"string", true}, 568 }, 569 }}, 570 }, { 571 ID: "test_rule2", 572 Expression: `open.file.path == "/tmp/test2" && ` + 573 `${var1} == true`, 574 }}, 575 } 576 577 if _, err := loadPolicyIntoProbeEvaluationRuleSet(t, testPolicy, PolicyLoaderOpts{}); err == nil { 578 t.Error("expected policy to fail to load") 579 } else { 580 t.Log(err) 581 } 582 }) 583 584 t.Run("nil-values", func(t *testing.T) { 585 testPolicy := &PolicyDef{ 586 Rules: []*RuleDefinition{{ 587 ID: "test_rule", 588 Expression: `open.file.path == "/tmp/test"`, 589 Actions: []*ActionDefinition{{ 590 Set: &SetDefinition{ 591 Name: "var1", 592 Value: nil, 593 }, 594 }}, 595 }}, 596 } 597 598 if _, err := loadPolicyIntoProbeEvaluationRuleSet(t, testPolicy, PolicyLoaderOpts{}); err == nil { 599 t.Error("expected policy to fail to load") 600 } else { 601 t.Log(err) 602 } 603 }) 604 605 t.Run("append-array", func(t *testing.T) { 606 testPolicy := &PolicyDef{ 607 Rules: []*RuleDefinition{{ 608 ID: "test_rule", 609 Expression: `open.file.path == "/tmp/test"`, 610 Actions: []*ActionDefinition{{ 611 Set: &SetDefinition{ 612 Name: "var1", 613 Value: []string{"abc"}, 614 Append: true, 615 }, 616 }, { 617 Set: &SetDefinition{ 618 Name: "var1", 619 Value: true, 620 Append: true, 621 }, 622 }}, 623 }, { 624 ID: "test_rule2", 625 Expression: `open.file.path == "/tmp/test2" && ` + 626 `${var1} == true`, 627 }}, 628 } 629 630 if _, err := loadPolicyIntoProbeEvaluationRuleSet(t, testPolicy, PolicyLoaderOpts{}); err == nil { 631 t.Error("expected policy to fail to load") 632 } else { 633 t.Log(err) 634 } 635 }) 636 637 t.Run("conflicting-field-type", func(t *testing.T) { 638 testPolicy := &PolicyDef{ 639 Rules: []*RuleDefinition{{ 640 ID: "test_rule", 641 Expression: `open.file.path == "/tmp/test"`, 642 Actions: []*ActionDefinition{{ 643 Set: &SetDefinition{ 644 Name: "var1", 645 Field: "open.file.path", 646 }, 647 }, { 648 Set: &SetDefinition{ 649 Name: "var1", 650 Value: true, 651 Append: true, 652 }, 653 }}, 654 }, { 655 ID: "test_rule2", 656 Expression: `open.file.path == "/tmp/test2" && ` + 657 `${var1} == "true"`, 658 }}, 659 } 660 661 if _, err := loadPolicyIntoProbeEvaluationRuleSet(t, testPolicy, PolicyLoaderOpts{}); err == nil { 662 t.Error("expected policy to fail to load") 663 } else { 664 t.Log(err) 665 } 666 }) 667 668 t.Run("conflicting-field-type", func(t *testing.T) { 669 testPolicy := &PolicyDef{ 670 Rules: []*RuleDefinition{{ 671 ID: "test_rule", 672 Expression: `open.file.path == "/tmp/test"`, 673 Actions: []*ActionDefinition{{ 674 Set: &SetDefinition{ 675 Name: "var1", 676 Field: "open.file.path", 677 Append: true, 678 }, 679 }, { 680 Set: &SetDefinition{ 681 Name: "var1", 682 Field: "process.is_root", 683 Append: true, 684 }, 685 }}, 686 }, { 687 ID: "test_rule2", 688 Expression: `open.file.path == "/tmp/test2" && ` + 689 `${var1} == "true"`, 690 }}, 691 } 692 693 if _, err := loadPolicyIntoProbeEvaluationRuleSet(t, testPolicy, PolicyLoaderOpts{}); err == nil { 694 t.Error("expected policy to fail to load") 695 } else { 696 t.Log(err) 697 } 698 }) 699 } 700 701 // go test -v github.com/DataDog/datadog-agent/pkg/security/secl/rules --run="TestLoadPolicy" 702 func TestLoadPolicy(t *testing.T) { 703 type args struct { 704 name string 705 source string 706 fileContent string 707 macroFilters []MacroFilter 708 ruleFilters []RuleFilter 709 } 710 tests := []struct { 711 name string 712 args args 713 want *Policy 714 wantErr assert.ErrorAssertionFunc 715 }{ 716 { 717 name: "empty yaml file", 718 args: args{ 719 name: "myLocal.policy", 720 source: PolicyProviderTypeRC, 721 fileContent: ``, 722 macroFilters: nil, 723 ruleFilters: nil, 724 }, 725 want: nil, 726 wantErr: func(t assert.TestingT, err error, i ...interface{}) bool { 727 return assert.EqualError(t, err, ErrPolicyLoad{Name: "myLocal.policy", Err: fmt.Errorf(`EOF`)}.Error()) 728 }, 729 }, 730 { 731 name: "empty yaml file with new line char", 732 args: args{ 733 name: "myLocal.policy", 734 source: PolicyProviderTypeRC, 735 fileContent: ` 736 `, 737 macroFilters: nil, 738 ruleFilters: nil, 739 }, 740 want: nil, 741 wantErr: func(t assert.TestingT, err error, i ...interface{}) bool { 742 return assert.EqualError(t, err, ErrPolicyLoad{Name: "myLocal.policy", Err: fmt.Errorf(`EOF`)}.Error()) 743 }, 744 }, 745 { 746 name: "no rules in yaml file", 747 args: args{ 748 name: "myLocal.policy", 749 source: PolicyProviderTypeRC, 750 fileContent: ` 751 rules: 752 `, 753 macroFilters: nil, 754 ruleFilters: nil, 755 }, 756 want: &Policy{ 757 Name: "myLocal.policy", 758 Source: PolicyProviderTypeRC, 759 Rules: nil, 760 }, 761 wantErr: assert.NoError, 762 }, 763 { 764 name: "broken yaml file", 765 args: args{ 766 name: "myLocal.policy", 767 source: PolicyProviderTypeRC, 768 fileContent: ` 769 broken 770 `, 771 macroFilters: nil, 772 ruleFilters: nil, 773 }, 774 want: nil, 775 wantErr: func(t assert.TestingT, err error, i ...interface{}) bool { 776 return assert.ErrorContains(t, err, ErrPolicyLoad{Name: "myLocal.policy", Err: fmt.Errorf(`yaml: unmarshal error`)}.Error()) 777 }, 778 }, 779 { 780 name: "disabled tag", 781 args: args{ 782 name: "myLocal.policy", 783 source: PolicyProviderTypeRC, 784 fileContent: `rules: 785 - id: rule_test 786 disabled: true 787 `, 788 macroFilters: nil, 789 ruleFilters: nil, 790 }, 791 want: &Policy{ 792 Name: "myLocal.policy", 793 Source: PolicyProviderTypeRC, 794 Rules: []*RuleDefinition{ 795 { 796 ID: "rule_test", 797 Expression: "", 798 Disabled: true, 799 Policy: &Policy{ 800 Name: "myLocal.policy", 801 Source: PolicyProviderTypeRC, 802 }, 803 }, 804 }, 805 }, 806 wantErr: assert.NoError, 807 }, 808 { 809 name: "combine:override tag", 810 args: args{ 811 name: "myLocal.policy", 812 source: PolicyProviderTypeRC, 813 fileContent: `rules: 814 - id: rule_test 815 expression: open.file.path == "/etc/gshadow" 816 combine: override 817 `, 818 macroFilters: nil, 819 ruleFilters: nil, 820 }, 821 want: &Policy{ 822 Name: "myLocal.policy", 823 Source: PolicyProviderTypeRC, 824 Rules: []*RuleDefinition{ 825 { 826 ID: "rule_test", 827 Expression: "open.file.path == \"/etc/gshadow\"", 828 Combine: OverridePolicy, 829 Policy: &Policy{ 830 Name: "myLocal.policy", 831 Source: PolicyProviderTypeRC, 832 }, 833 }, 834 }, 835 }, 836 wantErr: assert.NoError, 837 }, 838 } 839 for _, tt := range tests { 840 t.Run(tt.name, func(t *testing.T) { 841 r := strings.NewReader(tt.args.fileContent) 842 843 got, err := LoadPolicy(tt.args.name, tt.args.source, r, tt.args.macroFilters, tt.args.ruleFilters) 844 845 if !tt.wantErr(t, err, fmt.Sprintf("LoadPolicy(%v, %v, %v, %v, %v)", tt.args.name, tt.args.source, r, tt.args.macroFilters, tt.args.ruleFilters)) { 846 return 847 } 848 849 if !cmp.Equal(tt.want, got, cmpopts.IgnoreFields(RuleDefinition{}, "Policy")) { 850 t.Errorf("LoadPolicy(%v, %v, %v, %v, %v)", tt.args.name, tt.args.source, r, tt.args.macroFilters, tt.args.ruleFilters) 851 } 852 }) 853 } 854 }