mirror of
https://github.com/trufflesecurity/trufflehog.git
synced 2024-11-10 07:04:24 +00:00
Support azure git links (#1662)
* Support azure git links. * update comment. * update test names.
This commit is contained in:
parent
f2bfcc7ac6
commit
4f4a79f62b
6 changed files with 133 additions and 74 deletions
|
@ -2,6 +2,7 @@ package giturl
|
|||
|
||||
import (
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
@ -13,8 +14,29 @@ const (
|
|||
providerGithub provider = "Github"
|
||||
providerGitlab provider = "Gitlab"
|
||||
providerBitbucket provider = "Bitbucket"
|
||||
providerAzure provider = "Azure"
|
||||
|
||||
urlGithub = "github.com/"
|
||||
urlGitlab = "gitlab.com/"
|
||||
urlBitbucket = "bitbucket.org/"
|
||||
urlAzure = "dev.azure.com/"
|
||||
)
|
||||
|
||||
func determineProvider(repo string) provider {
|
||||
switch {
|
||||
case strings.Contains(repo, urlGithub):
|
||||
return providerGithub
|
||||
case strings.Contains(repo, urlGitlab):
|
||||
return providerGitlab
|
||||
case strings.Contains(repo, urlBitbucket):
|
||||
return providerBitbucket
|
||||
case strings.Contains(repo, urlAzure):
|
||||
return providerAzure
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func NormalizeBitbucketRepo(repoURL string) (string, error) {
|
||||
if !strings.HasPrefix(repoURL, "https") {
|
||||
return "", errors.New("Bitbucket requires https repo urls: e.g. https://bitbucket.org/org/repo.git")
|
||||
|
@ -88,3 +110,35 @@ func NormalizeOrgRepoURL(provider provider, repoURL string) (string, error) {
|
|||
parsed.Path += ".git"
|
||||
return parsed.String(), nil
|
||||
}
|
||||
|
||||
// GenerateLink crafts a link to the specific file from a commit.
|
||||
// Supports GitHub, GitLab, Bitbucket, and Azure Repos.
|
||||
// If the provider supports hyperlinks to specific lines, the line number will be included.
|
||||
func GenerateLink(repo, commit, file string, line int64) string {
|
||||
switch determineProvider(repo) {
|
||||
case providerBitbucket:
|
||||
return repo[:len(repo)-4] + "/commits/" + commit
|
||||
|
||||
case providerGithub, providerGitlab:
|
||||
var baseLink string
|
||||
if file == "" {
|
||||
baseLink = repo[:len(repo)-4] + "/commit/" + commit
|
||||
} else {
|
||||
baseLink = repo[:len(repo)-4] + "/blob/" + commit + "/" + file
|
||||
if line > 0 {
|
||||
baseLink += "#L" + strconv.FormatInt(line, 10)
|
||||
}
|
||||
}
|
||||
return baseLink
|
||||
|
||||
case providerAzure:
|
||||
baseLink := repo + "?path=" + file + "&version=GB" + commit
|
||||
if line > 0 {
|
||||
baseLink += "&line=" + strconv.FormatInt(line, 10)
|
||||
}
|
||||
return baseLink
|
||||
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ import (
|
|||
)
|
||||
|
||||
func Test_NormalizeOrgRepoURL(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := map[string]struct {
|
||||
Provider provider
|
||||
Repo string
|
||||
|
@ -43,6 +45,8 @@ func Test_NormalizeOrgRepoURL(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_NormalizeBitbucketRepo(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := map[string]struct {
|
||||
Repo string
|
||||
Out string
|
||||
|
@ -69,6 +73,8 @@ func Test_NormalizeBitbucketRepo(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_NormalizeGitlabRepo(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := map[string]struct {
|
||||
Repo string
|
||||
Out string
|
||||
|
@ -93,3 +99,73 @@ func Test_NormalizeGitlabRepo(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateLink(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
type args struct {
|
||||
repo string
|
||||
commit string
|
||||
file string
|
||||
line int64
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "github link gen",
|
||||
args: args{
|
||||
repo: "https://github.com/trufflesec-julian/confluence-go-api.git",
|
||||
commit: "047b4a2ba42fc5b6c0bd535c5307434a666db5ec",
|
||||
file: ".gitignore",
|
||||
},
|
||||
want: "https://github.com/trufflesec-julian/confluence-go-api/blob/047b4a2ba42fc5b6c0bd535c5307434a666db5ec/.gitignore",
|
||||
},
|
||||
{
|
||||
name: "github link gen with line",
|
||||
args: args{
|
||||
repo: "https://github.com/trufflesec-julian/confluence-go-api.git",
|
||||
commit: "047b4a2ba42fc5b6c0bd535c5307434a666db5ec",
|
||||
file: ".gitignore",
|
||||
line: int64(4),
|
||||
},
|
||||
want: "https://github.com/trufflesec-julian/confluence-go-api/blob/047b4a2ba42fc5b6c0bd535c5307434a666db5ec/.gitignore#L4",
|
||||
},
|
||||
{
|
||||
name: "github link gen - no file",
|
||||
args: args{
|
||||
repo: "https://github.com/trufflesec-julian/confluence-go-api.git",
|
||||
commit: "047b4a2ba42fc5b6c0bd535c5307434a666db5ec",
|
||||
},
|
||||
want: "https://github.com/trufflesec-julian/confluence-go-api/commit/047b4a2ba42fc5b6c0bd535c5307434a666db5ec",
|
||||
},
|
||||
{
|
||||
name: "Azure link gen",
|
||||
args: args{
|
||||
repo: "https://dev.azure.com/org/project/_git/repo",
|
||||
commit: "abcdef",
|
||||
file: "main.go",
|
||||
},
|
||||
want: "https://dev.azure.com/org/project/_git/repo?path=main.go&version=GBabcdef",
|
||||
},
|
||||
{
|
||||
name: "Azure link gen with line",
|
||||
args: args{
|
||||
repo: "https://dev.azure.com/org/project/_git/repo",
|
||||
commit: "abcdef",
|
||||
file: "main.go",
|
||||
line: int64(20),
|
||||
},
|
||||
want: "https://dev.azure.com/org/project/_git/repo?path=main.go&version=GBabcdef&line=20",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := GenerateLink(tt.args.repo, tt.args.commit, tt.args.file, tt.args.line); got != tt.want {
|
||||
t.Errorf("generateLink() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ import (
|
|||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
@ -693,28 +692,6 @@ func normalizeConfig(scanOptions *ScanOptions, repo *git.Repository) (err error)
|
|||
return nil
|
||||
}
|
||||
|
||||
// GenerateLink crafts a link to the specific file from a commit. This works in most major git providers (Github/Gitlab)
|
||||
func GenerateLink(repo, commit, file string, line int64) string {
|
||||
// bitbucket links are commits not commit...
|
||||
if strings.Contains(repo, "bitbucket.org/") {
|
||||
return repo[:len(repo)-4] + "/commits/" + commit
|
||||
}
|
||||
var link string
|
||||
if file == "" {
|
||||
link = repo[:len(repo)-4] + "/commit/" + commit
|
||||
} else {
|
||||
link = repo[:len(repo)-4] + "/blob/" + commit + "/" + file
|
||||
|
||||
// Both GitHub and Gitlab support hyperlinking to a specific line with #L<number>, e.g.:
|
||||
// https://github.com/trufflesecurity/trufflehog/blob/e856a6890d0da5a218f4f9283500b80043884641/go.mod#L169
|
||||
// https://gitlab.com/pdftk-java/pdftk/-/blob/88559a08f34175b6fae76c40a88f0377f64a12d7/java/com/gitlab/pdftk_java/report.java#L893
|
||||
if line > 0 && (strings.Contains(repo, "github") || strings.Contains(repo, "gitlab")) {
|
||||
link += "#L" + strconv.FormatInt(line, 10)
|
||||
}
|
||||
}
|
||||
return link
|
||||
}
|
||||
|
||||
func stripPassword(u string) (string, error) {
|
||||
if strings.HasPrefix(u, "git@") {
|
||||
return u, nil
|
||||
|
|
|
@ -151,55 +151,6 @@ func TestSource_Scan(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func Test_generateLink(t *testing.T) {
|
||||
type args struct {
|
||||
repo string
|
||||
commit string
|
||||
file string
|
||||
line int64
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "test link gen",
|
||||
args: args{
|
||||
repo: "https://github.com/trufflesec-julian/confluence-go-api.git",
|
||||
commit: "047b4a2ba42fc5b6c0bd535c5307434a666db5ec",
|
||||
file: ".gitignore",
|
||||
},
|
||||
want: "https://github.com/trufflesec-julian/confluence-go-api/blob/047b4a2ba42fc5b6c0bd535c5307434a666db5ec/.gitignore",
|
||||
},
|
||||
{
|
||||
name: "test link gen",
|
||||
args: args{
|
||||
repo: "https://github.com/trufflesec-julian/confluence-go-api.git",
|
||||
commit: "047b4a2ba42fc5b6c0bd535c5307434a666db5ec",
|
||||
file: ".gitignore",
|
||||
line: int64(4),
|
||||
},
|
||||
want: "https://github.com/trufflesec-julian/confluence-go-api/blob/047b4a2ba42fc5b6c0bd535c5307434a666db5ec/.gitignore#L4",
|
||||
},
|
||||
{
|
||||
name: "test link gen - no file",
|
||||
args: args{
|
||||
repo: "https://github.com/trufflesec-julian/confluence-go-api.git",
|
||||
commit: "047b4a2ba42fc5b6c0bd535c5307434a666db5ec",
|
||||
},
|
||||
want: "https://github.com/trufflesec-julian/confluence-go-api/commit/047b4a2ba42fc5b6c0bd535c5307434a666db5ec",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := GenerateLink(tt.args.repo, tt.args.commit, tt.args.file, tt.args.line); got != tt.want {
|
||||
t.Errorf("generateLink() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// We ran into an issue where upgrading a dependency caused the git patch chunking to break
|
||||
// So this test exists to make sure that when something changes, we know about it.
|
||||
func TestSource_Chunks_Integration(t *testing.T) {
|
||||
|
|
|
@ -29,6 +29,7 @@ import (
|
|||
"github.com/trufflesecurity/trufflehog/v3/pkg/cache/memory"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/context"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/giturl"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/credentialspb"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/source_metadatapb"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/sourcespb"
|
||||
|
@ -261,7 +262,7 @@ func (s *Source) Init(aCtx context.Context, name string, jobID, sourceID int64,
|
|||
File: sanitizer.UTF8(file),
|
||||
Email: sanitizer.UTF8(email),
|
||||
Repository: sanitizer.UTF8(repository),
|
||||
Link: git.GenerateLink(repository, commit, file, line),
|
||||
Link: giturl.GenerateLink(repository, commit, file, line),
|
||||
Timestamp: sanitizer.UTF8(timestamp),
|
||||
Line: line,
|
||||
Visibility: s.visibilityOf(aCtx, repository),
|
||||
|
|
|
@ -127,7 +127,7 @@ func (s *Source) Init(_ context.Context, name string, jobId, sourceId int64, ver
|
|||
File: sanitizer.UTF8(file),
|
||||
Email: sanitizer.UTF8(email),
|
||||
Repository: sanitizer.UTF8(repository),
|
||||
Link: git.GenerateLink(repository, commit, file, line),
|
||||
Link: giturl.GenerateLink(repository, commit, file, line),
|
||||
Timestamp: sanitizer.UTF8(timestamp),
|
||||
Line: line,
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue