github.com/aquasecurity/trivy-iac@v0.8.1-0.20240127024015-3d8e412cf0ab/pkg/scanners/json/scanner.go (about) 1 package json 2 3 import ( 4 "context" 5 "io" 6 "io/fs" 7 "sync" 8 9 "github.com/aquasecurity/defsec/pkg/debug" 10 "github.com/aquasecurity/defsec/pkg/framework" 11 "github.com/aquasecurity/defsec/pkg/rego" 12 "github.com/aquasecurity/defsec/pkg/scan" 13 "github.com/aquasecurity/defsec/pkg/scanners/options" 14 "github.com/aquasecurity/defsec/pkg/types" 15 "github.com/aquasecurity/trivy-iac/pkg/scanners" 16 "github.com/aquasecurity/trivy-iac/pkg/scanners/json/parser" 17 ) 18 19 var _ scanners.FSScanner = (*Scanner)(nil) 20 var _ options.ConfigurableScanner = (*Scanner)(nil) 21 22 type Scanner struct { 23 debug debug.Logger 24 policyDirs []string 25 policyReaders []io.Reader 26 parser *parser.Parser 27 regoScanner *rego.Scanner 28 skipRequired bool 29 options []options.ScannerOption 30 sync.Mutex 31 frameworks []framework.Framework 32 spec string 33 loadEmbeddedPolicies bool 34 loadEmbeddedLibraries bool 35 } 36 37 func (s *Scanner) SetRegoOnly(bool) { 38 } 39 40 func (s *Scanner) SetFrameworks(frameworks []framework.Framework) { 41 s.frameworks = frameworks 42 } 43 44 func (s *Scanner) SetSpec(spec string) { 45 s.spec = spec 46 } 47 48 func (s *Scanner) SetUseEmbeddedPolicies(b bool) { 49 s.loadEmbeddedPolicies = b 50 } 51 52 func (s *Scanner) SetUseEmbeddedLibraries(b bool) { 53 s.loadEmbeddedLibraries = b 54 } 55 56 func (s *Scanner) SetPolicyReaders(readers []io.Reader) { 57 s.policyReaders = readers 58 } 59 60 func (s *Scanner) SetDebugWriter(writer io.Writer) { 61 s.debug = debug.New(writer, "json", "scanner") 62 } 63 64 func (s *Scanner) SetTraceWriter(_ io.Writer) { 65 } 66 67 func (s *Scanner) SetPerResultTracingEnabled(_ bool) { 68 } 69 70 func (s *Scanner) SetPolicyDirs(dirs ...string) { 71 s.policyDirs = dirs 72 } 73 74 func (s *Scanner) SetDataDirs(_ ...string) {} 75 func (s *Scanner) SetPolicyNamespaces(_ ...string) {} 76 77 func (s *Scanner) SetSkipRequiredCheck(skip bool) { 78 s.skipRequired = skip 79 } 80 81 func (s *Scanner) SetPolicyFilesystem(_ fs.FS) { 82 // handled by rego when option is passed on 83 } 84 85 func (s *Scanner) SetDataFilesystem(_ fs.FS) { 86 // handled by rego when option is passed on 87 } 88 func (s *Scanner) SetRegoErrorLimit(_ int) {} 89 90 func NewScanner(opts ...options.ScannerOption) *Scanner { 91 s := &Scanner{ 92 options: opts, 93 } 94 for _, opt := range opts { 95 opt(s) 96 } 97 s.parser = parser.New(options.ParserWithSkipRequiredCheck(s.skipRequired)) 98 return s 99 } 100 101 func (s *Scanner) Name() string { 102 return "JSON" 103 } 104 105 func (s *Scanner) ScanFS(ctx context.Context, fs fs.FS, path string) (scan.Results, error) { 106 107 files, err := s.parser.ParseFS(ctx, fs, path) 108 if err != nil { 109 return nil, err 110 } 111 112 if len(files) == 0 { 113 return nil, nil 114 } 115 116 var inputs []rego.Input 117 for path, file := range files { 118 inputs = append(inputs, rego.Input{ 119 Path: path, 120 FS: fs, 121 Contents: file, 122 }) 123 } 124 125 results, err := s.scanRego(ctx, fs, inputs...) 126 if err != nil { 127 return nil, err 128 } 129 return results, nil 130 } 131 132 func (s *Scanner) ScanFile(ctx context.Context, fs fs.FS, path string) (scan.Results, error) { 133 parsed, err := s.parser.ParseFile(ctx, fs, path) 134 if err != nil { 135 return nil, err 136 } 137 s.debug.Log("Scanning %s...", path) 138 return s.scanRego(ctx, fs, rego.Input{ 139 Path: path, 140 Contents: parsed, 141 }) 142 } 143 144 func (s *Scanner) initRegoScanner(srcFS fs.FS) (*rego.Scanner, error) { 145 s.Lock() 146 defer s.Unlock() 147 if s.regoScanner != nil { 148 return s.regoScanner, nil 149 } 150 regoScanner := rego.NewScanner(types.SourceJSON, s.options...) 151 regoScanner.SetParentDebugLogger(s.debug) 152 if err := regoScanner.LoadPolicies(s.loadEmbeddedLibraries, s.loadEmbeddedPolicies, srcFS, s.policyDirs, s.policyReaders); err != nil { 153 return nil, err 154 } 155 s.regoScanner = regoScanner 156 return regoScanner, nil 157 } 158 159 func (s *Scanner) scanRego(ctx context.Context, srcFS fs.FS, inputs ...rego.Input) (scan.Results, error) { 160 regoScanner, err := s.initRegoScanner(srcFS) 161 if err != nil { 162 return nil, err 163 } 164 results, err := regoScanner.ScanInput(ctx, inputs...) 165 if err != nil { 166 return nil, err 167 } 168 results.SetSourceAndFilesystem("", srcFS, false) 169 return results, nil 170 }