github.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. package hosts
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/google/go-github/github"
  6. log "github.com/sirupsen/logrus"
  7. "github.com/zricethezav/gitleaks-ng/audit"
  8. "github.com/zricethezav/gitleaks-ng/manager"
  9. "github.com/zricethezav/gitleaks-ng/options"
  10. "golang.org/x/oauth2"
  11. "gopkg.in/src-d/go-git.v4"
  12. "gopkg.in/src-d/go-git.v4/plumbing"
  13. "gopkg.in/src-d/go-git.v4/plumbing/object"
  14. "strconv"
  15. "strings"
  16. "sync"
  17. )
  18. type GithubError struct {
  19. Err string
  20. Repo string
  21. Commit string
  22. }
  23. func (githubError *GithubError) Error() string {
  24. return fmt.Sprintf("repo: %s, err: %s",
  25. githubError.Repo, githubError.Err)
  26. }
  27. type Github struct {
  28. client *github.Client
  29. errChan chan GithubError
  30. manager manager.Manager
  31. wg sync.WaitGroup
  32. }
  33. func NewGithubClient(m manager.Manager) *Github {
  34. ctx := context.Background()
  35. token := oauth2.StaticTokenSource(
  36. &oauth2.Token{AccessToken: options.GetAccessToken(m.Opts)},
  37. )
  38. return &Github{
  39. manager: m,
  40. client: github.NewClient(oauth2.NewClient(ctx, token)),
  41. errChan: make(chan GithubError),
  42. }
  43. }
  44. // Audit will audit a github user or organization's repos.
  45. func (g *Github) Audit() {
  46. ctx := context.Background()
  47. listOptions := github.ListOptions{
  48. PerPage: 100,
  49. }
  50. var githubRepos []*github.Repository
  51. for {
  52. var (
  53. _githubRepos []*github.Repository
  54. resp *github.Response
  55. err error
  56. )
  57. if g.manager.Opts.User != "" {
  58. _githubRepos, resp, err = g.client.Repositories.List(ctx, g.manager.Opts.User,
  59. &github.RepositoryListOptions{ListOptions: listOptions})
  60. } else if g.manager.Opts.Organization != "" {
  61. _githubRepos, resp, err = g.client.Repositories.ListByOrg(ctx, g.manager.Opts.Organization,
  62. &github.RepositoryListByOrgOptions{ListOptions: listOptions})
  63. }
  64. githubRepos = append(githubRepos, _githubRepos...)
  65. if resp == nil {
  66. break
  67. }
  68. listOptions.Page = resp.NextPage
  69. if err != nil || listOptions.Page == 0 {
  70. break
  71. }
  72. }
  73. for _, repo := range githubRepos {
  74. r := audit.NewRepo(&g.manager)
  75. err := r.Clone(&git.CloneOptions{
  76. URL: *repo.CloneURL,
  77. })
  78. r.Name = *repo.Name
  79. if err != nil {
  80. log.Warn(err)
  81. }
  82. if err = r.Audit(); err != nil {
  83. log.Warn(err)
  84. }
  85. }
  86. }
  87. // AuditPR audits a single github PR
  88. func (g *Github) AuditPR() {
  89. ctx := context.Background()
  90. splits := strings.Split(g.manager.Opts.PullRequest, "/")
  91. owner := splits[len(splits)-4]
  92. repoName := splits[len(splits)-3]
  93. prNum, err := strconv.Atoi(splits[len(splits)-1])
  94. repo := audit.NewRepo(&g.manager)
  95. repo.Name = repoName
  96. log.Infof("auditing pr %s\n", g.manager.Opts.PullRequest)
  97. if err != nil {
  98. return
  99. }
  100. page := 1
  101. for {
  102. commits, resp, err := g.client.PullRequests.ListCommits(ctx, owner, repoName, prNum, &github.ListOptions{
  103. PerPage: 100, Page: page})
  104. if err != nil {
  105. return
  106. }
  107. for _, c := range commits {
  108. c, _, err := g.client.Repositories.GetCommit(ctx, owner, repo.Name, *c.SHA)
  109. if err != nil {
  110. continue
  111. }
  112. commitObj := object.Commit{
  113. Hash: plumbing.NewHash(*c.SHA),
  114. Author: object.Signature{
  115. Name: *c.Commit.Author.Name,
  116. Email: *c.Commit.Author.Email,
  117. When: *c.Commit.Author.Date,
  118. },
  119. }
  120. for _, f := range c.Files {
  121. if f.Patch == nil {
  122. continue
  123. }
  124. audit.InspectString(*f.Patch, &commitObj, repo, *f.Filename)
  125. }
  126. }
  127. page = resp.NextPage
  128. if resp.LastPage == 0 {
  129. break
  130. }
  131. }
  132. }