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