Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Git Audit - Add scm providers #297

Open
wants to merge 52 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
37d19f9
Align after build-info-go changes
attiasas Dec 25, 2024
ee30078
Merge remote-tracking branch 'upstream/dev' into align_pipenv_change
attiasas Jan 5, 2025
6378660
update build-go
attiasas Jan 5, 2025
8f3276b
Merge remote-tracking branch 'upstream/dev' into align_pipenv_change
attiasas Jan 6, 2025
55eecbd
update build-go
attiasas Jan 6, 2025
a12654c
Merge remote-tracking branch 'upstream/dev' into align_pipenv_change
attiasas Jan 6, 2025
96870df
Merge remote-tracking branch 'upstream/dev' into align_pipenv_change
attiasas Jan 6, 2025
62a39a4
update deps to current dev
attiasas Jan 6, 2025
365c501
fix skip report error
attiasas Jan 7, 2025
ace340d
fix static test
attiasas Jan 7, 2025
3cb0812
update jas results to dump also violation runs
attiasas Jan 7, 2025
5d744b2
update build-info-go v1.10.8 jfrog-client-go v1.49.0
attiasas Jan 7, 2025
2b4d733
update jfrog-cli-core/v2 v2.57.6
attiasas Jan 7, 2025
45f2547
start transfer xsc audit integration test to git audit
attiasas Jan 7, 2025
1ae140d
add basic command infra
attiasas Jan 8, 2025
f22741e
add tests data
attiasas Jan 8, 2025
35058a2
start git manager
attiasas Jan 8, 2025
3e10cf7
done basic git-manager
attiasas Jan 9, 2025
f774c89
Merge remote-tracking branch 'upstream/dev' into git_audit_cmd_basic
attiasas Jan 9, 2025
26b425d
update
attiasas Jan 9, 2025
2feff2d
fix tests
attiasas Jan 9, 2025
a511a6b
fix integration tests
attiasas Jan 12, 2025
3eec463
fix tests and add more
attiasas Jan 12, 2025
149f0e4
start clean
attiasas Jan 12, 2025
7b4448d
cleanup
attiasas Jan 13, 2025
626a585
Merge remote-tracking branch 'upstream/dev' into git_audit_cmd_basic
attiasas Jan 16, 2025
3fc576c
update go-git to v5
attiasas Jan 20, 2025
18c0e15
detect remote if multi exists
attiasas Jan 20, 2025
4ba43c9
format, start CR changes
attiasas Jan 20, 2025
5082a96
continue CR
attiasas Jan 21, 2025
64204e4
done CR changes add tests
attiasas Jan 21, 2025
f56fd1a
Merge remote-tracking branch 'upstream/dev' into git_audit_cmd_basic
attiasas Jan 21, 2025
dee6891
remove project key - apply after application
attiasas Jan 28, 2025
025f24e
Revert "remove project key - apply after application"
attiasas Jan 28, 2025
6d5b1ae
start to support new scm providers detection
attiasas Jan 28, 2025
15fbaf7
merge fix
attiasas Jan 28, 2025
ae920f8
Git Audit - Support more Scm Providers
attiasas Jan 28, 2025
b9adf83
Merge remote-tracking branch 'upstream/dev' into add_scm_providers
attiasas Jan 29, 2025
b910bb1
refactor scm for future types other than git
attiasas Jan 29, 2025
0cba6fc
add gerrit provider
attiasas Jan 30, 2025
cb88179
Merge remote-tracking branch 'upstream/dev' into add_scm_providers
attiasas Jan 30, 2025
7eaab80
rename to sc
attiasas Jan 30, 2025
e2ea431
add gitea, fix project path to show full
attiasas Jan 30, 2025
34d6041
add codecommit
attiasas Jan 30, 2025
6c988d3
move scm methods
attiasas Jan 30, 2025
bc663b7
add comment on indicator
attiasas Feb 2, 2025
37eecc2
Merge remote-tracking branch 'upstream/dev' into add_scm_providers
attiasas Feb 2, 2025
e9de9c0
add debug if not clean fix gerrit test
attiasas Feb 3, 2025
015574c
Merge remote-tracking branch 'upstream/dev' into add_scm_providers
attiasas Feb 3, 2025
0d8f7a4
use cache value
attiasas Feb 3, 2025
f621b06
try fix windows test
attiasas Feb 4, 2025
abadf7b
fix tests
attiasas Feb 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions commands/git/audit/gitaudit.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import (

sourceAudit "github.com/jfrog/jfrog-cli-security/commands/audit"
"github.com/jfrog/jfrog-cli-security/utils"
"github.com/jfrog/jfrog-cli-security/utils/gitutils"
"github.com/jfrog/jfrog-cli-security/utils/results"
"github.com/jfrog/jfrog-cli-security/utils/results/output"
"github.com/jfrog/jfrog-cli-security/utils/scm"
"github.com/jfrog/jfrog-cli-security/utils/xsc"
)

Expand Down Expand Up @@ -46,7 +46,7 @@ func (gaCmd *GitAuditCommand) Run() (err error) {
// Detect git info
gitInfo, err := DetectGitInfo(gaCmd.repositoryLocalPath)
if err != nil {
return fmt.Errorf("failed to get git context: %v", err)
return fmt.Errorf("failed to get source control context: %v", err)
}
if gitInfo == nil {
// No Error but no git info = project working tree is dirty
Expand All @@ -65,11 +65,11 @@ func (gaCmd *GitAuditCommand) Run() (err error) {
}

func DetectGitInfo(wd string) (gitInfo *services.XscGitInfoContext, err error) {
gitManager, err := gitutils.NewGitManager(wd)
scmManager, err := scm.DetectScmInProject(wd)
if err != nil {
return
}
return gitManager.GetGitContext()
return scmManager.GetSourceControlContext()
}

func toAuditParams(params GitAuditParams) *sourceAudit.AuditParams {
Expand Down
Binary file added tests/testdata/git/projects/gerrit/gerrit.zip
Binary file not shown.
97 changes: 9 additions & 88 deletions utils/gitutils/gitmanager.go → utils/scm/gitmanager.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package gitutils
package scm

import (
"fmt"
Expand All @@ -10,32 +10,6 @@ import (
"github.com/jfrog/jfrog-client-go/xsc/services"
)

const (
Github GitProvider = "github"
Gitlab GitProvider = "gitlab"
Bitbucket GitProvider = "bitbucket"
Azure GitProvider = "azure"

// TODO: Add support for other git providers

// git clone https://sourceforge.net/projects/svn-sample-repo/
SourceForge GitProvider = "sourceforge"
// git clone https://git-codecommit.{region}.amazonaws.com/v1/repos/{repository_name}
AWSCodeCommit GitProvider = "codecommit"
// git clone https://gerrit.googlesource.com/git-repo
Gerrit GitProvider = "gerrit"
// git clone https://gitea.com/gitea/helm-chart.git
Gitea GitProvider = "gitea"

Unknown GitProvider = ""
)

type GitProvider string

func (gp GitProvider) String() string {
return string(gp)
}

type GitManager struct {
// repository represents a git repository as a .git dir.
localGitRepository *goGit.Repository
Expand Down Expand Up @@ -109,7 +83,7 @@ func getRemoteNames(remotes ...*goGit.Remote) []string {
}

// IsClean returns true if all the files are in Unmodified status.
func (gm *GitManager) IsClean() (bool, error) {
func (gm *GitManager) isClean() (bool, error) {
worktree, err := gm.localGitRepository.Worktree()
if err != nil {
return false, err
Expand All @@ -118,12 +92,15 @@ func (gm *GitManager) IsClean() (bool, error) {
if err != nil {
return false, err
}

return status.IsClean(), nil
isClean := status.IsClean()
if !isClean {
log.Debug(fmt.Sprintf("Git status:\n%v", status))
}
return isClean, nil
}

// Detect git information
func (gm *GitManager) GetGitContext() (gitInfo *services.XscGitInfoContext, err error) {
func (gm *GitManager) GetSourceControlContext() (gitInfo *services.XscGitInfoContext, err error) {
remoteUrl, err := getRemoteUrl(gm.remote)
if err != nil {
return nil, err
Expand All @@ -150,7 +127,7 @@ func (gm *GitManager) GetGitContext() (gitInfo *services.XscGitInfoContext, err
LastCommitMessage: strings.TrimSpace(lastCommit.Message),
LastCommitAuthor: lastCommit.Author.Name,
}
isClean, err := gm.IsClean()
isClean, err := gm.isClean()
if err != nil {
return nil, err
}
Expand All @@ -173,59 +150,3 @@ func getRemoteUrl(remote *goGit.Remote) (remoteUrl string, err error) {
}
return remote.Config().URLs[0], nil
}

// Normalize the URL by removing protocol prefix and any trailing ".git"
func normalizeGitUrl(url string) string {
// jfrog-ignore - false positive, not used for communication
url = strings.TrimPrefix(url, "http://")
url = strings.TrimPrefix(url, "https://")
url = strings.TrimPrefix(url, "ssh://")
return strings.TrimSuffix(url, ".git")
}

func getGitRepoName(url string) string {
urlParts := strings.Split(normalizeGitUrl(url), "/")
return urlParts[len(urlParts)-1]
}

func getGitProject(url string) string {
// First part after base Url is the owner or the organization name.
urlParts := strings.Split(normalizeGitUrl(url), "/")
if len(urlParts) < 2 {
log.Debug(fmt.Sprintf("Failed to get project name from URL: %s", url))
return ""
}
if len(urlParts) > 2 && urlParts[1] == "scm" {
// In BB https clone url looks like this: https://git.id.info/scm/repo-name/repo-name.git --> ['git.id.info', 'scm', 'repo-name', 'repo-name']
return urlParts[2]
}
return urlParts[1]
}

func getGitProvider(url string) GitProvider {
if strings.Contains(url, Github.String()) {
return Github
}
if strings.Contains(url, Gitlab.String()) {
return Gitlab
}
if isBitbucketProvider(url) {
return Bitbucket
}
if strings.Contains(url, Azure.String()) {
return Azure
}
// Unknown for self-hosted git providers
log.Debug(fmt.Sprintf("Unknown git provider for URL: %s", url))
return Unknown
}

func isBitbucketProvider(url string) bool {
if urlParts := strings.Split(normalizeGitUrl(url), "/"); len(urlParts) > 2 && urlParts[1] == "scm" {
return true
}
if projectName := getGitProject(url); strings.Contains(projectName, "~") {
return true
}
return strings.Contains(url, Bitbucket.String())
}
52 changes: 48 additions & 4 deletions utils/gitutils/gitmanager_test.go → utils/scm/gitmanager_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package gitutils
package scm

import (
"path/filepath"
Expand Down Expand Up @@ -62,14 +62,28 @@ func TestGetGitContext(t *testing.T) {
gitInfo: &services.XscGitInfoContext{
GitRepoHttpsCloneUrl: "https://gitlab.com/attiasas/test-group/test-security-git.git",
GitRepoName: "test-security-git",
GitProject: "attiasas",
GitProject: "attiasas/test-group",
GitProvider: "gitlab",
BranchName: "main",
LastCommitHash: "ada14e9f525d8cbfb3c8c31ebe345d85ec342480",
LastCommitMessage: "add npm",
LastCommitAuthor: "attiasas",
},
},
{
name: "Gerrit Project (no owner)",
testProjectZipDirPath: filepath.Join(basePath, "gerrit"),
gitInfo: &services.XscGitInfoContext{
GitRepoHttpsCloneUrl: "https://gerrit.googlesource.com/git-repo",
GitRepoName: "git-repo",
GitProject: "git-repo",
GitProvider: "gerrit",
BranchName: "main",
LastCommitHash: "0533dc46c6521837bb7f222e311a86017781f8f3",
LastCommitMessage: `add to ignore`,
LastCommitAuthor: "attiasas",
},
},
{
name: "Forked Project (multiple remotes)",
testProjectZipDirPath: filepath.Join(basePath, "forked"),
Expand Down Expand Up @@ -115,7 +129,7 @@ func TestGetGitContext(t *testing.T) {
}
assert.NoError(t, err)
assert.NotNil(t, gitManager)
gitInfo, err := gitManager.GetGitContext()
gitInfo, err := gitManager.GetSourceControlContext()

if testCase.gitInfo == nil {
// Dirty project, we can't assert the git info
Expand All @@ -134,7 +148,7 @@ func TestGetGitProvider(t *testing.T) {
testCases := []struct {
name string
url string
provider GitProvider
provider ScProvider
}{
{
name: "Github",
Expand All @@ -161,6 +175,21 @@ func TestGetGitProvider(t *testing.T) {
url: "https://dev.azure.com/attiasas/test-security-git/_git/test-security-git",
provider: Azure,
},
{
name: "Gerrit",
url: "https://gerrit.googlesource.com/git-repo",
provider: Gerrit,
},
{
name: "Gitea",
url: "https://gitea.com/gitea/helm-chart.git",
provider: Gitea,
},
{
name: "AWS CodeCommit",
url: "https://git-codecommit.us-west-2.amazonaws.com/v1/repos/test-repo",
provider: AWSCodeCommit,
},
{
name: "Unknown",
url: "ssh://[email protected]/assafa/test-security-git.git",
Expand Down Expand Up @@ -197,11 +226,26 @@ func TestGetGitProject(t *testing.T) {
url: "https://git.id.info/scm/repo-name/repo-name.git",
project: "repo-name",
},
{
name: "Gitlab Project (group tree structure)",
url: "https://gitlab.com/attiasas/test-group/test-security-git.git",
project: "attiasas/test-group",
},
{
name: "Bitbucket SSH",
url: "ssh://[email protected]/~assafa/test-security-git.git",
project: "~assafa",
},
{
name: "Gerrit - No project name",
url: "https://gerrit.googlesource.com/git-repo",
project: "git-repo",
},
{
name: "codecommit",
url: "https://git-codecommit.us-west-2.amazonaws.com/v1/repos/test-repo",
project: "test-repo",
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
Expand Down
Loading
Loading