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