gitlab.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "os"
  6. log "github.com/sirupsen/logrus"
  7. "github.com/xanzy/go-gitlab"
  8. "gopkg.in/src-d/go-git.v4"
  9. "gopkg.in/src-d/go-git.v4/storage/memory"
  10. )
  11. // auditGitlabRepos kicks off audits if --gitlab-user or --gitlab-org options are set.
  12. // Getting all repositories from the GitLab API and run audit. If an error occurs during an audit of a repo,
  13. // that error is logged.
  14. func auditGitlabRepos() ([]Leak, error) {
  15. leaks := make([]Leak, 0)
  16. repos := make([]*gitlab.Project, 0, 10)
  17. page := 1
  18. cl := gitlab.NewClient(nil, os.Getenv("GITLAB_TOKEN"))
  19. // if self hosted GitLab server
  20. if url := os.Getenv("GITLAB_URL"); url != "" {
  21. cl.SetBaseURL(url)
  22. }
  23. var (
  24. ps []*gitlab.Project
  25. resp *gitlab.Response
  26. err error
  27. )
  28. for {
  29. if opts.GitLabOrg != "" {
  30. opt := &gitlab.ListGroupProjectsOptions{
  31. ListOptions: gitlab.ListOptions{
  32. PerPage: 10,
  33. Page: page,
  34. },
  35. }
  36. ps, resp, err = cl.Groups.ListGroupProjects(opts.GitLabOrg, opt)
  37. } else if opts.GitLabUser != "" {
  38. opt := &gitlab.ListProjectsOptions{
  39. ListOptions: gitlab.ListOptions{
  40. PerPage: 10,
  41. Page: page,
  42. },
  43. }
  44. ps, resp, err = cl.Projects.ListUserProjects(opts.GitLabUser, opt)
  45. }
  46. if err != nil {
  47. log.Fatal("error listing projects: ", err) // exit when can't make API call
  48. }
  49. repos = append(repos, ps...)
  50. if page >= resp.TotalPages {
  51. break // exit when we've seen all pages
  52. }
  53. page = resp.NextPage
  54. }
  55. log.Infof("found projects: %d", len(repos))
  56. tempDir, err := createGitlabTempDir()
  57. if err != nil {
  58. log.Fatal("error creating temp directory: ", err)
  59. }
  60. // TODO: use goroutines?
  61. for _, p := range repos {
  62. repo, err := cloneGitlabRepo(tempDir, p)
  63. if err != nil {
  64. log.Warn(err)
  65. continue
  66. }
  67. leaksFromRepo, err := auditGitRepo(repo)
  68. if err != nil {
  69. log.Warn(err)
  70. }
  71. if opts.Disk {
  72. os.RemoveAll(fmt.Sprintf("%s/%s", tempDir, p.ID))
  73. }
  74. if len(leaksFromRepo) == 0 {
  75. log.Infof("no leaks found for repo %s", p.Name)
  76. } else {
  77. log.Warnf("leaks found for repo %s", p.Name)
  78. }
  79. leaks = append(leaks, leaksFromRepo...)
  80. }
  81. return leaks, nil
  82. }
  83. func createGitlabTempDir() (string, error) {
  84. if !opts.Disk {
  85. return "", nil
  86. }
  87. pathName := opts.GitLabUser
  88. if opts.GitLabOrg != "" {
  89. pathName = opts.GitLabOrg
  90. }
  91. os.RemoveAll(fmt.Sprintf("%s/%s", dir, pathName))
  92. ownerDir, err := ioutil.TempDir(dir, opts.GithubUser)
  93. if err != nil {
  94. return "", nil
  95. }
  96. return ownerDir, nil
  97. }
  98. func cloneGitlabRepo(tempDir string, p *gitlab.Project) (*RepoDescriptor, error) {
  99. if opts.ExcludeForks && p.ForkedFromProject != nil {
  100. return nil, fmt.Errorf("skipping %s, excluding forks", p.Name)
  101. }
  102. for _, repoName := range whiteListRepos {
  103. if repoName == p.Name {
  104. return nil, fmt.Errorf("skipping %s, whitelisted", p.Name)
  105. }
  106. }
  107. opt := &git.CloneOptions{
  108. URL: p.HTTPURLToRepo,
  109. }
  110. if opts.IncludePrivate {
  111. if sshAuth == nil {
  112. return nil, fmt.Errorf("no ssh auth available")
  113. }
  114. opt.URL = p.SSHURLToRepo
  115. opt.Auth = sshAuth
  116. }
  117. log.Infof("cloning: %s", p.Name)
  118. var repo *git.Repository
  119. var err error
  120. if opts.Disk {
  121. repo, err = git.PlainClone(fmt.Sprintf("%s/%s", tempDir, p.ID), false, opt)
  122. } else {
  123. repo, err = git.Clone(memory.NewStorage(), nil, opt)
  124. }
  125. if err != nil {
  126. return nil, err
  127. }
  128. return &RepoDescriptor{
  129. repository: repo,
  130. name: p.Name,
  131. }, nil
  132. }