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