detect.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package cmd
  2. import (
  3. "os"
  4. "time"
  5. "github.com/rs/zerolog/log"
  6. "github.com/spf13/cobra"
  7. "github.com/zricethezav/gitleaks/v8/report"
  8. "github.com/zricethezav/gitleaks/v8/sources"
  9. )
  10. func init() {
  11. rootCmd.AddCommand(detectCmd)
  12. detectCmd.Flags().Bool("no-git", false, "treat git repo as a regular directory and scan those files, --log-opts has no effect on the scan when --no-git is set")
  13. detectCmd.Flags().Bool("pipe", false, "scan input from stdin, ex: `cat some_file | gitleaks detect --pipe`")
  14. }
  15. var detectCmd = &cobra.Command{
  16. Use: "detect",
  17. Short: "detect secrets in code",
  18. Run: runDetect,
  19. }
  20. func runDetect(cmd *cobra.Command, args []string) {
  21. initConfig()
  22. var (
  23. findings []report.Finding
  24. err error
  25. )
  26. // setup config (aka, the thing that defines rules)
  27. cfg := Config(cmd)
  28. // start timer
  29. start := time.Now()
  30. // grab source
  31. source, err := cmd.Flags().GetString("source")
  32. if err != nil {
  33. log.Fatal().Err(err).Msg("could not get source")
  34. }
  35. detector := Detector(cmd, cfg, source)
  36. // set exit code
  37. exitCode, err := cmd.Flags().GetInt("exit-code")
  38. if err != nil {
  39. log.Fatal().Err(err).Msg("could not get exit code")
  40. }
  41. // determine what type of scan:
  42. // - git: scan the history of the repo
  43. // - no-git: scan files by treating the repo as a plain directory
  44. noGit, err := cmd.Flags().GetBool("no-git")
  45. if err != nil {
  46. log.Fatal().Err(err).Msg("could not call GetBool() for no-git")
  47. }
  48. fromPipe, err := cmd.Flags().GetBool("pipe")
  49. if err != nil {
  50. log.Fatal().Err(err).Msg("could not call GetBool() for pipe")
  51. }
  52. // start the detector scan
  53. if noGit {
  54. var paths <-chan sources.ScanTarget
  55. paths, err = sources.DirectoryTargets(source, detector.Sema, detector.FollowSymlinks)
  56. if err != nil {
  57. log.Fatal().Err(err)
  58. }
  59. findings, err = detector.DetectFiles(paths)
  60. if err != nil {
  61. // don't exit on error, just log it
  62. log.Error().Err(err).Msg("failed scan directory")
  63. }
  64. } else if fromPipe {
  65. findings, err = detector.DetectReader(os.Stdin, 10)
  66. if err != nil {
  67. // log fatal to exit, no need to continue since a report
  68. // will not be generated when scanning from a pipe...for now
  69. log.Fatal().Err(err).Msg("failed scan input from stdin")
  70. }
  71. } else {
  72. var (
  73. gitCmd *sources.GitCmd
  74. logOpts string
  75. )
  76. logOpts, err = cmd.Flags().GetString("log-opts")
  77. if err != nil {
  78. log.Fatal().Err(err).Msg("could not call GetString() for log-opts")
  79. }
  80. gitCmd, err = sources.NewGitLogCmd(source, logOpts)
  81. if err != nil {
  82. log.Fatal().Err(err).Msg("could not create Git cmd")
  83. }
  84. findings, err = detector.DetectGit(gitCmd)
  85. if err != nil {
  86. // don't exit on error, just log it
  87. log.Error().Err(err).Msg("failed to scan Git repository")
  88. }
  89. }
  90. findingSummaryAndExit(findings, cmd, cfg, exitCode, start, err)
  91. }