diff --git a/.github/workflows/fortify-analysis.yml b/.github/workflows/fortify-analysis.yml index 7520c30f69..aa4a1b2b75 100644 --- a/.github/workflows/fortify-analysis.yml +++ b/.github/workflows/fortify-analysis.yml @@ -18,18 +18,16 @@ name: Fortify on Demand Scan -# TODO: Customize trigger events based on your DevSecOps processes and typical FoD SAST scan time on: workflow_dispatch: push: branches: [ develop ] + pull_request: schedule: - cron: '16 0 * * 5' jobs: FoD-SAST-Scan: - # Use the appropriate runner for building your source code. - # TODO: Use a Windows runner for .NET projects that use msbuild. Additional changes to RUN commands will be required to switch to Windows syntax. runs-on: ubuntu-latest permissions: actions: read @@ -37,64 +35,32 @@ jobs: security-events: write steps: - # Check out source code - name: Check Out Source Code uses: actions/checkout@v4 with: ref: develop - # Java is required to run the various Fortify utilities. - # When scanning a Java application, please use the appropriate Java version for building your application. - name: Setup Java uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: '17' - # Prepare source+dependencies for upload. The default example is for a Maven project that uses pom.xml. - # TODO: Update PACKAGE_OPTS based on the ScanCentral Client documentation for your project's included tech stack(s). Helpful hints: - # ScanCentral Client will download dependencies for maven (-bt mvn) and gradle (-bt gradle). - # ScanCentral Client can download dependencies for msbuild projects (-bt msbuild); however, you must convert the workflow to use a Windows runner. - # ScanCentral has additional options that should be set for PHP and Python projects - # For other build tools, add your build commands to download necessary dependencies and prepare according to Fortify on Demand Packaging documentation. - # ScanCentral Client documentation is located at https://www.microfocus.com/documentation/fortify-software-security-center/ - - name: Download Fortify ScanCentral Client - uses: fortify/gha-setup-scancentral-client@v2 - - name: Package Code + Dependencies - run: scancentral package $PACKAGE_OPTS -o package.zip - env: - PACKAGE_OPTS: "-bt gradle -oss" - - # Start Fortify on Demand SAST scan and wait until results complete. For more information on FoDUploader commands, see https://github.com/fod-dev/fod-uploader-java - # TODO: Update ENV variables for your application and create the necessary GitHub Secrets. Helpful hints: - # Credentials and release ID should be obtained from your FoD tenant (either Personal Access Token or API Key can be used). - # Automated Audit preference should be configured for the release's Static Scan Settings in the Fortify on Demand portal. - - name: Download Fortify on Demand Universal CI Tool - uses: fortify/gha-setup-fod-uploader@v1 - - name: Perform SAST Scan - run: java -jar $FOD_UPLOAD_JAR -z package.zip -aurl $FOD_API_URL -purl $FOD_URL -rid "$FOD_RELEASE_ID" -tc "$FOD_TENANT" -uc "$FOD_USER" "$FOD_PAT" $FOD_UPLOADER_OPTS -n "$FOD_UPLOADER_NOTES" - env: - FOD_URL: "https://ams.fortify.com/" - FOD_API_URL: "https://api.ams.fortify.com/" - FOD_TENANT: ${{ secrets.OSS_FOD_TENANT }} - FOD_USER: ${{ secrets.OSS_FOD_USER }} - FOD_PAT: ${{ secrets.OSS_FOD_PAT }} - FOD_RELEASE_ID: 345729 - FOD_UPLOADER_OPTS: "-ep 2 -pp 0 -I 1 -apf" - FOD_UPLOADER_NOTES: 'Triggered by GitHub Actions (${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})' - - # Once scan completes, pull SAST issues from Fortify on Demand and generate SARIF output. - - name: Export results to GitHub-optimized SARIF - uses: fortify/gha-export-vulnerabilities@v1 + - name: Run FoD SAST scan + uses: fortify/github-action@v1 with: - fod_base_url: "https://ams.fortify.com/" - fod_tenant: ${{ secrets.OSS_FOD_TENANT }} - fod_user: ${{ secrets.OSS_FOD_USER }} - fod_password: ${{ secrets.OSS_FOD_PAT }} - fod_release_id: 345729 - - # Import Fortify on Demand results to GitHub Security Code Scanning - - name: Import Results - uses: github/codeql-action/upload-sarif@v3 - with: - sarif_file: ./gh-fortify-sast.sarif + sast-scan: true + env: + FOD_URL: https://ams.fortify.com/ + FOD_TENANT: ${{secrets.OSS_FOD_TENANT}} + FOD_USER: ${{secrets.OSS_FOD_USER}} + FOD_PASSWORD: ${{secrets.OSS_FOD_PAT}} + FOD_LOGIN_EXTRA_OPTS: --socket-timeout=600s + FOD_SAST_SCAN_EXTRA_OPTS: --notes "These are notes from the GitHub Action" + DO_SETUP: true + # DO_POLICY_CHECK: true + DO_JOB_SUMMARY: true + # DO_PR_COMMENT: true + DO_EXPORT: true + SETUP_EXTRA_OPTS: --sdlc-status Development --scan-types sast + PACKAGE_EXTRA_OPTS: -oss diff --git a/fcli-core/fcli-app/src/main/java/com/fortify/cli/app/runner/DefaultFortifyCLIRunner.java b/fcli-core/fcli-app/src/main/java/com/fortify/cli/app/runner/DefaultFortifyCLIRunner.java index 2cc2d80865..b5d242a3cb 100644 --- a/fcli-core/fcli-app/src/main/java/com/fortify/cli/app/runner/DefaultFortifyCLIRunner.java +++ b/fcli-core/fcli-app/src/main/java/com/fortify/cli/app/runner/DefaultFortifyCLIRunner.java @@ -23,6 +23,9 @@ import com.fortify.cli.common.variable.FcliVariableHelper; import picocli.CommandLine; +import picocli.CommandLine.Help.Ansi.Text; +import picocli.CommandLine.Model.ArgGroupSpec; +import picocli.CommandLine.Model.CommandSpec; public final class DefaultFortifyCLIRunner implements IFortifyCLIRunner { // TODO See https://github.com/remkop/picocli/issues/2066 @@ -36,6 +39,7 @@ private CommandLine createCommandLine() { // See comments in I18nParameterExceptionHandler for more detail. //cl.setParameterExceptionHandler(new I18nParameterExceptionHandler(cl.getParameterExceptionHandler())); cl.setDefaultValueProvider(FortifyCLIDefaultValueProvider.getInstance()); + cl.setHelpFactory((commandSpec, colorScheme)->new FcliHelp(commandSpec, colorScheme)); return cl; } @@ -70,4 +74,34 @@ public int run(List args) { public void close() { GenericUnirestFactory.shutdown(); } + + private static final class FcliHelp extends CommandLine.Help { + public FcliHelp(CommandSpec commandSpec, ColorScheme colorScheme) { + super(commandSpec, colorScheme); + } + + public FcliHelp(Object command, Ansi ansi) { + super(command, ansi); + } + + public FcliHelp(Object command) { + super(command); + } + + protected String makeSynopsisFromParts(int synopsisHeadingLength, Text optionText, Text groupsText, Text endOfOptionsText, Text positionalParamText, Text commandText) { + boolean positionalsOnly = true; + for (ArgGroupSpec group : commandSpec().argGroups()) { + if (group.validate()) { // non-validating groups are not shown in the synopsis + positionalsOnly &= group.allOptionsNested().isEmpty(); + } + } + Text text; + if (positionalsOnly) { // show end-of-options delimiter before the (all-positional params) groups + text = positionalParamText.concat(optionText).concat(endOfOptionsText).concat(groupsText).concat(commandText); + } else { + text = positionalParamText.concat(optionText).concat(groupsText).concat(endOfOptionsText).concat(commandText); + } + return insertSynopsisCommandName(synopsisHeadingLength, text); + } + } } diff --git a/fcli-core/fcli-common/src/main/java/com/fortify/cli/common/action/cli/cmd/AbstractActionRunCommand.java b/fcli-core/fcli-common/src/main/java/com/fortify/cli/common/action/cli/cmd/AbstractActionRunCommand.java index 652530708e..af174d1a35 100644 --- a/fcli-core/fcli-common/src/main/java/com/fortify/cli/common/action/cli/cmd/AbstractActionRunCommand.java +++ b/fcli-core/fcli-common/src/main/java/com/fortify/cli/common/action/cli/cmd/AbstractActionRunCommand.java @@ -39,8 +39,8 @@ public abstract class AbstractActionRunCommand extends AbstractRunnableCommand { @Mixin private ActionResolverMixin.RequiredParameter actionResolver; - @DisableTest({TestType.MULTI_OPT_SPLIT, TestType.MULTI_OPT_PLURAL_NAME, TestType.OPT_LONG_NAME}) - @Option(names="--", paramLabel="", descriptionKey="fcli.action.run.action-parameter") + @DisableTest({TestType.MULTI_OPT_SPLIT, TestType.MULTI_OPT_PLURAL_NAME, TestType.OPT_LONG_NAME, TestType.OPT_LONG_NAME_COUNT, TestType.OPT_NAME_FORMAT, TestType.OPT_ARITY_PRESENT}) + @Option(names="action-parameters", arity="0", descriptionKey="fcli.action.run.action-parameter") private List dummyForSynopsis; @Mixin private ProgressWriterFactoryMixin progressWriterFactory; @Mixin private CommandHelperMixin commandHelper; diff --git a/fcli-core/fcli-common/src/main/java/com/fortify/cli/common/output/cli/mixin/OutputOptionsArgGroup.java b/fcli-core/fcli-common/src/main/java/com/fortify/cli/common/output/cli/mixin/OutputOptionsArgGroup.java index 01bfd51d12..bb39716699 100644 --- a/fcli-core/fcli-common/src/main/java/com/fortify/cli/common/output/cli/mixin/OutputOptionsArgGroup.java +++ b/fcli-core/fcli-common/src/main/java/com/fortify/cli/common/output/cli/mixin/OutputOptionsArgGroup.java @@ -28,7 +28,7 @@ public final class OutputOptionsArgGroup implements IOutputOptions { @Option(names = {"-o", "--output"}, order=1, converter = OutputFormatConfigConverter.class, completionCandidates = OutputFormatIterable.class, paramLabel = "format[=]") @Getter private OutputFormatConfig outputFormatConfig; - @Option(names = {"--store"}, order=1, converter = VariableStoreConfigConverter.class, paramLabel = "variableName[=]") + @Option(names = {"--store"}, order=1, converter = VariableStoreConfigConverter.class, paramLabel = "variableName[:]") @Getter private VariableStoreConfig variableStoreConfig; @Option(names = {"--to-file"}, order=7) diff --git a/fcli-core/fcli-fod/src/main/resources/com/fortify/cli/fod/actions/zip/release-summary.yaml b/fcli-core/fcli-fod/src/main/resources/com/fortify/cli/fod/actions/zip/release-summary.yaml index 44ab2514af..bf16abb75d 100644 --- a/fcli-core/fcli-fod/src/main/resources/com/fortify/cli/fod/actions/zip/release-summary.yaml +++ b/fcli-core/fcli-fod/src/main/resources/com/fortify/cli/fod/actions/zip/release-summary.yaml @@ -65,16 +65,16 @@ steps: value: ${issues_raw.totalCount} - set: - name: ossCritical - value: ${issues_raw.filters.?[#this.fieldName == 'severity'][0].fieldFilterValues.^[#this.value == "Critical"]?.count?:0} + value: ${issues_raw.filters.^[#this.fieldName == 'severity']?.fieldFilterValues?.^[#this.value == "Critical"]?.count?:0} - set: - name: ossHigh - value: ${issues_raw.filters.?[#this.fieldName == 'severity'][0].fieldFilterValues.^[#this.value == "High"]?.count?:0} + value: ${issues_raw.filters.^[#this.fieldName == 'severity']?.fieldFilterValues?.^[#this.value == "High"]?.count?:0} - set: - name: ossMedium - value: ${issues_raw.filters.?[#this.fieldName == 'severity'][0].fieldFilterValues.^[#this.value == "Medium"]?.count?:0} + value: ${issues_raw.filters.^[#this.fieldName == 'severity']?.fieldFilterValues?.^[#this.value == "Medium"]?.count?:0} - set: - name: ossLow - value: ${issues_raw.filters.?[#this.fieldName == 'severity'][0].fieldFilterValues.^[#this.value == "Low"]?.count?:0} + value: ${issues_raw.filters.^[#this.fieldName == 'severity']?.fieldFilterValues?.^[#this.value == "Low"]?.count?:0} # replace up to here - write: