diff --git a/fcli-core/fcli-common/src/main/java/com/fortify/cli/common/rest/unirest/config/UrlConfig.java b/fcli-core/fcli-common/src/main/java/com/fortify/cli/common/rest/unirest/config/UrlConfig.java index b59ff45f7f..a9a9ebe525 100644 --- a/fcli-core/fcli-common/src/main/java/com/fortify/cli/common/rest/unirest/config/UrlConfig.java +++ b/fcli-core/fcli-common/src/main/java/com/fortify/cli/common/rest/unirest/config/UrlConfig.java @@ -35,13 +35,9 @@ public static final UrlConfig from(IUrlConfig other) { } public static final UrlConfigBuilder builderFrom(IUrlConfig other) { - UrlConfigBuilder builder = UrlConfig.builder(); - if ( other!=null ) { - builder = builder - .url(other.getUrl()) - .insecureModeEnabled(other.isInsecureModeEnabled()) - .connectTimeoutInMillis(other.getConnectTimeoutInMillis()) - .socketTimeoutInMillis(other.getSocketTimeoutInMillis()); + var builder = builderFromConnectionConfig(other); + if (null != other) { + builder = builder.url(other.getUrl()); } return builder; } @@ -57,6 +53,17 @@ public static final UrlConfigBuilder builderFrom(IUrlConfig other, IUrlConfig ov return builder; } + public static final UrlConfigBuilder builderFromConnectionConfig(IConnectionConfig other) { + UrlConfigBuilder builder = UrlConfig.builder(); + if ( other!=null ) { + builder = builder + .insecureModeEnabled(other.isInsecureModeEnabled()) + .connectTimeoutInMillis(other.getConnectTimeoutInMillis()) + .socketTimeoutInMillis(other.getSocketTimeoutInMillis()); + } + return builder; + } + private static final void override(String value, Consumer setter) { if ( StringUtils.isNotBlank(value) ) { setter.accept(value); } } diff --git a/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/_common/session/cli/cmd/SCSastSessionLoginCommand.java b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/_common/session/cli/cmd/SCSastSessionLoginCommand.java index 565daccb71..0c39d81221 100644 --- a/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/_common/session/cli/cmd/SCSastSessionLoginCommand.java +++ b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/_common/session/cli/cmd/SCSastSessionLoginCommand.java @@ -15,10 +15,10 @@ import com.fortify.cli.common.output.cli.mixin.OutputHelperMixins; import com.fortify.cli.common.rest.unirest.GenericUnirestFactory; import com.fortify.cli.common.rest.unirest.UnexpectedHttpResponseException; -import com.fortify.cli.common.rest.unirest.config.IUrlConfig; import com.fortify.cli.common.session.cli.cmd.AbstractSessionLoginCommand; import com.fortify.cli.sc_sast._common.rest.helper.SCSastUnirestHelper; import com.fortify.cli.sc_sast._common.session.cli.mixin.SCSastSessionLoginOptions; +import com.fortify.cli.sc_sast._common.session.helper.ISCSastAndSSCUrlConfig; import com.fortify.cli.sc_sast._common.session.helper.SCSastSessionDescriptor; import com.fortify.cli.sc_sast._common.session.helper.SCSastSessionHelper; import com.fortify.cli.ssc._common.session.helper.ISSCCredentialsConfig; @@ -41,9 +41,9 @@ protected void logoutBeforeNewLogin(String sessionName, SCSastSessionDescriptor @Override protected SCSastSessionDescriptor login(String sessionName) { - IUrlConfig urlConfig = sessionLoginOptions.getUrlConfigOptions(); + ISCSastAndSSCUrlConfig scSastAndSscUrlConfig = sessionLoginOptions.getScSastAndSscUrlConfigOptions(); ISSCCredentialsConfig credentialsConfig = sessionLoginOptions.getCredentialOptions(); - return new SCSastSessionDescriptor(urlConfig, credentialsConfig, sessionLoginOptions.getClientAuthToken()); + return new SCSastSessionDescriptor(scSastAndSscUrlConfig, credentialsConfig, sessionLoginOptions.getClientAuthToken()); } @Override diff --git a/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/_common/session/cli/mixin/SCSastUrlConfigOptions.java b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/_common/session/cli/mixin/SCSastAndSSCUrlConfigOptions.java similarity index 74% rename from fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/_common/session/cli/mixin/SCSastUrlConfigOptions.java rename to fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/_common/session/cli/mixin/SCSastAndSSCUrlConfigOptions.java index cb04ef44d3..709dc39bed 100644 --- a/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/_common/session/cli/mixin/SCSastUrlConfigOptions.java +++ b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/_common/session/cli/mixin/SCSastAndSSCUrlConfigOptions.java @@ -13,16 +13,15 @@ package com.fortify.cli.sc_sast._common.session.cli.mixin; import com.fortify.cli.common.rest.cli.mixin.ConnectionConfigOptions; -import com.fortify.cli.common.rest.unirest.config.IUrlConfig; +import com.fortify.cli.sc_sast._common.session.helper.ISCSastAndSSCUrlConfig; import lombok.Getter; import picocli.CommandLine.Option; -public class SCSastUrlConfigOptions extends ConnectionConfigOptions implements IUrlConfig { +public class SCSastAndSSCUrlConfigOptions extends ConnectionConfigOptions implements ISCSastAndSSCUrlConfig { @Option(names = {"--ssc-url"}, required = true, order=1) - @Getter private String url; + @Getter private String sscUrl; - public boolean hasUrlConfig() { - return url!=null; - } + @Option(names = {"--ctrl-url"}, required = false, order=1) + @Getter private String controllerUrl; } diff --git a/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/_common/session/cli/mixin/SCSastSessionLoginOptions.java b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/_common/session/cli/mixin/SCSastSessionLoginOptions.java index 4e3cabca3a..e17b69710a 100644 --- a/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/_common/session/cli/mixin/SCSastSessionLoginOptions.java +++ b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/_common/session/cli/mixin/SCSastSessionLoginOptions.java @@ -21,7 +21,7 @@ public class SCSastSessionLoginOptions { @ArgGroup(exclusive = false, multiplicity = "1", order = 1) - @Getter private SCSastUrlConfigOptions urlConfigOptions = new SCSastUrlConfigOptions(); + @Getter private SCSastAndSSCUrlConfigOptions scSastAndSscUrlConfigOptions = new SCSastAndSSCUrlConfigOptions(); @Option(names = {"--client-auth-token", "-c"}, required = true, interactive = true, arity = "0..1", echo = false) @Getter private char[] clientAuthToken; diff --git a/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/_common/session/helper/ISCSastAndSSCUrlConfig.java b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/_common/session/helper/ISCSastAndSSCUrlConfig.java new file mode 100644 index 0000000000..e7cc4f1ced --- /dev/null +++ b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/_common/session/helper/ISCSastAndSSCUrlConfig.java @@ -0,0 +1,14 @@ +/** + * + */ +package com.fortify.cli.sc_sast._common.session.helper; + +import com.fortify.cli.common.rest.unirest.config.IConnectionConfig; + +/** + * Interface for the functions to get the SSC URL and the Controller URL + */ +public interface ISCSastAndSSCUrlConfig extends IConnectionConfig { + String getSscUrl(); + String getControllerUrl(); +} diff --git a/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/_common/session/helper/SCSastSessionDescriptor.java b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/_common/session/helper/SCSastSessionDescriptor.java index 8a2c8ad101..d6be5d6a7e 100644 --- a/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/_common/session/helper/SCSastSessionDescriptor.java +++ b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/_common/session/helper/SCSastSessionDescriptor.java @@ -34,8 +34,8 @@ import com.fortify.cli.ssc._common.session.helper.ISSCUserCredentialsConfig; import com.fortify.cli.ssc.access_control.helper.SSCTokenCreateRequest; import com.fortify.cli.ssc.access_control.helper.SSCTokenGetOrCreateResponse; -import com.fortify.cli.ssc.access_control.helper.SSCTokenHelper; import com.fortify.cli.ssc.access_control.helper.SSCTokenGetOrCreateResponse.SSCTokenData; +import com.fortify.cli.ssc.access_control.helper.SSCTokenHelper; import kong.unirest.UnirestInstance; import lombok.Data; @@ -53,17 +53,14 @@ public class SCSastSessionDescriptor extends AbstractSessionDescriptor { private char[] predefinedSscToken; private SSCTokenGetOrCreateResponse cachedSscTokenResponse; - public SCSastSessionDescriptor(IUrlConfig sscUrlConfig, ISSCCredentialsConfig credentialsConfig, char[] scSastClientAuthToken) { - this(sscUrlConfig, null, credentialsConfig, scSastClientAuthToken); - } - public SCSastSessionDescriptor(IUrlConfig sscUrlConfig, IUrlConfig scSastUrlConfig, ISSCCredentialsConfig credentialsConfig, char[] scSastClientAuthToken) { - this.sscUrlConfig = sscUrlConfig; + public SCSastSessionDescriptor(ISCSastAndSSCUrlConfig scSastAndSscUrlConfig, ISSCCredentialsConfig credentialsConfig, char[] scSastClientAuthToken) { + this.sscUrlConfig = UrlConfig.builderFromConnectionConfig(scSastAndSscUrlConfig).url(scSastAndSscUrlConfig.getSscUrl()).build(); this.predefinedSscToken = credentialsConfig.getPredefinedToken(); this.scSastClientAuthToken = scSastClientAuthToken; this.cachedSscTokenResponse = getOrGenerateToken(sscUrlConfig, credentialsConfig); char[] activeToken = getActiveSSCToken(); - this.scSastUrlConfig = activeToken==null ? null : buildScSastUrlConfig(sscUrlConfig, scSastUrlConfig, activeToken); + this.scSastUrlConfig = activeToken==null ? null : buildScSastUrlConfig(sscUrlConfig, scSastAndSscUrlConfig, activeToken); } @JsonIgnore @@ -164,13 +161,12 @@ private SSCTokenData getCachedSscTokenResponseData() { : cachedSscTokenResponse.getData(); } - private static final IUrlConfig buildScSastUrlConfig(IUrlConfig sscUrlConfig, IUrlConfig scSastUrlConfig, char[] activeToken) { - String scSastUrl = scSastUrlConfig!=null && StringUtils.isNotBlank(scSastUrlConfig.getUrl()) - ? scSastUrlConfig.getUrl() - : getScSastUrl(sscUrlConfig, activeToken); - UrlConfig.UrlConfigBuilder builder = UrlConfig.builderFrom(sscUrlConfig, scSastUrlConfig); - builder.url(scSastUrl); - return builder.build(); + private static final IUrlConfig buildScSastUrlConfig(IUrlConfig sscUrlConfig, ISCSastAndSSCUrlConfig scSastAndSscUrlConfig, char[] activeToken) { + String controllerUrl = scSastAndSscUrlConfig.getControllerUrl(); + if (null == controllerUrl || StringUtils.isBlank(controllerUrl)) { + controllerUrl = getScSastUrl(sscUrlConfig, activeToken); + } + return UrlConfig.builderFromConnectionConfig(scSastAndSscUrlConfig).url(controllerUrl).build(); } private static String getScSastUrl(IUrlConfig sscUrlConfig, char[] activeToken) { 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 1f7ed00324..4d1cf718a8 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 @@ -74,6 +74,7 @@ fcli.sc-sast.session.login.ssc-url.0 = SSC URL. fcli.sc-sast.session.login.ssc-url.1 = Environment variables:%n \ ${fcli.env.default.prefix}_SSC_URL: Shared with SSC/SC DAST%n \ ${fcli.env.default.prefix}_SC_SAST_SSC_URL: Only SC SAST commands +fcli.sc-sast.session.login.ctrl-url = Override ScanCentral SAST Controller URL. If not specified, the controller URL as configured in SSC will be used. # fcli sc-sast session logout fcli.sc-sast.session.logout.usage.header = Terminate ScanCentral SAST session. diff --git a/fcli-core/fcli-ssc/src/main/java/com/fortify/cli/ssc/appversion/cli/cmd/SSCAppVersionUpdateCommand.java b/fcli-core/fcli-ssc/src/main/java/com/fortify/cli/ssc/appversion/cli/cmd/SSCAppVersionUpdateCommand.java index af43c3ccda..61b4536fb5 100644 --- a/fcli-core/fcli-ssc/src/main/java/com/fortify/cli/ssc/appversion/cli/cmd/SSCAppVersionUpdateCommand.java +++ b/fcli-core/fcli-ssc/src/main/java/com/fortify/cli/ssc/appversion/cli/cmd/SSCAppVersionUpdateCommand.java @@ -53,6 +53,8 @@ public class SSCAppVersionUpdateCommand extends AbstractSSCJsonNodeOutputCommand private String name; @Option(names={"--description","-d"}, required = false) private String description; + @Option(names={"--active"}, required = false, defaultValue=Option.NULL_VALUE, arity="1") + private Boolean active; @Override public JsonNode getJsonNode(UnirestInstance unirest) { @@ -100,6 +102,10 @@ private final HttpRequest getAppVersionUpdateRequest(UnirestInstance unirest, boolean hasUpdate = optionalUpdate(updateData, "name", getUnqualifiedVersionName(name, descriptor)); hasUpdate |= optionalUpdate(updateData, "description", description); hasUpdate |= optionalUpdate(updateData, issueTemplateResolver.getIssueTemplateDescriptor(unirest)); + if (null != active) { + updateData.put("active", active); + hasUpdate |= true; + } return hasUpdate ? unirest.put(SSCUrls.PROJECT_VERSION(descriptor.getVersionId())).body(updateData) : null; diff --git a/fcli-core/fcli-ssc/src/main/java/com/fortify/cli/ssc/appversion/helper/SSCAppVersionHelper.java b/fcli-core/fcli-ssc/src/main/java/com/fortify/cli/ssc/appversion/helper/SSCAppVersionHelper.java index dc5af3fa9b..3a3abe5392 100644 --- a/fcli-core/fcli-ssc/src/main/java/com/fortify/cli/ssc/appversion/helper/SSCAppVersionHelper.java +++ b/fcli-core/fcli-ssc/src/main/java/com/fortify/cli/ssc/appversion/helper/SSCAppVersionHelper.java @@ -60,7 +60,7 @@ public static final SSCAppVersionDescriptor getOptionalAppVersionFromAppAndVersi } private static GetRequest getBaseRequest(UnirestInstance unirest, String... fields) { - GetRequest request = unirest.get("/api/v1/projectVersions?limit=2"); + GetRequest request = unirest.get("/api/v1/projectVersions?includeInactive=true&limit=2"); if ( fields!=null && fields.length>0 ) { request.queryString("fields", String.join(",", fields)); } diff --git a/fcli-core/fcli-ssc/src/main/java/com/fortify/cli/ssc/artifact/cli/cmd/SSCArtifactGetCommand.java b/fcli-core/fcli-ssc/src/main/java/com/fortify/cli/ssc/artifact/cli/cmd/SSCArtifactGetCommand.java index a9f40b33ba..386b1b5bfb 100644 --- a/fcli-core/fcli-ssc/src/main/java/com/fortify/cli/ssc/artifact/cli/cmd/SSCArtifactGetCommand.java +++ b/fcli-core/fcli-ssc/src/main/java/com/fortify/cli/ssc/artifact/cli/cmd/SSCArtifactGetCommand.java @@ -31,7 +31,7 @@ public class SSCArtifactGetCommand extends AbstractSSCArtifactOutputCommand impl @Override public HttpRequest getBaseRequest() { - return getUnirestInstance().get(SSCUrls.ARTIFACT(artifactId)); + return getUnirestInstance().get(SSCUrls.ARTIFACT(artifactId)).queryString("embed","scans"); } @Override diff --git a/fcli-core/fcli-ssc/src/main/resources/com/fortify/cli/ssc/i18n/SSCMessages.properties b/fcli-core/fcli-ssc/src/main/resources/com/fortify/cli/ssc/i18n/SSCMessages.properties index 79ef6b9c31..01fbf07a2d 100644 --- a/fcli-core/fcli-ssc/src/main/resources/com/fortify/cli/ssc/i18n/SSCMessages.properties +++ b/fcli-core/fcli-ssc/src/main/resources/com/fortify/cli/ssc/i18n/SSCMessages.properties @@ -369,6 +369,8 @@ fcli.ssc.appversion.update.usage.description = This command allows for updating or --rm-users option may not be applied if the fcli session was created using a CIToken. fcli.ssc.appversion.update.name = Update application version name. fcli.ssc.appversion.update.description = Update application version description. +fcli.ssc.appversion.update.active = Specify whether application version should be activated (true) \ + or not (false). fcli.ssc.appversion.resolver.name = Application and version name. fcli.ssc.appversion.resolver.nameOrId = Application version id or : name. fcli.ssc.appversion.resolver.copy-from.nameOrId = Copy FROM application version: \nid or : name. diff --git a/fcli-other/fcli-functional-test/src/ftest/groovy/com/fortify/cli/ftest/sc_sast/SCSastScanSpec.groovy b/fcli-other/fcli-functional-test/src/ftest/groovy/com/fortify/cli/ftest/sc_sast/SCSastScanSpec.groovy index fc0533f50b..30228b6cbe 100644 --- a/fcli-other/fcli-functional-test/src/ftest/groovy/com/fortify/cli/ftest/sc_sast/SCSastScanSpec.groovy +++ b/fcli-other/fcli-functional-test/src/ftest/groovy/com/fortify/cli/ftest/sc_sast/SCSastScanSpec.groovy @@ -20,6 +20,7 @@ import spock.lang.Stepwise class SCSastScanSpec extends FcliBaseSpec { @Shared @TestResource("runtime/shared/EightBall-package.zip") String packageZip @Shared @TestResource("runtime/shared/EightBall-22.1.0.mbs") String packageMbs + @Shared @TestResource("runtime/shared/Filter.txt") String fileFilter String user = System.getProperty('ft.ssc.user'); String pass = System.getProperty('ft.ssc.password'); @@ -46,44 +47,51 @@ class SCSastScanSpec extends FcliBaseSpec { verifyAll(result.stdout) { size()>1 it[0].replace(' ', '').equals("HostnameStatePoolnameIpaddressScaversionLastseenSensorstarttime") - } } - def "extractHighestVersionSensor"() { - def args = "util variable contents sensors -q uuid==#var('sensors').get(#var('sensors').size()-1).uuid --store highestSensor" + def args = "util variable contents sensors -q uuid==#var('sensors').get(#var('sensors').size()-1).uuid --store highestSensor -o table=hostName,scaVersion" when: def result = Fcli.run(args) then: verifyAll(result.stdout) { size()>=2 - it[0].replace(' ', '').equals("UuidProcessuuidStateWorkerstarttimeWorkerexpirytimeLastseenLastactivityIpaddressHostnameScaversionVmnameAvailableprocessorsTotalphysicalmemoryOsnameOsversionOsarchitectureCloudpooluuidCloudpoolpathCloudpoolnameCloudpooldescriptionCloudpoolchildofglobalpoolCloudpoolisdeletableCloudpoolstatsHref") - - } - } - - - def "startScan"() { - def args = "sc-sast scan start -v ::highestSensor::get(0).scaVersion -p=$packageZip --store upload" - when: - def result = Fcli.run(args) - then: - verifyAll(result.stdout) { - size()==2 - it[0].replace(' ', '').equals("JobtokenHasfilesScanstatePublishstateSscprocessingstateEndpointversionAction") - } - } - - def "wait-for"() { - // Depending on externalmetadata versions in FPR and on SSC, approval - // may be required - def args = "sc-sast scan wait-for ::upload:: -i 2s --until=all-match --any-scan-state=COMPLETED,CANCELLED,FAILED,RUNNING" - when: - def result = Fcli.run(args) - then: - verifyAll(result.stdout) { - // + it[0].replace(' ', '').equals("HostnameScaversion") } } + + def "startScanFilter"() { + def args = "sc-sast scan start -v ::highestSensor::get(0).scaVersion -p=$packageZip --sargs -quick\\ -filter\\ file:$fileFilter --store scanfilter" + when: + def result = Fcli.run(args) + then: + verifyAll(result.stdout) { + size()==2 + it[0].replace(' ', '').equals("JobtokenHasfilesScanstatePublishstateSscprocessingstateEndpointversionAction") + } + } + + def "wait-for"() { + // Depending on externalmetadata versions in FPR and on SSC, approval + // may be required + def args = "sc-sast scan wait-for ::scanfilter:: -i 2s --until=all-match --any-scan-state=COMPLETED,CANCELLED,FAILED" + when: + def result = Fcli.run(args) + then: + verifyAll(result.stdout) { + // + } + } + + def "verifyScanRule"() { + def args = "ssc rest call ::scanfilter::'/api/v1/cloudjobs/'+jobToken -o expr={scaArgs}" + when: + def result = Fcli.run(args) + then: + verifyAll(result.stdout) { + it[0].contains("-quick") + it[0].contains("-filter") + } + } } \ No newline at end of file diff --git a/fcli-other/fcli-functional-test/src/ftest/resources/runtime/shared/Filter.txt b/fcli-other/fcli-functional-test/src/ftest/resources/runtime/shared/Filter.txt new file mode 100644 index 0000000000..97270ced7c --- /dev/null +++ b/fcli-other/fcli-functional-test/src/ftest/resources/runtime/shared/Filter.txt @@ -0,0 +1,3 @@ +#This is a category to filter from scan output +Unchecked Return Value +9C5BD1B5-C296-48d4-B5F5-5D2958661BC4 \ No newline at end of file