Skip to content
Merged
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
27 changes: 16 additions & 11 deletions sca/bom/buildinfo/buildinfobom.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,17 +271,7 @@ func GetTechDependencyTree(params technologies.BuildInfoBomGeneratorParams, arti

switch tech {
case techutils.Maven, techutils.Gradle:
depTreeResult.FullDepTrees, uniqDepsNodes, err = java.BuildDependencyTree(java.DepTreeParams{
Server: artifactoryServerDetails,
DepsRepo: params.DependenciesRepository,
IsMavenDepTreeInstalled: params.IsMavenDepTreeInstalled,
UseWrapper: params.UseWrapper,
IsCurationCmd: params.IsCurationCmd,
MvnIncludePluginDeps: params.MvnIncludePluginDeps,
CurationCacheFolder: curationCacheFolder,
UseIncludedBuilds: params.UseIncludedBuilds,
GradleExcludeTestDependencies: params.GradleExcludeTestDependencies,
}, tech)
depTreeResult.FullDepTrees, uniqDepsNodes, err = java.BuildDependencyTree(buildJavaDepTreeParams(params, artifactoryServerDetails, curationCacheFolder), tech)
case techutils.Npm:
depTreeResult.FullDepTrees, uniqueDepsIds, err = npm.BuildDependencyTree(params)
case techutils.Pnpm:
Expand Down Expand Up @@ -332,6 +322,21 @@ func GetTechDependencyTree(params technologies.BuildInfoBomGeneratorParams, arti
return
}

func buildJavaDepTreeParams(params technologies.BuildInfoBomGeneratorParams, artifactoryServerDetails *config.ServerDetails, curationCacheFolder string) java.DepTreeParams {
return java.DepTreeParams{
Server: artifactoryServerDetails,
DepsRepo: params.DependenciesRepository,
InsecureTls: params.InsecureTls,
IsMavenDepTreeInstalled: params.IsMavenDepTreeInstalled,
UseWrapper: params.UseWrapper,
IsCurationCmd: params.IsCurationCmd,
MvnIncludePluginDeps: params.MvnIncludePluginDeps,
CurationCacheFolder: curationCacheFolder,
UseIncludedBuilds: params.UseIncludedBuilds,
GradleExcludeTestDependencies: params.GradleExcludeTestDependencies,
}
}

func getUniqueDependencyCount(uniqueDepsIds []string, uniqDepsNodes map[string]*xray.DepTreeNode) int {
if len(uniqDepsNodes) > 0 {
return len(uniqDepsNodes)
Expand Down
9 changes: 9 additions & 0 deletions sca/bom/buildinfo/buildinfobom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,3 +323,12 @@ func TestGetDiffDependencyTree(t *testing.T) {
})
}
}

func TestBuildJavaDepTreeParamsPreservesInsecureTls(t *testing.T) {
t.Parallel()
params := technologies.BuildInfoBomGeneratorParams{InsecureTls: true, DependenciesRepository: "test-repo"}
result := buildJavaDepTreeParams(params, nil, "cache-folder")
assert.True(t, result.InsecureTls)
assert.Equal(t, "test-repo", result.DepsRepo)
assert.Equal(t, "cache-folder", result.CurationCacheFolder)
}
1 change: 1 addition & 0 deletions sca/bom/buildinfo/technologies/java/deptreemanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type DepTreeParams struct {
UseWrapper bool
Server *config.ServerDetails
DepsRepo string
InsecureTls bool
IsMavenDepTreeInstalled bool
IsCurationCmd bool
MvnIncludePluginDeps bool
Expand Down
60 changes: 58 additions & 2 deletions sca/bom/buildinfo/technologies/java/mvn.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ import (
"path/filepath"
"strings"
"text/template"
"unicode/utf8"

"github.com/beevik/etree"
"github.com/jfrog/jfrog-cli-security/sca/bom/buildinfo/technologies"
"github.com/jfrog/jfrog-cli-security/utils/techutils"
"github.com/jfrog/jfrog-cli-security/utils/xray"

"github.com/jfrog/jfrog-cli-core/v2/utils/config"
"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
"github.com/jfrog/jfrog-cli-core/v2/utils/ioutils"
"github.com/jfrog/jfrog-client-go/utils/errorutils"
Expand Down Expand Up @@ -66,6 +68,7 @@ type MavenDepTreeManager struct {
settingsXmlPath string
// userSettingsXmlPath overrides the ~/.m2/settings.xml seed path (test-only).
userSettingsXmlPath string
insecureTls bool
}

func NewMavenDepTreeManager(params *DepTreeParams, cmdName MavenDepTreeCmd) *MavenDepTreeManager {
Expand All @@ -77,6 +80,7 @@ func NewMavenDepTreeManager(params *DepTreeParams, cmdName MavenDepTreeCmd) *Mav
isCurationCmd: params.IsCurationCmd,
mvnIncludePluginDeps: params.MvnIncludePluginDeps,
curationCacheFolder: params.CurationCacheFolder,
insecureTls: params.InsecureTls,
}
}

Expand Down Expand Up @@ -220,24 +224,76 @@ func (mdt *MavenDepTreeManager) RunMvnCmd(goals []string) (cmdOutput []byte, err
if mdt.settingsXmlPath != "" {
goals = append(goals, "-s", mdt.settingsXmlPath)
}
if mdt.insecureTls {
// aether.* covers Maven 3.9+'s native resolver transport; wagon.* covers the legacy one.
goals = append(goals,
"-Dmaven.wagon.http.ssl.insecure=true",
"-Dmaven.wagon.http.ssl.allowall=true",
"-Dmaven.wagon.http.ssl.ignore.validity.dates=true",
"-Daether.connector.https.securityMode=insecure",
)
}

execPath := getMavenExecPath(mdt.useWrapper)
//#nosec G204
cmdOutput, err = buildMvnExecCommand(mdt.useWrapper, execPath, goals).CombinedOutput()
if err != nil {
stringOutput := string(cmdOutput)
stringOutput := maskCredentials(string(cmdOutput), mdt.server)
if len(cmdOutput) > 0 {
log.Verbose(stringOutput)
}
if msg := technologies.GetMsgToUserForCurationBlock(mdt.isCurationCmd, techutils.Maven, stringOutput); msg != "" {
Comment thread
gauriy-tech marked this conversation as resolved.
err = fmt.Errorf("failed running command '%s %s'\n\n%s", execPath, strings.Join(goals, " "), msg)
} else {
err = fmt.Errorf("failed running command '%s %s': %s", execPath, strings.Join(goals, " "), err.Error())
err = fmt.Errorf("failed running command '%s %s': %w", execPath, strings.Join(goals, " "), err)
if stringOutput != "" {
err = fmt.Errorf("%w\n%s", err, truncateForError(stringOutput))
}
}
}
return
}

// maskCredentials redacts known credentials from output, mirroring uv.go's maskPassword.
func maskCredentials(output string, server *config.ServerDetails) string {
if server == nil {
return output
}
username, password, err := server.GetAuthenticationCredentials()
if err != nil {
return output
}
if password != "" {
output = strings.ReplaceAll(output, password, "***")
Comment thread
gauriy-tech marked this conversation as resolved.
}
if username != "" {
output = strings.ReplaceAll(output, username, "***")
}
// Also mask percent-encoded forms, in case a userinfo-embedded URL is ever echoed back.
encodedUser, encodedPass, _ := strings.Cut(url.UserPassword(username, password).String(), ":")
if encodedPass != "" && encodedPass != password {
output = strings.ReplaceAll(output, encodedPass, "***")
}
if encodedUser != "" && encodedUser != username {
output = strings.ReplaceAll(output, encodedUser, "***")
}
return output
}

const maxCapturedOutputInError = 8 * 1024

// truncateForError keeps the tail, advanced to a rune boundary to avoid invalid UTF-8.
func truncateForError(output string) string {
if len(output) <= maxCapturedOutputInError {
return output
}
cut := len(output) - maxCapturedOutputInError
for cut < len(output) && !utf8.RuneStart(output[cut]) {
cut++
}
return fmt.Sprintf("...(truncated %d bytes; see verbose log for full output)...\n%s", cut, output[cut:])
}

func (mdt *MavenDepTreeManager) GetSettingsXmlPath() string {
return mdt.settingsXmlPath
}
Expand Down
Loading
Loading