Support common ssh repo format (#878)

* Try ssh repo format

* Add tests
This commit is contained in:
Bill Rich 2022-10-28 11:56:03 -07:00 committed by GitHub
parent ab71b93f7d
commit 965279421c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 84 additions and 6 deletions

View file

@ -231,6 +231,21 @@ func CleanOnError(err *error, path string) {
}
}
func gitURLParse(gitURL string) (*url.URL, error) {
parsedURL, originalError := url.Parse(gitURL)
if originalError != nil {
var err error
gitURLBytes := []byte("ssh://" + gitURL)
colonIndex := bytes.LastIndex(gitURLBytes, []byte(":"))
gitURLBytes[colonIndex] = byte('/')
parsedURL, err = url.Parse(string(gitURLBytes))
if err != nil {
return nil, originalError
}
}
return parsedURL, nil
}
func CloneRepo(userInfo *url.Userinfo, gitUrl string, args ...string) (clonePath string, repo *git.Repository, err error) {
if err = GitCmdCheck(); err != nil {
return
@ -241,12 +256,13 @@ func CloneRepo(userInfo *url.Userinfo, gitUrl string, args ...string) (clonePath
return
}
defer CleanOnError(&err, clonePath)
cloneURL, err := url.Parse(gitUrl)
cloneURL, err := gitURLParse(gitUrl)
if err != nil {
err = errors.WrapPrefix(err, "could not parse url", 0)
return
return "", nil, err
}
if cloneURL.User == nil {
cloneURL.User = userInfo
}
cloneURL.User = userInfo
gitArgs := []string{"clone", cloneURL.String(), clonePath}
gitArgs = append(gitArgs, args...)
@ -651,7 +667,7 @@ func PrepareRepoSinceCommit(uriString, commitHash string) (string, bool, error)
// the uriString is github.com, then we query the API for the timestamp of the
// hash and use that to clone.
uri, err := url.Parse(uriString)
uri, err := gitURLParse(uriString)
if err != nil {
return "", false, fmt.Errorf("unable to parse Git URI: %s", err)
}
@ -715,7 +731,7 @@ func PrepareRepoSinceCommit(uriString, commitHash string) (string, bool, error)
// PrepareRepo clones a repo if possible and returns the cloned repo path.
func PrepareRepo(uriString string) (string, bool, error) {
var path string
uri, err := url.Parse(uriString)
uri, err := gitURLParse(uriString)
if err != nil {
return "", false, fmt.Errorf("unable to parse Git URI: %s", err)
}

View file

@ -8,6 +8,7 @@ import (
"github.com/kylelemons/godebug/pretty"
log "github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"google.golang.org/protobuf/types/known/anypb"
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
@ -494,3 +495,64 @@ func BenchmarkPrepareRepo(b *testing.B) {
_, _, _ = PrepareRepo(uri)
}
}
func TestGitURLParse(t *testing.T) {
for _, tt := range []struct {
url string
host string
user string
password string
port string
path string
scheme string
}{
{
"https://user@github.com/org/repo",
"github.com",
"user",
"",
"",
"/org/repo",
"https",
},
{
"https://user:pass@github.com/org/repo",
"github.com",
"user",
"pass",
"",
"/org/repo",
"https",
},
{
"ssh://user@github.com/org/repo",
"github.com",
"user",
"",
"",
"/org/repo",
"ssh",
},
{
"user@github.com:org/repo",
"github.com",
"user",
"",
"",
"/org/repo",
"ssh",
},
} {
u, err := gitURLParse(tt.url)
if err != nil {
t.Fatal(err)
}
assert.Equal(t, tt.host, u.Host)
assert.Equal(t, tt.user, u.User.Username())
password, _ := u.User.Password()
assert.Equal(t, tt.password, password)
assert.Equal(t, tt.port, u.Port())
assert.Equal(t, tt.path, u.Path)
assert.Equal(t, tt.scheme, u.Scheme)
}
}