fortify / fcli

fcli is a command-line utility for interacting with various Fortify products
https://fortify.github.io/fcli/
Other
28 stars 16 forks source link

FoD: Cannot find release for "XXX:YYY" in 2.0.0.develop #445

Closed kadraman closed 9 months ago

kadraman commented 9 months ago

When trying to resolved a valid release, some FoD commands are failing, e.g.:

> fcli fod assessment-type list --release="IWA-Java [KAL]:main"
java.lang.IllegalArgumentException: Cannot find release IWA-Java [KAL]:main
        at com.fortify.cli.fod.release.helper.FoDReleaseHelper.getDescriptor(FoDReleaseHelper.java:91)
        at com.fortify.cli.fod.release.helper.FoDReleaseHelper.getReleaseDescriptorFromQualifiedName(FoDReleaseHelper.java:61)
        at com.fortify.cli.fod.release.helper.FoDReleaseHelper.getReleaseDescriptor(FoDReleaseHelper.java:44)
        at com.fortify.cli.fod.release.cli.mixin.FoDReleaseByQualifiedNameOrIdResolverMixin$AbstractFoDQualifiedReleaseNameOrIdResolverMixin.getReleaseDescriptor(FoDReleaseByQualifiedNameOrIdResolverMixin.java:38)
        at com.fortify.cli.fod.release.cli.mixin.FoDReleaseByQualifiedNameOrIdResolverMixin$AbstractFoDQualifiedReleaseNameOrIdResolverMixin.getReleaseId(FoDReleaseByQualifiedNameOrIdResolverMixin.java:42)
        at com.fortify.cli.fod.assessment_type.cli.cmd.FoDAssessmentTypeListCommand.getForScanType(FoDAssessmentTypeListCommand.java:58)
        at com.fortify.cli.fod.assessment_type.cli.cmd.FoDAssessmentTypeListCommand.lambda$getJsonNode$0(FoDAssessmentTypeListCommand.java:50)
        at java.base@17.0.8/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.base@17.0.8/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:992)
        at java.base@17.0.8/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
        at java.base@17.0.8/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
        at java.base@17.0.8/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
        at java.base@17.0.8/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
        at java.base@17.0.8/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base@17.0.8/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
        at com.fortify.cli.fod.assessment_type.cli.cmd.FoDAssessmentTypeListCommand.getJsonNode(FoDAssessmentTypeListCommand.java:51)
        at com.fortify.cli.fod._common.output.cli.AbstractFoDJsonNodeOutputCommand.getJsonNode(AbstractFoDJsonNodeOutputCommand.java:23)
        at com.fortify.cli.common.output.cli.cmd.AbstractOutputCommand.run(AbstractOutputCommand.java:33)
        at picocli.CommandLine.executeUserObject(CommandLine.java:2103)
        at picocli.CommandLine$RunLast.executeUserObjectOfLastSubcommandWithSameParent(CommandLine.java:2538)
        at picocli.CommandLine$RunLast.handle(CommandLine.java:2530)
        at picocli.CommandLine$RunLast.handle(CommandLine.java:2492)
        at picocli.CommandLine$AbstractParseResultHandler.execute(CommandLine.java:2350)
        at picocli.CommandLine$RunLast.execute(CommandLine.java:2494)
        at picocli.CommandLine.execute(CommandLine.java:2247)
        at com.fortify.cli.app.runner.DefaultFortifyCLIRunner.run(DefaultFortifyCLIRunner.java:49)
        at com.fortify.cli.app.FortifyCLI.execute(FortifyCLI.java:38)
        at com.fortify.cli.app.FortifyCLI.main(FortifyCLI.java:32)

Using a release Id works fine, e.g.

> fcli fod assessment-type list --release=127137
 Id   Name                         Scan type  Frequency type  Units       Entitlement id  Entitlement description
 117  Static Assessment            Static     Subscription    0 (of 70)   2772            2772 - Remediation
 117  Static Assessment            Static     Subscription    0 (of 70)   2772            2772 - Subscription (Ends 2/23/2024)
 118  Static+ Assessment           Static     Subscription    6 (of 70)   2772            2772 - Subscription (6 Units)
 118  Static+ Assessment           Static     SingleScan      2 (of 70)   2772            2772 - Single Scan (2 Units)
 120  Dynamic+ Website Assessment  Dynamic    Subscription    18 (of 70)  2772            2772 - Subscription (18 Units)
 120  Dynamic+ Website Assessment  Dynamic    SingleScan      6 (of 70)   2772            2772 - Single Scan (6 Units)
 119  Dynamic Website Assessment   Dynamic    Subscription    0 (of 70)   2772            2772 - Subscription (Ends 2/23/2024)
 121  Dynamic+ API Assessment      Dynamic    SingleScan      6 (of 70)   2772            2772 - Single Scan (6 Units)
 138  Dynamic API Assessment       Dynamic    Subscription    6 (of 70)   2772            2772 - Subscription (6 Units)
 138  Dynamic API Assessment       Dynamic    SingleScan      2 (of 70)   2772            2772 - Single Scan (2 Units)

so there is something wrong in resolving the name.

I believe it might be down to a change in release\cli\helper\FoDQualifiedReleaseNameDescriptor as I dont recognise:

    public final String getQualifiedName() {
        var optionalMsQualifier = StringUtils.isBlank(microserviceName)?"":(":"+microserviceName);
        return String.format("%s%s:%s", appName, optionalMsQualifier, releaseName);
    }
rsenden commented 9 months ago

I'm looking at this now, for now it seems like this issue is only present in the assessment-type list command. The release get and release download-fpr commands seem to be able to resolve releases just fine.

rsenden commented 9 months ago

Found the problem; it's AbstractFoDQualifiedReleaseNameOrIdResolverMixin::getReleaseId that's broken. To fix #427, we now do client-side filtering on app, microservice, and release name. However, the getReleaseId method requests only releaseId field to be returned by FoD, so client-side filtering can't find any matching releases.

The easy fix would be to simply add the fields needed for client-side filtering in the getReleaseId method, however the better fix is to handle this in FoDReleaseHelper::addFieldsParam; if the fields array contains any values, we should add applicationName etcetera if they're not present.

@kadraman Can you take care of fixing this?

rsenden commented 9 months ago

For proper behavior in all situations, if fields is not empty, the addFieldsParam method should make sure that app/ms/release name fields are always being requested, but also releaseId. Not applicable in this case, but if any command ever requests fields={'releaseName'} for example, and then a user tries to look up a release by id, that would fail similarly because the returned records won't have the releaseId field for client-side matching

Also, other helpers like FoDAppHelper might be affected by the same issue. We need to find all references to FoDDataHelper::findUnique; if the helper supports fields selection, the helper should ensure that all fields required for client-side filtering are included as well.