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
54 changes: 54 additions & 0 deletions src/main/java/com/jfrog/ide/common/configuration/AuditConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.jfrog.ide.common.configuration;

import lombok.Getter;

import java.util.List;
import java.util.Map;

@Getter
public class AuditConfig {
// Getters
private final List<String> scannedDirectories;
private final String serverId;
private final List<String> excludedPattern;
private final Map<String, String> envVars;

private AuditConfig(Builder builder) {
this.scannedDirectories = builder.scannedDirectories;
this.serverId = builder.serverId;
this.excludedPattern = builder.excludedPattern;
this.envVars = builder.envVars;
}

public static class Builder {
private List<String> scannedDirectories;
private String serverId;
private List<String> excludedPattern;
private Map<String, String> envVars;

public Builder serverId(String serverId) {
this.serverId = serverId;
return this;
}

public Builder scannedDirectories(List<String> scannedDirectories) {
this.scannedDirectories = scannedDirectories;
return this;
}

public Builder excludedPattern(List<String> excludedPattern) {
this.excludedPattern = excludedPattern;
return this;
}

public Builder envVars(Map<String, String> envVars) {
this.envVars = envVars;
return this;
}

public AuditConfig build() {
return new AuditConfig(this);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -182,17 +182,36 @@ public CommandResults addCliServerConfig(String xrayUrl, String artifactoryUrl,
}
}

public CommandResults runCliAudit(File workingDirectory, List<String> scannedDirectories, String serverId, List<String> extraArgs, Map<String, String> envVars) throws Exception {
public CommandResults runCliAudit(File workingDirectory, List<String> scannedDirectories, String serverId, Map<String, String> envVars) throws Exception {
AuditConfig config = new AuditConfig.Builder()
.scannedDirectories(scannedDirectories)
.serverId(serverId)
.envVars(envVars)
.build();
return runCliAudit(workingDirectory, config);
}

public CommandResults runCliAudit(File workingDirectory, AuditConfig config) throws Exception {
List<String> args = new ArrayList<>();
args.add("audit");
if (scannedDirectories != null && !scannedDirectories.isEmpty()) {
String workingDirsString = scannedDirectories.size() > 1 ? String.join(", ", scannedDirectories) : scannedDirectories.get(0);
args.add("--working-dirs=" + workingDirsString);

if (config.getScannedDirectories() != null && !config.getScannedDirectories().isEmpty()) {
String workingDirsString = config.getScannedDirectories().size() > 1 ?
String.join(", ", config.getScannedDirectories()) :
config.getScannedDirectories().get(0);
args.add("--working-dirs=" + quoteArgumentForUnix(workingDirsString));
}
args.add("--server-id=" + serverId);

args.add("--server-id=" + config.getServerId());
args.add("--format=sarif");

if (config.getExcludedPattern() != null && !config.getExcludedPattern().isEmpty()) {
String excludedPatterns = String.join(",", config.getExcludedPattern());
args.add("--exclusions=" + quoteArgumentForUnix(excludedPatterns));
}

try {
return runCommand(workingDirectory, envVars, args.toArray(new String[0]), extraArgs != null ? extraArgs : Collections.emptyList(), null, log);
return runCommand(workingDirectory, config.getEnvVars(), args.toArray(new String[0]), Collections.emptyList(), null, log);
} catch (IOException | InterruptedException e) {
throw new Exception("Failed to run JF audit. Reason: " + e.getMessage(), e);
}
Expand All @@ -218,4 +237,9 @@ private void addDefaultEnvVars(Map<String, String> env) {
env.put("JFROG_CLI_AVOID_NEW_VERSION_WARNING", "true");
}
}

private String quoteArgumentForUnix(String commaSeparatedValues) {
// macOS/Linux: add quotes around the comma-separated values
return SystemUtils.IS_OS_WINDOWS ? commaSeparatedValues : "\"" + commaSeparatedValues + "\"";
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
package com.jfrog.ide.common.configuration;

import com.jfrog.ide.common.nodes.FileIssueNode;
import com.jfrog.ide.common.nodes.FileTreeNode;
import com.jfrog.ide.common.nodes.subentities.Severity;
import com.jfrog.ide.common.nodes.subentities.SourceCodeScanType;
import com.jfrog.ide.common.parse.SarifParser;
import org.apache.commons.lang3.SystemUtils;
import org.jfrog.build.api.util.NullLog;
import org.jfrog.build.extractor.executor.CommandResults;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
Expand All @@ -19,7 +26,6 @@
import java.text.SimpleDateFormat;
import java.util.*;

import static java.util.Collections.singletonList;
import static org.testng.Assert.*;

/**
Expand All @@ -40,6 +46,8 @@ public class JfrogCliDriverTest {
private final String XRAY_URL = SERVER_URL + "xray/";
private String testServerId;
private File tempDir;
private final SarifParser parser = new SarifParser(new NullLog());
private final Logger logger = LoggerFactory.getLogger(JfrogCliDriverTest.class);

@SuppressWarnings("unused")
@Test()
Expand Down Expand Up @@ -82,6 +90,8 @@ private void configJfrogCli(Boolean skipDownload) {
fail(e.getMessage(), e);
}
testEnv.put("JFROG_CLI_HOME_DIR", tempDir.getAbsolutePath());
testEnv.put("JFROG_CLI_LOG_LEVEL", "DEBUG");
testEnv.put("CI", "true");
jfrogCliDriver = new JfrogCliDriver(testEnv, tempDir.getAbsolutePath() + File.separator, new NullLog());
}

Expand Down Expand Up @@ -152,7 +162,6 @@ public void testAddCliServerConfig_withUsernameAndPassword() {
CommandResults response = jfrogCliDriver.addCliServerConfig(XRAY_URL, ARTIFACTORY_URL, testServerId, USER_NAME, PASSWORD, null, tempDir, testEnv);
JfrogCliServerConfig serverConfig = jfrogCliDriver.getServerConfig(tempDir, Collections.emptyList(), testEnv);
assertTrue(response.isOk());
assertTrue(response.getErr().isBlank());
assertNotNull(serverConfig);
assertEquals(serverConfig.getUsername(), USER_NAME);
assertEquals(serverConfig.getPassword(), PASSWORD);
Expand All @@ -169,7 +178,6 @@ public void testAddCliServerConfig_withAccessToken() {
CommandResults response = jfrogCliDriver.addCliServerConfig(XRAY_URL, ARTIFACTORY_URL, testServerId, null, null, ACCESS_TOKEN, tempDir, testEnv);
JfrogCliServerConfig serverConfig = jfrogCliDriver.getServerConfig(tempDir, Collections.emptyList(), testEnv);
assertTrue(response.isOk());
assertTrue(response.getErr().isBlank());
assertNotNull(serverConfig);
assertEquals(serverConfig.getAccessToken(), ACCESS_TOKEN);
assertEquals(serverConfig.getArtifactoryUrl(), ARTIFACTORY_URL);
Expand All @@ -195,13 +203,23 @@ public void testAddServerConfig_withBadCredentials() {

@Test
public void testRunAudit_NpmProject() {
String projectToCheck = "npm";
try {
Path exampleProjectsFolder = Path.of("src/test/resources/example-projects/npm");
CommandResults response = jfrogCliDriver.runCliAudit(exampleProjectsFolder.toFile(),
singletonList(projectToCheck), testServerId, null, testEnv);
//TODO: check real values after the sarif parser is added
null, testServerId, testEnv);
assertEquals(response.getExitValue(),0);
logger.info("Audit debug logs: \n" + response.getErr());
logger.info("Audit response: \n" + response.getRes());
List<FileTreeNode> findings = parser.parse(response.getRes());
assertNotNull(findings);
assertFalse(findings.isEmpty(), "Expected findings in SARIF output for npm project");
// Verify the findings
assertEquals(findings.size(), 1, "Expected exactly one file with findings");
FileTreeNode node = findings.get(0);
assertEquals(node.getChildren().size(), 1, "Expected exactly one vulnerabilities");
FileIssueNode issue = (FileIssueNode) node.getChildren().get(0);
assertEquals(issue.getSeverity(), Severity.High, "Expected severity to be HIGH");
assertEquals(issue.getReporterType(), SourceCodeScanType.SCA, "Expected reporter type to be SCA");
} catch (Exception e) {
fail(e.getMessage(), e);
}
Expand All @@ -213,9 +231,20 @@ public void testRunAudit_MultiMavenProject() {
try {
Path exampleProjectsFolder = Path.of("src/test/resources/example-projects/maven-example");
CommandResults response = jfrogCliDriver.runCliAudit(exampleProjectsFolder.toFile(),
projectsToCheck, testServerId, null, testEnv);
//TODO: check real values after the sarif parser is added
projectsToCheck, testServerId, testEnv);
assertEquals(response.getExitValue(), 0);
logger.info("Audit debug logs: \n" + response.getErr());
logger.info("Audit response: \n" + response.getRes());
List<FileTreeNode> findings = parser.parse(response.getRes());
assertNotNull(findings);
assertFalse(findings.isEmpty(), "Expected findings in SARIF output for multi-maven project");
// Verify the findings
assertEquals(findings.size(), 1, "Expected exactly one file with findings");
FileTreeNode node = findings.get(0);
assertEquals(node.getChildren().size(), 3, "Expected exactly three vulnerabilities");
assertEquals(node.getSeverity(), Severity.High, "Expected severity to be HIGH");
FileIssueNode issue = (FileIssueNode) node.getChildren().get(0);
assertEquals(issue.getReporterType(), SourceCodeScanType.SCA, "Expected reporter type to be SCA");
} catch (Exception e) {
fail(e.getMessage(), e);
}
Expand All @@ -225,6 +254,35 @@ private String createServerId() {
return "ide-plugins-common-test-server-" + timeStampFormat.format(System.currentTimeMillis());
}

@Test
public void testRunAudit_WithExcludedPattern() {
try {
Path exampleProjectsFolder = Path.of("src/test/resources/example-projects/maven-example");
AuditConfig config = new AuditConfig.Builder()
.serverId(testServerId)
.excludedPattern(new ArrayList<>(List.of("*multi3*")))
.serverId(testServerId)
.envVars(testEnv)
.build();
CommandResults response = jfrogCliDriver.runCliAudit(exampleProjectsFolder.toFile(), config);
assertEquals(response.getExitValue(), 0);
logger.info("Audit debug logs: \n" + response.getErr());
logger.info("Audit response: \n" + response.getRes());
List<FileTreeNode> findings = parser.parse(response.getRes());
assertNotNull(findings);
assertFalse(findings.isEmpty(), "Expected findings in SARIF output for multi-maven project");
// Verify the findings
assertEquals(findings.size(), 1, "Expected exactly one file with findings");
FileTreeNode node = findings.get(0);
assertEquals(node.getChildren().size(), 3, "Expected exactly three vulnerabilities");
assertEquals(node.getSeverity(), Severity.High, "Expected severity to be HIGH");
FileIssueNode issue = (FileIssueNode) node.getChildren().get(0);
assertEquals(issue.getReporterType(), SourceCodeScanType.SCA, "Expected reporter type to be SCA");
} catch (Exception e) {
fail(e.getMessage(), e);
}
}

@AfterMethod
public void cleanUp(Method method) {
try {
Expand All @@ -236,4 +294,4 @@ public void cleanUp(Method method) {
fail(e.getMessage(), e);
}
}
}
}
Loading