From 1bc9af58b176e29225f0f43f757aa42edb9a3639 Mon Sep 17 00:00:00 2001 From: Michelangelo Mori Date: Fri, 25 Oct 2024 14:53:50 +0200 Subject: [PATCH] Fix `mindev ruletype lint`. (#4828) We recently changed the behaviour of `minder ruletype create` and `apply` to ignore files that do not define rule types. This allowed us to add test files to `mindersec/minder-rules-and-profiles`, but it in turn broke `mindev`. This change makes `mindev` behave like `minder` by splitting folder walk from ruletype validation. Fixes #4819 --- cmd/cli/app/ruletype/ruletype_apply.go | 2 +- cmd/cli/app/ruletype/ruletype_create.go | 2 +- cmd/dev/app/rule_type/lint.go | 64 ++++++++++++++----------- internal/util/helpers.go | 38 +++++++-------- 4 files changed, 53 insertions(+), 53 deletions(-) diff --git a/cmd/cli/app/ruletype/ruletype_apply.go b/cmd/cli/app/ruletype/ruletype_apply.go index 8d39b30cd1..6b9ad4f316 100644 --- a/cmd/cli/app/ruletype/ruletype_apply.go +++ b/cmd/cli/app/ruletype/ruletype_apply.go @@ -41,7 +41,7 @@ func applyCommand(_ context.Context, cmd *cobra.Command, _ []string, conn *grpc. return cli.MessageAndError("Error validating file flag", err) } - files, err := util.ExpandFileArgs(fileFlag) + files, err := util.ExpandFileArgs(fileFlag...) if err != nil { return cli.MessageAndError("Error expanding file args", err) } diff --git a/cmd/cli/app/ruletype/ruletype_create.go b/cmd/cli/app/ruletype/ruletype_create.go index 531ad338c2..4325aabe90 100644 --- a/cmd/cli/app/ruletype/ruletype_create.go +++ b/cmd/cli/app/ruletype/ruletype_create.go @@ -40,7 +40,7 @@ func createCommand(_ context.Context, cmd *cobra.Command, _ []string, conn *grpc return cli.MessageAndError("Error validating file flag", err) } - files, err := util.ExpandFileArgs(fileFlag) + files, err := util.ExpandFileArgs(fileFlag...) if err != nil { return cli.MessageAndError("Error expanding file args", err) } diff --git a/cmd/dev/app/rule_type/lint.go b/cmd/dev/app/rule_type/lint.go index ebd1271f35..4b820352af 100644 --- a/cmd/dev/app/rule_type/lint.go +++ b/cmd/dev/app/rule_type/lint.go @@ -17,7 +17,7 @@ import ( "gopkg.in/yaml.v3" "github.com/mindersec/minder/internal/engine/eval/rego" - "github.com/mindersec/minder/internal/util/cli" + "github.com/mindersec/minder/internal/util" minderv1 "github.com/mindersec/minder/pkg/api/protobuf/go/minder/v1" ) @@ -46,58 +46,51 @@ func lintCmdRun(cmd *cobra.Command, _ []string) error { skipRego := cmd.Flag("skip-rego").Value.String() == "true" ctx := cmd.Context() - rtpathStr := rtpath.Value.String() - var errors []error - walkerr := filepath.Walk(rtpathStr, func(path string, info os.FileInfo, walkerr error) error { - if walkerr != nil { - return fmt.Errorf("error walking path %s: %w", path, walkerr) - } + files, err := util.ExpandFileArgs(rtpathStr) + if err != nil { + return fmt.Errorf("error expanding file args: %w", err) + } - if info.IsDir() { - return nil + var errors []error + for _, f := range files { + if shouldSkipFile(f.Path) { + continue } - if !cli.IsYAMLFileAndNotATest(path) { - return nil + rt, err := readRuleTypeFromFile(f.Path) + if err != nil && f.Expanded && minderv1.YouMayHaveTheWrongResource(err) { + cmd.PrintErrf("Skipping file %s: not a rule type\n", f.Path) + continue } - - rt, err := readRuleTypeFromFile(path) if err != nil { - errors = append(errors, fmt.Errorf("error reading rule type from file %s: %w", path, err)) - return nil + errors = append(errors, fmt.Errorf("error reading rule type from file %s: %w", f.Path, err)) + continue } if err := rt.Validate(); err != nil { - errors = append(errors, fmt.Errorf("error validating rule type: %w", err)) - return nil + errors = append(errors, fmt.Errorf("error validating rule type from file %s: %w", f.Path, err)) + continue } - // get file name without extension - ruleName := strings.TrimSuffix(filepath.Base(path), filepath.Ext(path)) + ruleName := strings.TrimSuffix(filepath.Base(f.Path), filepath.Ext(f.Path)) if rt.Name != ruleName { errors = append(errors, fmt.Errorf("rule type name does not match file name: %s != %s", rt.Name, ruleName)) - return nil + continue } if rt.Def.Eval.Type == rego.RegoEvalType && !skipRego { if err := validateRegoRule(ctx, rt.Def.Eval.Rego, rtpathStr, cmd.OutOrStdout()); err != nil { - errors = append(errors, fmt.Errorf("failed validating rego rule: %w", err)) - return nil + errors = append(errors, fmt.Errorf("failed validating rego rule from file %s: %w", f.Path, err)) + continue } } - - return nil - }) - - if walkerr != nil { - return fmt.Errorf("error walking path %s: %w", rtpathStr, walkerr) } if len(errors) > 0 { for _, err := range errors { - fmt.Fprintln(cmd.ErrOrStderr(), err) + cmd.PrintErrf("%s\n", err) } return fmt.Errorf("failed linting rule type") } @@ -105,6 +98,19 @@ func lintCmdRun(cmd *cobra.Command, _ []string) error { return nil } +func shouldSkipFile(f string) bool { + // if the file is not json or yaml, skip it + // Get file extension + ext := filepath.Ext(f) + switch ext { + case ".yaml", ".yml", ".json": + return false + default: + fmt.Fprintf(os.Stderr, "Skipping file %s: not a yaml or json file\n", f) + return true + } +} + func validateRegoRule(ctx context.Context, r *minderv1.RuleType_Definition_Eval_Rego, path string, out io.Writer) error { if r == nil { return fmt.Errorf("rego rule is nil") diff --git a/internal/util/helpers.go b/internal/util/helpers.go index 2b53be92e8..8fdde4e9fa 100644 --- a/internal/util/helpers.go +++ b/internal/util/helpers.go @@ -11,7 +11,6 @@ import ( "errors" "fmt" "io" - "io/fs" "math" "net/http" "net/url" @@ -415,7 +414,7 @@ type ExpandedFile struct { // ExpandFileArgs expands a list of file arguments into a list of files. // If the file list contains "-" or regular files, it will leave them as-is. // If the file list contains directories, it will expand them into a list of files. -func ExpandFileArgs(files []string) ([]ExpandedFile, error) { +func ExpandFileArgs(files ...string) ([]ExpandedFile, error) { var expandedFiles []ExpandedFile for _, f := range files { if f == "-" { @@ -425,37 +424,32 @@ func ExpandFileArgs(files []string) ([]ExpandedFile, error) { }) continue } + f = filepath.Clean(f) fi, err := os.Stat(f) if err != nil { return nil, fmt.Errorf("error getting file info: %w", err) } - if fi.IsDir() { - // expand directory - err := filepath.Walk(f, func(path string, info fs.FileInfo, err error) error { - if err != nil { - return fmt.Errorf("error walking directory: %w", err) - } - - if !info.IsDir() { - expandedFiles = append(expandedFiles, ExpandedFile{ - Path: path, - Expanded: true, - }) - } + expanded := fi.IsDir() + err = filepath.Walk(f, func(path string, info os.FileInfo, walkerr error) error { + if walkerr != nil { + return fmt.Errorf("error walking path %s: %w", path, walkerr) + } + if info.IsDir() { return nil - }) - if err != nil { - return nil, fmt.Errorf("error walking directory: %w", err) } - } else { - // add file + expandedFiles = append(expandedFiles, ExpandedFile{ - Path: f, - Expanded: false, + Path: path, + Expanded: expanded, }) + + return nil + }) + if err != nil { + return nil, fmt.Errorf("error walking directory: %w", err) } }