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