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
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,17 @@ public static final FoDScanDescriptor handleInProgressScan(UnirestInstance unire
.queryString("fields", "scanId,scanType,analysisStatusType")
.asObject(JsonNode.class).getBody();
JsonNode itemsNode = response.path("items");
if (!itemsNode.isArray() || itemsNode.isEmpty()) continue;
if (!itemsNode.isArray() || itemsNode.isEmpty()) {
// No scans exist for this release yet; nothing to handle
progressWriter.writeProgress("Status: No previous scans found");
return null;
}

boolean foundActive = false;
for (JsonNode node : itemsNode) {
if (!"Dynamic".equals(node.path("scanType").asText())) continue;
String status = node.path("analysisStatusType").asText();

if (isActiveStatus(status)) {
foundActive = true;
FoDScanDescriptor result = handleActiveScan(
Expand All @@ -107,10 +111,13 @@ public static final FoDScanDescriptor handleInProgressScan(UnirestInstance unire
throw new FcliSimpleException("Unable to start Dynamic scan after " + maxAttempts + " attempts. Please check the UI and try again.");
}

public static final FoDScanDescriptor startScan(UnirestInstance unirest, FoDReleaseDescriptor releaseDescriptor) {
JsonNode response = unirest.post(FoDUrls.DAST_AUTOMATED_SCANS + "/start-scan")
.routeParam("relId", releaseDescriptor.getReleaseId())
.asObject(JsonNode.class).getBody();
public static final FoDScanDescriptor startScan(UnirestInstance unirest, String networkName, FoDReleaseDescriptor releaseDescriptor) {
var request = unirest.post(FoDUrls.DAST_AUTOMATED_SCANS + "/start-scan")
.routeParam("relId", releaseDescriptor.getReleaseId());
if ( networkName != null && !networkName.isBlank() ) {
request = request.queryString("networkName", networkName);
}
JsonNode response = request.asObject(JsonNode.class).getBody();
FoDStartScanResponse startScanResponse = JsonHelper.treeToValue(response, FoDStartScanResponse.class);
if (startScanResponse == null || startScanResponse.getScanId() <= 0) {
throw new FcliSimpleException("Unable to retrieve scan id from response when starting Dynamic scan.");
Expand Down Expand Up @@ -151,7 +158,7 @@ private static FoDScanDescriptor handleActiveScan(
Thread.sleep(waitMillis);
break;
case DoNotStartScan:
progressWriter.writeProgress("Status: A scan is running %s, no new scan will be started", scanId);
progressWriter.writeProgress("Status: A scan with id %s is %s, no new scan will be started", scanId, status);
JsonNode scan = objectMapper.createObjectNode()
.put("scanId", scanId)
.put("scanType", FoDScanType.Dynamic.name())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@
*/
package com.fortify.cli.fod.dast_scan.cli.cmd;

import com.fortify.cli.common.exception.FcliSimpleException;
import com.fortify.cli.common.output.cli.mixin.OutputHelperMixins;
import com.fortify.cli.common.progress.cli.mixin.ProgressWriterFactoryMixin;
import com.fortify.cli.common.rest.unirest.UnexpectedHttpResponseException;
import com.fortify.cli.fod._common.scan.cli.cmd.AbstractFoDScanStartCommand;
import com.fortify.cli.fod._common.scan.cli.mixin.FoDInProgressScanActionTypeMixins;
import com.fortify.cli.fod._common.scan.helper.FoDScanDescriptor;
Expand All @@ -36,6 +38,8 @@ public class FoDDastAutomatedScanStartCommand extends AbstractFoDScanStartComman
private Integer waitInterval;
@Option(names="--max-attempts", descriptionKey = "fcli.fod.scan.max-attempts", defaultValue = "30", required = false)
private Integer maxAttempts;
@Option(names = {"--vpn"})
private String fodConnectNetwork;

@Mixin private ProgressWriterFactoryMixin progressWriterFactory;

Expand All @@ -48,26 +52,45 @@ protected FoDScanDescriptor startScan(UnirestInstance unirest, FoDReleaseDescrip
try (var progressWriter = progressWriterFactory.create()) {

// get current setup to ensure the scan has been configured
FoDScanDastAutomatedHelper.getSetupDescriptor(unirest, relId);
var setup = FoDScanDastAutomatedHelper.getSetupDescriptor(unirest, relId);
if (setup == null) {
throw new FcliSimpleException("DAST Automated scan is not configured for release '" + releaseDescriptor.getReleaseName() + "'. Please run one of the 'fod dast-scan setup-xxx' commands to configure the scan before starting.");
}

// check if scan is already in progress
// handle any in-progress or active scans according to the configured action
FoDScanDescriptor scan = FoDScanDastAutomatedHelper.handleInProgressScan(unirest, releaseDescriptor,
inProgressScanActionType.getInProgressScanActionType(), progressWriter, maxAttempts,
waitInterval);

// if the action was to not start a new scan, return the in progress scan descriptor
if (scan != null && scan.getAnalysisStatusType().equals("In_Progress")) {
if (inProgressScanActionType.getInProgressScanActionType() == FoDEnums.InProgressScanActionType.DoNotStartScan) {
scanAction = "NOT_STARTED_SCAN_IN_PROGRESS";
return scan;
}
}

return FoDScanDastAutomatedHelper.startScan(unirest, releaseDescriptor);
try {
return FoDScanDastAutomatedHelper.startScan(unirest, fodConnectNetwork, releaseDescriptor);
} catch (UnexpectedHttpResponseException e) {
// If FoD rejects start because a dynamic scan is in progress, try to fetch that scan and return it
if (e.getStatus() == 422 && (e.getMessage().contains("dynamic scan is currently in progress") || e.getMessage().contains("errorCode: -10"))) {
FoDScanDescriptor running = FoDScanDastAutomatedHelper.handleInProgressScan(unirest, releaseDescriptor,
FoDEnums.InProgressScanActionType.DoNotStartScan, progressWriter, maxAttempts,
waitInterval);
if (running != null) {
scanAction = "NOT_STARTED_SCAN_IN_PROGRESS";
return running;
}
}
throw e;
}
}
}

@Override
public final String getActionCommandResult() {
return scanAction;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import com.fasterxml.jackson.databind.JsonNode;
import com.fortify.cli.common.cli.mixin.CommonOptionMixins;
import com.fortify.cli.common.exception.FcliSimpleException;
import com.fortify.cli.common.output.cli.mixin.OutputHelperMixins;
import com.fortify.cli.common.output.transform.IActionCommandResultSupplier;
import com.fortify.cli.fod._common.cli.mixin.FoDDelimiterMixin;
Expand Down Expand Up @@ -46,12 +47,16 @@ public class FoDMicroserviceCreateCommand extends AbstractFoDJsonNodeOutputComma

@Override
public JsonNode getJsonNode(UnirestInstance unirest) {
FoDAppDescriptor appDescriptor = qualifiedMicroserviceNameResolver.getAppDescriptor(unirest, true);
FoDQualifiedMicroserviceNameDescriptor qualifiedMicroserviceNameDescriptor = qualifiedMicroserviceNameResolver.getQualifiedMicroserviceNameDescriptor();
// throw an exception if the application is not microservice-enabled
if (!appDescriptor.isHasMicroservices()) {
throw new FcliSimpleException("Cannot create microservice for non-microservice application "+appDescriptor.getApplicationName());
}
if (skipIfExistsOption.isSkipIfExists()) {
FoDMicroserviceDescriptor descriptor = qualifiedMicroserviceNameResolver.getMicroserviceDescriptor(unirest, false);
if (descriptor != null) { return descriptor.asObjectNode().put("__action__", "SKIPPED_EXISTING"); }
}
FoDAppDescriptor appDescriptor = qualifiedMicroserviceNameResolver.getAppDescriptor(unirest, true);
FoDQualifiedMicroserviceNameDescriptor qualifiedMicroserviceNameDescriptor = qualifiedMicroserviceNameResolver.getQualifiedMicroserviceNameDescriptor();
FoDMicroserviceUpdateRequest msCreateRequest = FoDMicroserviceUpdateRequest.builder()
.microserviceName(qualifiedMicroserviceNameDescriptor.getMicroserviceName())
.attributes(FoDAttributeHelper.getAttributesNode(unirest, FoDEnums.AttributeTypes.Microservice,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,7 @@ fcli.fod.dast-scan.start.usage.description.0 = This command is intended for DAST
fcli.fod.dast-scan.start.usage.description.1 = The scan will need to have been previously setup using the FoD UI or one of the \
'fod dast-scan setup-xxx' commands.
fcli.fod.dast-scan.start.validate-entitlement = Validate if an entitlement has been set and is still valid.
fcli.fod.dast-scan.start.vpn = Fortify Connect network name to use for site-to-site VPN.
fcli.fod.dast-scan.start-legacy.usage.header = (LEGACY) Start a new DAST scan.
fcli.fod.dast-scan.start-legacy.usage.description.0 = This command is not fully implemented and is intended for legacy DAST scanning (not DAST Automated). \
It can only be used for starting a configured Dynamic scan and does not support file uploads (i.e. API definitions \
Expand Down
Loading