Conditions | 51 |
Total Lines | 217 |
Code Lines | 138 |
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 |
||
202 | func (p *ReportCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus { |
||
203 | util.Log = util.NewCustomLogger(c.ServerInfo{}) |
||
204 | cvelog.SetLogger(c.Conf.LogDir, false, c.Conf.Debug, false) |
||
205 | |||
206 | if err := c.Load(p.configPath, ""); err != nil { |
||
207 | util.Log.Errorf("Error loading %s, %s", p.configPath, err) |
||
208 | return subcommands.ExitUsageError |
||
209 | } |
||
210 | |||
211 | c.Conf.CveDict.Overwrite(p.cveDict) |
||
212 | c.Conf.OvalDict.Overwrite(p.ovalDict) |
||
213 | c.Conf.Gost.Overwrite(p.gostConf) |
||
214 | c.Conf.Exploit.Overwrite(p.exploitConf) |
||
215 | c.Conf.HTTP.Overwrite(p.httpConf) |
||
216 | |||
217 | var dir string |
||
218 | var err error |
||
219 | if c.Conf.Diff { |
||
220 | dir, err = report.JSONDir([]string{}) |
||
221 | } else { |
||
222 | dir, err = report.JSONDir(f.Args()) |
||
223 | } |
||
224 | if err != nil { |
||
225 | util.Log.Errorf("Failed to read from JSON: %s", err) |
||
226 | return subcommands.ExitFailure |
||
227 | } |
||
228 | |||
229 | // report |
||
230 | reports := []report.ResultWriter{ |
||
231 | report.StdoutWriter{}, |
||
232 | } |
||
233 | |||
234 | if c.Conf.ToSlack { |
||
235 | reports = append(reports, report.SlackWriter{}) |
||
236 | } |
||
237 | |||
238 | if c.Conf.ToStride { |
||
239 | reports = append(reports, report.StrideWriter{}) |
||
240 | } |
||
241 | |||
242 | if c.Conf.ToHipChat { |
||
243 | reports = append(reports, report.HipChatWriter{}) |
||
244 | } |
||
245 | |||
246 | if c.Conf.ToChatWork { |
||
247 | reports = append(reports, report.ChatWorkWriter{}) |
||
248 | } |
||
249 | |||
250 | if c.Conf.ToEmail { |
||
251 | reports = append(reports, report.EMailWriter{}) |
||
252 | } |
||
253 | |||
254 | if c.Conf.ToSyslog { |
||
255 | reports = append(reports, report.SyslogWriter{}) |
||
256 | } |
||
257 | |||
258 | if c.Conf.ToHTTP { |
||
259 | reports = append(reports, report.HTTPRequestWriter{}) |
||
260 | } |
||
261 | |||
262 | if c.Conf.ToLocalFile { |
||
263 | reports = append(reports, report.LocalFileWriter{ |
||
264 | CurrentDir: dir, |
||
265 | }) |
||
266 | } |
||
267 | |||
268 | if c.Conf.ToS3 { |
||
269 | if err := report.CheckIfBucketExists(); err != nil { |
||
270 | util.Log.Errorf("Check if there is a bucket beforehand: %s, err: %s", |
||
271 | c.Conf.AWS.S3Bucket, err) |
||
272 | return subcommands.ExitUsageError |
||
273 | } |
||
274 | reports = append(reports, report.S3Writer{}) |
||
275 | } |
||
276 | |||
277 | if c.Conf.ToAzureBlob { |
||
278 | if len(c.Conf.Azure.AccountName) == 0 { |
||
279 | c.Conf.Azure.AccountName = os.Getenv("AZURE_STORAGE_ACCOUNT") |
||
280 | } |
||
281 | |||
282 | if len(c.Conf.Azure.AccountKey) == 0 { |
||
283 | c.Conf.Azure.AccountKey = os.Getenv("AZURE_STORAGE_ACCESS_KEY") |
||
284 | } |
||
285 | |||
286 | if len(c.Conf.Azure.ContainerName) == 0 { |
||
287 | util.Log.Error("Azure storage container name is required with -azure-container option") |
||
288 | return subcommands.ExitUsageError |
||
289 | } |
||
290 | if err := report.CheckIfAzureContainerExists(); err != nil { |
||
291 | util.Log.Errorf("Check if there is a container beforehand: %s, err: %s", |
||
292 | c.Conf.Azure.ContainerName, err) |
||
293 | return subcommands.ExitUsageError |
||
294 | } |
||
295 | reports = append(reports, report.AzureBlobWriter{}) |
||
296 | } |
||
297 | |||
298 | if c.Conf.ToSaas { |
||
299 | if !c.Conf.UUID { |
||
300 | util.Log.Errorf("If you use the -to-saas option, you need to enable the uuid option") |
||
301 | return subcommands.ExitUsageError |
||
302 | } |
||
303 | reports = append(reports, report.SaasWriter{}) |
||
304 | } |
||
305 | |||
306 | if !(c.Conf.FormatJSON || c.Conf.FormatOneLineText || |
||
307 | c.Conf.FormatList || c.Conf.FormatFullText || c.Conf.FormatXML) { |
||
308 | c.Conf.FormatList = true |
||
309 | } |
||
310 | |||
311 | util.Log.Info("Validating config...") |
||
312 | if !c.Conf.ValidateOnReport() { |
||
313 | return subcommands.ExitUsageError |
||
314 | } |
||
315 | |||
316 | var loaded models.ScanResults |
||
317 | if loaded, err = report.LoadScanResults(dir); err != nil { |
||
318 | util.Log.Error(err) |
||
319 | return subcommands.ExitFailure |
||
320 | } |
||
321 | util.Log.Infof("Loaded: %s", dir) |
||
322 | |||
323 | var res models.ScanResults |
||
324 | for _, r := range loaded { |
||
325 | if len(r.Errors) == 0 { |
||
326 | res = append(res, r) |
||
327 | } else { |
||
328 | util.Log.Warnf("Ignored since errors occurred during scanning: %s", |
||
329 | r.ServerName) |
||
330 | } |
||
331 | } |
||
332 | |||
333 | for _, r := range res { |
||
334 | util.Log.Debugf("%s: %s", |
||
335 | r.ServerInfo(), |
||
336 | pp.Sprintf("%s", c.Conf.Servers[r.ServerName])) |
||
337 | } |
||
338 | |||
339 | if c.Conf.UUID { |
||
340 | // Ensure UUIDs of scan target servers in config.toml |
||
341 | if err := report.EnsureUUIDs(p.configPath, res); err != nil { |
||
342 | util.Log.Errorf("Failed to ensure UUIDs: %s", err) |
||
343 | return subcommands.ExitFailure |
||
344 | } |
||
345 | } |
||
346 | |||
347 | if !c.Conf.ToSaas { |
||
348 | util.Log.Info("Validating db config...") |
||
349 | if !c.Conf.ValidateOnReportDB() { |
||
350 | return subcommands.ExitUsageError |
||
351 | } |
||
352 | |||
353 | if c.Conf.CveDict.URL != "" { |
||
354 | if err := report.CveClient.CheckHealth(); err != nil { |
||
355 | util.Log.Errorf("CVE HTTP server is not running. err: %s", err) |
||
356 | 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") |
||
357 | return subcommands.ExitFailure |
||
358 | } |
||
359 | } |
||
360 | |||
361 | if c.Conf.OvalDict.URL != "" { |
||
362 | err := oval.Base{}.CheckHTTPHealth() |
||
363 | if err != nil { |
||
364 | util.Log.Errorf("OVAL HTTP server is not running. err: %s", err) |
||
365 | 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") |
||
366 | return subcommands.ExitFailure |
||
367 | } |
||
368 | } |
||
369 | |||
370 | if c.Conf.Gost.URL != "" { |
||
371 | util.Log.Infof("gost: %s", c.Conf.Gost.URL) |
||
372 | err := gost.Base{}.CheckHTTPHealth() |
||
373 | if err != nil { |
||
374 | util.Log.Errorf("gost HTTP server is not running. err: %s", err) |
||
375 | util.Log.Errorf("Run gost as server mode before reporting or run with `-gostdb-type=sqlite3 -gostdb-sqlite3-path` option instead of -gostdb-url") |
||
376 | return subcommands.ExitFailure |
||
377 | } |
||
378 | } |
||
379 | |||
380 | if c.Conf.Exploit.URL != "" { |
||
381 | err := exploit.CheckHTTPHealth() |
||
382 | if err != nil { |
||
383 | util.Log.Errorf("exploit HTTP server is not running. err: %s", err) |
||
384 | util.Log.Errorf("Run go-exploitdb as server mode before reporting") |
||
385 | return subcommands.ExitFailure |
||
386 | } |
||
387 | } |
||
388 | dbclient, locked, err := report.NewDBClient(report.DBClientConf{ |
||
389 | CveDictCnf: c.Conf.CveDict, |
||
390 | OvalDictCnf: c.Conf.OvalDict, |
||
391 | GostCnf: c.Conf.Gost, |
||
392 | ExploitCnf: c.Conf.Exploit, |
||
393 | DebugSQL: c.Conf.DebugSQL, |
||
394 | }) |
||
395 | if locked { |
||
396 | util.Log.Errorf("SQLite3 is locked. Close other DB connections and try again: %s", err) |
||
397 | return subcommands.ExitFailure |
||
398 | } |
||
399 | if err != nil { |
||
400 | util.Log.Errorf("Failed to init DB Clients: %s", err) |
||
401 | return subcommands.ExitFailure |
||
402 | } |
||
403 | defer dbclient.CloseDB() |
||
404 | |||
405 | if res, err = report.FillCveInfos(*dbclient, res, dir); err != nil { |
||
406 | util.Log.Error(err) |
||
407 | return subcommands.ExitFailure |
||
408 | } |
||
409 | } |
||
410 | |||
411 | for _, w := range reports { |
||
412 | if err := w.Write(res...); err != nil { |
||
413 | util.Log.Errorf("Failed to report: %s", err) |
||
414 | return subcommands.ExitFailure |
||
415 | } |
||
416 | } |
||
417 | |||
418 | return subcommands.ExitSuccess |
||
419 | } |
||
420 |