Conditions | 51 |
Total Lines | 231 |
Code Lines | 146 |
Lines | 0 |
Ratio | 0 % |
Changes | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like commands.*ReportCmd.Execute often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
1 | /* Vuls - Vulnerability Scanner |
||
207 | func (p *ReportCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus { |
||
208 | util.Log = util.NewCustomLogger(c.ServerInfo{}) |
||
209 | cvelog.SetLogger(c.Conf.LogDir, false, c.Conf.Debug, false) |
||
210 | |||
211 | if err := c.Load(p.configPath, ""); err != nil { |
||
212 | util.Log.Errorf("Error loading %s, %+v", p.configPath, err) |
||
213 | return subcommands.ExitUsageError |
||
214 | } |
||
215 | |||
216 | c.Conf.CveDict.Overwrite(p.cveDict) |
||
217 | c.Conf.OvalDict.Overwrite(p.ovalDict) |
||
218 | c.Conf.Gost.Overwrite(p.gostConf) |
||
219 | c.Conf.Exploit.Overwrite(p.exploitConf) |
||
220 | c.Conf.HTTP.Overwrite(p.httpConf) |
||
221 | |||
222 | var dir string |
||
223 | var err error |
||
224 | if c.Conf.Diff { |
||
225 | dir, err = report.JSONDir([]string{}) |
||
226 | } else { |
||
227 | dir, err = report.JSONDir(f.Args()) |
||
228 | } |
||
229 | if err != nil { |
||
230 | util.Log.Errorf("Failed to read from JSON: %+v", err) |
||
231 | return subcommands.ExitFailure |
||
232 | } |
||
233 | |||
234 | // report |
||
235 | reports := []report.ResultWriter{ |
||
236 | report.StdoutWriter{}, |
||
237 | } |
||
238 | |||
239 | if c.Conf.ToSlack { |
||
240 | reports = append(reports, report.SlackWriter{}) |
||
241 | } |
||
242 | |||
243 | if c.Conf.ToStride { |
||
244 | reports = append(reports, report.StrideWriter{}) |
||
245 | } |
||
246 | |||
247 | if c.Conf.ToHipChat { |
||
248 | reports = append(reports, report.HipChatWriter{}) |
||
249 | } |
||
250 | |||
251 | if c.Conf.ToChatWork { |
||
252 | reports = append(reports, report.ChatWorkWriter{}) |
||
253 | } |
||
254 | |||
255 | if c.Conf.ToTelegram { |
||
256 | reports = append(reports, report.TelegramWriter{}) |
||
257 | } |
||
258 | |||
259 | if c.Conf.ToEmail { |
||
260 | reports = append(reports, report.EMailWriter{}) |
||
261 | } |
||
262 | |||
263 | if c.Conf.ToSyslog { |
||
264 | reports = append(reports, report.SyslogWriter{}) |
||
265 | } |
||
266 | |||
267 | if c.Conf.ToHTTP { |
||
268 | reports = append(reports, report.HTTPRequestWriter{}) |
||
269 | } |
||
270 | |||
271 | if c.Conf.ToLocalFile { |
||
272 | reports = append(reports, report.LocalFileWriter{ |
||
273 | CurrentDir: dir, |
||
274 | }) |
||
275 | } |
||
276 | |||
277 | if c.Conf.ToS3 { |
||
278 | if err := report.CheckIfBucketExists(); err != nil { |
||
279 | util.Log.Errorf("Check if there is a bucket beforehand: %s, err: %+v", |
||
280 | c.Conf.AWS.S3Bucket, err) |
||
281 | return subcommands.ExitUsageError |
||
282 | } |
||
283 | reports = append(reports, report.S3Writer{}) |
||
284 | } |
||
285 | |||
286 | if c.Conf.ToAzureBlob { |
||
287 | if len(c.Conf.Azure.AccountName) == 0 { |
||
288 | c.Conf.Azure.AccountName = os.Getenv("AZURE_STORAGE_ACCOUNT") |
||
289 | } |
||
290 | |||
291 | if len(c.Conf.Azure.AccountKey) == 0 { |
||
292 | c.Conf.Azure.AccountKey = os.Getenv("AZURE_STORAGE_ACCESS_KEY") |
||
293 | } |
||
294 | |||
295 | if len(c.Conf.Azure.ContainerName) == 0 { |
||
296 | util.Log.Error("Azure storage container name is required with -azure-container option") |
||
297 | return subcommands.ExitUsageError |
||
298 | } |
||
299 | if err := report.CheckIfAzureContainerExists(); err != nil { |
||
300 | util.Log.Errorf("Check if there is a container beforehand: %s, err: %+v", |
||
301 | c.Conf.Azure.ContainerName, err) |
||
302 | return subcommands.ExitUsageError |
||
303 | } |
||
304 | reports = append(reports, report.AzureBlobWriter{}) |
||
305 | } |
||
306 | |||
307 | if c.Conf.ToSaas { |
||
308 | if !c.Conf.UUID { |
||
309 | util.Log.Errorf("If you use the -to-saas option, you need to enable the uuid option") |
||
310 | return subcommands.ExitUsageError |
||
311 | } |
||
312 | reports = append(reports, report.SaasWriter{}) |
||
313 | } |
||
314 | |||
315 | if !(c.Conf.FormatJSON || c.Conf.FormatOneLineText || |
||
316 | c.Conf.FormatList || c.Conf.FormatFullText || c.Conf.FormatXML) { |
||
317 | c.Conf.FormatList = true |
||
318 | } |
||
319 | |||
320 | util.Log.Info("Validating config...") |
||
321 | if !c.Conf.ValidateOnReport() { |
||
322 | return subcommands.ExitUsageError |
||
323 | } |
||
324 | |||
325 | var loaded models.ScanResults |
||
326 | if loaded, err = report.LoadScanResults(dir); err != nil { |
||
327 | util.Log.Error(err) |
||
328 | return subcommands.ExitFailure |
||
329 | } |
||
330 | util.Log.Infof("Loaded: %s", dir) |
||
331 | |||
332 | var res models.ScanResults |
||
333 | hasError := false |
||
334 | for _, r := range loaded { |
||
335 | if len(r.Errors) == 0 { |
||
336 | res = append(res, r) |
||
337 | } else { |
||
338 | util.Log.Errorf("Ignored since errors occurred during scanning: %s, err: %v", |
||
339 | r.ServerName, r.Errors) |
||
340 | hasError = true |
||
341 | } |
||
342 | } |
||
343 | |||
344 | if len(res) == 0 { |
||
345 | return subcommands.ExitFailure |
||
346 | } |
||
347 | |||
348 | for _, r := range res { |
||
349 | util.Log.Debugf("%s: %s", |
||
350 | r.ServerInfo(), |
||
351 | pp.Sprintf("%s", c.Conf.Servers[r.ServerName])) |
||
352 | } |
||
353 | |||
354 | if c.Conf.UUID { |
||
355 | // Ensure UUIDs of scan target servers in config.toml |
||
356 | if err := report.EnsureUUIDs(p.configPath, res); err != nil { |
||
357 | util.Log.Errorf("Failed to ensure UUIDs. err: %+v", err) |
||
358 | return subcommands.ExitFailure |
||
359 | } |
||
360 | } |
||
361 | |||
362 | if !c.Conf.ToSaas { |
||
363 | util.Log.Info("Validating db config...") |
||
364 | if !c.Conf.ValidateOnReportDB() { |
||
365 | return subcommands.ExitUsageError |
||
366 | } |
||
367 | |||
368 | if c.Conf.CveDict.URL != "" { |
||
369 | if err := report.CveClient.CheckHealth(); err != nil { |
||
370 | util.Log.Errorf("CVE HTTP server is not running. err: %+v", err) |
||
371 | util.Log.Errorf("Run go-cve-dictionary as server mode before reporting or run with `-cvedb-type=sqlite3 -cvedb-sqlite3-path` option instead of -cvedb-url") |
||
372 | return subcommands.ExitFailure |
||
373 | } |
||
374 | } |
||
375 | |||
376 | if c.Conf.OvalDict.URL != "" { |
||
377 | err := oval.Base{}.CheckHTTPHealth() |
||
378 | if err != nil { |
||
379 | util.Log.Errorf("OVAL HTTP server is not running. err: %+v", err) |
||
380 | util.Log.Errorf("Run goval-dictionary as server mode before reporting or run with `-ovaldb-type=sqlite3 -ovaldb-sqlite3-path` option instead of -ovaldb-url") |
||
381 | return subcommands.ExitFailure |
||
382 | } |
||
383 | } |
||
384 | |||
385 | if c.Conf.Gost.URL != "" { |
||
386 | util.Log.Infof("gost: %s", c.Conf.Gost.URL) |
||
387 | err := gost.Base{}.CheckHTTPHealth() |
||
388 | if err != nil { |
||
389 | util.Log.Errorf("gost HTTP server is not running. err: %+v", err) |
||
390 | util.Log.Errorf("Run gost as server mode before reporting or run with `-gostdb-type=sqlite3 -gostdb-sqlite3-path` option instead of -gostdb-url") |
||
391 | return subcommands.ExitFailure |
||
392 | } |
||
393 | } |
||
394 | |||
395 | if c.Conf.Exploit.URL != "" { |
||
396 | err := exploit.CheckHTTPHealth() |
||
397 | if err != nil { |
||
398 | util.Log.Errorf("exploit HTTP server is not running. err: %+v", err) |
||
399 | util.Log.Errorf("Run go-exploitdb as server mode before reporting") |
||
400 | return subcommands.ExitFailure |
||
401 | } |
||
402 | } |
||
403 | dbclient, locked, err := report.NewDBClient(report.DBClientConf{ |
||
404 | CveDictCnf: c.Conf.CveDict, |
||
405 | OvalDictCnf: c.Conf.OvalDict, |
||
406 | GostCnf: c.Conf.Gost, |
||
407 | ExploitCnf: c.Conf.Exploit, |
||
408 | DebugSQL: c.Conf.DebugSQL, |
||
409 | }) |
||
410 | if locked { |
||
411 | util.Log.Errorf("SQLite3 is locked. Close other DB connections and try again. err: %+v", err) |
||
412 | return subcommands.ExitFailure |
||
413 | } |
||
414 | if err != nil { |
||
415 | util.Log.Errorf("Failed to init DB Clients. err: %+v", err) |
||
416 | return subcommands.ExitFailure |
||
417 | } |
||
418 | defer dbclient.CloseDB() |
||
419 | |||
420 | if res, err = report.FillCveInfos(*dbclient, res, dir); err != nil { |
||
421 | util.Log.Errorf("%+v", err) |
||
422 | return subcommands.ExitFailure |
||
423 | } |
||
424 | } |
||
425 | |||
426 | for _, w := range reports { |
||
427 | if err := w.Write(res...); err != nil { |
||
428 | util.Log.Errorf("Failed to report. err: %+v", err) |
||
429 | return subcommands.ExitFailure |
||
430 | } |
||
431 | } |
||
432 | |||
433 | if hasError { |
||
434 | return subcommands.ExitFailure |
||
435 | } |
||
436 | |||
437 | return subcommands.ExitSuccess |
||
438 | } |
||
439 |