Skip to content
Open
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 @@ -39,9 +39,45 @@
import lombok.Getter;

public class FoDScanSastHelper extends FoDScanHelper {
private static final String LEGACY_SETUP_SCAN_POLICY = "FoD_Legacy";
private static final String LEGACY_START_SCAN_POLICY = "FoD_Legacy_";
private static final String SECURITY_SCAN_POLICY = "Security";
private static final String DEVOPS_SCAN_POLICY = "DevOps";
private static final String CLASSIC_SCAN_POLICY = "Classic";

@Getter
private static final ObjectMapper objectMapper = new ObjectMapper();

public static final String normalizeSetupScanPolicy(String scanPolicy) {
String normalizedScanPolicy = normalizeScanPolicy(scanPolicy);
return isLegacyScanPolicy(normalizedScanPolicy) ? LEGACY_SETUP_SCAN_POLICY : normalizedScanPolicy;
}

public static final String normalizeStartScanPolicy(String scanPolicy) {
String normalizedScanPolicy = normalizeScanPolicy(scanPolicy);
return isLegacyScanPolicy(normalizedScanPolicy) ? LEGACY_START_SCAN_POLICY : normalizedScanPolicy;
}

private static String normalizeScanPolicy(String scanPolicy) {
String normalizedScanPolicy = StringUtils.trimToNull(scanPolicy);
if (SECURITY_SCAN_POLICY.equalsIgnoreCase(normalizedScanPolicy)) {
return SECURITY_SCAN_POLICY;
} else if (DEVOPS_SCAN_POLICY.equalsIgnoreCase(normalizedScanPolicy)) {
return DEVOPS_SCAN_POLICY;
} else if (CLASSIC_SCAN_POLICY.equalsIgnoreCase(normalizedScanPolicy)) {
return CLASSIC_SCAN_POLICY;
}
return normalizedScanPolicy;
}

private static boolean isLegacyScanPolicy(String scanPolicy) {
return "Legacy".equalsIgnoreCase(scanPolicy)
|| LEGACY_SETUP_SCAN_POLICY.equalsIgnoreCase(scanPolicy)
|| LEGACY_START_SCAN_POLICY.equalsIgnoreCase(scanPolicy)
|| "FoD(Legacy)".equalsIgnoreCase(scanPolicy)
|| "FoD (Legacy)".equalsIgnoreCase(scanPolicy);
}

public static final FoDScanDescriptor startScanWithDefaults(UnirestInstance unirest, FoDReleaseDescriptor releaseDescriptor,
FoDScanSastStartRequest req, File scanFile, IProgressWriter progressWriter) {
var relId = releaseDescriptor.getReleaseId();
Expand All @@ -54,6 +90,9 @@ public static final FoDScanDescriptor startScanWithDefaults(UnirestInstance unir
String truncatedNotes = StringUtils.abbreviate(req.getNotes(), FoDConstants.MAX_NOTES_LENGTH);
request = request.queryString("notes", truncatedNotes);
}
if (StringUtils.isNotBlank(req.getSastScanPolicy())) {
request = request.queryString("sastScanPolicy", req.getSastScanPolicy());
}
return startScan(unirest, releaseDescriptor, request, scanFile, progressWriter);
}

Expand All @@ -78,6 +117,9 @@ public static final FoDScanDescriptor startScanAdvanced(UnirestInstance unirest,
String truncatedNotes = StringUtils.abbreviate(req.getNotes(), FoDConstants.MAX_NOTES_LENGTH);
request = request.queryString("notes", truncatedNotes);
}
if (StringUtils.isNotBlank(req.getSastScanPolicy())) {
request = request.queryString("sastScanPolicy", req.getSastScanPolicy());
}
return startScan(unirest, releaseDescriptor, request, scanFile, progressWriter);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ public class FoDScanSastStartRequest {
private String scanTool;
private String scanToolVersion;
private String notes;
private String sastScanPolicy;
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ public class FoDSastScanSetupCommand extends AbstractFoDScanSetupCommand<FoDScan
private Boolean performOpenSourceAnalysis;
@Option(names = {"--audit-preference"}, required = true)
private FoDEnums.AuditPreferenceTypes auditPreferenceType;
@Option(names = {"--scan-policy"})
private String scanPolicy;
@Option(names = {"--include-third-party-libs"})
private final Boolean includeThirdPartyLibraries = false;
@Option(names = {"--use-source-control"})
Expand Down Expand Up @@ -150,6 +152,8 @@ protected JsonNode setup(UnirestInstance unirest, FoDReleaseDescriptor releaseDe
builder.includeFortifyAviator(currentSetup.getIncludeFortifyAviator());
}

builder.scanPolicy(FoDScanSastHelper.normalizeSetupScanPolicy(scanPolicy));

FoDScanConfigSastSetupRequest setupSastScanRequest = builder.build();

return FoDScanConfigSastHelper.setupScan(unirest, releaseDescriptor, setupSastScanRequest).asJsonNode();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ public class FoDSastScanStartCommand extends AbstractFoDScanStartCommand {
private FoDEnums.InProgressScanActionType inProgressScanActionType;
@Option(names = {"--entitlement-preference"}, descriptionKey = "fcli.fod.scan.entitlement-preference")
private FoDEnums.EntitlementPreferenceType entitlementPreferenceType;
@Option(names = {"--scan-policy"})
private String scanPolicy;
@Mixin private CommonOptionMixins.RequiredFile scanFileMixin;

@Mixin private FoDRemediationScanPreferenceTypeMixins.OptionalOption remediationScanType;
Expand All @@ -55,7 +57,11 @@ public class FoDSastScanStartCommand extends AbstractFoDScanStartCommand {
protected FoDScanDescriptor startScan(UnirestInstance unirest, FoDReleaseDescriptor releaseDescriptor) {
String relId = releaseDescriptor.getReleaseId();

validateScanSetup(unirest, relId);
FoDScanConfigSastDescriptor currentSetup = validateScanSetup(unirest, relId);
String effectiveScanPolicy = FoDScanSastHelper.normalizeStartScanPolicy(scanPolicy);
if (effectiveScanPolicy == null) {
effectiveScanPolicy = FoDScanSastHelper.normalizeStartScanPolicy(currentSetup.getScanPolicy());
}

FoDEnums.RemediationScanPreferenceType remediationPref = remediationScanType != null
? remediationScanType.getRemediationScanPreferenceType() : null;
Expand All @@ -66,7 +72,8 @@ protected FoDScanDescriptor startScan(UnirestInstance unirest, FoDReleaseDescrip
.scanMethodType("Other")
.notes(notes != null && !notes.isEmpty() ? notes : "")
.scanTool(FcliBuildProperties.INSTANCE.getFcliProjectName())
.scanToolVersion(FcliBuildProperties.INSTANCE.getFcliVersion());
.scanToolVersion(FcliBuildProperties.INSTANCE.getFcliVersion())
.sastScanPolicy(effectiveScanPolicy);

try (IProgressWriter progressWriter = progressWriterFactory.create()) {
if (useAdvanced) {
Expand Down Expand Up @@ -113,7 +120,7 @@ private RuntimeException translateScanInProgressException(Exception e) {
return e instanceof RuntimeException ? (RuntimeException) e : new FcliSimpleException(e);
}

private void validateScanSetup(UnirestInstance unirest, String relId) {
private FoDScanConfigSastDescriptor validateScanSetup(UnirestInstance unirest, String relId) {
// get current setup and check if its valid
FoDScanConfigSastDescriptor currentSetup = FoDScanSastHelper.getSetupDescriptor(unirest, relId);
if (validateEntitlement) {
Expand All @@ -126,6 +133,7 @@ private void validateScanSetup(UnirestInstance unirest, String relId) {
throw new FcliSimpleException("The static scan configuration for release with id '" + relId +
"' has not been setup correctly - 'Technology Stack/Language Level' is missing or empty.");
}
return currentSetup;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,5 @@ public class FoDScanConfigSastDescriptor extends JsonNodeHolder {
private Boolean performOpenSourceAnalysis;
private String auditPreferenceType;
private Boolean includeFortifyAviator;
private String scanPolicy;
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,5 @@ public class FoDScanConfigSastSetupRequest {
private Boolean useSourceControl;
private Boolean scanBinary;
private Boolean includeFortifyAviator;
private String scanPolicy;
}
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,7 @@ fcli.fod.sast-scan.start.skip-if-running = Check to see if static scan is alread
fcli.fod.sast-scan.start.entitlement-id = The Id of the entitlement to use for the scan.
fcli.fod.sast-scan.start.purchase-entitlement = Purchase an entitlement if one is not currently allocated or available.
fcli.fod.sast-scan.start.in-progress-action = The action to use if a scan is already in progress. Valid values: ${COMPLETION-CANDIDATES}. Defaults to 'Queue' when this or '--entitlement-preference' is specified; otherwise the FoD-side default applies.
fcli.fod.sast-scan.start.scan-policy = Override the scan policy configured for the release. Use 'legacy' for the FoD legacy policy. If omitted, the configured scan policy is used.
fcli.fod.sast-scan.start.notes = Scan notes.
fcli.fod.sast-scan.start.file = Absolute path of the ScanCentral package (.Zip) file to upload.
fcli.fod.sast-scan.start.validate-entitlement = Validate if an entitlement has been set and is still valid.
Expand All @@ -580,6 +581,7 @@ 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.scan-policy = The scan policy to configure for the release. Use 'legacy' to select the FoD legacy policy.
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 \
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright 2021-2026 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.fod._common.scan.helper.sast;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;

import org.junit.jupiter.api.Test;

class FoDScanSastHelperTest {
@Test
void normalizeSetupScanPolicy() {
assertEquals("FoD_Legacy", FoDScanSastHelper.normalizeSetupScanPolicy("legacy"));
assertEquals("Security", FoDScanSastHelper.normalizeSetupScanPolicy("security"));
assertEquals("DevOps", FoDScanSastHelper.normalizeSetupScanPolicy("devops"));
assertEquals("Classic", FoDScanSastHelper.normalizeSetupScanPolicy("classic"));
assertEquals("FuturePolicy", FoDScanSastHelper.normalizeSetupScanPolicy(" FuturePolicy "));
assertNull(FoDScanSastHelper.normalizeSetupScanPolicy(" "));
}

@Test
void normalizeStartScanPolicy() {
assertEquals("FoD_Legacy_", FoDScanSastHelper.normalizeStartScanPolicy("legacy"));
assertEquals("FoD_Legacy_", FoDScanSastHelper.normalizeStartScanPolicy("FoD_Legacy"));
assertEquals("Security", FoDScanSastHelper.normalizeStartScanPolicy("security"));
assertEquals("DevOps", FoDScanSastHelper.normalizeStartScanPolicy("devops"));
assertEquals("Classic", FoDScanSastHelper.normalizeStartScanPolicy("classic"));
assertEquals("FuturePolicy", FoDScanSastHelper.normalizeStartScanPolicy(" FuturePolicy "));
assertNull(FoDScanSastHelper.normalizeStartScanPolicy(null));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,19 @@ class FoDScanSpec extends FcliBaseSpec {
then:
def e = thrown(UnexpectedFcliResultException)
e.result.stderr.any { it.contains("the entitlement has expired") }
e.result.stdout.first().replace(" ", "").equals("AssessmenttypeidEntitlementidEntitlementfrequencytypeReleaseidTechnologystackidTechnologystackLanguagelevelidLanguagelevelOSSAnalysisAuditpreferencetypeIncludethirdpartylibrariesUsesourcecontrolScanbinaryBsitokenApplicationReleaseMicroserviceAction")
verifyAll(e.result.stdout.first().replace(" ", "")) {
it.contains("Assessmenttypeid")
it.contains("Scanpolicy")
it.contains("ApplicationReleaseMicroserviceAction")
}
}

def "setup.sast-scan-help-shows-scan-policy"() {
def args = "fod sast-scan setup --help"
when:
def result = Fcli.run(args)
then:
result.stdout.any { it.contains("--scan-policy") }
}

def "get-config.sast-scan"() {
Expand Down Expand Up @@ -345,6 +357,7 @@ class FoDScanSpec extends FcliBaseSpec {
verifyAll(result.stdout) {
it.any { it.contains("--in-progress-action") }
it.any { it.contains("--entitlement-preference") }
it.any { it.contains("--scan-policy") }
it.any { it.contains("DoNotStartScan") }
it.any { it.contains("CancelScanInProgress") }
it.any { it.contains("Queue") }
Expand Down
Loading