feat(misconf): add ability to disable checks by ID (#7536)

Signed-off-by: nikpivkin <nikita.pivkin@smartforce.io>
Co-authored-by: Simar <simar@linux.com>
This commit is contained in:
Nikita Pivkin
2024-09-28 12:31:53 +06:00
committed by GitHub
parent ea0cf0379a
commit ef0a27d515
4 changed files with 110 additions and 6 deletions

View File

@@ -295,6 +295,12 @@ func (s *Scanner) filterModules(retriever *MetadataRetriever) error {
continue
}
if IsBuiltinNamespace(getModuleNamespace(module)) {
if _, disabled := s.disabledCheckIDs[meta.ID]; disabled { // ignore builtin disabled checks
continue
}
}
if len(meta.InputOptions.Selectors) == 0 {
s.logger.Warn(
"Module has no input selectors - it will be loaded for all inputs!",

View File

@@ -106,3 +106,14 @@ func WithCustomSchemas(schemas map[string][]byte) options.ScannerOption {
}
}
}
// WithDisabledCheckIDs disables checks by their ID (ID field in metadata)
func WithDisabledCheckIDs(ids ...string) options.ScannerOption {
return func(s options.ConfigurableScanner) {
if ss, ok := s.(*Scanner); ok {
for _, id := range ids {
ss.disabledCheckIDs[id] = struct{}{}
}
}
}
}

View File

@@ -69,6 +69,8 @@ type Scanner struct {
embeddedLibs map[string]*ast.Module
embeddedChecks map[string]*ast.Module
customSchemas map[string][]byte
disabledCheckIDs map[string]struct{}
}
func (s *Scanner) SetIncludeDeprecatedChecks(b bool) {
@@ -109,12 +111,13 @@ func NewScanner(source types.Source, opts ...options.ScannerOption) *Scanner {
}
s := &Scanner{
regoErrorLimit: ast.CompileErrorLimitDefault,
sourceType: source,
ruleNamespaces: make(map[string]struct{}),
runtimeValues: addRuntimeValues(),
logger: log.WithPrefix("rego"),
customSchemas: make(map[string][]byte),
regoErrorLimit: ast.CompileErrorLimitDefault,
sourceType: source,
ruleNamespaces: make(map[string]struct{}),
runtimeValues: addRuntimeValues(),
logger: log.WithPrefix("rego"),
customSchemas: make(map[string][]byte),
disabledCheckIDs: make(map[string]struct{}),
}
maps.Copy(s.ruleNamespaces, builtinNamespaces)

View File

@@ -1153,3 +1153,87 @@ deny {
})
}
}
func Test_RegoScanner_WithDisabledCheckIDs(t *testing.T) {
check := `# METADATA
# custom:
# id: TEST-001
# avd_id: AVD-TEST-001
# severity: LOW
# provider: aws
# service: s3
# short_code: test
package builtin.test
deny {
true
}
`
tests := []struct {
name string
disabledChecks []string
inputCheck string
expected bool
}{
{
name: "no disabled checks",
expected: true,
inputCheck: check,
},
{
name: "disable check by ID",
disabledChecks: []string{"TEST-001"},
inputCheck: check,
},
{
name: "disabling a non-existent check",
disabledChecks: []string{"FOO"},
expected: true,
inputCheck: check,
},
{
name: "one of the identifiers does not exist",
disabledChecks: []string{"FOO", "TEST-001"},
inputCheck: check,
},
{
name: "do not disable user checks with builtin IDs",
inputCheck: `# METADATA
# custom:
# id: TEST-001
# avd_id: AVD-TEST-001
# severity: LOW
# provider: aws
# service: s3
# short_code: test
package user.test
deny {
true
}
`,
disabledChecks: []string{"TEST-001"},
expected: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
scanner := rego.NewScanner(
types.SourceYAML,
rego.WithPolicyReader(strings.NewReader(tt.inputCheck)),
rego.WithDisabledCheckIDs(tt.disabledChecks...),
rego.WithPolicyNamespaces("user"),
)
require.NoError(t, scanner.LoadPolicies(nil))
results, err := scanner.ScanInput(context.TODO(), rego.Input{})
require.NoError(t, err)
require.Equal(t, tt.expected, len(results.GetFailed()) > 0)
})
}
}