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 Command #221

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
156 changes: 89 additions & 67 deletions audit_test.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ func GetJfrogCliSecurityApp() components.App {
app.Subcommands = append(app.Subcommands, components.Namespace{
Name: "git",
Description: "Git commands.",
Hidden: true,
Commands: getGitNameSpaceCommands(),
Hidden: true,
Category: "Command Namespaces",
})
return app
Expand Down
26 changes: 16 additions & 10 deletions cli/docs/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package docs

import (
"fmt"
"github.com/jfrog/jfrog-cli-security/commands/git"
"github.com/jfrog/jfrog-cli-security/commands/git/contributors"
"strings"

"github.com/jfrog/jfrog-cli-core/v2/common/cliutils"
Expand All @@ -21,6 +21,7 @@ const (
DockerScan = "docker scan"
Audit = "audit"
CurationAudit = "curation-audit"
GitAudit = "git-audit"
GitCountContributors = "count-contributors"
Enrich = "sbom-enrich"

Expand Down Expand Up @@ -135,6 +136,15 @@ const (
DetailedSummary = "detailed-summary"
)

func getAuditFlags() []string {
return []string{
url, user, password, accessToken, ServerId, InsecureTls, Project, Watches, RepoPath, Licenses, OutputFormat, ExcludeTestDeps,
useWrapperAudit, DepType, RequirementsFile, Fail, ExtendedTable, WorkingDirs, ExclusionsAudit, Mvn, Gradle, Npm,
Pnpm, Yarn, Go, Nuget, Pip, Pipenv, Poetry, MinSeverity, FixableOnly, ThirdPartyContextualAnalysis, Threads,
Sca, Iac, Sast, Secrets, WithoutCA, ScanVuln, SecretValidation, OutputDir, SkipAutoInstall, AllowPartialResults,
}
}

// Mapping between security commands (key) and their flags (key).
var commandFlags = map[string][]string{
XrCurl: {ServerId},
Expand All @@ -152,12 +162,8 @@ var commandFlags = map[string][]string{
DockerScan: {
ServerId, Project, Watches, RepoPath, Licenses, OutputFormat, Fail, ExtendedTable, BypassArchiveLimits, MinSeverity, FixableOnly, ScanVuln, SecretValidation,
},
Audit: {
url, user, password, accessToken, ServerId, InsecureTls, Project, Watches, RepoPath, Licenses, OutputFormat, ExcludeTestDeps,
useWrapperAudit, DepType, RequirementsFile, Fail, ExtendedTable, WorkingDirs, ExclusionsAudit, Mvn, Gradle, Npm,
Pnpm, Yarn, Go, Nuget, Pip, Pipenv, Poetry, MinSeverity, FixableOnly, ThirdPartyContextualAnalysis, Threads,
Sca, Iac, Sast, Secrets, WithoutCA, ScanVuln, SecretValidation, OutputDir, SkipAutoInstall, AllowPartialResults,
},
Audit: getAuditFlags(),
GitAudit: getAuditFlags(),
CurationAudit: {
CurationOutput, WorkingDirs, Threads, RequirementsFile,
},
Expand Down Expand Up @@ -267,12 +273,12 @@ var flagsMap = map[string]components.Flag{

// Git flags
InputFile: components.NewStringFlag(InputFile, "Path to an input file in YAML format contains multiple git providers. With this option, all other scm flags will be ignored and only git servers mentioned in the file will be examined.."),
ScmType: components.NewStringFlag(ScmType, fmt.Sprintf("SCM type. Possible values are: %s.", git.NewScmType().GetValidScmTypeString()), components.SetMandatory()),
ScmType: components.NewStringFlag(ScmType, fmt.Sprintf("SCM type. Possible values are: %s.", contributors.NewScmType().GetValidScmTypeString()), components.SetMandatory()),
ScmApiUrl: components.NewStringFlag(ScmApiUrl, "SCM API URL. For example: 'https://api.github.com'.", components.SetMandatory()),
Token: components.NewStringFlag(Token, fmt.Sprintf("SCM API token. In the absence of a flag, tokens should be passed in the %s environment variable, or in the corresponding environment variables '%s'.", git.GenericGitTokenEnvVar, git.NewScmType().GetOptionalScmTypeTokenEnvVars()), components.SetMandatory()),
Token: components.NewStringFlag(Token, fmt.Sprintf("SCM API token. In the absence of a flag, tokens should be passed in the %s environment variable, or in the corresponding environment variables '%s'.", contributors.GenericGitTokenEnvVar, contributors.NewScmType().GetOptionalScmTypeTokenEnvVars()), components.SetMandatory()),
Owner: components.NewStringFlag(Owner, "The format of the owner key depends on the Git provider: On GitHub and GitLab, the owner is typically an individual or an organization, On Bitbucket, the owner can also be a project. In the case of a private instance on Bitbucket, the individual or organization name should be prefixed with '~'.", components.SetMandatory()),
RepoName: components.NewStringFlag(RepoName, "List of semicolon-separated(;) repositories names to analyze, If not provided all repositories related to the provided owner will be analyzed."),
Months: components.NewStringFlag(Months, "Number of months to analyze.", components.WithIntDefaultValue(git.DefaultContContributorsMonths)),
Months: components.NewStringFlag(Months, "Number of months to analyze.", components.WithIntDefaultValue(contributors.DefaultContContributorsMonths)),
DetailedSummary: components.NewBoolFlag(DetailedSummary, "Set to true to get a contributors detailed summary."),
}

Expand Down
5 changes: 5 additions & 0 deletions cli/docs/git/audit/help.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package audit

func GetDescription() string {
return "Audit your local git repository project for security issues."
}
2 changes: 1 addition & 1 deletion cli/docs/git/help.go → cli/docs/git/contributors/help.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package git
package contributors

func GetContContributorsDescription() string {
return "List all GIT providers' contributing developers."
Expand Down
52 changes: 37 additions & 15 deletions cli/gitcommands.go
Original file line number Diff line number Diff line change
@@ -1,36 +1,58 @@
package cli

import (
"os"
"strings"

"github.com/jfrog/froggit-go/vcsutils"
"github.com/jfrog/jfrog-cli-core/v2/common/progressbar"
"github.com/jfrog/jfrog-cli-core/v2/plugins/components"
flags "github.com/jfrog/jfrog-cli-security/cli/docs"
gitDocs "github.com/jfrog/jfrog-cli-security/cli/docs/git"
"github.com/jfrog/jfrog-cli-security/commands/git"
gitAuditDocs "github.com/jfrog/jfrog-cli-security/cli/docs/git/audit"
gitContributorsDocs "github.com/jfrog/jfrog-cli-security/cli/docs/git/contributors"
"github.com/jfrog/jfrog-cli-security/commands/git/audit"
"github.com/jfrog/jfrog-cli-security/commands/git/contributors"
"github.com/jfrog/jfrog-client-go/utils/errorutils"
"os"
"strings"
)

func getGitNameSpaceCommands() []components.Command {
return []components.Command{
{
Name: "audit",
Aliases: []string{"a"},
Description: gitAuditDocs.GetDescription(),
Flags: flags.GetCommandFlags(flags.GitAudit),
Hidden: true,
Action: GitAuditCmd,
},
// TODO: Move cc cmd to Frogbot/Script
{
Name: "count-contributors",
Aliases: []string{"cc"},
Flags: flags.GetCommandFlags(flags.GitCountContributors),
Description: gitDocs.GetContContributorsDescription(),
Description: gitContributorsDocs.GetContContributorsDescription(),
Hidden: true,
Action: GitCountContributorsCmd,
},
}
}

func GetCountContributorsParams(c *components.Context) (*git.CountContributorsParams, error) {
params := git.CountContributorsParams{}
func GitAuditCmd(c *components.Context) error {
auditCmd, err := CreateAuditCmd(c)
if err != nil {
return err
}
gitAuditCmd := audit.NewGitAuditCommand(auditCmd)

return progressbar.ExecWithProgress(gitAuditCmd)
}

func GetCountContributorsParams(c *components.Context) (*contributors.CountContributorsParams, error) {
params := contributors.CountContributorsParams{}
params.InputFile = c.GetStringFlagValue(flags.InputFile)
if params.InputFile == "" {
// Mandatory flags in case no input file was provided.
scmTypes := git.NewScmType()
scmTypes := contributors.NewScmType()
// ScmType
scmType := c.GetStringFlagValue(flags.ScmType)
if scmType == "" {
Expand All @@ -48,22 +70,22 @@ func GetCountContributorsParams(c *components.Context) (*git.CountContributorsPa
var envVarToken string
switch params.ScmType {
case vcsutils.BitbucketServer:
envVarToken = os.Getenv(git.BitbucketTokenEnvVar)
envVarToken = os.Getenv(contributors.BitbucketTokenEnvVar)
case vcsutils.GitLab:
envVarToken = os.Getenv(git.GitlabTokenEnvVar)
envVarToken = os.Getenv(contributors.GitlabTokenEnvVar)
case vcsutils.GitHub:
envVarToken = os.Getenv(git.GithubTokenEnvVar)
envVarToken = os.Getenv(contributors.GithubTokenEnvVar)
default:
return nil, errorutils.CheckErrorf("Unsupported SCM type: %s, Possible values are: %v", scmType, scmTypes.GetValidScmTypeString())
}
if envVarToken != "" {
params.Token = envVarToken
} else {
envVarToken = os.Getenv(git.GenericGitTokenEnvVar)
envVarToken = os.Getenv(contributors.GenericGitTokenEnvVar)
if envVarToken != "" {
params.Token = envVarToken
} else {
return nil, errorutils.CheckErrorf("Providing a token is mandatory. should use --%s flag, the token environment variable %s, or corresponding provider environment variable %s.", flags.Token, git.GenericGitTokenEnvVar, scmTypes.GetOptionalScmTypeTokenEnvVars())
return nil, errorutils.CheckErrorf("Providing a token is mandatory. should use --%s flag, the token environment variable %s, or corresponding provider environment variable %s.", flags.Token, contributors.GenericGitTokenEnvVar, scmTypes.GetOptionalScmTypeTokenEnvVars())
}
}
}
Expand All @@ -84,7 +106,7 @@ func GetCountContributorsParams(c *components.Context) (*git.CountContributorsPa
// Optional flags
// Months
if !c.IsFlagSet(flags.Months) {
params.MonthsNum = git.DefaultContContributorsMonths
params.MonthsNum = contributors.DefaultContContributorsMonths
} else {
months, err := c.GetIntFlagValue(flags.Months)
if err != nil {
Expand Down Expand Up @@ -118,7 +140,7 @@ func GitCountContributorsCmd(c *components.Context) error {
if err != nil {
return err
}
gitContributionCommand, err := git.NewCountContributorsCommand(gitContrParams)
gitContributionCommand, err := contributors.NewCountContributorsCommand(gitContrParams)
if err != nil {
return err
}
Expand Down
40 changes: 29 additions & 11 deletions cli/scancommands.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package cli
import (
"errors"
"fmt"
"os"
"strings"

buildInfoUtils "github.com/jfrog/build-info-go/utils"
"github.com/jfrog/gofrog/datastructures"
"github.com/jfrog/jfrog-cli-core/v2/common/cliutils"
Expand All @@ -22,8 +25,6 @@ import (
"github.com/jfrog/jfrog-client-go/utils/io/fileutils"
"github.com/jfrog/jfrog-client-go/utils/log"
"github.com/urfave/cli"
"os"
"strings"

flags "github.com/jfrog/jfrog-cli-security/cli/docs"
auditSpecificDocs "github.com/jfrog/jfrog-cli-security/cli/docs/auditspecific"
Expand Down Expand Up @@ -373,6 +374,17 @@ func AuditCmd(c *components.Context) error {
if err != nil {
return err
}
err = progressbar.ExecWithProgress(auditCmd)
// Reporting error if Xsc service is enabled
reportErrorIfExists(err, auditCmd)
return err
}

func CreateAuditCmd(c *components.Context) (*audit.AuditCommand, error) {
auditCmd, err := CreateGenericAuditCmd(c)
if err != nil {
return nil, err
}

// Check if user used specific technologies flags
allTechnologies := techutils.GetAllTechnologiesList()
Expand All @@ -393,12 +405,12 @@ func AuditCmd(c *components.Context) error {

if c.GetBoolFlagValue(flags.WithoutCA) && !c.GetBoolFlagValue(flags.Sca) {
// No CA flag provided but sca flag is not provided, error
return pluginsCommon.PrintHelpAndReturnError(fmt.Sprintf("flag '--%s' cannot be used without '--%s'", flags.WithoutCA, flags.Sca), c)
return nil, pluginsCommon.PrintHelpAndReturnError(fmt.Sprintf("flag '--%s' cannot be used without '--%s'", flags.WithoutCA, flags.Sca), c)
}

if c.GetBoolFlagValue(flags.SecretValidation) && !c.GetBoolFlagValue(flags.Secrets) {
// No secrets flag but secret validation is provided, error
return pluginsCommon.PrintHelpAndReturnError(fmt.Sprintf("flag '--%s' cannot be used without '--%s'", flags.SecretValidation, flags.Secrets), c)
return nil, pluginsCommon.PrintHelpAndReturnError(fmt.Sprintf("flag '--%s' cannot be used without '--%s'", flags.SecretValidation, flags.Secrets), c)
}

allSubScans := utils.GetAllSupportedScans()
Expand All @@ -414,13 +426,19 @@ func AuditCmd(c *components.Context) error {

threads, err := pluginsCommon.GetThreadsCount(c)
if err != nil {
return err
return nil, err
}
auditCmd.SetThreads(threads)
err = progressbar.ExecWithProgress(auditCmd)
// Reporting error if Xsc service is enabled
reportErrorIfExists(err, auditCmd)
return err

// If no workingDirs were provided by the user, we apply a recursive scan on the root repository
isRecursiveScan := len(auditCmd.WorkingDirs()) == 0
workingDirs, err := coreutils.GetFullPathsWorkingDirs(auditCmd.WorkingDirs())
if err != nil {
return nil, err
}
auditCmd.SetWorkingDirs(workingDirs).SetIsRecursiveScan(isRecursiveScan)

return auditCmd, nil
}

func shouldAddSubScan(subScan utils.SubScanType, c *components.Context) bool {
Expand All @@ -443,7 +461,7 @@ func reportErrorIfExists(err error, auditCmd *audit.AuditCommand) {
}
}

func CreateAuditCmd(c *components.Context) (*audit.AuditCommand, error) {
func CreateGenericAuditCmd(c *components.Context) (*audit.AuditCommand, error) {
auditCmd := audit.NewGenericAuditCommand()
serverDetails, err := createServerDetailsWithConfigOffer(c)
if err != nil {
Expand Down Expand Up @@ -513,7 +531,7 @@ func logNonGenericAuditCommandDeprecation(cmdName string) {

func AuditSpecificCmd(c *components.Context, technology techutils.Technology) error {
logNonGenericAuditCommandDeprecation(c.CommandName)
auditCmd, err := CreateAuditCmd(c)
auditCmd, err := CreateGenericAuditCmd(c)
if err != nil {
return err
}
Expand Down
Loading
Loading