github.com/khulnasoft-lab/defsec@v1.0.5-0.20230827010352-5e9f46893d95/pkg/scanners/cloud/aws/scanner.go (about) 1 package aws 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "io" 8 "io/fs" 9 "os" 10 "runtime" 11 "sync" 12 13 adapter "github.com/khulnasoft-lab/defsec/internal/adapters/cloud" 14 cloudoptions "github.com/khulnasoft-lab/defsec/internal/adapters/cloud/options" 15 "github.com/khulnasoft-lab/defsec/pkg/errs" 16 17 "github.com/khulnasoft-lab/defsec/pkg/state" 18 19 "github.com/khulnasoft-lab/defsec/pkg/rego" 20 "github.com/khulnasoft-lab/defsec/pkg/types" 21 22 "github.com/khulnasoft-lab/defsec/internal/adapters/cloud/aws" 23 "github.com/khulnasoft-lab/defsec/internal/rules" 24 "github.com/khulnasoft-lab/defsec/pkg/concurrency" 25 "github.com/khulnasoft-lab/defsec/pkg/debug" 26 "github.com/khulnasoft-lab/defsec/pkg/framework" 27 "github.com/khulnasoft-lab/defsec/pkg/progress" 28 _ "github.com/khulnasoft-lab/defsec/pkg/rules" 29 "github.com/khulnasoft-lab/defsec/pkg/scan" 30 "github.com/khulnasoft-lab/defsec/pkg/scanners/options" 31 ) 32 33 var _ ConfigurableAWSScanner = (*Scanner)(nil) 34 35 type Scanner struct { 36 sync.Mutex 37 regoScanner *rego.Scanner 38 debug debug.Logger 39 options []options.ScannerOption 40 progressTracker progress.Tracker 41 region string 42 endpoint string 43 services []string 44 frameworks []framework.Framework 45 spec string 46 concurrencyStrategy concurrency.Strategy 47 policyDirs []string 48 policyReaders []io.Reader 49 policyFS fs.FS 50 dataFs fs.FS 51 loadEmbeddedPolicies bool 52 loadEmbeddedLibraries bool 53 regoOnly bool 54 } 55 56 func (s *Scanner) SetRegoOnly(value bool) { 57 s.regoOnly = value 58 } 59 60 func (s *Scanner) SetFrameworks(frameworks []framework.Framework) { 61 s.frameworks = frameworks 62 } 63 64 func (s *Scanner) SetSpec(spec string) { 65 s.spec = spec 66 } 67 68 func (s *Scanner) Name() string { 69 return "AWS API" 70 } 71 72 func (s *Scanner) SetDebugWriter(writer io.Writer) { 73 s.debug = debug.New(writer, "aws-api", "scanner") 74 } 75 76 func (s *Scanner) SetProgressTracker(t progress.Tracker) { 77 s.progressTracker = t 78 } 79 80 func (s *Scanner) SetPolicyReaders(readers []io.Reader) { 81 s.policyReaders = readers 82 } 83 84 func (s *Scanner) SetPolicyDirs(dirs ...string) { 85 s.policyDirs = dirs 86 } 87 88 func (s *Scanner) SetPolicyFilesystem(fs fs.FS) { 89 s.policyFS = fs 90 } 91 92 func (s *Scanner) SetDataFilesystem(fs fs.FS) { 93 s.dataFs = fs 94 } 95 96 func (s *Scanner) SetUseEmbeddedPolicies(b bool) { 97 s.loadEmbeddedPolicies = b 98 } 99 100 func (s *Scanner) SetUseEmbeddedLibraries(b bool) { 101 s.loadEmbeddedLibraries = b 102 } 103 104 func (s *Scanner) SetTraceWriter(writer io.Writer) {} 105 func (s *Scanner) SetPerResultTracingEnabled(b bool) {} 106 func (s *Scanner) SetDataDirs(s2 ...string) {} 107 func (s *Scanner) SetPolicyNamespaces(s2 ...string) {} 108 func (s *Scanner) SetSkipRequiredCheck(b bool) {} 109 func (s *Scanner) SetRegoErrorLimit(_ int) {} 110 111 func AllSupportedServices() []string { 112 return aws.AllServices() 113 } 114 115 func (s *Scanner) SetAWSRegion(region string) { 116 s.region = region 117 } 118 119 func (s *Scanner) SetAWSEndpoint(endpoint string) { 120 s.endpoint = endpoint 121 } 122 123 func (s *Scanner) SetAWSServices(services []string) { 124 s.services = services 125 } 126 127 func (s *Scanner) SetConcurrencyStrategy(strategy concurrency.Strategy) { 128 s.concurrencyStrategy = strategy 129 } 130 131 func New(opts ...options.ScannerOption) *Scanner { 132 133 s := &Scanner{ 134 options: opts, 135 progressTracker: progress.NoProgress, 136 concurrencyStrategy: concurrency.DefaultStrategy, 137 } 138 for _, opt := range opts { 139 opt(s) 140 } 141 return s 142 } 143 144 func (s *Scanner) CreateState(ctx context.Context) (*state.State, error) { 145 cloudState, err := adapter.Adapt(ctx, cloudoptions.Options{ 146 ProgressTracker: s.progressTracker, 147 Region: s.region, 148 Endpoint: s.endpoint, 149 Services: s.services, 150 DebugWriter: s.debug, 151 ConcurrencyStrategy: s.concurrencyStrategy, 152 }) 153 if err != nil { 154 var adaptionError errs.AdapterError 155 if errors.As(err, &adaptionError) { 156 s.debug.Log("There were %d errors during adaption process: %s", len(adaptionError.Errors()), adaptionError) 157 } else { 158 return nil, err 159 } 160 } 161 return cloudState, nil 162 } 163 164 func (s *Scanner) ScanWithStateRefresh(ctx context.Context) (results scan.Results, err error) { 165 cloudState, err := s.CreateState(ctx) 166 if err != nil { 167 return nil, err 168 } 169 return s.Scan(ctx, cloudState) 170 } 171 172 func (s *Scanner) Scan(ctx context.Context, cloudState *state.State) (results scan.Results, err error) { 173 174 if cloudState == nil { 175 return nil, fmt.Errorf("cloud state is nil") 176 } 177 178 // evaluate go rules 179 if !s.regoOnly { 180 for _, rule := range s.getRegisteredRules() { 181 select { 182 case <-ctx.Done(): 183 return nil, ctx.Err() 184 default: 185 } 186 if rule.Rule().RegoPackage != "" { 187 continue 188 } 189 ruleResults := rule.Evaluate(cloudState) 190 if len(ruleResults) > 0 { 191 s.debug.Log("Found %d results for %s", len(ruleResults), rule.Rule().AVDID) 192 results = append(results, ruleResults...) 193 } 194 } 195 } 196 197 // evaluate rego rules 198 regoScanner, err := s.initRegoScanner() 199 if err != nil { 200 return nil, err 201 } 202 regoResults, err := regoScanner.ScanInput(ctx, rego.Input{ 203 Contents: cloudState.ToRego(), 204 }) 205 if err != nil { 206 return nil, err 207 } 208 return append(results, regoResults...), nil 209 } 210 211 func (s *Scanner) getRegisteredRules() []rules.RegisteredRule { 212 if len(s.frameworks) > 0 { // Only for maintaining backwards compat 213 return rules.GetFrameworkRules(s.frameworks...) 214 } 215 return rules.GetSpecRules(s.spec) 216 } 217 218 func (s *Scanner) initRegoScanner() (*rego.Scanner, error) { 219 s.Lock() 220 defer s.Unlock() 221 if s.regoScanner != nil { 222 return s.regoScanner, nil 223 } 224 225 srcFS := s.policyFS 226 if srcFS == nil { 227 if runtime.GOOS == "windows" { 228 homeDrive := os.Getenv("HOMEDRIVE") 229 if homeDrive == "" { 230 homeDrive = "C:" 231 } 232 srcFS = os.DirFS(homeDrive + "\\") 233 } else { 234 srcFS = os.DirFS("/") 235 } 236 } 237 238 regoScanner := rego.NewScanner(types.SourceCloud, s.options...) 239 regoScanner.SetParentDebugLogger(s.debug) 240 if err := regoScanner.LoadPolicies(s.loadEmbeddedLibraries, s.loadEmbeddedPolicies, srcFS, s.policyDirs, s.policyReaders); err != nil { 241 return nil, err 242 } 243 s.regoScanner = regoScanner 244 return regoScanner, nil 245 }