Skip to content

Commit

Permalink
feat: fcli fod sast-scan setup: Add --skip-if-exists option
Browse files Browse the repository at this point in the history
  • Loading branch information
rsenden committed Sep 16, 2024
1 parent 4b2a244 commit 855d4f3
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -81,92 +81,113 @@ public class FoDSastScanSetupCommand extends AbstractFoDJsonNodeOutputCommand im
private final Boolean includeThirdPartyLibraries = false;
@Option(names = {"--use-source-control"})
private final Boolean useSourceControl = false;
@Option(names={"--skip-if-exists"})
private boolean skipIfExists = false;

@Mixin
private ProgressWriterFactoryMixin progressWriterFactory;
// TODO We don't actually use a progress writer, but for now we can't
// remove the --progress option to maintain backward compatibility.
// This should be removed once we move to fcli 3.x (and probably
// check other FoD commands as well), unless we actually start
// using this of course.
@Mixin private ProgressWriterFactoryMixin progressWriterFactory;

// TODO Split into multiple methods
@Override
public JsonNode getJsonNode(UnirestInstance unirest) {
try (var progressWriter = progressWriterFactory.create()) {
var releaseDescriptor = releaseResolver.getReleaseDescriptor(unirest);
var relId = releaseDescriptor.getReleaseId();
Integer entitlementIdToUse = 0;
Integer assessmentTypeId = 0;
Integer technologyStackId = 0;
Integer languageLevelId = 0;

// get current setup
FoDScanConfigSastDescriptor currentSetup = FoDScanSastHelper.getSetupDescriptor(unirest, relId);

LOG.info("Finding appropriate entitlement to use.");

// find an appropriate assessment type to use
Optional<FoDReleaseAssessmentTypeDescriptor> atd = Arrays.stream(
FoDReleaseAssessmentTypeHelper.getAssessmentTypes(unirest,
relId, FoDScanType.Static,
entitlementFrequencyTypeMixin.getEntitlementFrequencyType(),
false, true)
).filter(n -> n.getName().equals(staticAssessmentType))
.findFirst();
if (atd.isEmpty()) {
throw new IllegalArgumentException("Cannot find appropriate assessment type for specified options.");
}
assessmentTypeId = atd.get().getAssessmentTypeId();
entitlementIdToUse = atd.get().getEntitlementId();

// validate entitlement specified or currently in use against assessment type found
if (entitlementId != null && entitlementId > 0) {
// check if "entitlement id" explicitly matches what has been found
if (!Objects.equals(entitlementIdToUse, entitlementId)) {
throw new IllegalArgumentException("Cannot appropriate assessment type for use with entitlement: " + entitlementId);
}
var setupDescriptor = FoDScanSastHelper.getSetupDescriptor(unirest, releaseDescriptor.getReleaseId());
if ( skipIfExists && setupDescriptor.getAssessmentTypeId()!=0 ) {
return setupDescriptor.asObjectNode().put("__action__", "SKIPPED_EXISTING");
} else {
if (currentSetup.getEntitlementId() != null && currentSetup.getEntitlementId() > 0) {
// check if "entitlement id" is already configured
if (!Objects.equals(entitlementIdToUse, currentSetup.getEntitlementId())) {
LOG.warn("Changing current release entitlement from " + currentSetup.getEntitlementId());
}
}
return setup(unirest, releaseDescriptor, setupDescriptor).asObjectNode();
}
LOG.info("Configuring release to use entitlement " + entitlementIdToUse);
}
}

// check if the entitlement is still valid
FoDReleaseAssessmentTypeHelper.validateEntitlement(relId, atd.get());
LOG.info("The entitlement " + entitlementIdToUse + " is valid.");
private FoDScanConfigSastDescriptor setup(UnirestInstance unirest, FoDReleaseDescriptor releaseDescriptor, FoDScanConfigSastDescriptor currentSetup) {
var relId = releaseDescriptor.getReleaseId();

// find/check technology stack / language level
FoDLookupDescriptor lookupDescriptor = null;
LOG.info("Finding appropriate entitlement to use.");

var atd = getAssessmentTypeDescriptor(unirest, relId);
var assessmentTypeId = atd.getAssessmentTypeId();
var entitlementIdToUse = atd.getEntitlementId();

validateEntitlement(currentSetup, entitlementIdToUse, relId, atd);
LOG.info("Configuring release to use entitlement " + entitlementIdToUse);

var technologyStackId = getTechnologyStackId(unirest);
var languageLevelId = getLanguageLevelId(unirest, technologyStackId);

FoDScanConfigSastSetupRequest setupSastScanRequest = FoDScanConfigSastSetupRequest.builder()
.entitlementId(entitlementIdToUse)
.assessmentTypeId(assessmentTypeId)
.entitlementFrequencyType(entitlementFrequencyTypeMixin.getEntitlementFrequencyType().name())
.technologyStackId(technologyStackId)
.languageLevelId(languageLevelId)
.performOpenSourceAnalysis(performOpenSourceAnalysis)
.auditPreferenceType(auditPreferenceType.name())
.includeThirdPartyLibraries(includeThirdPartyLibraries)
.useSourceControl(useSourceControl).build();

return FoDScanConfigSastHelper.setupScan(unirest, releaseDescriptor, setupSastScanRequest);
}

private Integer getLanguageLevelId(UnirestInstance unirest, Integer technologyStackId) {
Integer languageLevelId = 0;
FoDLookupDescriptor lookupDescriptor = null;
if (languageLevel != null && languageLevel.length() > 0) {
try {
lookupDescriptor = FoDLookupHelper.getDescriptor(unirest, FoDLookupType.TechnologyTypes, technologyStack, true);
lookupDescriptor = FoDLookupHelper.getDescriptor(unirest, FoDLookupType.LanguageLevels, String.valueOf(technologyStackId), languageLevel, true);
} catch (JsonProcessingException ex) {
throw new IllegalStateException(ex.getMessage());
}
if (lookupDescriptor != null) technologyStackId = Integer.valueOf(lookupDescriptor.getValue());
//System.out.println("technologyStackId = " + technologyStackId);
if (languageLevel != null && languageLevel.length() > 0) {
try {
lookupDescriptor = FoDLookupHelper.getDescriptor(unirest, FoDLookupType.LanguageLevels, String.valueOf(technologyStackId), languageLevel, true);
} catch (JsonProcessingException ex) {
throw new IllegalStateException(ex.getMessage());
if (lookupDescriptor != null) languageLevelId = Integer.valueOf(lookupDescriptor.getValue());
}
return languageLevelId;
}

private Integer getTechnologyStackId(UnirestInstance unirest) {
// find/check technology stack / language level
FoDLookupDescriptor lookupDescriptor = null;
try {
lookupDescriptor = FoDLookupHelper.getDescriptor(unirest, FoDLookupType.TechnologyTypes, technologyStack, true);
} catch (JsonProcessingException ex) {
throw new IllegalStateException(ex.getMessage());
}
// TODO return 0 or null, or throw exception?
return lookupDescriptor==null ? 0 : Integer.valueOf(lookupDescriptor.getValue());
}

private void validateEntitlement(FoDScanConfigSastDescriptor currentSetup, Integer entitlementIdToUse, String relId, FoDReleaseAssessmentTypeDescriptor atd) {
// validate entitlement specified or currently in use against assessment type found
if (entitlementId != null && entitlementId > 0) {
// check if "entitlement id" explicitly matches what has been found
if (!Objects.equals(entitlementIdToUse, entitlementId)) {
throw new IllegalArgumentException("Cannot appropriate assessment type for use with entitlement: " + entitlementId);
}
} else {
if (currentSetup.getEntitlementId() != null && currentSetup.getEntitlementId() > 0) {
// check if "entitlement id" is already configured
if (!Objects.equals(entitlementIdToUse, currentSetup.getEntitlementId())) {
LOG.warn("Changing current release entitlement from " + currentSetup.getEntitlementId());
}
if (lookupDescriptor != null) languageLevelId = Integer.valueOf(lookupDescriptor.getValue());
//System.out.println("languageLevelId = " + languageLevelId);
}

FoDScanConfigSastSetupRequest setupSastScanRequest = FoDScanConfigSastSetupRequest.builder()
.entitlementId(entitlementIdToUse)
.assessmentTypeId(assessmentTypeId)
.entitlementFrequencyType(entitlementFrequencyTypeMixin.getEntitlementFrequencyType().name())
.technologyStackId(technologyStackId)
.languageLevelId(languageLevelId)
.performOpenSourceAnalysis(performOpenSourceAnalysis)
.auditPreferenceType(auditPreferenceType.name())
.includeThirdPartyLibraries(includeThirdPartyLibraries)
.useSourceControl(useSourceControl).build();

return FoDScanConfigSastHelper.setupScan(unirest, releaseDescriptor, setupSastScanRequest).asJsonNode();
}
// check if the entitlement is still valid
FoDReleaseAssessmentTypeHelper.validateEntitlement(relId, atd);
}

private FoDReleaseAssessmentTypeDescriptor getAssessmentTypeDescriptor(UnirestInstance unirest, String relId) {
// find an appropriate assessment type to use
Optional<FoDReleaseAssessmentTypeDescriptor> atd = Arrays.stream(
FoDReleaseAssessmentTypeHelper.getAssessmentTypes(unirest,
relId, FoDScanType.Static,
entitlementFrequencyTypeMixin.getEntitlementFrequencyType(),
false, true)
).filter(n -> n.getName().equals(staticAssessmentType))
.findFirst();
return atd.orElseThrow(()->new IllegalArgumentException("Cannot find appropriate assessment type for specified options."));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,8 @@ 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.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.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.
Expand Down

0 comments on commit 855d4f3

Please sign in to comment.