github.com/aquasecurity/trivy-iac@v0.8.1-0.20240127024015-3d8e412cf0ab/pkg/scanners/json/parser/parser.go (about) 1 package parser 2 3 import ( 4 "context" 5 "encoding/json" 6 "io" 7 "io/fs" 8 "path/filepath" 9 10 "github.com/aquasecurity/defsec/pkg/debug" 11 "github.com/aquasecurity/defsec/pkg/scanners/options" 12 "github.com/aquasecurity/trivy-iac/pkg/detection" 13 ) 14 15 var _ options.ConfigurableParser = (*Parser)(nil) 16 17 type Parser struct { 18 debug debug.Logger 19 skipRequired bool 20 } 21 22 func (p *Parser) SetDebugWriter(writer io.Writer) { 23 p.debug = debug.New(writer, "json", "parser") 24 } 25 26 func (p *Parser) SetSkipRequiredCheck(b bool) { 27 p.skipRequired = b 28 } 29 30 // New creates a new parser 31 func New(opts ...options.ParserOption) *Parser { 32 p := &Parser{} 33 for _, opt := range opts { 34 opt(p) 35 } 36 return p 37 } 38 39 func (p *Parser) ParseFS(ctx context.Context, target fs.FS, path string) (map[string]interface{}, error) { 40 41 files := make(map[string]interface{}) 42 if err := fs.WalkDir(target, filepath.ToSlash(path), func(path string, entry fs.DirEntry, err error) error { 43 select { 44 case <-ctx.Done(): 45 return ctx.Err() 46 default: 47 } 48 if err != nil { 49 return err 50 } 51 if entry.IsDir() { 52 return nil 53 } 54 if !p.Required(path) { 55 return nil 56 } 57 df, err := p.ParseFile(ctx, target, path) 58 if err != nil { 59 p.debug.Log("Parse error in '%s': %s", path, err) 60 return nil 61 } 62 files[path] = df 63 return nil 64 }); err != nil { 65 return nil, err 66 } 67 return files, nil 68 } 69 70 // ParseFile parses Dockerfile content from the provided filesystem path. 71 func (p *Parser) ParseFile(_ context.Context, fs fs.FS, path string) (interface{}, error) { 72 f, err := fs.Open(filepath.ToSlash(path)) 73 if err != nil { 74 return nil, err 75 } 76 defer func() { _ = f.Close() }() 77 var target interface{} 78 if err := json.NewDecoder(f).Decode(&target); err != nil { 79 return nil, err 80 } 81 return target, nil 82 } 83 84 func (p *Parser) Required(path string) bool { 85 if p.skipRequired { 86 return true 87 } 88 return detection.IsType(path, nil, detection.FileTypeJSON) 89 }