diff --git a/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/app/attr/helper/FoDAttributeHelper.java b/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/app/attr/helper/FoDAttributeHelper.java index 050457572f..b7aeffd51d 100644 --- a/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/app/attr/helper/FoDAttributeHelper.java +++ b/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/app/attr/helper/FoDAttributeHelper.java @@ -63,8 +63,8 @@ public static final Map getRequiredAttributesDefaultValues(Unire Iterator lookupIterator = lookupList.iterator(); while (lookupIterator.hasNext()) { FoDAttributeDescriptor currentLookup = lookupIterator.next(); - // currentLookup.getAttributeTypeId() == 1 is "Application" - filter above does not support querying on this yet! - if (currentLookup.getIsRequired() && currentLookup.getAttributeTypeId() == 1) { + // currentLookup.getAttributeTypeId() == 1 is "Application", 4 is "Release" - filter above does not support querying on this yet! + if (currentLookup.getIsRequired() && (currentLookup.getAttributeTypeId() == 1 || currentLookup.getAttributeTypeId() == 4)) { switch (currentLookup.getAttributeDataType()) { case "Text": reqAttrs.put(currentLookup.getName(), "autofilled by fcli"); diff --git a/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/release/cli/cmd/FoDReleaseCreateCommand.java b/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/release/cli/cmd/FoDReleaseCreateCommand.java index 1e4ab326eb..c70650680c 100644 --- a/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/release/cli/cmd/FoDReleaseCreateCommand.java +++ b/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/release/cli/cmd/FoDReleaseCreateCommand.java @@ -20,6 +20,8 @@ import com.fortify.cli.common.util.StringUtils; import com.fortify.cli.fod._common.cli.mixin.FoDDelimiterMixin; import com.fortify.cli.fod._common.output.cli.cmd.AbstractFoDJsonNodeOutputCommand; +import com.fortify.cli.fod.app.attr.cli.mixin.FoDAttributeUpdateOptions; +import com.fortify.cli.fod.app.attr.helper.FoDAttributeHelper; import com.fortify.cli.fod.app.cli.mixin.FoDSdlcStatusTypeOptions; import com.fortify.cli.fod.release.cli.mixin.FoDReleaseByQualifiedNameOrIdResolverMixin; import com.fortify.cli.fod.release.cli.mixin.FoDReleaseByQualifiedNameResolverMixin; @@ -43,9 +45,13 @@ public class FoDReleaseCreateCommand extends AbstractFoDJsonNodeOutputCommand im private String description; @Option(names={"--skip-if-exists"}) private boolean skipIfExists = false; + @Option(names={"--auto-required-attrs"}, required = false) + protected boolean autoRequiredAttrs = false; @Mixin private FoDSdlcStatusTypeOptions.RequiredOption sdlcStatus; + @Mixin + protected FoDAttributeUpdateOptions.OptionalAttrOption relAttrs; // TODO Consider splitting method @Override @@ -72,7 +78,8 @@ public JsonNode getJsonNode(UnirestInstance unirest) { .applicationId(Integer.valueOf(appDescriptor.getApplicationId())) .releaseName(simpleReleaseName) .releaseDescription(description) - .sdlcStatusType(sdlcStatus.getSdlcStatusType().name()); + .sdlcStatusType(sdlcStatus.getSdlcStatusType().name()) + .attributes(FoDAttributeHelper.getAttributesNode(unirest, relAttrs.getAttributes(), autoRequiredAttrs)); if ( microserviceDescriptor!=null ) { requestBuilder = requestBuilder.microserviceId(Integer.valueOf(microserviceDescriptor.getMicroserviceId())); } diff --git a/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/release/cli/cmd/FoDReleaseUpdateCommand.java b/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/release/cli/cmd/FoDReleaseUpdateCommand.java index 6911e49ac3..8f427de022 100644 --- a/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/release/cli/cmd/FoDReleaseUpdateCommand.java +++ b/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/release/cli/cmd/FoDReleaseUpdateCommand.java @@ -13,13 +13,20 @@ package com.fortify.cli.fod.release.cli.cmd; +import java.util.ArrayList; +import java.util.Map; + import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import com.fortify.cli.common.output.cli.mixin.OutputHelperMixins; import com.fortify.cli.common.output.transform.IActionCommandResultSupplier; import com.fortify.cli.common.output.transform.IRecordTransformer; import com.fortify.cli.common.util.StringUtils; import com.fortify.cli.fod._common.cli.mixin.FoDDelimiterMixin; import com.fortify.cli.fod._common.output.cli.cmd.AbstractFoDJsonNodeOutputCommand; +import com.fortify.cli.fod.app.attr.cli.mixin.FoDAttributeUpdateOptions; +import com.fortify.cli.fod.app.attr.helper.FoDAttributeDescriptor; +import com.fortify.cli.fod.app.attr.helper.FoDAttributeHelper; import com.fortify.cli.fod.app.cli.mixin.FoDSdlcStatusTypeOptions; import com.fortify.cli.fod.release.cli.mixin.FoDReleaseByQualifiedNameOrIdResolverMixin; import com.fortify.cli.fod.release.helper.FoDReleaseDescriptor; @@ -36,6 +43,7 @@ @Command(name = OutputHelperMixins.Update.CMD_NAME) public class FoDReleaseUpdateCommand extends AbstractFoDJsonNodeOutputCommand implements IRecordTransformer, IActionCommandResultSupplier { @Getter @Mixin private OutputHelperMixins.Update outputHelper; + private final ObjectMapper objectMapper = new ObjectMapper(); @Mixin private FoDDelimiterMixin delimiterMixin; // Is automatically injected in resolver mixins @Mixin private FoDReleaseByQualifiedNameOrIdResolverMixin.PositionalParameter releaseResolver; @Option(names = {"--name", "-n"}) @@ -49,18 +57,28 @@ public class FoDReleaseUpdateCommand extends AbstractFoDJsonNodeOutputCommand im @Mixin private FoDSdlcStatusTypeOptions.OptionalOption sdlcStatus; + @Mixin + private FoDAttributeUpdateOptions.OptionalAttrOption appAttrsUpdate; @Override public JsonNode getJsonNode(UnirestInstance unirest) { FoDReleaseDescriptor releaseDescriptor = releaseResolver.getReleaseDescriptor(unirest); + ArrayList releaseAttrsCurrent = releaseDescriptor.getAttributes(); FoDSdlcStatusTypeOptions.FoDSdlcStatusType sdlcStatusTypeNew = sdlcStatus.getSdlcStatusType(); - + Map attributeUpdates = appAttrsUpdate.getAttributes(); + JsonNode jsonAttrs = objectMapper.createArrayNode(); + if (attributeUpdates != null && !attributeUpdates.isEmpty()) { + jsonAttrs = FoDAttributeHelper.mergeAttributesNode(unirest, releaseAttrsCurrent, attributeUpdates); + } else { + jsonAttrs = FoDAttributeHelper.getAttributesNode(releaseAttrsCurrent); + } FoDReleaseUpdateRequest appRelUpdateRequest = FoDReleaseUpdateRequest.builder() .releaseName(StringUtils.isNotBlank(releaseName) ? getUnqualifiedReleaseName(releaseName, releaseDescriptor) : releaseDescriptor.getReleaseName()) .releaseDescription(StringUtils.isNotBlank(description) ? description : releaseDescriptor.getReleaseDescription()) .ownerId(StringUtils.isNotBlank(releaseOwner) ? Integer.valueOf(releaseOwner) : releaseDescriptor.getOwnerId()) .microserviceId(releaseDescriptor.getMicroserviceId()) - .sdlcStatusType(sdlcStatusTypeNew != null ? String.valueOf(sdlcStatusTypeNew) : releaseDescriptor.getSdlcStatusType()).build(); + .sdlcStatusType(sdlcStatusTypeNew != null ? String.valueOf(sdlcStatusTypeNew) : releaseDescriptor.getSdlcStatusType()) + .attributes(jsonAttrs).build(); return FoDReleaseHelper.updateRelease(unirest, releaseDescriptor.getReleaseId(), appRelUpdateRequest).asJsonNode(); } diff --git a/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/release/helper/FoDReleaseCreateRequest.java b/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/release/helper/FoDReleaseCreateRequest.java index b047fe7781..931cb22217 100644 --- a/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/release/helper/FoDReleaseCreateRequest.java +++ b/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/release/helper/FoDReleaseCreateRequest.java @@ -15,6 +15,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.databind.JsonNode; import com.formkiq.graalvm.annotations.Reflectable; import lombok.AllArgsConstructor; @@ -35,4 +36,6 @@ public class FoDReleaseCreateRequest { private Integer copyStateReleaseId; private String sdlcStatusType; private Integer microserviceId; + private JsonNode attributes; + private Boolean autoRequiredAttrs; } diff --git a/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/release/helper/FoDReleaseDescriptor.java b/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/release/helper/FoDReleaseDescriptor.java index ad60ec39a7..5c7141f4c5 100644 --- a/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/release/helper/FoDReleaseDescriptor.java +++ b/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/release/helper/FoDReleaseDescriptor.java @@ -14,11 +14,15 @@ package com.fortify.cli.fod.release.helper; import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; import com.fasterxml.jackson.annotation.JsonIgnore; import com.formkiq.graalvm.annotations.Reflectable; import com.fortify.cli.common.json.JsonNodeHolder; import com.fortify.cli.common.util.StringUtils; +import com.fortify.cli.fod.app.attr.helper.FoDAttributeDescriptor; import lombok.Data; import lombok.EqualsAndHashCode; @@ -54,7 +58,8 @@ public class FoDReleaseDescriptor extends JsonNodeHolder { private LocalDateTime staticScanDate; private LocalDateTime dynamicScanDate; private LocalDateTime mobileScanDate; - + private ArrayList attributes; + @JsonIgnore public String getQualifiedName() { return StringUtils.isBlank(microserviceName) ? String.format("%s:%s", applicationName, releaseName) @@ -66,4 +71,12 @@ public String getQualifierPrefix(String delimiter) { var msQualifierPrefix = StringUtils.isBlank(microserviceName) ? "" : (microserviceName+delimiter); return applicationName+delimiter+msQualifierPrefix; } + + public Map attributesAsMap() { + Map attrMap = new HashMap<>(); + for (FoDAttributeDescriptor attr : attributes) { + attrMap.put(attr.getId(), attr.getValue()); + } + return attrMap; + } } diff --git a/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/release/helper/FoDReleaseUpdateRequest.java b/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/release/helper/FoDReleaseUpdateRequest.java index 6918a2e61d..1a377db455 100644 --- a/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/release/helper/FoDReleaseUpdateRequest.java +++ b/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/release/helper/FoDReleaseUpdateRequest.java @@ -12,6 +12,7 @@ *******************************************************************************/ package com.fortify.cli.fod.release.helper; +import com.fasterxml.jackson.databind.JsonNode; import com.formkiq.graalvm.annotations.Reflectable; import lombok.AllArgsConstructor; @@ -28,4 +29,5 @@ public class FoDReleaseUpdateRequest { private String sdlcStatusType; private Integer ownerId; private String microserviceId; + private JsonNode attributes; } diff --git a/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/sast_scan/cli/cmd/FoDSastScanSetupCommand.java b/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/sast_scan/cli/cmd/FoDSastScanSetupCommand.java index 061d161b0f..4bf5d20da3 100644 --- a/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/sast_scan/cli/cmd/FoDSastScanSetupCommand.java +++ b/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/sast_scan/cli/cmd/FoDSastScanSetupCommand.java @@ -23,6 +23,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fortify.cli.common.cli.util.CommandGroup; import com.fortify.cli.common.output.cli.mixin.OutputHelperMixins; import com.fortify.cli.common.output.transform.IActionCommandResultSupplier; import com.fortify.cli.common.output.transform.IRecordTransformer; @@ -52,7 +53,7 @@ import picocli.CommandLine.Mixin; import picocli.CommandLine.Option; -@Command(name = OutputHelperMixins.Setup.CMD_NAME, hidden = false) +@Command(name = OutputHelperMixins.Setup.CMD_NAME, hidden = false) @CommandGroup("*-scan-setup") @DisableTest(TestType.CMD_DEFAULT_TABLE_OPTIONS_PRESENT) public class FoDSastScanSetupCommand extends AbstractFoDJsonNodeOutputCommand implements IRecordTransformer, IActionCommandResultSupplier { private static final Log LOG = LogFactory.getLog(FoDSastScanSetupCommand.class); @@ -82,7 +83,9 @@ public class FoDSastScanSetupCommand extends AbstractFoDJsonNodeOutputCommand im @Option(names = {"--use-source-control"}) private final Boolean useSourceControl = false; @Option(names={"--skip-if-exists"}) - private boolean skipIfExists = false; + private Boolean skipIfExists = false; + @Option(names={"--use-aviator"}) + private Boolean useAviator = false; // TODO We don't actually use a progress writer, but for now we can't // remove the --progress option to maintain backward compatibility. @@ -128,7 +131,8 @@ private FoDScanConfigSastDescriptor setup(UnirestInstance unirest, FoDReleaseDes .performOpenSourceAnalysis(performOpenSourceAnalysis) .auditPreferenceType(auditPreferenceType.name()) .includeThirdPartyLibraries(includeThirdPartyLibraries) - .useSourceControl(useSourceControl).build(); + .useSourceControl(useSourceControl) + .includeFortifyAviator(useAviator).build(); return FoDScanConfigSastHelper.setupScan(unirest, releaseDescriptor, setupSastScanRequest); } @@ -194,6 +198,10 @@ private FoDReleaseAssessmentTypeDescriptor getAssessmentTypeDescriptor(UnirestIn public JsonNode transformRecord(JsonNode record) { FoDReleaseDescriptor releaseDescriptor = releaseResolver.getReleaseDescriptor(getUnirestInstance()); return ((ObjectNode)record) + // Start partial fix for (#598) + .put("scanType", staticAssessmentType) + .put("setupType", auditPreferenceType.name()) + // End .put("applicationName", releaseDescriptor.getApplicationName()) .put("releaseName", releaseDescriptor.getReleaseName()) .put("microserviceName", releaseDescriptor.getMicroserviceName()); diff --git a/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/sast_scan/helper/FoDScanConfigSastSetupRequest.java b/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/sast_scan/helper/FoDScanConfigSastSetupRequest.java index 5f3fbfb388..4d84f03285 100644 --- a/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/sast_scan/helper/FoDScanConfigSastSetupRequest.java +++ b/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/sast_scan/helper/FoDScanConfigSastSetupRequest.java @@ -33,4 +33,5 @@ public class FoDScanConfigSastSetupRequest { private Boolean includeThirdPartyLibraries; private Boolean useSourceControl; private Boolean scanBinary; + private Boolean includeFortifyAviator; } diff --git a/fcli-core/fcli-fod/src/main/resources/com/fortify/cli/fod/i18n/FoDMessages.properties b/fcli-core/fcli-fod/src/main/resources/com/fortify/cli/fod/i18n/FoDMessages.properties index 5678d9db67..45272ca3e4 100644 --- a/fcli-core/fcli-fod/src/main/resources/com/fortify/cli/fod/i18n/FoDMessages.properties +++ b/fcli-core/fcli-fod/src/main/resources/com/fortify/cli/fod/i18n/FoDMessages.properties @@ -299,7 +299,7 @@ fcli.fod.app.create.owner = The owner of the application/release who will receiv fcli.fod.app.create.groups = User group ids or names to give access of the application to. fcli.fod.app.create.criticality = The business criticality of the application. Valid values: ${COMPLETION-CANDIDATES}. fcli.fod.app.create.status = The SDLC lifecycle status of the release. Valid values: ${COMPLETION-CANDIDATES} -fcli.fod.app.create.attr = Attribute id or name and its value to set on the application. +fcli.fod.app.create.attr = Attribute id or name and its value to set on the application. For User attributes only userId is currently supported. fcli.fod.app.create.skip-if-exists = Check to see if application already exists before creating. fcli.fod.app.create.auto-required-attrs = Automatically set a default value for required attributes. fcli.fod.app.create.microservice = The name of the first microservice to create for the application. @@ -319,7 +319,7 @@ fcli.fod.app.update.name = The updated name for the application. fcli.fod.app.update.description = The updated description for the application. fcli.fod.app.update.notify = Email address of user(s) to send notifications to (Please note, any existing entries will be replaced). fcli.fod.app.update.criticality = The business criticality of the application. -fcli.fod.app.update.attr = Attribute id or name and its value to set on the application. +fcli.fod.app.update.attr = Attribute id or name and its value to set on the application. For User attributes only userId is currently supported. fcli.fod.app.list-scans.usage.header = List scans for a given application. # fcli fod microservice @@ -352,14 +352,18 @@ fcli.fod.release.output.header.applicationName = Application fcli.fod.release.output.header.releaseDescription = Description fcli.fod.release.output.header.sdlcStatusType = SDLC Status -fcli.fod.release.create.usage.header = Create a new application release. +fcli.fod.release.create.usage.header = Create a new application release. \ + Please note some attributes might be mandatory depending on the configuration of your tenant. Please check the \ + Fortify on Demand web portal first. fcli.fod.release.create.application-name = The id or name of the application to create the release on. fcli.fod.release.create.release-name = The name of the release to create for the application. fcli.fod.release.create.description = Description of the release. fcli.fod.release.create.copy-from = The id or name of a release to copy existing state from. fcli.fod.release.create.microservice = The id or name of the microservice to create the release on. fcli.fod.release.create.status = SDLC lifecycle status of the release. Valid values: ${COMPLETION-CANDIDATES}. +fcli.fod.release.create.attr = Attribute id or name and its value to set on the release. For User attributes only userId is currently supported. fcli.fod.release.create.skip-if-exists = Check to see if release already exists before creating. +fcli.fod.release.create.auto-required-attrs = Automatically set a default value for required attributes. fcli.fod.release.delete.usage.header = Delete an application release. fcli.fod.release.list.usage.header = List application releases. fcli.fod.release.get.usage.header = Get application release details. @@ -372,6 +376,7 @@ fcli.fod.release.update.description = Updated description for the release. fcli.fod.release.update.owner = Updated id or username for the owner of the release. fcli.fod.release.update.microservice = The updated microservice id or name to create the release on. fcli.fod.release.update.status = SDLC lifecycle status of the release. Valid values: ${COMPLETION-CANDIDATES}. +fcli.fod.release.update.attr = Attribute id or name and its value to set on the application. For User attributes only userId is currently supported. fcli.fod.release.list-assessment-types.usage.header = List assessment types for a given release. fcli.fod.release.list-assessment-types.scan-types = Comma-separated list of scan types for which to list assessment types. Default value: ${DEFAULT-VALUE}. Valid values: ${COMPLETION-CANDIDATES}. fcli.fod.release.list-scans.usage.header = List scans for a given release. @@ -491,10 +496,11 @@ fcli.fod.sast-scan.setup.technology-stack = The technology stack of the applicat fcli.fod.sast-scan.setup.language-level = The language level of the technology stack (if needed). fcli.fod.sast-scan.setup.oss = Perform Open Source Analysis scan. fcli.fod.sast-scan.setup.audit-preference = Audit preference, e.g. Manual or Automated -fcli.fod.sast-scan.setup.include-third-party-libs = Indicates if third party libraries should be included. -fcli.fod.sast-scan.setup.use-source-control = Indicates if source control should be used. +fcli.fod.sast-scan.setup.include-third-party-libs = (LEGACY) Indicates if third party libraries should be included. +fcli.fod.sast-scan.setup.use-source-control = (LEGACY) Indicates if source control should be used. fcli.fod.sast-scan.setup.skip-if-exists = Skip setup if a scan has already been set up. If not specified, any existing scan \ setup will be replaced based on the given setup options. +fcli.fod.sast-scan.setup.use-aviator = Use Fortify Aviator to audit results and provide enhanced remediation guidance. fcli.fod.sast-scan.import.usage.header = Import existing SAST scan results (from an FPR file). fcli.fod.sast-scan.import.usage.description = As FoD doesn't return a scan id for imported scans, the output of this command cannot be used with commands that expect a scan id, like the wait-for command. fcli.fod.sast-scan.import.file = FPR file containing existing SAST scan results to be imported.