From d071d25944fbd06b79bc622d323fa6d42b5d75ba Mon Sep 17 00:00:00 2001 From: Alex Gendry Date: Wed, 25 Sep 2024 09:29:26 +0200 Subject: [PATCH] feat: `fcli sc-sast scan start`: Add option to select sensor pool for the scan --- .../cmd/SCSastControllerScanStartCommand.java | 23 ++++++-- .../helper/SCSastSensorPoolDescriptor.java | 32 +++++++++++ .../cli/helper/SCSastSensorPoolHelper.java | 55 +++++++++++++++++++ .../mixin/SCSastSensorPoolResolverMixin.java | 45 +++++++++++++++ .../sc_sast/i18n/SCSastMessages.properties | 1 + 5 files changed, 152 insertions(+), 4 deletions(-) create mode 100644 fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/sensor_pool/cli/helper/SCSastSensorPoolDescriptor.java create mode 100644 fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/sensor_pool/cli/helper/SCSastSensorPoolHelper.java create mode 100644 fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/sensor_pool/cli/mixin/SCSastSensorPoolResolverMixin.java 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 76ab68b697..b73ec22f9b 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 @@ -28,6 +28,7 @@ import com.fortify.cli.sc_sast.scan.helper.SCSastControllerJobType; import com.fortify.cli.sc_sast.scan.helper.SCSastControllerScanJobHelper; import com.fortify.cli.sc_sast.scan.helper.SCSastControllerScanJobHelper.StatusEndpointVersion; +import com.fortify.cli.sc_sast.sensor_pool.cli.mixin.SCSastSensorPoolResolverMixin.AbstractSCSastSensorPoolResolverMixin; import com.fortify.cli.ssc.access_control.helper.SSCTokenConverter; import com.fortify.cli.ssc.appversion.cli.mixin.SSCAppVersionResolverMixin.AbstractSSCAppVersionResolverMixin; @@ -46,6 +47,7 @@ public final class SCSastControllerScanStartCommand extends AbstractSCSastContro @Getter @Mixin private OutputHelperMixins.Start outputHelper; private String userName = System.getProperty("user.name", "unknown"); // TODO Do we want to give an option to override this? @Option(names = "--notify") private String email; // TODO Add email address validation + @Mixin private SensorPoolResolverMixin sensorPoolResolver; @Mixin private PublishToAppVersionResolverMixin sscAppVersionResolver; @Option(names = "--ssc-ci-token") private String ciToken; @@ -66,6 +68,7 @@ public final JsonNode getJsonNode(UnirestInstance unirest) { body = updateBody(body, "email", email); body = updateBody(body, "buildId", optionsProvider.getScanStartOptions().getBuildId()); body = updateBody(body, "pvId", getAppVersionId()); + body = updateBody(body, "poolUuid", getSensorPoolUuid()); body = updateBody(body, "uploadToken", getUploadToken()); body = updateBody(body, "dotNetRequired", String.valueOf(optionsProvider.getScanStartOptions().isDotNetRequired())); body = updateBody(body, "dotNetFrameworkRequiredVersion", optionsProvider.getScanStartOptions().getDotNetVersion()); @@ -86,11 +89,17 @@ public final String getActionCommandResult() { public final boolean isSingular() { return true; } - + private String getAppVersionId() { return sscAppVersionResolver.hasValue() - ? sscAppVersionResolver.getAppVersionId(getSscUnirestInstance()) - : null; + ? sscAppVersionResolver.getAppVersionId(getSscUnirestInstance()) + : null; + } + + private String getSensorPoolUuid() { + return sensorPoolResolver.hasValue() + ? sensorPoolResolver.getSensorPoolUuid(getUnirestInstance()) + : null; } private String getUploadToken() { @@ -154,10 +163,16 @@ private void addFile(ZipOutputStream zout, String fileName, File file) throws IO zout.closeEntry(); } } - + private static final class PublishToAppVersionResolverMixin extends AbstractSSCAppVersionResolverMixin { @Option(names = {"--publish-to"}, required = false) @Getter private String appVersionNameOrId; public final boolean hasValue() { return StringUtils.isNotBlank(appVersionNameOrId); } } + + private static final class SensorPoolResolverMixin extends AbstractSCSastSensorPoolResolverMixin { + @Option(names = {"--sensor-pool"}, required = false, descriptionKey = "fcli.sc-sast.sensor-pool.resolver.nameOrUuid") + @Getter private String sensorPoolNameOrUuid; + public final boolean hasValue() { return StringUtils.isNotBlank(sensorPoolNameOrUuid); } + } } diff --git a/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/sensor_pool/cli/helper/SCSastSensorPoolDescriptor.java b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/sensor_pool/cli/helper/SCSastSensorPoolDescriptor.java new file mode 100644 index 0000000000..2fb481ae60 --- /dev/null +++ b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/sensor_pool/cli/helper/SCSastSensorPoolDescriptor.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright 2021, 2023 Open Text. + * + * The only warranties for products and services of Open Text + * and its affiliates and licensors ("Open Text") are as may + * be set forth in the express warranty statements accompanying + * such products and services. Nothing herein should be construed + * as constituting an additional warranty. Open Text shall not be + * liable for technical or editorial errors or omissions contained + * herein. The information contained herein is subject to change + * without notice. + *******************************************************************************/ +package com.fortify.cli.sc_sast.sensor_pool.cli.helper; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.formkiq.graalvm.annotations.Reflectable; +import com.fortify.cli.common.json.JsonNodeHolder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import java.util.Map; + +@Reflectable @NoArgsConstructor +@Data @EqualsAndHashCode(callSuper=true) +public class SCSastSensorPoolDescriptor extends JsonNodeHolder { + private String uuid; + private String path; + private String name; + private String lastChangedOn; +} diff --git a/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/sensor_pool/cli/helper/SCSastSensorPoolHelper.java b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/sensor_pool/cli/helper/SCSastSensorPoolHelper.java new file mode 100644 index 0000000000..061a9440e4 --- /dev/null +++ b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/sensor_pool/cli/helper/SCSastSensorPoolHelper.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright 2021, 2023 Open Text. + * + * The only warranties for products and services of Open Text + * and its affiliates and licensors ("Open Text") are as may + * be set forth in the express warranty statements accompanying + * such products and services. Nothing herein should be construed + * as constituting an additional warranty. Open Text shall not be + * liable for technical or editorial errors or omissions contained + * herein. The information contained herein is subject to change + * without notice. + *******************************************************************************/ +package com.fortify.cli.sc_sast.sensor_pool.cli.helper; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.formkiq.graalvm.annotations.Reflectable; +import com.fortify.cli.common.json.JsonHelper; +import com.fortify.cli.common.output.transform.fields.RenameFieldsTransformer; +import com.fortify.cli.ssc._common.rest.SSCUrls; +import com.fortify.cli.ssc.appversion.helper.SSCAppAndVersionNameDescriptor; +import com.fortify.cli.ssc.appversion.helper.SSCAppVersionDescriptor; +import com.fortify.cli.ssc.system_state.helper.SSCJobDescriptor; +import com.fortify.cli.ssc.system_state.helper.SSCJobHelper; +import kong.unirest.GetRequest; +import kong.unirest.UnirestInstance; +import lombok.AllArgsConstructor; +import lombok.Data; + +public class SCSastSensorPoolHelper { + public static final SCSastSensorPoolDescriptor getRequiredSensorPool(UnirestInstance unirest, String sensorPoolNameOrUuid) { + SCSastSensorPoolDescriptor descriptor = getOptionalSensorPool(unirest, sensorPoolNameOrUuid); + if ( descriptor==null ) { + throw new IllegalArgumentException("No sensor pool found for name or uuid: "+sensorPoolNameOrUuid); + } + return descriptor; + } + + public static final SCSastSensorPoolDescriptor getOptionalSensorPool(UnirestInstance unirest, String sensorPoolNameOrUuid) { + JsonNode sensorPools = getBaseRequest(unirest).asObject(ObjectNode.class).getBody().get("beans"); + JsonNode sensorPool = JsonHelper.evaluateSpelExpression(sensorPools,String.format("#this.?[#this.name=='%s' || #this.uuid=='%s' ]", sensorPoolNameOrUuid, sensorPoolNameOrUuid),ArrayNode.class); + + if ( sensorPool.size()>1 ) { + throw new IllegalArgumentException("Multiple sensor pools found"); + } + + return sensorPool.size()==0 ? null : JsonHelper.treeToValue(sensorPool.get(0), SCSastSensorPoolDescriptor.class); + } + + private static GetRequest getBaseRequest(UnirestInstance unirest) { + GetRequest request = unirest.get("/rest/v4/info/pools"); + return request; + } +} diff --git a/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/sensor_pool/cli/mixin/SCSastSensorPoolResolverMixin.java b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/sensor_pool/cli/mixin/SCSastSensorPoolResolverMixin.java new file mode 100644 index 0000000000..17339e8f3a --- /dev/null +++ b/fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/sensor_pool/cli/mixin/SCSastSensorPoolResolverMixin.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright 2021, 2023 Open Text. + * + * The only warranties for products and services of Open Text + * and its affiliates and licensors ("Open Text") are as may + * be set forth in the express warranty statements accompanying + * such products and services. Nothing herein should be construed + * as constituting an additional warranty. Open Text shall not be + * liable for technical or editorial errors or omissions contained + * herein. The information contained herein is subject to change + * without notice. + *******************************************************************************/ +package com.fortify.cli.sc_sast.sensor_pool.cli.mixin; + +import com.fortify.cli.common.cli.util.EnvSuffix; +import com.fortify.cli.sc_sast.sensor_pool.cli.helper.SCSastSensorPoolDescriptor; +import com.fortify.cli.sc_sast.sensor_pool.cli.helper.SCSastSensorPoolHelper; +import kong.unirest.UnirestInstance; +import lombok.Getter; +import picocli.CommandLine.Option; +import picocli.CommandLine.Parameters; + +public class SCSastSensorPoolResolverMixin { + public static abstract class AbstractSCSastSensorPoolResolverMixin { + public abstract String getSensorPoolNameOrUuid(); + + public SCSastSensorPoolDescriptor getSensorPoolDescriptor(UnirestInstance unirest){ + return SCSastSensorPoolHelper.getRequiredSensorPool(unirest, getSensorPoolNameOrUuid()); + } + + public String getSensorPoolUuid(UnirestInstance unirest) { + return getSensorPoolDescriptor(unirest).getUuid(); + } + } + + public static class RequiredOption extends AbstractSCSastSensorPoolResolverMixin { + @Option(names = {"--sensor-pool"}, required = true, descriptionKey = "fcli.sc-sast.sensor-pool.resolver.nameOrUuid") + @Getter private String sensorPoolNameOrUuid; + } + + public static class PositionalParameter extends AbstractSCSastSensorPoolResolverMixin { + @EnvSuffix("SENSORPOOL") @Parameters(index = "0", arity = "1", descriptionKey = "fcli.sc-sast.sensor-pool.resolver.nameOrUuid") + @Getter private String sensorPoolNameOrUuid; + } +} 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 6b2665ebf0..a1dc185ddf 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 @@ -150,6 +150,7 @@ fcli.sc-sast.sensor.list.usage.description = This command lists sensor informati # fcli sc-sast sensor-pool fcli.sc-sast.sensor-pool.usage.header = Manage ScanCentral SAST sensor pools +fcli.sc-sast.sensor-pool.resolver.nameOrUuid = Sensor pool Uuid or Name fcli.sc-sast.sensor-pool.list.usage.header = List ScanCentral SAST sensor pools # fcli sc-sast rest