Support remote git repos using https (#9)

Co-authored-by: Bill Rich <bill.rich@trufflesec.com>
This commit is contained in:
Bill Rich 2022-01-14 16:07:45 -08:00 committed by GitHub
parent f798e488a8
commit a70937bfe6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 58 additions and 20 deletions

10
main.go
View file

@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"github.com/trufflesecurity/trufflehog/pkg/common"
"github.com/trufflesecurity/trufflehog/pkg/sources/git"
"log"
"os"
"runtime"
@ -79,7 +80,14 @@ func main() {
switch cmd {
case gitScan.FullCommand():
err := e.ScanGit(ctx, *gitScanURI, *gitScanBranch, "HEAD", filter)
repoPath, remote, err := git.PrepareRepo(*gitScanURI)
if err != nil || repoPath == "" {
logrus.WithError(err).Fatal("error preparing git repo for scanning")
}
if remote {
defer os.RemoveAll(repoPath)
}
err = e.ScanGit(ctx, repoPath, *gitScanBranch, "HEAD", filter)
if err != nil {
logrus.WithError(err).Fatal("Failed to scan git.")
}

View file

@ -2,36 +2,22 @@ package engine
import (
"context"
"errors"
"fmt"
"github.com/trufflesecurity/trufflehog/pkg/common"
"runtime"
"strings"
gogit "github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/sirupsen/logrus"
"github.com/trufflesecurity/trufflehog/pkg/common"
"github.com/trufflesecurity/trufflehog/pkg/pb/source_metadatapb"
"github.com/trufflesecurity/trufflehog/pkg/pb/sourcespb"
"github.com/trufflesecurity/trufflehog/pkg/sources/git"
"runtime"
)
func (e *Engine) ScanGit(ctx context.Context, gitScanURI, gitScanBranch, headRef string, filter *common.Filter) error {
var path string
switch {
case strings.HasPrefix(gitScanURI, "file://"):
path = strings.TrimPrefix(gitScanURI, "file://")
case strings.HasPrefix(gitScanURI, "https://"):
// TODO: clone repo and get path
return errors.New("TODO: clone repo and get path")
default:
logrus.Fatalf("Unsupported Git URI: %s", gitScanURI)
}
repo, err := gogit.PlainOpenWithOptions(path, &gogit.PlainOpenOptions{DetectDotGit: true})
func (e *Engine) ScanGit(ctx context.Context, repoPath, gitScanBranch, headRef string, filter *common.Filter) error {
repo, err := gogit.PlainOpenWithOptions(repoPath, &gogit.PlainOpenOptions{DetectDotGit: true})
if err != nil {
return fmt.Errorf("could open repo: %s: %w", path, err)
return fmt.Errorf("could open repo: %s: %w", repoPath, err)
}
scanOptions := &gogit.LogOptions{

View file

@ -211,6 +211,9 @@ func CloneRepoUsingToken(token, url, user string) (clonePath string, repo *git.R
return
}
repo, err = git.PlainClone(clonePath, false, cloneOptions)
if err != nil {
return
}
safeRepo, err := stripPassword(url)
if err != nil {
err = errors.New(err)
@ -234,6 +237,9 @@ func CloneRepoUsingUnauthenticated(url string) (clonePath string, repo *git.Repo
return
}
repo, err = git.PlainClone(clonePath, false, cloneOptions)
if err != nil {
return
}
safeRepo, err := stripPassword(url)
if err != nil {
err = errors.New(err)
@ -546,3 +552,41 @@ func TryAdditionalBaseRefs(repo *git.Repository, base string) (*plumbing.Hash, e
return nil, fmt.Errorf("no base refs succeeded for base: %q", base)
}
func PrepareRepo(uriString string) (string, bool, error) {
var path string
uri, err := url.Parse(uriString)
if err != nil {
return "", false, fmt.Errorf("unable to parse Git URI: %s", err)
}
remote := false
switch uri.Scheme {
case "file":
path = fmt.Sprintf("%s%s", uri.Host, uri.Path)
case "https":
remotePath := fmt.Sprintf("%s://%s%s", uri.Scheme, uri.Host, uri.Path)
remote = true
switch {
case uri.User != nil:
log.Debugf("Cloning remote Git repo with authentication")
password, ok := uri.User.Password()
if !ok {
return "", remote, fmt.Errorf("password must be included in Git repo URL when username is provided")
}
path, _, err = CloneRepoUsingToken(password, remotePath, uri.User.Username())
if err != nil {
return path, remote, fmt.Errorf("failed to clone authenticated Git repo (%s): %s", remotePath, err)
}
default:
log.Debugf("Cloning remote Git repo without authentication")
path, _, err = CloneRepoUsingUnauthenticated(remotePath)
if err != nil {
return path, remote, fmt.Errorf("failed to clone unauthenticated Git repo (%s): %s", remotePath, err)
}
}
default:
return "", remote, fmt.Errorf("unsupported Git URI: %s", uriString)
}
log.Debugf("Git repo local path: %s", path)
return path, remote, nil
}