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