Introduction

The fcli utility can be used to interact with various Fortify products, like Fortify on Demand (FoD), Software Security Center (SSC), ScanCentral SAST and ScanCentral DAST. This document describes installation and general usage of fcli. For a full listing of fcli commands and corresponding command line options, please see the man-pages as listed in the Manual Pages section.

Some of the fcli highlights:

The following Fortify products are currently supported by fcli:

  • Software Security Center (SSC)

    • Includes virtually all functionality provided by the legacy FortifyClient utility

    • Includes virtually all functionality provided by the ssc-client sample shipped with SSC

    • Adds a wide range of other functionalities not previously included in any Fortify client-side utilities

  • ScanCentral SAST

    • Support for starting and managing ScanCentral SAST scans

  • ScanCentral DAST

    • Support for starting and managing ScanCentral DAST scans

    • Support for listing scan policies and settings

    • Support for listing and managing sensors

  • Fortify on Demand (FoD)

    • Support for creating and managing applications, microservices and releases

    • Support for starting and managing SAST & OSS scans

    • Support for importing/downloading SAST/DAST/MAST & OSS results

    • Partial/preview support for starting and managing DAST & MAST scans

    • Partial/preview support for managing users, groups and their assignments

Some commands and options are either hidden or marked as PREVIEW or LEGACY; these may change at any time, even between minor fcli versions. Any fcli invocations using these commands or options may break when upgrading to a future fcli 2.x version, so if possible you should refrain from using these in pipelines for example. Most notably, this includes the following functionalities:

  • Commands for configuring and running FoD DAST & MAST scans will change significantly, based on upcoming FoD API changes & improvements

Hidden commands are not listed in fcli help output and not included in the Manual Pages. If needed, you can view the list of hidden commands using the fcli util all-commands list -q hidden command.

Release Assets

Release assets for fcli are available on the Releases page. This page lists both development releases (named Development Release - <branch> branch) and final releases. In general, the use of a final release is recommended, unless you want to use any functionality that hasn’t made it into a final release yet.

Each release comes with a list of assets:

  • docs-html.zip & docs-manpage.zip: Manual pages in either HTML or manpage format

  • fcli-linux.tgz, fcli-mac.tgz & fcli-windows.zip: Native binaries for each of the mentioned platforms

    • Note that some browsers by default will disallow downloading of fcli-windows.zip; please bypass the warning

    • Linux and Mac downloads include an auto-completion script that makes interactive fcli usage easier

  • fcli.jar: Java version of fcli, which should be runnable on any platform that has Java 17+ installed

    • Note that in general, the native binaries are easier to invoke, offer better performance, and have the benefit of auto-completion capabilities on Linux & Mac

    • If you experience any unexpected behavior with native binaries, like commands or command line options not being listed or recognized, or technical error messages about methods, constructors or serializers not being found, please try with the Java version as it may be an issue specific to the native binaries. See the Troubleshooting section for details.

  • fcli-thirdparty.zip: Third-party licenses and sources for license purposes; usually no need to download

  • LICENSE.TXT & README.md: Some generic information and license for fcli

  • *.sha256: SHA256 checksum for each asset

  • *.rsa_sha256: RSA SHA256 signature for each asset, to be verified using this public key

Please note that when publishing a new release, it may take up to 30-60 minutes before release assets are posted. If the latest release doesn’t show any of the assets listed above, please check again in 30-60 minutes. If you encounter a release without these assets after waiting for 60 minutes, please consider submitting an issue on the fcli issue tracker.

Installation

To install fcli, start by visiting the fcli Releases page as described in the previous section, and downloading the fcli.jar file or appropriate native binary archive for your platform. Native binary archives will need to be extracted to a temporary directory, the fcli.jar file can be used as-is.

As a best practice, you should verify the integrity of the downloaded file. Release assets include *.sha256 and *.rsa_sha256 for this purpose, with the latter being preferred for better security. For example, after downloading both fcli-linux.tgz and fcli-linux.tgz.rsa_sha256, you can verify integrity by running the following OpenSSL command:

  openssl dgst -sha256 -verify <(echo "-----BEGIN PUBLIC KEY-----
  MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArij9U9yJVNc53oEMFWYp
  NrXUG1UoRZseDh/p34q1uywD70RGKKWZvXIcUAZZwbZtCu4i0UzsrKRJeUwqanbc
  woJvYanp6lc3DccXUN1w1Y0WOHOaBxiiK3B1TtEIH1cK/X+ZzazPG5nX7TSGh8Tp
  /uxQzUFli2mDVLqaP62/fB9uJ2joX9Gtw8sZfuPGNMRoc8IdhjagbFkhFT7WCZnk
  FH/4Co007lmXLAe12lQQqR/pOTeHJv1sfda1xaHtj4/Tcrq04Kx0ZmGAd5D9lA92
  8pdBbzoe/mI5/Sk+nIY3AHkLXB9YAaKJf//Wb1yiP1/hchtVkfXyIaGM+cVyn7AN
  VQIDAQAB
  -----END PUBLIC KEY-----") -signature "fcli-linux.tgz.rsa_sha256" "fcli-linux.tgz"

If your shell doesn’t support <(...) syntax, you’ll need to save the public key to a file and pass the file name to the -verify command line option, for example:

  openssl dgst -sha256 -verify pubkey.pem -signature "fcli-linux.tgz.rsa_sha256" "fcli-linux.tgz"

Once downloaded, verified and extracted (if applicable), you can either perform a manual or managed installation. Managed installation is recommended, but only available on internet-connected systems. Please see the sections below for more information.

Managed Installation

Managed installation is only available on internet-connected systems, or if your company hosts the various Fortify tools (including fcli) internally and provides a corresponding custom tool definitions bundle. Advantages of a managed installation:

  • Both fcli and other tools installed using fcli tool commands will be hosted under a single base directory

  • This base directory will contain a single bin directory that can be added to your PATH for easy invocation of all tools installed through fcli

  • The fcli tool fcli list command can be used to list both installed and available fcli versions

  • The fcli tool fcli install command can be used to easily upgrade the current fcli version

The steps below describe how to perform a managed fcli installation. The syntax for invoking the various commands depends on the fcli variant that you downloaded. If you downloaded fcli.jar, fcli can be invoked using java -jar /path/to/fcli.jar. If you downloaded a native binary, fcli can be invoked using /path/to/fcli (Linux/Mac) or C:\path\to\fcli.exe (Windows). Any use of fcli in the commands below should be replaced by the appropriate command for invoking fcli on your system.

  • If necessary, configure fcli proxy settings:

    • View usage information:
      fcli config proxy add -h

    • Configure proxy settings:
      fcli config proxy add [options]

    • For example:
      fcli config proxy add myproxy:8080 -u<proxy user> -p<proxy password>

  • Update tool definitions to make fcli aware of latest tool releases:

    • View usage information:
      fcli tool definitions update -h

    • Update with default Fortify tool definitions:
      fcli tool definitions update

    • Update with company-provided tool definitions:
      fcli tool definitions update --source <tool-definitions-source>

  • Install the latest available fcli version:

    • View usage information:
      fcli tool fcli install -h

    • View available fcli versions:
      fcli tool fcli list

    • Install the latest available fcli version to the default base directory:
      fcli tool fcli install -v latest

  • Add the global Fortify tools bin directory to your PATH environment variable, for example in the Windows User or System Environment variables, or in your .bashrc or .profile file.

    • Unless --base-dir is specified on the fcli tool fcli install command, the Fortify tools global bin directory defaults to <user.home>/fortify/tools/bin.

  • Linux/Mac only: Run the following command to install fcli auto command completion, allowing for use of the <tab> key to get suggestions for fcli command and option names. You may want to add this to your shell startup script like .bashrc, such that fcli auto-completion is readily available in every shell.
    source <user.home>/fortify/tools/bin/fcli_completion

Manual Installation

  • Copy the fcli.jar file or the extracted native binaries to a directory of your choosing.

  • If using fcli.jar, create a simple wrapper script/batch file that invokes java -jar /path/to/fcli.jar, passing all the script arguments to this Java command.

  • For ease of use, add the directory to your operating system or shell PATH environment variable, or move fcli/fcli.exe/wrapper script to a directory that is already on the PATH

  • Linux/Mac only: Run the following command to install fcli auto command completion, allowing for use of the <tab> to get suggestions for fcli command and option names. You may want to add this to your shell startup script, such that fcli auto-completion is readily available in every shell.
    source <extraction-dir>/fcli_completion

Upgrade

If you prefer a manual installation/upgrade, you can download the latest fcli version for your platform from the fcli Releases page and follow the Manual Installation instructions above, adjusting any manually created wrapper scripts to point to the new installation.

However, on internet-connected systems, or if your company hosts the various Fortify tools (including fcli) internally and provides a corresponding custom tool definitions bundle, the preferred upgrade approach is through the use of fcli commands as described below.

Notes:

  • These steps assume that all other steps from the Managed Installation instructions have already been performed during initial installation, like configuring a proxy server if applicable, and adding the global bin directory to your PATH.

  • If the requested version has already been installed, it will be used as-is; only post-installation tasks like replacing the global bin-script(s) will be performed.

  • Similar steps apply for upgrading any of the Fortify-related tools installed through the various fcli tool * install commands.

Upgrade steps:

  • Update tool definitions to make fcli aware of latest tool releases:

    • Update with default Fortify tool definitions:
      fcli tool definitions update

    • Update with company-provided tool definitions:
      fcli tool definitions update --source <tool-definitions-source>

  • Upgrade fcli

    • Install latest version, removing all previous (managed) fcli installations:
      fcli tool fcli install -v latest --uninstall all

    • Install latest 2.x.y version, removing all previous 2.x.y installations but keeping any 1.x.y installations:
      fcli tool fcli install -v 2 --uninstall 2

  • Re-source the fcli_completion script if applicable on your platform

Command Structure

Fcli provides a product-oriented command structure, with each product represented by a separate tree of subcommands. For example, the fcli fod command tree can be used to interact with Fortify on Demand (FoD), and the fcli ssc command tree can be used to interact with Fortify Software Security Center (SSC). There are also some non product-related command trees, like the fcli config command tree to manage fcli configuration.

To see what top-level fcli commands are available, you can use the fcli --help command. You can drill down into the command tree to see what sub-commands are available within a particular parent command, for example by running fcli ssc --help to see all fcli ssc sub-commands, or fcli ssc session --help to see all SSC session management commands.

Note that the --help option must be specified after the sub-command for which you want view usage instructions, i.e. fcli ssc --help and not fcli --help ssc. A listing of all available fcli commands can be viewed using the fcli util all-commands list command.

If you don’t have fcli up and running yet, you can also refer to the downloadable or online manual pages; refer to the Manual Pages section for more information.

Common Options

The following sections describe common options that are available on (most) fcli commands.

-h | --help

This option can be used on every fcli (sub-)command to view usage information for that command. Usage information usually shows the command synopsis, a description of the functionality provided by the command, and a description of each command line option or parameter accepted by the command.

--env-prefix

As described in the Environment Variables section, default option and parameter values can be retrieved from environment variables starting with FCLI_DEFAULT. This option allows for configuring a different environment variable prefix. This may be useful if, for example, you want to login to multiple instances of the same system using environment variables. For example, when running fcli ssc session login --env-prefix PROD, fcli will look for environment variables like PROD_SSC_URL instead of FCLI_DEFAULT_SSC_URL.

Note that a default value for the --env-prefix option itself can be specified through an FCLI_DEFAULT_ENV_PREFIX environment variable, for example if you want to globally override the FCLI_DEFAULT prefix.

--log-level

This option can be used on every fcli (sub-)command to specify the fcli log level; see the help output for a list of allowed levels. Note that this option also requires the --log-file option to be specified, otherwise no log will be written.

--log-file

This option can be used on every fcli (sub-)command to specify the file to which to output log data. If not specified, currently no log data will be written, although future versions may specify a default log file location in the fcli data folder.

-o | --output

Available on virtually all (leaf) commands that output data, this option can be used to specify the output format. Fcli supports a wide variety of output formats, like table, csv, json, xml, and tree formats, allowing for both human-readable output or output suitable for automations. The csv-plain and table-plain output formats produce CSV or table output without headers. The *-flat output formats produce a flattened view of the output data, potentially making it easier to process that data without having to navigate through an object tree. For a full list of output formats supported by your fcli version, please refer to the help output or Manual Pages.

Most output formats allow for specifying the JSON properties to be included in the output, for example -o csv=id,name. If no JSON properties are specified, most output formats will output all available JSON properties, except for table output, which usually outputs a predefined set of JSON properties.

There are two output formats that are somewhat special:

  • -o 'expr=Text with {expression1} or {expression2}\n'
    Formats the output data based on the given template expression, which is a combination of (optional) plain text and SpEL expressions; see Option Expressions for details. In most cases, expressions will be simple property references, i.e., {property.subProperty}. This can be used for a variety of purposes, for example generating output in a human-readable format, or for generating a list of commands to be run at a later stage. Note that by default, no newline character will be inserted after evaluating the given expression. If necessary, the expression should explicitly include \n to output a newline character. Also note that depending on your shell, the expr option must be properly quoted. For most shells, the expr=... value should be enclosed in single or double quotes. To demonstrate the power of this output format, following are two examples of how -o expr can be used to generate a script that purges all application versions matching certain criteria:

    • fcli ssc appversion list -q 'createdBy=="admin"' -o 'expr=fcli ssc appversion purge-artifacts --older-than 30d {id}\n'

    • for id in $(fcli ssc appversion list -q 'createdBy=="admin"' -o 'expr={id} '); do echo "fcli ssc appversion purge-artifacts –older-than 30d ${id}'"; done

  • -o json-properties
    List all JSON properties returned by the current command, which can be used on options that take JSON properties as input, like output expressions (-o expr={prop}), properties to include in the output (-o table=prop1,prop2), queries (-q 'prop1=="value1"'), and fcli variables (--store var:prop1,prop2 & ::var::prop1}). Two important notes about this output format:

    • The command will be executed as specified, so be careful when using this output option on any command that changes state (delete/update/create/…). In most cases, the get or list operations will return a similar set of properties, so you can use those commands to view available properties.

    • On some commands, the list of available JSON properties may vary depending on command line options. For example, when a query returns no records, then -o json-properties will not output any properties. Likewise, a command may provide options for including additional data for each record; the corresponding JSON properties will only be shown if -o json-properties is used in combination with these options that load additional data.

--output-to-file

Available on virtually all (leaf) commands that output data, this option can be used to write the command output data to a file, in the format specified by the --output option listed above. In some cases, this may be more convenient than redirecting the output to a file. For example, although currently not implemented, fcli could potentially skip creating the output file if there is no output data or if an error occurs. Also, for commands that output status updates, like wait-for commands, the --output-to-file option allows for status updates to be written to standard output while the final output of the command will be written to the file specified.

--progress

Various commands offer a --progress option to specify how to output progress messages. This option supports the following values:

  • auto: Automatically select between ansi, single-line and simple depending on console capabilities.

  • none: Don’t output any progress messages.

  • simple: Output every progress message on a separate line, effectively leaving older progress messages visible. This will be used by default if no console is available, for example during pipeline runs. Supports multi-line progress messages.

  • single-line: Uses the \r (carriage return) character to overwrite previous progress message. This will be used by default if a non-ANSI console is detected. Supports single-line progress messages only.

  • ansi: Uses ANSI escape sequences to overwrite previous progress messages. This will be used by default if ANSI capabilities are detected. Supports multi-line progress messages.

--store

Available on virtually all (leaf) commands that output data, this option can be used to store command output data in an fcli variable. For more details, see the Fcli Variables section.

-q | --query

Available on most list commands and some other commands, this option allows for querying the output data, outputting only records that match the given Spring Expression Language (SpEL) expression. See the Option Expressions section for details.

Expressions are evaluated on individual records; record properties can be accessed as shown in the SpEL documentation. The list of properties that can be queried can be obtained by executing the current command with the -o json-properties option; see -o | –output for details.

Following are some examples using bash syntax, assuming the record contains p1, p2, …​ properties:

  • -q 'p1=="v1"'
    Only output records if the value of property p1 equals v1

  • -q 'p1=="v1" || p1=="v2"'
    Only output records if the value of property p1 equals either v1 or v2

  • -q '{"v1","v2"}.contains(p1)'
    Same as previous, but more concise if matching against many different values

  • -q 'name matches "val1|val2"'
    Similar as above, but using regex-based OR matching

  • -q 'p2==25 || p2<5'
    Only output records if the value of property p2 either equals 25 or is less than 5

  • -q 'p1=="v1" && (p2=="v2" || p3=="v2")'
    Only output records if the value of property p1 equals v1 and the value of either property p2 or p3 is v2

  • fcli ssc artifact list --appversion MyApp:main -q 'scanTypes matches "\bSCA\b"'
    Only output artifacts containing a Fortify SCA scan (matching the whole word SCA against scanTypes property)

  • fcli ssc artifact list --appversion MyApp:main -q '_embed.scans.![buildLabel].contains("myLabel")'
    Only output artifacts for which any of the scans included in the artifact has a buildLabel that equals myLabel

  • fcli ssc artifact list --appversion MyApp:main -q '#now("-90d") < #date(uploadDate)'
    Only output artifacts that were uploaded less than 90 days ago.

Server-side queries

In general, queries specified using the -q / --query option are evaluated on the client. Some commands will analyze the given query and generate corresponding server-side query parameters to minimize the amount of data that needs to be transferred from server to client. Generated queries can be viewed in the log file if --log-level is set to DEBUG level.

All commands that automatically generate server-side queries also provide a dedicated option for overriding the automatically generated server-side query, for example to further optimize the query or in case the automatically generated query is causing any issues. Following bullet points provide details on server-side queries for the various product modules:

  • FoD:
    All commands that automatically generate server-side queries provide the --filters-param option to override the automatically generated query. Server-side queries are automatically generated for the following SpEL expressions:

    • prop1=='value' (simple equals expressions)

    • prop1=='val1' || prop1=='val2' (or-expressions on a single property)

    • {'value1','value2'}.contains(prop1) (or-expression on a single property)

    • prop1 matches 'literalValue1|literalValue2' (or-expression on a single property)

    • prop1=='value' && prop2 matches 'val1|val2' (and-expression containing any of the above)

  • ScanCentral SAST:
    No server-side queries are automatically being generated.

  • ScanCentral DAST:
    No server-side queries are automatically being generated. Some commands provide the --server-query option to explicitly pass query parameters to the server.

  • SSC:
    All commands that automatically generate server-side queries provide the --q-param option to override the automatically generated query. Server-side queries are automatically generated for the following SpEL expressions:

    • prop1=='value' (simple equals expressions)

    • prop1=='value' && prop2=='val2' (and-expression containing simple equals expressions)

--session

Available on virtually all commands that interact with a target system, this option allows for specifying a session name. For more details, see the Session Management section.

Option Expressions

Various fcli options take either plain expressions, like -q | --query, or template expressions (plain text combined with expressions embedded between curly braces), like -o | –output expr=…​. These expressions use Spring Expression Language (SpEL); general information on syntax, supported operators and more can be found in the SpEL Documentation.

When evaluating expressions, fcli configures SpEL for 'data binding and condition evaluation', meaning that not all SpEL features are available. In particular, query expressions cannot invoke constructors nor static methods, and write access is mostly disabled. Attempts to access non-existing JSON properties will result in an error, which, although uncommon, may be an issue if the server doesn’t consistently return all expected properties. You’ll need to explicitly check for property existence in such cases, for example:

  • Top-level properties:
    fcli ... list -q '(has("property2") && property2=="value2")'

  • Nested properties:
    fcli ... list -q 'nestedObject!=null && get("nestedObject").has("stringValue") && nestedObject.stringValue=="nestedObjectValue1"'

  • Nested array properties:
    fcli ... list -q 'nestedObjectArray !=null && !(nestedObjectArray.isEmpty()) && get("nestedObjectArray").get(0).has("stringValue") && nestedObjectArray.get(0).stringValue=="nestedArrayValue1"'

Some SpEL operators like matches may throw an exception if any of the operands is null. For example, the following will result in an error if the prop1 propery is null for any of the records returned by the list command:

  • fcli ... list -q 'prop1 matches "value1|value2"'

Such errors can be avoided using one of the following approaches:

  • Rewrite the expression to not use the matches operator, for example:
    fcli ... list -q '{"value1","value2"}.contains(prop1)'

  • Add null-check (include all records for which prop is null):
    fcli ... list -q 'prop1==null || prop1 matches "value1|value2"'

  • Add null-check (exclude all records for which prop is null):
    fcli ... list -q 'prop1!=null && prop1 matches "value1|value2"'

Fcli provides some utility functions that may be used in expressions. Note that these functions calls are preceded by a # character.

  • #date(string): Convert the given date/time in string format to a proper date/time representation, allowing for date/time-based comparison operations. This can be used on property references or literal strings.

  • #now(): Get the current date/time, allowing for date/time-based comparison operations.

  • #now(period): Get the current date/time plus or minus the given period. The given period must start with either a + or -, followed by a number and the time unit. Some examples: -90d (now minus 90 days), +15m (now plus 15 minutes) and -90s (now minus 90 seconds).

  • #var(name): Get fcli variable contents; variable properties can be accessed as usual, i.e. #var("myVar")?.rootProp?.subProp.

  • #env(name): Get the value of an environment variable.

Note that for date comparisons, both sides of the comparison operator need to be explicitly defined as date/time objects. For example:

  • Invalid comparison: #date(myprop) < '2023-01-01'

  • Valid comparison: #date(myprop) < #date('2023-01-01')

  • Valid comparison: #date(myprop) < #now('-90d')

SpEL expressions may contain various characters that will be interpreted by some shells, like the # character for calling functions, and either single or double quotes around literal string values. As such, with most shells you should enclose the full expression in single or double quotes, and use the other quotes in the expression, for example:

  • -q '... "literal SpEL string" ...' (single quotes for shell, double quotes for SpEL literals)

  • -q "... 'literal SpEL string' ..." (double quotes for shell, single quotes for SpEL literals)

Which one to choose depends on any other characters appearing in the expression. For example, in bash you’d usually use single quotes to have everything in-between passed to fcli as-is, unless you want to use specific shell features inside the expression. Note that you can use the #env function to retrieve environment variable contents, so you don’t need to use shell syntax to insert environment variable contents into expressions.

Session Management

Most fcli product modules are session-based, meaning that you need to run a session login command before you can use most of the other commands provided by a product module, and run a session logout command when finished, for example:

fcli ssc session login --url https://my.ssc.org/ssc --user <user> --password <password>
fcli ssc appversion list
fcli ssc session logout --user <user> --password <password>

For interactive use, you can choose to keep the session open until it expires (expiration period depends on target system and login method). For pipeline use or other automation scenarios, it is highly recommended to issue a session logout command when no further interaction with the target system is required, to allow for any client-side and server-side cleanup to be performed.

For example, upon logging in to SSC with user credentials, fcli will generate a UnifiedLoginToken, which will be invalidated when the ssc session logout is being run. If you have many (frequently executed) pipelines that interact with SSC, and you don’t run the ssc session logout command when the pipeline finishes, you risk exhausting SSC’s limit on active tokens. In addition, the logout commands will perform client-side cleanup, like removing session details like URL and authentication tokens from the client system.

For product modules that support it, like SSC or ScanCentral DAST, it is also highly recommended to use token-based authentication rather than username/password-based authentication when incorporating fcli into pipelines or other automation tasks. This will avoid creation of a temporary token as described above, but also allows for better access control based on token permissions. Similarly, for systems that support Personal Access tokens, like FoD, it is highly recommended to utilize a Personal Access Token rather than user password.

Note however that depending on (personal access) token permissions, not all fcli functionality may be available. In particular, even the least restrictive SSC CIToken may not provide access to all endpoints covered by fcli. If you need access to functionality not covered by CIToken, you may need to define a custom token definition, but this can only be done on self-hosted SSC environments, not on Fortify Hosted. If all else fails, you may need to revert to username/password-based authentication to utilize the short-lived UnifiedLoginToken.

Named Sessions

Fcli supports named sessions, allowing you to have multiple open sessions for a single product. When issuing a session login command, you can optionally provide a session name as in fcli ssc session login mySession ..., and then use that session in other commands using the --session mySession command line option. If no session name is specified, a session named default will be created/used. Named sessions allow for a variety of use cases, for example:

  • Run fcli commands against multiple instances of the same product, like DEV and PROD instances or an on-premise instance and a Fortify Hosted instance, without having to continuously login and logout from one instance to switch to another instance

  • Run fcli commands against a single instance of a product, but with alternating credentials, for example with one session providing admin rights and another session providing limited user rights

  • Run one session with username/password credentials to allow access to all fcli functionality (based on user permissions), and another session with token-based authentication with access to only a subset of fcli functionality

  • Run multiple pipelines or automation scripts simultaneously, each with their own session name, to reduce chances of these pipelines and scripts affecting each other (see Fcli Data Folder though for a potentially better solution for this scenario)

Session Storage

To keep session state between fcli invocations, fcli stores session data like URL and authentication tokens in the Fcli Data Folder. To reduce the risk of unauthorized access to this sensitive data, fcli encrypts the session data files. However, this is not bullet-proof, as the default encryption key and algorithm can be easily viewed in fcli source code. As such, it is recommended to ensure file permissions on the fcli data folder are properly configured to disallow access by other users. Being stored in the user’s home directory by default, the correct file permissions should usually already be in place. For enhanced security, you may also consider setting the FCLI_ENCRYPT_KEY environment variable; see the Fcli Data Folder section for details.

Fcli Data Folder

By default, fcli stores configuration and state data like session files (see Session Management), fcli variable contents (see Fcli Variables) and proxy settings in its data folder. Future versions of fcli may also automatically generated log files in this data directory, if no --log-file option is provided.

The locations of these files can be controlled through the following environment variables:

  • FCLI_STATE_DIR: Location of fcli state like session and variable data.
    Default: <FCLI_DATA_DIR>/state

  • FCLI_CONFIG_DIR: Location of fcli configuration data like proxy and trust store settings.
    Default: <FCLI_DATA_DIR>/config

  • FCLI_DATA_DIR: Default base directory for the two directories listed above.
    Default: <FORTIFY_DATA_DIR>/fcli

  • FORTIFY_DATA_DIR: Default base directory for the directories listed above.
    Default: <user home directory>/.fortify

If none of these environment variables have been set, then state data will be stored in <user home directory>/.fortify/fcli/state, and configuration data will be stored in <user home directory>/.fortify/fcli/config.

Note: earlier versions of fcli used different environment variable names, but this was causing issues (see Issue 248). If you are using an older fcli version, please refer to the corresponding documentation. When upgrading fcli from an older version, you may need to adjust the environment variable names.

When utilizing fcli in pipelines or automation scripts, especially when multiple pipelines or scripts may be running simultaneously on a single, non-containerized system, it is highly recommended to have each pipeline use a separate fcli state directory, to avoid those pipelines from sharing session data, variables and other persistent fcli state data. This will avoid issues like different pipelines overwriting each others session data (for example with different URLs or credentials), or one pipeline logging out of a session while another pipeline is still using the session.

Depending on the situation, pipelines can either share fcli configuration data, or be configured to have different configuration data directories. When sharing the configuration data, it is recommended that these pipelines do not update any configuration data during pipeline execution, but rather use pre-configured settings. For example, you could pre-configure fcli with proxy and trust store settings.

On containerized systems, like pipelines running in GitLab or GitHub, the default folders will usually be stored inside the individual pipeline containers and thus will not interfere with each others state.

Note that some files stored in the fcli data directory may contain sensitive data, like authentication tokens generated by login commands, or proxy credentials configured through the fcli config proxy commands. Fcli encrypts any sensitive files, but since the encryption key and algorithm are hardcoded, these files can be decrypted fairly easily. You should ensure proper file access permissions on the fcli data folder. In addition, you can consider setting the FCLI_ENCRYPT_KEY environment variable to configure an alternative encryption key. That way, the sensitive files can only be decrypted if someone has access to this custom encryption key.

Environment Variables

Apart from the special-purpose environment variables described in other sections, like the Fcli Data Folder section, fcli allows for specifying default option and parameter values through environment variables. This is particularly useful for specifying product URL’s and credentials through pipeline secrets, but also allows for preventing having to manually supply command line options if you frequently invoke a particular command with the same option value(s). For example, you could define a default value for --issue-template option of the +fcli ssc appversion create option, to avoid having to remember the issue template name every time you invoke this command.

Fcli walks the command tree to find an environment variable that matches a particular option, starting with the most detailed command prefix first. For the issue-template example above, fcli would look for the following environment variable names, in this order:

  • FCLI_DEFAULT_SSC_APPVERSION_CREATE_ISSUE_TEMPLATE

  • FCLI_DEFAULT_SSC_APPVERSION_ISSUE_TEMPLATE

  • FCLI_DEFAULT_SSC_ISSUE_TEMPLATE

  • FCLI_DEFAULT_ISSUE_TEMPLATE

Environment variable lookups are based on the following rules:

  • Command aliases are not taken into account when looking for environment variables; suppose we have a delete command with alias rm, you will need to use FCLI_DEFAULT_..._DELETE_... and not FCLI_DEFAULT_..._RM_...

  • For options, fcli will use the longest option name when looking for environment variables; suppose we have an option with names -a, --ab and --abc, you will need to use FCLI_DEFAULT_..._ABC and not FCLI_DEFAULT_..._AB or FCLI_DEFAULT_..._A

  • For positional parameters, the environment variable name will be based on the parameter label, converted to SNAKE_CASE with all special characters replaced by an underscore. For example, <attributeDefinitionId> will become ATTRIBUTE_DEFINITION_ID, and HOST:PORT will become HOST_PORT.

Although powerful, these environment variables for providing default option and parameter values should be used with some care to avoid unexpected results:

  1. Obviously command option requirements should be respected; supplying default values for exclusive options may result in errors or unexpected behavior

  2. Preferably, you should use the most specific environment variable name, like FCLI_DEFAULT_SSC_APPVERSION_CREATE_ISSUE_TEMPLATE from the example above, to avoid accidentally supplying default values to a similarly named option on other commands

Despite #2 above, in some cases it may be useful to use less specific environment names, in particular if the same default values should be applied to multiple commands. As an example, consider an environment variable named FCLI_DEFAULT_SSC_URL:

  • This variable value will be used as a default value for all --url options in the SSC module

  • This variable value will be used as a default value for all --ssc-url options in other product modules

This means that defining a single FCLI_DEFAULT_SSC_URL environment variable, together with for example FCLI_DEFAULT_SSC_USER and FCLI_DEFAULT_SSC_PASSWORD environment variables, allows for applying these default values to all of the fcli ssc session login, fcli sc-sast session login, fcli sc-dast session login, and corresponding logout commands.

Note that as described in the –env-prefix section, you can override the FCLI_DEFAULT prefix. For example, with --env-prefix MYPREFIX, fcli will look for MYPREFIX_* environment variables instead of FCLI_DEFAULT_* environment variables.

Fcli Variables

Fcli allows for storing fcli output data in fcli variables for use by subsequent fcli commands. This is a powerful feature that prevents users from having to use shell features to parse fcli output when needing to provide output from one command as input to another command. For example, this feature allows for starting a scan, and then passing the scan id to a corresponding wait-for command, or for creating an SSC application version, and passing the SSC application version id to the artifact upload command.

Variables can be stored using the --store myVarName[:prop1,prop2] option on data output commands. If property names are specified, then only these property names will be stored. If no property names are provided, all available JSON properties will be stored.

Variables can be referenced in subsequent fcli commands using the ::myVarName::prop syntax anywhere on the command line; such occurrences will be substituted with the value of the given property name.

Many (but not all) fcli commands will also store an entity-specific default property name when using the --store option. Whether a default property name has been stored can be seen in the output of the fcli util variable list command. If a default property name was stored, the ::myVarName:: syntax can be used to reference the value of the default property name, thereby avoiding the need to manually specify the appropriate property name.

Following are some examples, assuming the necessary login sessions are available:

fcli ssc appversion create myApp:1.0 --auto-required-attrs --skip-if-exists --store myVersion
fcli ssc artifact upload myScan.fpr --appversion ::myVersion::

fcli ssc appversion create myApp:1.0 --auto-required --skip-if-exists --store myVersion:id,name
fcli ssc artifact upload myScan.fpr --appversion ::myVersion::id

fcli sc-sast scan start -p package.zip -v 22.2 --appversion test:1.0 --store x
fcli sc-sast scan wait-for ::x::

fcli sc-sast scan start -p package.zip -v 22.2 --appversion test:1.0 --store x
fcli sc-sast scan wait-for ::x::jobToken

Fcli provides the regular get, list and delete operations on the +fcli util variable command tree, and actual variable contents can be retrieved using the fcli util variable contents command. Please see help output or manual pages for more information on these commands.

The fcli util variable contents command supports the regular fcli output options and query capabilities. This allows for advanced us cases, like retrieving server data once and then outputting it in multiple formats, potentially even applying separate filters. As an example:

fcli ssc appversion list --store myVersions
fcli util variable contents myVersions -o csv --output-to-file myVersions.csv
fcli util variable contents myVersions -o json -q createdBy=admin --output-to-file myAdminVersions.json
fcli util variable contents myVersions -o 'expr={id}\n' --output-to-file myVersionIds.txt

Note: variable-related syntax and behavior was changed in fcli version 2.0.0. If you are using an older fcli version, please refer to the documentation for that version. When upgrading from 1.x.x to 2.x.x, you may need to update your fcli invocations to match the new syntax. See Issue 160 for information on why syntax and behavior was changed.

Actions

Fcli actions are a powerful feature that allows for rich integration and automation by running a customizable set of instructions defined in YAML files. These instructions allow for processing data collected from Fortify or third-party products, updating data in those products, and writing output to files or console.

Built-in Actions

Fci comes with various built-in actions, currently focused on providing the following functionality:

  • Vulnerability export to various third-party formats like SARIF or GitHub, GitLab, BitBucket, and SonarQube reports, as a replacement for FortifyVulnerabilityExporter.

  • Generating GitHub Pull Request comments, listing (re-)introduced and removed vulnerabilities.

  • Generating application version/release summaries in Markdown format, for example for use as pipeline summaries.

  • Evaluating security policy criteria, for example allowing to break a build if one or more checks are failing.

Future fcli versions may introduce new built-in actions, enhance existing built-in actions, or provide enhanced action syntax, for example to allow for running pipeline-style actions that run a set of commands to package source code, submit a scan request, wait for scan completion, and perform post-scan activities like data export or policy checks.

Action support is centralized into the action entity of the various product modules. For now, fcli supports fcli fod action * and fcli ssc action * commands. Based on user feedback, we may consider adding action support on other modules like sc-sast or sc-dast as well. The following commands may be used to manage and run built-in actions:

  • fcli * action list: List available built-in actions (and imported custom actions, see next section).

  • fcli * action help <action>: Display action usage information like description and list of action-specific command-line options.

  • fcli * action get <action>: Display action YAML contents.

  • fcli * action run <action>: Run a given action.

Custom Actions

Apart from built-in actions, users can also develop and run custom actions, which could be customized versions of built-in actions or completely new actions. Note that the ability to run custom actions is currently considered PREVIEW functionality; as fcli actions are a new functionality, we are collecting user feedback regarding action syntax, which could potentially result in breaking action syntax changes across minor fcli releases (although we’ll try to avoid this as much as possible).

As such, custom actions that run fine on the current fcli version may fail to run on any other fcli version. Fcli does perform action version checks based on action schema version (see below), but supported schema versions may change between minor or patch releases of fcli. Once we are comfortable with moving custom actions out of PREVIEW status, breaking schema/action syntax changes will be allowed only on major fcli releases, for example when moving from fcli 2.x to fcli 3.x.

Custom actions can be loaded from various sources, like a local or remote YAML file, optionally embedded in a zip-file that contains multiple actions. Each of the fcli commands listed in the previous section also support custom actions:

  • fcli * action list --from-zip <file|url>: List available actions from the given zip-file.

  • fcli * action help|get|run <file|url>: Load the action from the given file or URL.

  • fcli * action help|get|run <action> --from-zip <file|url>: Load the given action from the given zip-file.

To allow for easy access, custom actions can also be imported into fcli using the fcli * action import command, which allows for importing either a single action YAML file or all action YAML files from a local or remote zip-file. Once imported, these actions can be accessed in the same way as built-in actions. Note that imported custom actions will override built-in actions if they have the same name. You can use the fcli * action reset command to remove all previously imported custom actions.

Custom Action Development

There are several resources available to help you developing custom actions. To start with, you can use the fcli * action get <action> command to view the contents of any built-in action as a basis for developing your own custom actions. Fcli provides a built-in __sample__ action that explains various concepts and lists many of the supported action YAML elements together with a description. To view the sample action, use the fcli ssc action get __sample__ or fcli fod action get __sample__ command.

Fcli also 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-1.0.0.json
  • YAML property, supported by Eclipse and some other YAML editors:

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

Fcli requires at least one of these statements to be provided in action YAML files. 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 2.4.0 supports schema version 1.0.0. Other fcli versions may support different schema versions. In general, fcli also 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.

Security Considerations

As actions can potentially perform dangerous operations, like sending confidential data to third-party systems, or updating or deleting data in Fortify or third-party systems, you should only run trusted actions. If you wish to run any actions provided by a third party, you could potentially review action contents, and potentially in the future we may provide functionality for performing a security analysis on action contents (either as a new fcli command or through Fortify rules).

However, this won’t be sufficient for actions that are dynamically loaded from a remote location, as action contents could change at any time. For example, a legitimate action can easily be replaced by some malicious action.

For this reason, fcli by default requires custom actions to be signed. Organizations, teams or individuals can sign actions with their own private key using the fcli * action sign command, the corresponding public key can be imported into fcli using the fcli config public-key import command. Most action commands also allow for explicitly passing a public key through the --pubkey option.

Public keys can be loaded from a local file, URL, string or environment variable, see command help or next section for details. Obviously, you should only use trusted public keys; loading a public key from a third-party URL may be dangerous for the same reasons as explained above.

Actions in CI/CD pipelines

Fcli is commonly used in CI/CD pipelines to perform all sorts of Fortify-related operations, and fcli actions allow for even more advanced use cases. This section provides some hints as to how to integrate actions into CI/CD pipelines, considering deployment and security aspects.

Publishing

Fcli actions can be loaded from any URL, but for CI/CD integration you could consider hosting fcli actions in a shared source code repository like https://some-scm.our.org/repositories/shared-ci-tools/fcli/actions. This allows for easy sharing and maintainance of fcli actions that are used across many CI/CD pipelines. This even allows for automatically signing those action using CI/CD pipelines on this shared repository.

Public & private key management

Of course, those actions should be signed using an organization-specific private key. For example, this could be either an existing private key that’s used throughout the organization, or a private key that’s managed by the CI/CD team. There are several ways to pass the corresponding public key to fcli from within CI/CD pipelines:

  • Explicitly run fcli config public-key import command from each pipeline before running any actions.

  • Explicitly pass the --pubkey option on any fcli * action run commands.

  • Set the FCLI_DEFAULT_PUBKEY environment variable to configure a default value for the --pubkey option.

With each of these approaches, the public key can be be loaded from:

  • Local file, for example public key stored in current source code repository.

  • URL, for example pointing to public key stored in same shared source code repository as the actions themselves.

  • Environment variable, for example defined as system environment variable on self-hosted CI/CD nodes, or configured through (global) CI/CD secrets/variables.

  • Plain string, for example having the environment variable FCLI_DEFAULT_PUBKEY set to string:<public key contents>. You can use CI/CD secrets/variables to set the FCLI_DEFAULT_PUBKEY to a value like this. For testing, you can use a bash command like the following: export FCLI_DEFAULT_PUBKEY=string:$(cat my-public.key).

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 a highly configurable check-policy action, but instead just provide an example 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 or based on actions that perform policy checks, but the same principles and considerations (may) apply to other types of actions.

Manual Pages

Manual pages are automatically generated and contain the same information as fcli help output. Manual pages in HTML and Linux man-page formats can be downloaded for offline use from the fcli releases page at https://github.com/fortify/fcli/releases, or can be viewed online at https://fortify.github.io/fcli.

Please select the proper fcli version from the links above to access the corresponding manual pages. When using the offline HTML documentation bundle, please make sure to extract the full documentation archive to allow for hyperlinks to work correctly.

The manual pages for the currently selected fcli release can be found here: fcli (1).

Troubleshooting

Native Binaries

Native binaries require some special source code annotations for proper operation, which are not required for the plain Java .jar version of fcli. If fcli developers forgot to include any of these annotations, you may experience any of the following behavior:

  • Commands and/or option listed in manual pages are not listed by the help output of a native binary

  • Trying to use commands and/or options listed in the manual pages result in errors stating that the command or option is not recognized

  • Some commands and/or options result in technical error messages about classes, constructors or methods not being found or not being accessible

If you encounter any of these issues, please submit a bug report as described in Submitting a Bug Report. As described in that section, please include information on whether the .jar version of fcli exhibits the same erroneous behavior. While fcli developers are working on fixing the issue, you can temporarily use the .jar version of fcli until the issue is resolved.

Submitting a Bug Report

After confirming that an issue cannot be resolved based on the information above, and is not caused by user error, please consider submitting a bug report on the fcli issue tracker. Before doing so, please verify that there is not already a bug report open for the issue that you are experiencing; in that case, feel free to leave a comment on the existing bug report to confirm the issue and/or provide additional details.

When opening a bug report, please include the following information:

  • Fcli version, as shown by the fcli --version command

  • Which fcli variant you are using; one of the native binaries or the .jar variant invoked using java -jar fcli.jar

  • If you are experiencing an issue with the native binaries, please confirm whether the .jar version of fcli exhibits the same behavior

  • Operating system and any other relevant environment details, for example:

    • Interactive or pipeline/automation use

    • If pipeline use, what CI/CD system are you running fcli on (Jenkins, GitHub, GitLab, …)

    • What FCLI environment variables have been set

  • Steps to reproduce

  • Any other information that may be relevant