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  }