diff --git a/pkg/flag/report_flags_test.go b/pkg/flag/report_flags_test.go index b113d7c62f97..ab4baa53fbff 100644 --- a/pkg/flag/report_flags_test.go +++ b/pkg/flag/report_flags_test.go @@ -213,7 +213,7 @@ func TestReportFlagGroup_ToOptions(t *testing.T) { t.Run("Error on non existing ignore file", func(t *testing.T) { t.Cleanup(viper.Reset) - setValue(flag.IgnoreFileFlag.ConfigName, string("doesntexist")) + setValue(flag.IgnoreFileFlag.ConfigName, "doesntexist") f := &flag.ReportFlagGroup{ IgnoreFile: flag.IgnoreFileFlag.Clone(), } diff --git a/pkg/result/ignore.go b/pkg/result/ignore.go index dbd1cab83db9..4c17691f4e09 100644 --- a/pkg/result/ignore.go +++ b/pkg/result/ignore.go @@ -185,6 +185,7 @@ func ParseIgnoreFile(ctx context.Context, ignoreFile string) (IgnoreConfig, erro var conf IgnoreConfig if _, err := os.Stat(ignoreFile); errors.Is(err, fs.ErrNotExist) { // .trivyignore doesn't necessarily exist + log.Debug("Specified ignore file does not exist", log.String("file", ignoreFile)) return IgnoreConfig{}, nil } else if filepath.Ext(ignoreFile) == ".yml" || filepath.Ext(ignoreFile) == ".yaml" { conf, err = parseIgnoreYAML(ignoreFile) @@ -218,16 +219,17 @@ func ParseIgnoreFile(ctx context.Context, ignoreFile string) (IgnoreConfig, erro func parseIgnoreYAML(ignoreFile string) (IgnoreConfig, error) { // Read .trivyignore.yaml - f, err := os.Open(ignoreFile) + b, err := os.ReadFile(ignoreFile) if err != nil { return IgnoreConfig{}, xerrors.Errorf("file open error: %w", err) } - defer f.Close() log.Debug("Found an ignore yaml", log.FilePath(ignoreFile)) // Parse the YAML content + // We have to use Unmarshal() due to go-yaml returning an error with Decode() + // ref: https://github.com/go-yaml/yaml/issues/805 var ignoreConfig IgnoreConfig - if err = yaml.NewDecoder(f).Decode(&ignoreConfig); err != nil { + if err = yaml.Unmarshal(b, &ignoreConfig); err != nil { return IgnoreConfig{}, xerrors.Errorf("yaml decode error: %w", err) } return ignoreConfig, nil diff --git a/pkg/result/ignore_test.go b/pkg/result/ignore_test.go new file mode 100644 index 000000000000..68248d7e17b1 --- /dev/null +++ b/pkg/result/ignore_test.go @@ -0,0 +1,72 @@ +package result + +import ( + "context" + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestParseIgnoreFile(t *testing.T) { + t.Run("happy path valid config file", func(t *testing.T) { + got, err := ParseIgnoreFile(context.TODO(), "testdata/.trivyignore") + require.NoError(t, err) + assert.Equal(t, "testdata/.trivyignore", got.FilePath) + + // IDs in .trivyignore are treated as IDs for all scanners + // as it is unclear which type of security issue they are + assert.Len(t, got.Vulnerabilities, 6) + assert.Len(t, got.Misconfigurations, 6) + assert.Len(t, got.Secrets, 6) + assert.Len(t, got.Licenses, 6) + }) + + t.Run("happy path valid YAML config file", func(t *testing.T) { + got, err := ParseIgnoreFile(context.TODO(), "testdata/.trivyignore.yaml") + require.NoError(t, err) + assert.Equal(t, "testdata/.trivyignore.yaml", got.FilePath) + assert.Len(t, got.Vulnerabilities, 5) + assert.Len(t, got.Misconfigurations, 3) + assert.Len(t, got.Secrets, 3) + assert.Len(t, got.Licenses, 1) + }) + + t.Run("empty YAML file passed", func(t *testing.T) { + f, err := os.CreateTemp("", "TestParseIgnoreFile-*.yaml") + require.NoError(t, err) + defer os.Remove(f.Name()) + + _, err = ParseIgnoreFile(context.TODO(), f.Name()) + require.NoError(t, err) + }) + + t.Run("invalid YAML file passed", func(t *testing.T) { + f, err := os.CreateTemp("", "TestParseIgnoreFile-*.yaml") + require.NoError(t, err) + defer os.Remove(f.Name()) + _, _ = f.WriteString("this file is not a yaml file") + + got, err := ParseIgnoreFile(context.TODO(), f.Name()) + assert.Contains(t, err.Error(), "yaml decode error") + assert.Empty(t, got) + }) + + t.Run("invalid file passed", func(t *testing.T) { + f, err := os.CreateTemp("", "TestParseIgnoreFile-*") + require.NoError(t, err) + defer os.Remove(f.Name()) + _, _ = f.WriteString("this file is not a valid trivyignore file") + + _, err = ParseIgnoreFile(context.TODO(), f.Name()) + require.NoError(t, err) // TODO(simar7): We don't verify correctness, should we? + }) + + t.Run("non existing file passed", func(t *testing.T) { + got, err := ParseIgnoreFile(context.TODO(), "does-not-exist.yaml") + require.NoError(t, err) + assert.Empty(t, got) + }) + +}