|
@@ -9,7 +9,7 @@ import (
|
|
|
"os"
|
|
"os"
|
|
|
"os/exec"
|
|
"os/exec"
|
|
|
"os/signal"
|
|
"os/signal"
|
|
|
- "strings"
|
|
|
|
|
|
|
+ "path/filepath"
|
|
|
"sync"
|
|
"sync"
|
|
|
"syscall"
|
|
"syscall"
|
|
|
)
|
|
)
|
|
@@ -22,64 +22,74 @@ type LeakElem struct {
|
|
|
Reason string `json:"reason"`
|
|
Reason string `json:"reason"`
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// start clones and determines if there are any leaks
|
|
|
|
|
-func start(opts *Options) {
|
|
|
|
|
|
|
+func start(repos []RepoDesc, owner *Owner, opts *Options) {
|
|
|
|
|
+ var report []LeakElem
|
|
|
|
|
+
|
|
|
|
|
+ // interrupt handling
|
|
|
c := make(chan os.Signal, 2)
|
|
c := make(chan os.Signal, 2)
|
|
|
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
|
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
|
|
-
|
|
|
|
|
- fmt.Printf("Cloning \x1b[37;1m%s\x1b[0m...\n", opts.RepoURL)
|
|
|
|
|
- err := exec.Command("git", "clone", opts.RepoURL).Run()
|
|
|
|
|
- if err != nil {
|
|
|
|
|
- log.Printf("failed to clone repo %v", err)
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
- fmt.Printf("Evaluating \x1b[37;1m%s\x1b[0m...\n", opts.RepoURL)
|
|
|
|
|
- repoName := getLocalRepoName(opts.RepoURL)
|
|
|
|
|
- if err = os.Chdir(repoName); err != nil {
|
|
|
|
|
- log.Fatal(err)
|
|
|
|
|
- }
|
|
|
|
|
go func() {
|
|
go func() {
|
|
|
<-c
|
|
<-c
|
|
|
- cleanup(repoName)
|
|
|
|
|
- os.Exit(1)
|
|
|
|
|
|
|
+ if opts.Tmp {
|
|
|
|
|
+ err := os.RemoveAll(owner.path)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ log.Printf("failed to properly remove tmp gitleaks dir: %v", err)
|
|
|
|
|
+ // exit code?
|
|
|
|
|
+ }
|
|
|
|
|
+ os.Exit(1)
|
|
|
|
|
+ }
|
|
|
}()
|
|
}()
|
|
|
|
|
|
|
|
- report := getLeaks(repoName, opts)
|
|
|
|
|
- if len(report) == 0 {
|
|
|
|
|
- fmt.Printf("No Leaks detected for \x1b[35;2m%s\x1b[0m...\n\n", opts.RepoURL)
|
|
|
|
|
- }
|
|
|
|
|
- cleanup(repoName)
|
|
|
|
|
- reportJSON, _ := json.MarshalIndent(report, "", "\t")
|
|
|
|
|
- err = ioutil.WriteFile(fmt.Sprintf("%s_leaks.json", repoName), reportJSON, 0644)
|
|
|
|
|
- if err != nil {
|
|
|
|
|
- log.Fatalf("Can't write to file: %s", err)
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
|
|
+ // run checks on repos
|
|
|
|
|
+ for _, repo := range repos {
|
|
|
|
|
+ // change to owner root
|
|
|
|
|
+ if err := os.Chdir(fmt.Sprintf(owner.path)); err != nil {
|
|
|
|
|
+ log.Fatal(err)
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
-// getLocalRepoName generates the name of the local clone folder based on the given URL
|
|
|
|
|
-func getLocalRepoName(url string) string {
|
|
|
|
|
- splitSlashes := strings.Split(url, "/")
|
|
|
|
|
- name := splitSlashes[len(splitSlashes)-1]
|
|
|
|
|
- name = strings.TrimSuffix(name, ".git")
|
|
|
|
|
- splitColons := strings.Split(name, ":")
|
|
|
|
|
- name = splitColons[len(splitColons)-1]
|
|
|
|
|
|
|
+ dotGitPath := filepath.Join(repo.path, ".git")
|
|
|
|
|
+ if _, err := os.Stat(dotGitPath); err == nil {
|
|
|
|
|
+ report = getLeaks(repo, opts)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ fmt.Printf("Cloning \x1b[37;1m%s\x1b[0m...\n", repo.url)
|
|
|
|
|
+ err := exec.Command("git", "clone", repo.url).Run()
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ log.Printf("failed to clone repo %v", err)
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ report = getLeaks(repo, opts)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if len(report) == 0 {
|
|
|
|
|
+ fmt.Printf("No Leaks detected for \x1b[35;2m%s\x1b[0m...\n\n", repo.url)
|
|
|
|
|
+ }
|
|
|
|
|
+ fmt.Println(opts.EnableJSON)
|
|
|
|
|
+ // write report
|
|
|
|
|
+ if opts.EnableJSON {
|
|
|
|
|
+ writeGitLeaksReport(report, repo, opts)
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- return name
|
|
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// cleanup deletes the repo
|
|
|
|
|
-func cleanup(repoName string) {
|
|
|
|
|
- if err := os.Chdir(appRoot); err != nil {
|
|
|
|
|
- log.Fatalf("failed cleaning up repo. Does the repo exist? %v", err)
|
|
|
|
|
|
|
+func writeGitLeaksReport(report []LeakElem, repo RepoDesc, opts *Options) {
|
|
|
|
|
+ fmt.Println("writing report")
|
|
|
|
|
+ reportJSON, _ := json.MarshalIndent(report, "", "\t")
|
|
|
|
|
+ if _, err := os.Stat(repo.owner.reportPath); os.IsNotExist(err) {
|
|
|
|
|
+ os.Mkdir(repo.owner.reportPath, os.ModePerm)
|
|
|
}
|
|
}
|
|
|
- err := exec.Command("rm", "-rf", repoName).Run()
|
|
|
|
|
|
|
+
|
|
|
|
|
+ reportFileName := fmt.Sprintf("%s_leaks.json", repo.name)
|
|
|
|
|
+ reportFile := filepath.Join(repo.owner.reportPath, reportFileName)
|
|
|
|
|
+ err := ioutil.WriteFile(reportFile, reportJSON, 0644)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
- log.Fatal(err)
|
|
|
|
|
|
|
+ log.Fatalf("Can't write to file: %s", err)
|
|
|
|
|
+
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// getLeaks will attempt to find gitleaks
|
|
// getLeaks will attempt to find gitleaks
|
|
|
-func getLeaks(repoName string, opts *Options) []LeakElem {
|
|
|
|
|
|
|
+func getLeaks(repo RepoDesc, opts *Options) []LeakElem {
|
|
|
var (
|
|
var (
|
|
|
out []byte
|
|
out []byte
|
|
|
err error
|
|
err error
|
|
@@ -102,6 +112,10 @@ func getLeaks(repoName string, opts *Options) []LeakElem {
|
|
|
}
|
|
}
|
|
|
}(&commitWG, &gitLeakReceiverWG)
|
|
}(&commitWG, &gitLeakReceiverWG)
|
|
|
|
|
|
|
|
|
|
+ if err := os.Chdir(fmt.Sprintf(repo.path)); err != nil {
|
|
|
|
|
+ log.Fatal(err)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
out, err = exec.Command("git", "rev-list", "--all", "--remotes", "--topo-order").Output()
|
|
out, err = exec.Command("git", "rev-list", "--all", "--remotes", "--topo-order").Output()
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
log.Fatalf("error retrieving commits%v\n", err)
|
|
log.Fatalf("error retrieving commits%v\n", err)
|
|
@@ -119,11 +133,10 @@ func getLeaks(repoName string, opts *Options) []LeakElem {
|
|
|
|
|
|
|
|
commitWG.Add(1)
|
|
commitWG.Add(1)
|
|
|
go func(currCommit string, repoName string, commitWG *sync.WaitGroup,
|
|
go func(currCommit string, repoName string, commitWG *sync.WaitGroup,
|
|
|
- gitLeakReceiverWG *sync.WaitGroup) {
|
|
|
|
|
|
|
+ gitLeakReceiverWG *sync.WaitGroup, opts *Options) {
|
|
|
|
|
|
|
|
defer commitWG.Done()
|
|
defer commitWG.Done()
|
|
|
-
|
|
|
|
|
- if err := os.Chdir(fmt.Sprintf("%s/%s", appRoot, repoName)); err != nil {
|
|
|
|
|
|
|
+ if err := os.Chdir(fmt.Sprintf(repo.path)); err != nil {
|
|
|
log.Fatal(err)
|
|
log.Fatal(err)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -134,11 +147,10 @@ func getLeaks(repoName string, opts *Options) []LeakElem {
|
|
|
|
|
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
fmt.Printf("error retrieving diff for commit %s try turning concurrency factor down %v\n", currCommit, err)
|
|
fmt.Printf("error retrieving diff for commit %s try turning concurrency factor down %v\n", currCommit, err)
|
|
|
- cleanup(repoName)
|
|
|
|
|
- return
|
|
|
|
|
|
|
+ log.Fatal(err)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- leaks := doChecks(string(out), currCommit)
|
|
|
|
|
|
|
+ leaks := doChecks(string(out), currCommit, opts)
|
|
|
if len(leaks) == 0 {
|
|
if len(leaks) == 0 {
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
@@ -147,7 +159,7 @@ func getLeaks(repoName string, opts *Options) []LeakElem {
|
|
|
gitLeaks <- leak
|
|
gitLeaks <- leak
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- }(currCommit, repoName, &commitWG, &gitLeakReceiverWG)
|
|
|
|
|
|
|
+ }(currCommit, repo.name, &commitWG, &gitLeakReceiverWG, opts)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
commitWG.Wait()
|
|
commitWG.Wait()
|