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  }