From 0020c7352bf2b7131eeb0fe5a3c29e45aa06e21e Mon Sep 17 00:00:00 2001 From: Sangamesh Vijaykumar Date: Thu, 24 Oct 2024 15:04:03 +0530 Subject: [PATCH 1/3] fix:SC-SAST: Provide ability to pass custom targs/sargs when starting scan (fixes #449) --- .../cmd/SCSastControllerScanStartCommand.java | 160 +++++++++++++++++- .../cli/mixin/ISCSastScanStartOptions.java | 2 +- .../cli/mixin/SCSastScanStartMbsOptions.java | 3 +- .../mixin/SCSastScanStartPackageOptions.java | 1 - .../sc_sast/i18n/SCSastMessages.properties | 1 + 5 files changed, 157 insertions(+), 10 deletions(-) diff --git a/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/scan/cli/cmd/SCSastControllerScanStartCommand.java b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/scan/cli/cmd/SCSastControllerScanStartCommand.java index 1dfe2e0fb6..910c8c7e81 100644 --- a/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/scan/cli/cmd/SCSastControllerScanStartCommand.java +++ b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/scan/cli/cmd/SCSastControllerScanStartCommand.java @@ -16,6 +16,11 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @@ -50,21 +55,30 @@ public final class SCSastControllerScanStartCommand extends AbstractSCSastContro @Mixin private SCSastSensorPoolResolverMixin.OptionalOption sensorPoolResolver; @Mixin private PublishToAppVersionResolverMixin sscAppVersionResolver; @Option(names = "--ssc-ci-token") private String ciToken; - + @Option(names = { "--sargs", "--scan-args" }, description = "Runtime scan arguments to Source Analyzer.") + private String scanArguments = ""; + + private Map> scanFileArgs = new HashMap>(); + private Map> compressedFilesMap = new HashMap>(); + private Set scanArgumentsSet; + // TODO Add options for specifying (custom) rules file(s), filter file(s) and project template // TODO Add options for pool selection @Override public final JsonNode getJsonNode(UnirestInstance unirest) { String sensorVersion = normalizeSensorVersion(optionsProvider.getScanStartOptions().getSensorVersion()); + + processScanArguments(); MultipartBody body = unirest.post("/rest/v2/job") .multiPartContent() .field("zipFile", createZipFile(), "application/zip") .field("username", userName, "text/plain") .field("scaVersion", sensorVersion, "text/plain") .field("clientVersion", sensorVersion, "text/plain") - .field("scaRuntimeArgs", optionsProvider.getScanStartOptions().getScaRuntimeArgs(), "text/plain") - .field("jobType", optionsProvider.getScanStartOptions().getJobType().name(), "text/plain"); + .field("jobType", optionsProvider.getScanStartOptions().getJobType().name(), "text/plain") + .field("scaRuntimeArgs", constructSCAArgs(), "text/plain"); + body = updateBody(body, "email", email); body = updateBody(body, "buildId", optionsProvider.getScanStartOptions().getBuildId()); body = updateBody(body, "pvId", getAppVersionId()); @@ -72,6 +86,7 @@ public final JsonNode getJsonNode(UnirestInstance unirest) { body = updateBody(body, "uploadToken", getUploadToken()); body = updateBody(body, "dotNetRequired", String.valueOf(optionsProvider.getScanStartOptions().isDotNetRequired())); body = updateBody(body, "dotNetFrameworkRequiredVersion", optionsProvider.getScanStartOptions().getDotNetVersion()); + JsonNode response = body.asObject(JsonNode.class).getBody(); if ( !response.has("token") ) { throw new IllegalStateException("Unexpected response when submitting scan job: "+response); @@ -80,7 +95,80 @@ public final JsonNode getJsonNode(UnirestInstance unirest) { return SCSastControllerScanJobHelper.getScanJobDescriptor(unirest, scanJobToken, StatusEndpointVersion.v1).asJsonNode(); } - @Override + private String constructSCAArgs() { + StringBuffer buffer = new StringBuffer(); + for (ScanArgument scanArgument : scanArgumentsSet) { + String argKey = scanArgument.getArgKey(); + String argValue = scanArgument.getArgValue(); + boolean fileArgument = scanArgument.isFileArgument(); + if (fileArgument) { + Set scanArgFiles = compressedFilesMap.get(argKey); + if (null != scanArgFiles) { + int size = scanArgFiles.size(); + for (String scanArgumentFileName : scanArgFiles) { + buffer.append(argKey); + buffer.append(" \'"); + buffer.append(scanArgumentFileName); + buffer.append("\'"); + if (size > 1) { + buffer.append(" "); + --size; + } + } + } + compressedFilesMap.remove(argKey); + } else { + buffer.append(argKey); + if (argValue!=null) { + buffer.append(" "); + buffer.append(argValue); + } + } + buffer.append(" "); + } + return buffer.toString().trim(); + } + + private void processScanArguments() { + scanArgumentsSet = processScanRuntimeArgs(); + for (ScanArgument scanArgument : scanArgumentsSet) { + if (scanArgument.isFileArgument()) { + String key = scanArgument.getArgKey(); + String value = scanArgument.getArgValue(); + scanFileArgs.computeIfAbsent(key, k -> new HashSet<>()).add(value); + } + } + updateFileNamesToUniqueName(); + } + + private Set processScanRuntimeArgs() { + Set scanArgsSet = new HashSet(); + String[] parts = scanArguments.split(" (?=(?:[^\']*\'[^\']*\')*[^\']*$)"); + + ScanArgument scanArgument = null; + for (String part : parts) { + String key = null; + String value = null; + boolean isFileArg = false; + + if (part.startsWith("-")) { + key = part.trim(); + scanArgument = new ScanArgument(); + scanArgument.setArgKey(key); + } else { + if (part.startsWith("file:")) { + isFileArg = true; + } + value = part.replace("file:", "").replace("'", ""); + scanArgument.setArgValue(value); + scanArgument.setFileArgument(isFileArg); + } + scanArgsSet.add(scanArgument); + } + return scanArgsSet; + } + + @Override public final String getActionCommandResult() { return "SCAN_REQUESTED"; } @@ -144,7 +232,13 @@ private File createZipFile() { try (FileOutputStream fout = new FileOutputStream(zipFile); ZipOutputStream zout = new ZipOutputStream(fout)) { final String fileName = (optionsProvider.getScanStartOptions().getJobType() == SCSastControllerJobType.TRANSLATION_AND_SCAN_JOB) ? "translation.zip" : "session.mbs"; addFile( zout, fileName, optionsProvider.getScanStartOptions().getPayloadFile()); - // TODO Add rule files, filter files, issue template + + for (Entry> fileArgsMap : compressedFilesMap.entrySet()) { + Set files = fileArgsMap.getValue(); + for (String file : files) { + addFile(zout, file, optionsProvider.getScanStartOptions().getPayloadFile()); + } + } } return zipFile; } catch (IOException e) { @@ -152,7 +246,25 @@ private File createZipFile() { } } - private void addFile(ZipOutputStream zout, String fileName, File file) throws IOException { + private void updateFileNamesToUniqueName() { + for (Entry> fileArg : scanFileArgs.entrySet()) { + String argName = fileArg.getKey(); + Set argValues = fileArg.getValue(); + Set compressedFileNames = new HashSet(); + for (String argValue : argValues) { + String uniqueFileName = constructUniqueFileName(argValue); + compressedFileNames.add(uniqueFileName); + + } + compressedFilesMap.put(argName, compressedFileNames); + } + } + + private String constructUniqueFileName(String argValue) { + return argValue.replaceAll("[^A-Za-z0-9.]", "_"); + } + + private void addFile(ZipOutputStream zout, String fileName, File file) throws IOException { try ( FileInputStream in = new FileInputStream(file)) { zout.putNextEntry(new ZipEntry(fileName)); byte[] buffer = new byte[1024]; @@ -170,3 +282,39 @@ private static final class PublishToAppVersionResolverMixin extends AbstractSSCA public final boolean hasValue() { return StringUtils.isNotBlank(appVersionNameOrId); } } } + + +class ScanArgument { + private boolean isFileArgument; + private String argKey; + private String argValue; + + public void setFileArgument(boolean isFileArgument) { + this.isFileArgument = isFileArgument; + } + + public void setArgKey(String argKey) { + this.argKey = argKey; + } + + public void setArgValue(String argValue) { + this.argValue = argValue; + } + + public boolean isFileArgument() { + return isFileArgument; + } + + public String getArgKey() { + return argKey; + } + + public String getArgValue() { + return argValue; + } + + @Override + public String toString() { + return "Argument " + argKey + (isFileArgument? " is a file argument with value " : " is not a file argument with value ") + argValue; + } +} \ No newline at end of file diff --git a/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/scan/cli/mixin/ISCSastScanStartOptions.java b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/scan/cli/mixin/ISCSastScanStartOptions.java index 060e8f5127..30777072e0 100644 --- a/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/scan/cli/mixin/ISCSastScanStartOptions.java +++ b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/scan/cli/mixin/ISCSastScanStartOptions.java @@ -18,7 +18,7 @@ public interface ISCSastScanStartOptions { String getBuildId(); - String getScaRuntimeArgs(); +// String getScaRuntimeArgs(); boolean isDotNetRequired(); String getDotNetVersion(); File getPayloadFile(); diff --git a/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/scan/cli/mixin/SCSastScanStartMbsOptions.java b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/scan/cli/mixin/SCSastScanStartMbsOptions.java index 5a56359393..1c381f6795 100644 --- a/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/scan/cli/mixin/SCSastScanStartMbsOptions.java +++ b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/scan/cli/mixin/SCSastScanStartMbsOptions.java @@ -32,7 +32,6 @@ public class SCSastScanStartMbsOptions implements ISCSastScanStartOptions { @Getter private String buildId; @Getter private final boolean dotNetRequired = false; @Getter private final String dotNetVersion = null; - @Getter private final String scaRuntimeArgs = ""; // TODO Provide options @Getter private SCSastControllerJobType jobType = SCSastControllerJobType.SCAN_JOB; @Option(names = {"-m", "--mbs-file"}, required= true) @@ -40,7 +39,7 @@ public void setMbsFile(File mbsFile) { this.payloadFile = mbsFile; setMbsProperties(mbsFile); } - + private void setMbsProperties(File mbsFile) { try ( FileSystem fs = FileSystems.newFileSystem(mbsFile.toPath()) ) { Path mbsManifest = fs.getPath("MobileBuildSession.manifest"); diff --git a/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/scan/cli/mixin/SCSastScanStartPackageOptions.java b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/scan/cli/mixin/SCSastScanStartPackageOptions.java index ceb9314517..19dcf43923 100644 --- a/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/scan/cli/mixin/SCSastScanStartPackageOptions.java +++ b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/scan/cli/mixin/SCSastScanStartPackageOptions.java @@ -33,7 +33,6 @@ public class SCSastScanStartPackageOptions implements ISCSastScanStartOptions { @Getter private final String buildId = null; // TODO ScanCentral Client doesn't allow for specifying build id; should we provide a CLI option for this? @Getter private boolean dotNetRequired; @Getter private String dotNetVersion; - @Getter private final String scaRuntimeArgs = ""; @Getter private SCSastControllerJobType jobType = SCSastControllerJobType.TRANSLATION_AND_SCAN_JOB; @Option(names = {"-p", "--package-file"}, required = true) diff --git a/fcli-core/fcli-sc-sast/src/main/resources/com/fortify/cli/sc_sast/i18n/SCSastMessages.properties b/fcli-core/fcli-sc-sast/src/main/resources/com/fortify/cli/sc_sast/i18n/SCSastMessages.properties index 58b29cf819..1f51ce9775 100644 --- a/fcli-core/fcli-sc-sast/src/main/resources/com/fortify/cli/sc_sast/i18n/SCSastMessages.properties +++ b/fcli-core/fcli-sc-sast/src/main/resources/com/fortify/cli/sc_sast/i18n/SCSastMessages.properties @@ -141,6 +141,7 @@ fcli.sc-sast.scan.wait-for.any-scan-state=One or more scan states against which fcli.sc-sast.scan.wait-for.any-publish-state=One or more scan publishing states against which to match the given scans. fcli.sc-sast.scan.wait-for.any-ssc-state=One or more SSC artifact processing states against which to match the given scans. fcli.sc-sast.scan-job.resolver.jobToken = Scan job token. +fcli.sc-sast.scan.start.sargs = Fortify Source Analyzer runtime scan arguments. # fcli sc-sast sensor fcli.sc-sast.sensor.usage.header = Manage ScanCentral SAST sensors. From b8e7434c31d806a41df98912ab2bb271a1dcaa4e Mon Sep 17 00:00:00 2001 From: Ruud Senden <8635138+rsenden@users.noreply.github.com> Date: Thu, 24 Oct 2024 14:24:15 +0200 Subject: [PATCH 2/3] chore: Various updates --- .../cmd/SCSastControllerScanStartCommand.java | 165 ++++++------------ .../cli/mixin/ISCSastScanStartOptions.java | 1 - .../sc_sast/i18n/SCSastMessages.properties | 6 +- 3 files changed, 57 insertions(+), 115 deletions(-) diff --git a/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/scan/cli/cmd/SCSastControllerScanStartCommand.java b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/scan/cli/cmd/SCSastControllerScanStartCommand.java index 910c8c7e81..5b71e55035 100644 --- a/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/scan/cli/cmd/SCSastControllerScanStartCommand.java +++ b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/scan/cli/cmd/SCSastControllerScanStartCommand.java @@ -16,11 +16,11 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; -import java.util.HashMap; -import java.util.HashSet; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; +import java.util.regex.Pattern; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @@ -40,6 +40,7 @@ import kong.unirest.MultipartBody; import kong.unirest.UnirestInstance; import lombok.Getter; +import lombok.RequiredArgsConstructor; import picocli.CommandLine.ArgGroup; import picocli.CommandLine.Command; import picocli.CommandLine.Mixin; @@ -55,29 +56,21 @@ public final class SCSastControllerScanStartCommand extends AbstractSCSastContro @Mixin private SCSastSensorPoolResolverMixin.OptionalOption sensorPoolResolver; @Mixin private PublishToAppVersionResolverMixin sscAppVersionResolver; @Option(names = "--ssc-ci-token") private String ciToken; - @Option(names = { "--sargs", "--scan-args" }, description = "Runtime scan arguments to Source Analyzer.") + @Option(names = { "--sargs", "--scan-args" }) private String scanArguments = ""; - - private Map> scanFileArgs = new HashMap>(); - private Map> compressedFilesMap = new HashMap>(); - private Set scanArgumentsSet; - - // TODO Add options for specifying (custom) rules file(s), filter file(s) and project template - // TODO Add options for pool selection @Override public final JsonNode getJsonNode(UnirestInstance unirest) { String sensorVersion = normalizeSensorVersion(optionsProvider.getScanStartOptions().getSensorVersion()); - - processScanArguments(); + var scanArgsHelper = ScanArgsHelper.parse(scanArguments); MultipartBody body = unirest.post("/rest/v2/job") .multiPartContent() - .field("zipFile", createZipFile(), "application/zip") + .field("zipFile", createZipFile(scanArgsHelper.getInputFileToZipEntryMap()), "application/zip") .field("username", userName, "text/plain") .field("scaVersion", sensorVersion, "text/plain") .field("clientVersion", sensorVersion, "text/plain") .field("jobType", optionsProvider.getScanStartOptions().getJobType().name(), "text/plain") - .field("scaRuntimeArgs", constructSCAArgs(), "text/plain"); + .field("scaRuntimeArgs", scanArgsHelper.getScanArgs(), "text/plain"); body = updateBody(body, "email", email); body = updateBody(body, "buildId", optionsProvider.getScanStartOptions().getBuildId()); @@ -95,79 +88,6 @@ public final JsonNode getJsonNode(UnirestInstance unirest) { return SCSastControllerScanJobHelper.getScanJobDescriptor(unirest, scanJobToken, StatusEndpointVersion.v1).asJsonNode(); } - private String constructSCAArgs() { - StringBuffer buffer = new StringBuffer(); - for (ScanArgument scanArgument : scanArgumentsSet) { - String argKey = scanArgument.getArgKey(); - String argValue = scanArgument.getArgValue(); - boolean fileArgument = scanArgument.isFileArgument(); - if (fileArgument) { - Set scanArgFiles = compressedFilesMap.get(argKey); - if (null != scanArgFiles) { - int size = scanArgFiles.size(); - for (String scanArgumentFileName : scanArgFiles) { - buffer.append(argKey); - buffer.append(" \'"); - buffer.append(scanArgumentFileName); - buffer.append("\'"); - if (size > 1) { - buffer.append(" "); - --size; - } - } - } - compressedFilesMap.remove(argKey); - } else { - buffer.append(argKey); - if (argValue!=null) { - buffer.append(" "); - buffer.append(argValue); - } - } - buffer.append(" "); - } - return buffer.toString().trim(); - } - - private void processScanArguments() { - scanArgumentsSet = processScanRuntimeArgs(); - for (ScanArgument scanArgument : scanArgumentsSet) { - if (scanArgument.isFileArgument()) { - String key = scanArgument.getArgKey(); - String value = scanArgument.getArgValue(); - scanFileArgs.computeIfAbsent(key, k -> new HashSet<>()).add(value); - } - } - updateFileNamesToUniqueName(); - } - - private Set processScanRuntimeArgs() { - Set scanArgsSet = new HashSet(); - String[] parts = scanArguments.split(" (?=(?:[^\']*\'[^\']*\')*[^\']*$)"); - - ScanArgument scanArgument = null; - for (String part : parts) { - String key = null; - String value = null; - boolean isFileArg = false; - - if (part.startsWith("-")) { - key = part.trim(); - scanArgument = new ScanArgument(); - scanArgument.setArgKey(key); - } else { - if (part.startsWith("file:")) { - isFileArg = true; - } - value = part.replace("file:", "").replace("'", ""); - scanArgument.setArgValue(value); - scanArgument.setFileArgument(isFileArg); - } - scanArgsSet.add(scanArgument); - } - return scanArgsSet; - } - @Override public final String getActionCommandResult() { return "SCAN_REQUESTED"; @@ -225,7 +145,7 @@ private final MultipartBody updateBody(MultipartBody body, String field, String return StringUtils.isBlank(value) ? body : body.field(field, value, "text/plain"); } - private File createZipFile() { + private File createZipFile(Map extraFiles) { try { File zipFile = File.createTempFile("zip", ".zip"); zipFile.deleteOnExit(); @@ -233,11 +153,8 @@ private File createZipFile() { final String fileName = (optionsProvider.getScanStartOptions().getJobType() == SCSastControllerJobType.TRANSLATION_AND_SCAN_JOB) ? "translation.zip" : "session.mbs"; addFile( zout, fileName, optionsProvider.getScanStartOptions().getPayloadFile()); - for (Entry> fileArgsMap : compressedFilesMap.entrySet()) { - Set files = fileArgsMap.getValue(); - for (String file : files) { - addFile(zout, file, optionsProvider.getScanStartOptions().getPayloadFile()); - } + for (var extraFile : extraFiles.entrySet() ) { + addFile(zout, extraFile.getValue(), extraFile.getKey()); } } return zipFile; @@ -246,24 +163,6 @@ private File createZipFile() { } } - private void updateFileNamesToUniqueName() { - for (Entry> fileArg : scanFileArgs.entrySet()) { - String argName = fileArg.getKey(); - Set argValues = fileArg.getValue(); - Set compressedFileNames = new HashSet(); - for (String argValue : argValues) { - String uniqueFileName = constructUniqueFileName(argValue); - compressedFileNames.add(uniqueFileName); - - } - compressedFilesMap.put(argName, compressedFileNames); - } - } - - private String constructUniqueFileName(String argValue) { - return argValue.replaceAll("[^A-Za-z0-9.]", "_"); - } - private void addFile(ZipOutputStream zout, String fileName, File file) throws IOException { try ( FileInputStream in = new FileInputStream(file)) { zout.putNextEntry(new ZipEntry(fileName)); @@ -281,9 +180,49 @@ private static final class PublishToAppVersionResolverMixin extends AbstractSSCA @Getter private String appVersionNameOrId; public final boolean hasValue() { return StringUtils.isNotBlank(appVersionNameOrId); } } + + @RequiredArgsConstructor + private static final class ScanArgsHelper { + @Getter private final String scanArgs; + @Getter private final Map inputFileToZipEntryMap; + + public static final ScanArgsHelper parse(String scanArgs) { + List newArgs = new ArrayList<>(); + Map inputFileToZipEntryMap = new LinkedHashMap<>(); + String[] parts = scanArgs.split(" (?=(?:[^\']*\'[^\']*\')*[^\']*$)"); + for ( var part: parts ) { + var inputFileName = getInputFileName(part); + if ( inputFileName==null ) { + newArgs.add(part.replace("'", "\"")); + } else { + var inputFile = new File(inputFileName); + if ( !inputFile.canRead() ) { + throw new IllegalArgumentException("Can't read file "+inputFileName+" as specified in --sargs"); + } + // Re-use existing zip entry name if same file was processed before + var zipEntryFileName = inputFileToZipEntryMap.getOrDefault(inputFile, getZipEntryFileName(inputFileName)); + newArgs.add("\""+zipEntryFileName+"\""); + inputFileToZipEntryMap.put(inputFile, zipEntryFileName); + } + } + return new ScanArgsHelper(String.join(" ", newArgs), inputFileToZipEntryMap); + } + + private static final String getInputFileName(String part) { + var pattern = Pattern.compile("^'?file:'?([^\']*)'?$"); + var matcher = pattern.matcher(part); + return matcher.matches() ? matcher.group(1) : null; + } + + private static final String getZipEntryFileName(String orgFileName) { + return orgFileName.replaceAll("[^A-Za-z0-9.]", "_"); + } + } } + + class ScanArgument { private boolean isFileArgument; private String argKey; diff --git a/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/scan/cli/mixin/ISCSastScanStartOptions.java b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/scan/cli/mixin/ISCSastScanStartOptions.java index 30777072e0..2bdd47fd39 100644 --- a/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/scan/cli/mixin/ISCSastScanStartOptions.java +++ b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/scan/cli/mixin/ISCSastScanStartOptions.java @@ -18,7 +18,6 @@ public interface ISCSastScanStartOptions { String getBuildId(); -// String getScaRuntimeArgs(); boolean isDotNetRequired(); String getDotNetVersion(); File getPayloadFile(); diff --git a/fcli-core/fcli-sc-sast/src/main/resources/com/fortify/cli/sc_sast/i18n/SCSastMessages.properties b/fcli-core/fcli-sc-sast/src/main/resources/com/fortify/cli/sc_sast/i18n/SCSastMessages.properties index 1f51ce9775..1f7ed00324 100644 --- a/fcli-core/fcli-sc-sast/src/main/resources/com/fortify/cli/sc_sast/i18n/SCSastMessages.properties +++ b/fcli-core/fcli-sc-sast/src/main/resources/com/fortify/cli/sc_sast/i18n/SCSastMessages.properties @@ -123,6 +123,11 @@ fcli.sc-sast.scan.start.package-file = Package file to scan. fcli.sc-sast.scan.start.notify = Email address to which to send a scan completion notification. fcli.sc-sast.scan.start.sensor-version = Version of the sensor on which the package should be scanned. Officially, you should select the same sensor version as the version of the ScanCentral Client used to create the package. fcli.sc-sast.scan.start.publish-to = Publish scan results to the given SSC application version once the scan has completed. +fcli.sc-sast.scan.start.sargs = Fortify Static Code Analyzer scan arguments, see ScanCentral SAST documentation for supported \ + scan arguments for your ScanCentral SAST version. Multiple scan arguments must be provided as a single option argument, \ + arguments containing spaces must be embedded in single quotes, and local files must be referenced through the 'file:' prefix. \ + Note that contrary to fcli, scan arguments usually start with a single dash, not double dashes. For example: \ + %n --sargs "-quick -filter 'file:./my filters.txt'" fcli.sc-sast.scan.status.usage.header = Get status for a previously submitted scan request. fcli.sc-sast.scan.wait-for.usage.header = Wait for one or more scans to reach or exit specified scan statuses. fcli.sc-sast.scan.wait-for.usage.description.0 = Although this command offers a lot of options to cover many \ @@ -141,7 +146,6 @@ fcli.sc-sast.scan.wait-for.any-scan-state=One or more scan states against which fcli.sc-sast.scan.wait-for.any-publish-state=One or more scan publishing states against which to match the given scans. fcli.sc-sast.scan.wait-for.any-ssc-state=One or more SSC artifact processing states against which to match the given scans. fcli.sc-sast.scan-job.resolver.jobToken = Scan job token. -fcli.sc-sast.scan.start.sargs = Fortify Source Analyzer runtime scan arguments. # fcli sc-sast sensor fcli.sc-sast.sensor.usage.header = Manage ScanCentral SAST sensors. From d1b78c4b4caee79f228b88046ca7d02499aa6c8c Mon Sep 17 00:00:00 2001 From: Ruud Senden <8635138+rsenden@users.noreply.github.com> Date: Thu, 24 Oct 2024 14:32:45 +0200 Subject: [PATCH 3/3] chore: Remove obsolete class --- .../cmd/SCSastControllerScanStartCommand.java | 38 ------------------- 1 file changed, 38 deletions(-) diff --git a/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/scan/cli/cmd/SCSastControllerScanStartCommand.java b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/scan/cli/cmd/SCSastControllerScanStartCommand.java index 5b71e55035..c2198aba98 100644 --- a/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/scan/cli/cmd/SCSastControllerScanStartCommand.java +++ b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/scan/cli/cmd/SCSastControllerScanStartCommand.java @@ -218,42 +218,4 @@ private static final String getZipEntryFileName(String orgFileName) { return orgFileName.replaceAll("[^A-Za-z0-9.]", "_"); } } -} - - - - -class ScanArgument { - private boolean isFileArgument; - private String argKey; - private String argValue; - - public void setFileArgument(boolean isFileArgument) { - this.isFileArgument = isFileArgument; - } - - public void setArgKey(String argKey) { - this.argKey = argKey; - } - - public void setArgValue(String argValue) { - this.argValue = argValue; - } - - public boolean isFileArgument() { - return isFileArgument; - } - - public String getArgKey() { - return argKey; - } - - public String getArgValue() { - return argValue; - } - - @Override - public String toString() { - return "Argument " + argKey + (isFileArgument? " is a file argument with value " : " is not a file argument with value ") + argValue; - } } \ No newline at end of file