Fcli version Action schema version

3.8.1

2.2.0

Introduction

Fcli actions are defined in YAML files that describe action behavior through a set of instructions, combined with a rich expression syntax. This document provides information about the action instructions and expression syntax that are supported by the current fcli version, as well as some general hints and tips on custom action development.

Getting started

To get accustomed with action syntax and features, it is highly recommended to have a look at the YAML contents of some of the fcli built-in actions. You can view the contents of built-in actions by running the fcli * action get <action> command, or view the contents online at the following locations:

Schema-based code assistance

Fcli provides an action schema, which allows YAML editors and IDEs to provide code completion, documentation and validation for fcli action YAML documents. You may need to install a plugin to enable proper YAML editing and schema support. Following are some commonly used IDE plugins that are known to work with one of the schema associations listed below:

For optimal compatibility with various IDEs and YAML editors, fcli allows the schema to be declared in two ways:

  • YAML comment, supported by IDEs like Visual Studio Code, Eclipse and IntelliJ:

    # yaml-language-server: $schema=https://fortify.github.io/fcli/schemas/action/fcli-action-schema-2.2.0.json
  • YAML property, supported by Eclipse and some other YAML editors:

    $schema: https://fortify.github.io/fcli/schemas/action/fcli-action-schema-2.2.0.json

Fcli requires at least one of these statements to be provided in the action YAML file. You may also provide both, in which case the schema URL must be identical in both statements. Once you’ve added one of these statements to your action YAML file, your IDE or YAML editor may automatically provide support for editing and validating action YAML files. If not, try closing and re-opening the YAML file, or consult the documentation of your IDE or YAML editor.

As shown in the sample schema statements above, the current fcli version 3.8.1 supports schema version 2.2.0. Other fcli versions may support different schema versions. In general, fcli provides backward compatibility for earlier schema versions with the same schema major version range, and forward compatibility for later schema patch versions within the same schema minor version range.

Note
Fcli built-in actions should always point to the development version of the schema, for example https://fortify.github.io/fcli/schemas/action/fcli-action-schema-dev-2.x.json. This allows fcli developers to utilize the latest schema changes in their IDE, before the schema has been released. The fcli build process takes care of updating the schema URL to the appropriate schema release version, thereby making sure that all fcli built-in actions will eventually point to the current schema version.

Design considerations

Given that actions can define and process arbitrary parameters, it may be tempting to implement generic, highly configurable actions. For example, you could implement a highly configurable action for checking all kinds of security policy criteria, with the actual criteria to be checked being passed as action parameters.

However, from a CI/CD perspective, this means that every pipeline must properly set these action parameters. Pipeline authors may copy existing pipelines or use pipeline templates to have these action parameters set to predefined values, but what if those parameters need to updated globally? Potentially, this means that you’d need to update thousands of pipelines to adjust action parameters.

This is exactly the reason why we don’t provide highly configurable check-policy actions, but instead just provide a default implementation that can be customized according to organization requirements. Instead of passing fine-grained pass/fail criteria as action parameters, those criteria are hard-coded into the action. If there is a need to apply different criteria for different types of applications, for example based on business risk, multiple approaches are possible:

  • Use SSC/FoD application version/release attributes like Business Risk or other characteristics to identify what criteria to apply. This is the preferred approach, to allow the criteria to be applied to automatically match the centrally maintained attributes/characteristics.

  • Have the action take one or more parameters that identify what criteria to apply. This could be a policy name, or a functional identifier like --business-risk.

  • Publish separate actions that implement different policy criteria, like check-high-risk-policy and check-low-risk-policy.

The examples above are based on actions that perform policy checks, but the same principles and considerations (may) apply to other types of actions.

Primary YAML instructions

The sections below list the primary (top-level) YAML instructions supported by the current fcli (schema) version. Where applicable, links are provided to YAML types sub-sections that provide more details on the expected contents for each property type.

$schema

$schema - string

Required string unless yaml-language-server comment with schema location is provided: Defines the fcli action YAML schema version used by this action. When a user tries to run this action, fcli will check whether the current fcli version is compatible with the given action schema version.

Sample snippets

$schema: https://fortify.github.io/fcli/schemas/action/fcli-action-schema-2.2.0.json
# yaml-language-server: $schema=https://fortify.github.io/fcli/schemas/action/fcli-action-schema-2.2.0.json

author

author - string

Required string: Author of this action. This is a free-format string, allowing action users to see who provided this action.

Sample snippets

author: MyCompany
author: John Doe

usage

usage - usage

Required object: Action usage help, providing action usage instructions for users of this action. For example, this information may be included in action documentation, or can be viewed by users through the 'fcli * action help' command.

Sample snippet

usage:
  header: My action summary
  description: |
    Lorem ipsum dolor sit amet consectetur adipiscing elit. Consectetur adipiscing elit quisque
    faucibus ex sapien vitae. Ex sapien vitae pellentesque sem placerat in id. Placerat in id
    cursus mi pretium tellus duis. Pretium tellus duis convallis tempus leo eu aenean.

config

config - config

Optional object: Action configuration properties. This includes configuration properties for setting default values to be used by some action steps, or how action output should be processed.

Sample snippet

config:
  rest.target.default: fod
  output: immediate

cli.options

cli.options - map<string,cli.option>

Optional map: CLI options accepted by this action. Map keys define the identifier for an option, which can be used in later instructions through the ${cli.optionIdentifier} SpEL template expression. Map values define option definitions like option names that can be specified on the command line, option description, …​

Sample snippet

cli.options:
  file: # Can be referenced through ${cli.file} in action steps
    names: -f,--file
    description: Output file name
    required: false
    defaultValue: somefile.txt

steps

steps - array<step>

Required list: Steps to be executed when this action is being run. Each list item should consist of a single instruction to be executed, optionally together with the 'if:' instruction to allow for conditional execution. Note that the YAML schema allows for multiple instructions to be present within a single list item, but this will result in an error.

Sample snippet

steps:
  - var.set:
      ...
  - rest.call:
      ...
  - if: ${expr}
    run.fcli:
      ...

formatters

formatters - map<string,object>

Optional map: Formatters that can be referenced in action steps to format data. Map keys define formatter name, map values define how the data should be formatted. Each formatter can be defined as either a single string or a structured YAML object. Every string value in the formatter will be processed as a Spring Expression Language expression, allowing access to current action variables and SpEL functions. For example, if action variable 'name' is currently set to 'John Doe', a formatter node like 'hello: Hello ${name}' will set the property 'hello' to 'Hello John Doe'.

Sample snippet

formatters:
  plainText: |
    This is formatted plain text, with variable ${varName}.
  structured:
    prop1: Some text
    prop2: Hello ${name}!
    prop3:
      nestedProp1: xyz
      nestedProp2: ${varName}

YAML step instructions

The sections below list all supported step instructions, that can for example be used in the top-level steps instruction, but also other instructions that accept a list of steps, for example within for-each blocks. Where applicable, links are provided to YAML types sub-sections that provide more details on the expected contents for each property type.

[step] var.set

[step] var.set - map<expression,value-fmt>

Set one or more variables values for use in later action steps. This step takes a list of variables to set, with each list item taking a single yaml property that represents the variable name to set, which may be specified as an SpEL template expression.

Based on the format of the variable name, this step can either set/replace a single-value variable, set/replace a property on a variable containing a set of properties, or append a value to an array-type variable. By default, variables are only accessible by the current fcli action, unless they are prefixed with 'global.', in which case they are also accessible by other actions that execute within the context of a single fcli command-line invocation. For example, if action 1 uses the run.fcli step to execute action 2, any global variables set in action 1 will be accessibly by action 2, and vice versa.

Following are some examples that show how to specify the operation to perform, and thereby implicitly declaring the variable type:

# Set/replace the single-value variable named 'var1'
var1: …​

# Set/replace properties 'prop1' and 'prop2' on variable 'var2'
var2.prop1: …​
var2.prop2: …​

# Append two items to the array-type variable 'var3' (two trailing dots)
var3..: …​
var3..: …​

# Same as above, but setting global variables:
global.var1: …​
global.var2.prop1: …​
global.var2.prop2: …​
global.var3..: …​
global.var3..: …​

# The following would be illegal, as a variable cannot contain both
# a set of properties and an array:
var4.prop1: …​
var4..: …​

Due to this syntax, variable names cannot contain dots like 'var.1', as '1' would be interpreted as a property name on the 'var' variable. Property names may contain dots though, so 'var5.x.y' would be intepreted as property name 'x.y' on 'var5'.

Values may be specified as either an SpEL template expression, or as 'value' and 'fmt' properties. An 'if' property is also supported to conditionally set the variable. If formatter is specified, the given formatter from the 'formatters' section will be used to format the given value, or, if no value is given, the formatter will be evaluated against the set of all variables. Some examples:

global.name: John Doe
simpleValue1: Hello ${global.name}
formattedValue1: {fmt: myFormatter, if: "${someExpression}"}
formatterValue2: {value: "${myVar}", fmt: "${myVarFormatterExpression}"}

Within a single 'var.set*' step, variables are processed in the order that they are declared, allowing earlier declared variables to be referenced by variables or formatters that are declared later in the same step.

Sample snippets

steps:
  - var.set:
      var1: Hello ${name}
      var2.p1: This is property 1 on var2
      var2.p2: This is property 2 on var2
      var3..: This is element 1 on var3
  - var.set:
      var3..: This is element 2 on var3
steps:
  - var.set: # Variable values demonstrate how 'value-fmt' may be specified
    var1: 'xyz'       # Plain string, without formatter
    var2: true        # Plain boolean, without formatter
    var3: ${expr}     # Plain expression, without formatter
    var4: {fmt:myFmt} # Only formatter, allowing formatter to reference all variables
    var5:             # Same as var4, but expanded YAML syntax
      fmt: myFmt
    var6:             # Use the outcome of ${expr} as input for myFmt
      fmt:   myFmt
      value: ${expr}

[step] var.rm

[step] var.rm - array<expression>

Remove one or more local or global variables. Variable names to remove can be provided as plain text or as a SpEL template expression, resolving to for example 'var1' or 'global.var2'.

Sample snippet

steps:
  - var.rm:
      - var1    # Remove variable named 'var1'
      - ${var2} # Remove variable name as stored in var2 variable

[step] log.progress

[step] log.progress - expression

Write a progress message. Progress messages are usually written to console and log file directly. Depending on progress writer configuration, progress messages may disappear when the next progress message is written, or after all action steps have been executed. If you need to write an information message that is always displayed to the end user, without the possibility of the message being removed, please use log.info instead.

Sample snippet

steps:
  - log.progress: Processing record ${recordNumber}

[step] log.info

[step] log.info - expression

Write an informational message to console and log file (if enabled). Note that depending on the config:output setting, informational messages may be shown either immediately, or only after all action steps have been executed, to not interfere with progress messages.

Sample snippet

steps:
  - log.info: Output written to ${fileName}

[step] log.warn

[step] log.warn - expression

Write a warning message to console and log file (if enabled). Note that depending on the config:output setting, warning messages may be shown either immediately, or only after all action steps have been executed, to not interfere with progress messages.

Sample snippet

steps:
  - log.warn: Skipping this part due to errors: ${errors}

[step] log.debug

[step] log.debug - expression

Write a debug message to log file (if enabled).

Sample snippet

steps:
   - log.debug: ${#this}   # Log all action variables

[step] rest.target

[step] rest.target - map<string,rest.target>

Add REST request targets for use in 'rest.call' steps. This step takes a map, with keys defining REST target names, and values defining the REST target definition.

Sample snippet

steps:
  - rest.target:
      example:
        baseUrl: https://example.com/my-app
        headers:
          Authorization: ${exampleAuth}

[step] rest.call

[step] rest.call - map<string,rest.call>

Execute one or more REST calls. This step takes a map, with keys defining an indentifier for the REST call, and values defining the request data and how to process the response. For paged REST requests, a single 'rest.call' instruction will execute multiple REST requests to load the individual pages. The response of each individual REST request will be stored as local action variables. For example, given a rest.call identifier 'x' the following local action variables will be set:

x: The processed response
x_raw: The raw, unprocessed response
x_exception: Java Exception instance if the request failed

These variables can be referenced only within the current 'rest.call' map entry, for example by 'log.progress', 'on.success', and 'records.for-each'. They are not accessible
by later steps or other map entries within the same 'rest.call' step. If you wish to make any data produced by the REST call available to later steps, you’ll need to use 'var.*' steps in either 'on.success' or 'records.for-each' instructions.

Note that multiple REST calls defined within a single 'rest.call' step will be executed in the specified order, but the requests are built independent of each other. As such, within a single 'rest.call' step, variables set by one 'rest.call' map entry cannot be accessed in the request definition (uri, query, body, …​) of another map entry. The reason is that for target systems that supports bulk requests (like SSC), multiple requests within a single 'rest.call' instruction may be combined into a single bulk request, so none of the REST responses will be available yet while building the bulk request. If you need to use the output from one REST call as input for another REST call, these REST calls should be defined in separate 'rest.call' steps.

Sample snippet

steps:
  - rest.call:
      pvs:                            # Name for this REST call for later reference
        target: ssc                   # Default configured through config::rest.target.default
        method: GET                   # Default: GET
        uri: /api/v1/projectVersions  # URI
        query:                        # Query string parameters
          fields: id,name,project     # May also use expressions
        type: paged                   # simple or paged
        records.for-each:             # Iterate through response records
          record.var-name: pv         # Variable name to hold current record
          embed:                      # For each record, embed data from other REST call
            artifacts:                # Accessible through ${pv.artifacts}
              uri: /api/v1/projectVersions/${pv.id}/artifacts
          do:
            - ...                     # Steps to execute for each response record

[step] run.fcli

[step] run.fcli - map<string,run.fcli>

Execute one or more fcli commands. This step takes a map, with map keys defining an identifier for the fcli invocation, and values defining the fcli command to run and how to process the output and exit code. The identifier can be used in later steps (or later fcli invocations in the same 'run.fcli' step) to access the output of the fcli command, like stdout, stderr, and exit code that were produced by the fcli command, depending on step configuration. For example,
given an fcli invocation identifier named 'x', the following action variables may be set:

x.records: Array of records produced by the fcli invocation if 'records.collect' is set to 'true'
x.stdout: Output produced on stdout by the fcli invocation if 'stdout' is set to 'collect'
x.stderr: Output produced on stderr by the fcli invocation if 'stderr' is set to 'collect'
x.exitCode: Exit code of the fcli invocation

The following action variables may also be set by this fcli step, but these are considered preview functionality and may be removed or renamed at any time. For now, these are meant to be used only by built-in fcli actions; custom actions using these action variables may fail to run on other fcli 3.x versions.

x.skipped: Boolean value indicating whether execution was skipped due to skip.if-reason configuration
x.skipReason: Reason why execution was skipped; will be null if x.skipped==true (deprecated; see x.statusReason)
x.status: Set to either SKIPPED (x.skipped==true), SUCCESS (x.exitCode==0), or FAILED (x.exitCode!=0)
x.statusReason: Reason why execution failed or was skipped; will be null if step was executed successfully
x.dependencySkipReason: Optional skip reason for steps that are dependent on this fcli invocation
x.success: Set to true if fcli invocation was successful, false if failed
x.failed: Set to true if fcli invocation failed, false if successfull

Sample snippets

steps:
  - run.fcli:
      list-av: fcli ssc av ls
steps:
  - run.fcli:
      avList:
        cmd: ssc av ls
        records.collect: true
  - log.debug: ${avList.records}
steps:
  - run.fcli:
      process-av:
        cmd: ssc av ls
        records.for-each:
          record.var-name: av
          do:
            - log.debug: ${av}

[step] out.write

[step] out.write - map<expression,value-fmt>

Write data to a file, stdout, or stderr. This step takes a map, with map keys defining the destination, and map values defining the data to write to the destination. Destination can be specified as either stdout, stderr, or a file name. If a file already exists, it will be overwritten. Note that depending on the config:output setting, data written to stdout or stderr may be shown either immediately, or only after all action steps have been executed, to not interfere with progress messages.

Map values may be specified as either an SpEL template expression, or as 'value' and 'fmt' properties. An 'if' property is also supported to conditionally write to the output. If formatter is specified, the given formatter from the 'formatters' section will be used to format the given value, or, if no value is given, the formatter will be evaluated against the set of all variables. Some examples:

/path/to/myFile1: Hello ${name}
/path/to/myFile2: {fmt: myFormatter, if: "${someExpression}"}
/path/to/myFile3: {value: "${myVar}", fmt: "${myVarFormatterExpression}"}

Sample snippet

steps:
  - out.write:
      ${cli.file}: {fmt: output}

[step] check

[step] check - map<string,check>

Mostly used for security policy and similar actions to define PASS/FAIL criteria. Upon action termination, check results will be written to console and return a non-zero exit code if the outcome of one or more checks was FAIL. This instructions takes a map, with keys defining the check name, and values defining the check definition. Current check status can be accessed through ${checkStatus.checkName}, for example allowing to conditionally execute additional checks based on earlier check outcome. Note that if the same check name (map key) is used in different 'check' steps, they will be treated as separate checks, and ${checkStatus.checkName} will contain the status of the last executed check for the given check name.

Sample snippet

steps:
  - check:
      MY_CHECK:
        failIf: ${condition}
        ifSkipped: PASS

[step] records.for-each

[step] records.for-each - for-each

Execute the steps defined in the 'do' block for every record provided by the 'from' expression.

Sample snippet

steps:
  - records.for-each:
      from: ${collection}
      record.var-name: currentRecord
      do:
        - log.debug: ${currentRecord}
        - ...

[step] with

[step] with - with

This step allows for running initialization and cleanup steps around the steps listed in the 'do' block. This includes the ability to run the do-block within the context of an fcli session, with the session being created before running the do-block and being terminated afterwards, and the ability to define writers than can output data in various formats like CSV, appending data to those writers in the do-block, and closing those writers once the steps in the do-block have completed. Compared to the 'out.write' instruction, these writers support more output formats, and, depending on writer type and configuration, allows for streaming output, rather than having to collect all data in memory first.

Sample snippets

steps:
  - with:
      sessions:
        - login: fcli fod session login ... --fod-session=myActionSession
          logout: fcli fod session logout --fod-session=myActionSession
    do:
      - run.fcli:
          myCmd: fcli fod ... --fod-session-myActionSession
steps:
  - with:
      writers:
        csvWriter:
          to: ${cli.file}
        type: csv
    do:
      - records.for-each:
          from: ${records}
          record.var-name: record
          do:
            - writer.append:
                csvWriter: ${record}

[step] writer.append

[step] writer.append - map<string,value-fmt>

This instruction may only be used from within a with:do, with the with:writers instruction defining the writers that the writer.append instruction can append data to. The given data will be formatted an written according to the corresponding writer configuration.

Sample snippet

steps:
  - with:
      writers:
        csvWriter: ...
    do:
      - writer.append:
          csvWriter: ${myCsvRecord}

[step] steps

[step] steps - array<step>

Sub-steps to be executed; useful for grouping or conditional execution of multiple steps.

Sample snippet

steps:
  - ...
  - if: ${condition}
    steps:
      - ... # One or more steps to execute if ${condition} evaluates to true

[step] throw

[step] throw - expression

Throw an exception, thereby terminating action execution.

Sample snippet

steps:
  - throw: ERROR: ${errorMessage}

[step] exit

[step] exit - expression

Terminate action execution and return the given exit code.

Sample snippet

steps:
  - if: ${someCondition}
    exit: 1

[step] if

[step] if - expression

Optional SpEL template expression: Only execute this instruction if the given if-expression evaluates to 'true'

YAML types

The sections below list the various YAML types supported by the current fcli (schema) version. Where applicable, the Type column provides links to other YAML types sub-sections that provide more details on the expected contents for each property type.

[type] check

Define a (policy) check to be evaluated.

Sample snippet

steps:
  - check:
      MY_CHECK:
        failIf: ${condition}
        ifSkipped: PASS

Supported properties

Property Type Description

display-name

string

Optional string: Display name of this check, to be displayed in PASS/FAIL messages. If not defined, the display name will be set to the map key under which this check is defined.

fail.if

expression

Either 'passIf' or 'failIf' must be defined, both taking an SpEL template expression that evaluates to 'true' or 'false'.

For 'passIf', the outcome of the check will be 'PASS' if the given expression evaluates to 'true', or 'FAIL' is the given expression evaluates to 'false'.

For 'failIf', the outcome of the check will be 'FAIL' if the given expression evaluates to 'true', or 'PASS' is the given expression evaluates to 'false'.

pass.if

expression

Either 'passIf' or 'failIf' must be defined, both taking an SpEL template expression that evaluates to 'true' or 'false'.

For 'passIf', the outcome of the check will be 'PASS' if the given expression evaluates to 'true', or 'FAIL' is the given expression evaluates to 'false'.

For 'failIf', the outcome of the check will be 'FAIL' if the given expression evaluates to 'true', or 'PASS' is the given expression evaluates to 'false'.

ifSkipped

enum

Optional enum value: Define the check result in case the check is being skipped due to conditional execution or no records to be processed in forEach blocks. Allowed values:
FAIL: Fail the check if it was not executed
PASS: Pass the check if it was not executed
SKIP: Report that the test was skipped
HIDE: Hide the check from output

if

expression

Optional SpEL template expression: Only execute this instruction if the given if-expression evaluates to 'true'

* Generated from com.fortify.cli.common.action.model.ActionStepCheckEntry

[type] cli.option

Define command-line options supported by this action.

Sample snippet

cli.options:
  file: # Can be referenced through ${cli.file} in action steps
    names: -f,--file
    description: Output file name
    required: false
    defaultValue: somefile.txt

Supported properties

Property Type Description

names

string

Required string: The option names allowed on the command line to specify a value for this option. Multi-letter option names should be preceded by double dashes like --option-name, single-letter option names should be preceded by a single dash like-o. Multiple option names may be separated by a comma and optional whitespace, for example:
options: --option, -o

description

string

Required string: Action parameter description to be shown in action usage help.

type

string

Optional string: Action parameter type: string (default), boolean, int, long, double, float, or array.

default

expression

Optional SpEL template expression: Default value for this CLI option if no value is specified by the user. For example, this can be used to read a default value from an environment variable using ${#env('ENV_NAME')}

required

boolean

Optional boolean: CLI options are required by default, unless this property is set to false.

mask

mask

Optional object: Mask option value in the fcli log file using the given mask configuration.

group

string

Optional string: Allows for defining groups of options, which can for example be used with ${#action.copyParametersFromGroup("optionGroupName")}

* Generated from com.fortify.cli.common.action.model.ActionCliOption

[type] config

Define configuration settings for this action.

Sample snippet

config:
  rest.target.default: fod
  output: immediate

Supported properties

Property Type Description

rest.target.default

string

Optional string: Default target to use for rest.call steps.

run.fcli.status.check.default

boolean

(PREVIEW) Optional boolean: Default value for 'status.check' in 'run.fcli' instructions.

For now, this instruction is meant to be used only by built-in fcli actions; custom actions using this instruction may fail to run on other fcli 3.x versions.

run.fcli.status.log.default

boolean

(PREVIEW) Optional boolean: Default value for 'status.log' in 'run.fcli' instructions.

For now, this instruction is meant to be used only by built-in fcli actions; custom actions using this instruction may fail to run on other fcli 3.x versions.

run.fcli.group.default

string

(PREVIEW) Optional string: Default value for 'group' in 'run.fcli' instructions.

For now, this instruction is meant to be used only by built-in fcli actions; custom actions using this instruction may fail to run on other fcli 3.x versions.

output

enum

Optional enum value: If set to 'delayed' (default), all output to stdout/stderr except for progress messages will be delayed until the end of action execution. If set to 'immediate', output will be written immediately and progress writer will be configured to 'simple' mode (unless '--progress=none' is specified by the user) to avoid such output from interfering with progress messages.

mask.env-vars

map<string,mask>

Optional map: Environment variables used by this action for which values should be masked in the fcli log file. Map keys define environment variables names, map values define masking configuration.

* Generated from com.fortify.cli.common.action.model.ActionConfig

[type] for-each

Repeat the steps listed in the do block for each record provided by the from instruction.

Sample snippet

steps:
  - records.for-each:
      from: ${collection}
      record.var-name: currentRecord
      do:
        - log.debug: ${currentRecord}
        - ...

Supported properties

Property Type Description

from

expression

Required SpEL template expression, evaluating to either an array of values to be iterated over, or an IActionStepForEachProcessor instance like returned by ${#ssc.ruleDescriptionsProcessor(appVersionId)}. For each of the records in the given array or as produced by the IActionStepForEachProcessor, the steps given in the 'do' instruction will be executed until the breakIf condition (is specified) evaluates to true. The steps in the 'do' instruction may reference the current record through the action variable name specified through 'record.var-name'.

record.var-name

string

Required string: Variable name to assign to each individual record being processed, allowing the record to be accessed by other instructions like 'if' or 'breakIf' and the steps defined in the 'do' block through the specified variable name.

do

array<step>

Required list: Steps to be executed for each individual record.

breakIf

expression

Optional SpEL template expression: Stop execution of the steps configured in the 'do' instruction if the breakIf expression evaluates to 'true'.

if

expression

Optional SpEL template expression: Only execute this instruction if the given if-expression evaluates to 'true'

* Generated from com.fortify.cli.common.action.model.ActionStepRecordsForEach

[type] mask

Define log masking settings.

Sample snippets

config:
  mask.env-vars:
    SOME_PASSWORD:
      sensitivity: high
cli.options:
  pwd:
    names: -p,--password
    mask: {sensitivity: high}

Supported properties

Property Type Description

sensitivity

enum

Optional enum value: Value sensitivity; high/medium/low. Default value: high

description

string

Optional string: Mask description, used to generate the masked output.

pattern

string

Optional string: Pattern for fine-tuning which value contents should be
masked. Every matching regex group will be masked using the given description.
If no pattern is defined, or if the pattern doesn’t contain any groups, the
full value will be masked.

* Generated from com.fortify.cli.common.action.model.ActionInputMask

[type] rest.call

Define a REST call, like request method, URI, …​

Sample snippet

steps:
  - rest.call:
      pvs:                            # Name for this REST call for later reference
        target: ssc                   # Default configured through config::rest.target.default
        method: GET                   # Default: GET
        uri: /api/v1/projectVersions  # URI
        query:                        # Query string parameters
          fields: id,name,project     # May also use expressions
        type: paged                   # simple or paged
        records.for-each:             # Iterate through response records
          record.var-name: pv         # Variable name to hold current record
          embed:                      # For each record, embed data from other REST call
            artifacts:                # Accessible through ${pv.artifacts}
              uri: /api/v1/projectVersions/${pv.id}/artifacts
          do:
            - ...                     # Steps to execute for each response record

Supported properties

Property Type Description

method

string

Optional string: HTTP method like GET or POST to use for this REST request. Defaults value: GET.

uri

expression

Required SpEL template expression: Unqualified REST URI, like '/api/v3/some/api/${var.id}' to be appended to the base URL provided by the given 'target'.

target

string

Required string if no default target has been configured through config:rest.target.default. Target on which to execute the REST request. Third-party request targets can be configured through 'rest.target' steps; such steps should appear before the 'rest.call' steps that reference these request targets. In additionan, fcli provides the 'fod' target for actions run through 'fcli fod action run', and the 'ssc', 'sc-sast', and 'sc-dast' targets for actions run through the 'fcli ssc action run' command. These fcli-provided targets integrate with fcli session management.

query

map<string,expression>

Optional map: Query parameters to be added to the request. Map keys specify the query parameter name, map values specify the query parameter value. Keys must be plain strings, values are evaluated as SpEL template expressions, for example 'someParam: ${var1.prop1]}'.

body

expression

Optional SpEL template expression: Request body to send with the REST request.

type

enum

Optional enum value: Flag to indicate whether this is a 'paged' or 'simple' request. If set to 'paged' (for now only supported for built-in request targets like 'fod' or 'ssc'), the request will be repeated with the appropriate paging request parameters to load and process all available pages. Defaults value: simple.

log.progress

rest.call-log.progress

Optional object: Log progress messages during the various stages of request/response processing.

on.success

array<step>

Optional list: Steps to be executed on each successfull REST response. For simple requests, these steps will be executed once. For paged requests, these steps will be executed after every individual page has been received. Steps can reference the [requestName] and [requestName]_raw variables to access processed and raw response data respectively. Any steps define in 'on.success' will be executed before processing individual response records through the 'records.for-each' instruction.

on.fail

array<step>

Optional list: Steps to be executed on request failure. If not specified, an exception will be thrown on request failure. Steps can reference a variable named after the identifier for this REST call, for example 'x_exception', to access the Java Exception object that represents the failure that occurred.

records.for-each

rest.call-for-each

Optional object: If the processed (successfull) REST response provides an array of records, this instruction allows for executing the steps provided in the 'do' block for each individual record.

if

expression

Optional SpEL template expression: Only execute this instruction if the given if-expression evaluates to 'true'

* Generated from com.fortify.cli.common.action.model.ActionStepRestCallEntry

[type] rest.call-for-each

Property Type Description

embed

map<string,rest.call>

Optional map: Allows for making additional REST calls for each individual record being processed. Map values define the REST call to be executed, map keys define under which property the response will be embedded into the variable specified through the 'set.record-var' instruction, with similar behavior as described for the rest.call step, i.e., processed data will be available through a property named after the map key, whereas raw response data will be available through a property named [map key]_raw.

record.var-name

string

Required string: Variable name to assign to each individual record being processed, allowing the record to be accessed by other instructions like 'if' or 'breakIf' and the steps defined in the 'do' block through the specified variable name.

do

array<step>

Required list: Steps to be executed for each individual record.

breakIf

expression

Optional SpEL template expression: Stop execution of the steps configured in the 'do' instruction if the breakIf expression evaluates to 'true'.

if

expression

Optional SpEL template expression: Only execute this instruction if the given if-expression evaluates to 'true'

* Generated from com.fortify.cli.common.action.model.ActionStepRestCallEntry$ActionStepRequestForEachResponseRecord

[type] rest.call-log.progress

Property Type Description

page.pre-load

expression

Optional SpEL template expression: Log a progress message before loading the next page.

page.post-load

expression

Optional SpEL template expression: Log a progress message after a page has been loaded.

page.post-process

expression

Optional SpEL template expression: Log a progress message after a page has been processed.

* Generated from com.fortify.cli.common.action.model.ActionStepRestCallEntry$ActionStepRestCallLogProgressDescriptor

[type] rest.target

Define a (third-party) REST target against which REST calls can be executed.

Sample snippet

steps:
  - rest.target:
      example:
        baseUrl: https://example.com/my-app
        headers:
          Authorization: ${exampleAuth}

Supported properties

Property Type Description

baseUrl

expression

Required SpEL template expression: Base URL to use for REST requests to this request target.

headers

map<string,expression>

Optional map(string,SpEL template expression): Headers to be sent to this request target on every request.

if

expression

Optional SpEL template expression: Only execute this instruction if the given if-expression evaluates to 'true'

* Generated from com.fortify.cli.common.action.model.ActionStepRestTargetEntry

[type] run.fcli

Define an fcli command to be (optionally) executed. This can be supplied as either a set of YAML properties or as a plain expression, in which case the expression outcome is interpreted as the fcli command to run, with default values for all other properties.

Sample snippets

steps:
  - run.fcli:
      list-av: fcli ssc av ls
steps:
  - run.fcli:
      avList:
        cmd: ssc av ls
        records.collect: true
  - log.debug: ${avList.records}
steps:
  - run.fcli:
      process-av:
        cmd: ssc av ls
        records.for-each:
          record.var-name: av
          do:
            - log.debug: ${av}

Supported properties

Property Type Description

skip.if-reason

array<expression>

(PREVIEW) Optional list of SpEL template expression: List entries define optional skip reasons; if any of the given expressions evaluates to a non-blank string, this fcli invocation will be skipped and the (first) non-blank skip reason will be logged.

For now, this instruction is meant to be used only by built-in fcli actions; custom actions using this instruction may fail to run on other fcli 3.x versions.

group

string

(PREVIEW) Optional string: Define a group name for this fcli invocation. If defined, the output variables for this fcli invocation will be added to an action variable named groupName.fcliIdentifier. For example, given fcli invocation identifiers (map keys) CMD1 and CMD2, both specifying 'group: myGroup', the myGroup.CMD1 action variable will contain the output variables (like skipped, exitCode, …​) for CMD1, and the myGroup.CMD2 action variable will contain the output variables for CMD2, independent of whether these fcli invocations were skipped, failed, or successful.

This can be used to iterate over all fcli invocations in a given group using
'records.for-each: from: ${#properties(myGroup)}', with the do-block for example referencing ${groupEntry.status}.

For now, this instruction is meant to be used only by built-in fcli actions; custom actions using this instruction may fail to run on other fcli 3.x versions.

cmd

expression

Required SpEL template expression: The fcli command to run. This can be specified with or without the 'fcli' command itself. Some examples:

ssc appversion get --av ${av.id} --embed=attrValuesByName

fcli fod rel ls

stdout

enum

Optional enum value: Specify how to handle output written to stdout by this fcli command:

suppress: Suppress fcli output to stdout
collect: Collect stdout output in an action variable, for example x.stdout
show: Show fcli stdout output

Note that depending on the config:output setting, 'show' will either show the output immediately, or output is delayed until action processing has completed.

Default: 'suppress' if output is being processed through another instruction ('records.for-each', 'records.collect', 'stdout.parser'), 'show' otherwise.

stderr

enum

Optional enum value: Specify how to handle output written to stderr by this fcli command:

suppress: Suppress fcli output to stderr
collect: Collect stderr output in an action variable, for example x.stderr
show: Show fcli stderr output

Note that depending on the config:output setting, 'show' will either show the output immediately, or output is delayed until action processing has completed.

Default value: 'show'

on.success

array<step>

Optional list: Steps to be executed if the fcli command was completed successfully. Steps can reference the usual action variables generated by the fcli invocation to access any records, stdout/stderr output, and exit code produced by the fcli command.

on.fail

array<step>

Optional list: Steps to be executed if the fcli command returns a non-zero exit code. If not specified, an exception will be thrown and action execution will terminate if the fcli command returned a non-zero exit code, unless 'status' is configured to ignore exit status. Steps can reference the usual action variables generated by the fcli invocation to access any records, stdout/stderr output, and exit code produced by the fcli command.

status.check

boolean

(PREVIEW) Optional boolean value, indicating whether exit status of the fcli command should be checked:

true: Terminate action execution if the fcli command returned a non-zero exit code
false: Continue action execution if the fcli command returned a non-zero exit code

Default value is taken from 'config:run.fcli.status.status.check.default'. If not specified, default value is 'false' if 'on.fail' is specified, 'true' otherwise.

For now, this instruction is meant to be used only by built-in fcli actions; custom actions using this instruction may fail to run on other fcli 3.x versions.

status.log

boolean

(PREVIEW) Optional boolean value, indicating whether exit status of the fcli command should be logged:

true: Output an informational message showing exit status
false: Don’t output an informational message showing exit status

Default value is taken from 'config:run.fcli.status.status.log.default'. If not specified, default value is 'false'.

For now, this instruction is meant to be used only by built-in fcli actions; custom actions using this instruction may fail to run on other fcli 3.x versions.

records.collect

boolean

Optional boolean: If set to 'true', records produced by this fcli command will be collected and accessible through an action variable named after the 'run.fcli' identifier/map key.

records.for-each

run.fcli-for-each

Optional object: For fcli commands that produce records, this allows for running the steps specified in the 'do' instruction for each individual record.

if

expression

Optional SpEL template expression: Only execute this instruction if the given if-expression evaluates to 'true'

* Generated from com.fortify.cli.common.action.model.ActionStepRunFcliEntry

[type] run.fcli-for-each

Property Type Description

record.var-name

string

Required string: Variable name to assign to each individual record being processed, allowing the record to be accessed by other instructions like 'if' or 'breakIf' and the steps defined in the 'do' block through the specified variable name.

do

array<step>

Required list: Steps to be executed for each individual record.

breakIf

expression

Optional SpEL template expression: Stop execution of the steps configured in the 'do' instruction if the breakIf expression evaluates to 'true'.

if

expression

Optional SpEL template expression: Only execute this instruction if the given if-expression evaluates to 'true'

* Generated from com.fortify.cli.common.action.model.ActionStepRunFcliEntry$ActionStepFcliForEachDescriptor

[type] usage

Define action usage help.

Sample snippet

usage:
  header: My action summary
  description: |
    Lorem ipsum dolor sit amet consectetur adipiscing elit. Consectetur adipiscing elit quisque
    faucibus ex sapien vitae. Ex sapien vitae pellentesque sem placerat in id. Placerat in id
    cursus mi pretium tellus duis. Pretium tellus duis convallis tempus leo eu aenean.

Supported properties

Property Type Description

header

string

Required string: Action usage header, displayed in list and help outputs

description

expression

Required SpEL template expression: Action usage description, displayed in help output and online documentation. The template expression can reference the 'isAsciiDoc' and 'isPlainText' properties to determine whether the contents are to be rendered as AsciiDoc (for online documentation) or plain text (for help output). For internal use only, the template expression can utilize the '#include('path/to/classpath/resource') function to include contents of a class path resource.

* Generated from com.fortify.cli.common.action.model.ActionUsage

[type] value-fmt

Define a value that is optionally formatted or generated by a given formatter. This can be supplied as either a set of YAML properties or as a simple (string, boolean, …​) value, in which case the simple value is used to set the 'value' property.

Sample snippet

steps:
  - var.set: # Variable values demonstrate how 'value-fmt' may be specified
    var1: 'xyz'       # Plain string, without formatter
    var2: true        # Plain boolean, without formatter
    var3: ${expr}     # Plain expression, without formatter
    var4: {fmt:myFmt} # Only formatter, allowing formatter to reference all variables
    var5:             # Same as var4, but expanded YAML syntax
      fmt: myFmt
    var6:             # Use the outcome of ${expr} as input for myFmt
      fmt:   myFmt
      value: ${expr}

Supported properties

Property Type Description

value

expression

The optional value to use for this instruction, may be specified as an SpEL template expression. If value is specified without formatter, the value will be used as-is.

fmt

expression

The optional formatter (as defined through the top-level 'formatters' instruction) to use
for this instruction, may be specified as an SpEL template expression. If 'value' is specified, the given value will be provided as input for the formatter. If 'value' is not specified, the set of current action variables will be provided as input for the formatter.

if

expression

Optional SpEL template expression: Only execute this instruction if the given if-expression evaluates to 'true'

* Generated from com.fortify.cli.common.action.model.TemplateExpressionWithFormatter

[type] with

Run the steps in the do block within the context of one or more writers or sessions.

Sample snippets

steps:
  - with:
      sessions:
        - login: fcli fod session login ... --fod-session=myActionSession
          logout: fcli fod session logout --fod-session=myActionSession
    do:
      - run.fcli:
          myCmd: fcli fod ... --fod-session-myActionSession
steps:
  - with:
      writers:
        csvWriter:
          to: ${cli.file}
        type: csv
    do:
      - records.for-each:
          from: ${records}
          record.var-name: record
          do:
            - writer.append:
                csvWriter: ${record}

Supported properties

Property Type Description

sessions

array<with-session>

This instruction allows for setting up one or more sessions before running the steps specified in the do-block, and logging out of those sessions once the steps in the do-block have completed wither successfully or with failure.

Note that for now, these sessions can only be referenced by explicitly specifying the --session option on 'run.fcli' instructions. The 'rest.call' instructions and any SpEL functions that are dependent on an fcli session will use the session that was specified through the --session option on the 'fcli * action run' command; they will ignore sessions created through the 'with:session' instruction.

writers

map<string,with-writer>

This instruction allows for setting up one or more record writers that can referenced by writer.append steps in the associated do-block. After all steps in the do-block have been executed, the writer will be closed. This instruction takes a map, with map keys defining writer identifiers, and map values defining the writer configurations. The number of records that have been appended to the current writer can be accessed through the 'writerId.count' variable.

do

array<step>

Required list of steps to be run within the context of the given configuration.

if

expression

Optional SpEL template expression: Only execute this instruction if the given if-expression evaluates to 'true'

* Generated from com.fortify.cli.common.action.model.ActionStepWith

[type] with-session

Define session login and logout commands, respectively executed before and after the steps listed in the do block.

Sample snippet

steps:
  - with:
      sessions:
        - login: fcli fod session login ... --fod-session=myActionSession
          logout: fcli fod session logout --fod-session=myActionSession
    do:
      - run.fcli:
          myCmd: fcli fod ... --fod-session-myActionSession

Supported properties

Property Type Description

login

expression

Required SpEL template expression; the session login command to run before running the steps specified in the do-block.

logout

expression

Required SpEL template expression; the session logout command to run after the steps in the do-block have been completed either successfully or with failure.

if

expression

Optional SpEL template expression: Only execute this instruction if the given if-expression evaluates to 'true'

* Generated from com.fortify.cli.common.action.model.ActionStepWithSession

[type] with-writer

Define a writer that can be referenced by steps in the do block, automatically closing the writer once the steps in the do block have completed.

Sample snippet

steps:
  - with:
      writers:
        csvWriter:
          to: ${cli.file}
        type: csv
    do:
      - records.for-each:
          from: ${records}
          record.var-name: record
          do:
            - writer.append:
                csvWriter: ${record}

Supported properties

Property Type Description

to

expression

Required SpEL template expression; destination where to write the output of this writer. Destination can be specified as one of the following:

- A file name to write the output to
- 'stdout' to write the output to stdout
- 'stderr' to write the output to stderr
- 'var:varName' to write the output as text into the given 'varName' action variable

With 'var:varName', the given variable name will be available to steps after the current 'with' block has completed.

type

expression

Required SpEL template expression defining the writer type. The evaluated expression must evaluate to one of the following types:
csv, table, expr, json, xml, yaml

type-args

expression

Optional SpEL template expression defining arguments for the given writer type. In most cases, it’s much easier to just pass an already formatted object to the 'writer.append' step; this 'type-args' instruction is just meant to provide feature parity with the fcli '--output type=args' command line option. See fcli documentation for details on supported options for the various writer types.

style

expression

Optional SpEL template expression defining the writer style. If specified, the expression should evaluate to a comma-separated list of style elements to be applied to the output. Supported style elements:
header, no-header, pretty, no-pretty, flat, no-flat, array, single, border, no-border, md-border

if

expression

Optional SpEL template expression: Only execute this instruction if the given if-expression evaluates to 'true'

* Generated from com.fortify.cli.common.action.model.ActionStepWithWriter

Expressions

As shown in the sections above, fcli actions make extensive use of expressions. The following sections provide mode details on expression syntax.

Expression Syntax

Expressions may contain a combination of literal text and evaluation blocks, with the latter being surrounded by ${ and }. Some examples:

  • Plain text: Hello stranger, welcome!

  • Evaluation block: ${welcomeMessage}

  • Combination: Hello ${name}, welcome!

Evaluation blocks may be simple references to action variables that were previously set through a var.set step, or can be complex code blocks that utilize Spring Expression Language (SpEL), possibly combined with fcli-provided SpEL functions.

SpEL Functions

Fcli provides many functions that can be invoked from expressions. Function calls are identified by the # sign, for example:

${#join(' ', records}

Caution
Until SpEL functions have been documented and categorized based on stability & intended use (stable, unstable, preview, internal-use, …​), there’s no guarantee on the stability of SpEL functions; we may add, remove, or change SpEL functions between fcli releases without any notification, potentially causing errors or failures when running an fcli custom action on a different fcli version.

Later versions of this documentation may add an overview of fcli-provided SpEL functions that can be used in SpEL expressions. Until then, to see what SpEL functions are available in the current fcli version, you can either: