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