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:
-
Interact with many different Fortify products with just a single command-line utility
-
Both plain Java and native platform binaries for Windows, Linux and Mac available
-
Modular command structure, making it easy to focus on particular tasks
-
Rich output formats; save command output in JSON, CSV, XML or plain-text formats
-
Session-based; no need to pass URL’s and credentials on every individual fcli invocation
-
Support for configuring option values through environment variables
-
Support for fcli variables; pass data between fcli commands
-
Support for installing other Fortify-related tools
-
Support for running multi-purpose YAML-based actions
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 yourPATH
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 thefcli tool fcli install
command, the Fortify tools globalbin
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 invokesjava -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 yourPATH
. -
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, theexpr
option must be properly quoted. For most shells, theexpr=...
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
orlist
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 betweenansi
,single-line
andsimple
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 propertyp1
equalsv1
-
-q 'p1=="v1" || p1=="v2"'
Only output records if the value of propertyp1
equals eitherv1
orv2
-
-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 propertyp2
either equals 25 or is less than 5 -
-q 'p1=="v1" && (p2=="v2" || p3=="v2")'
Only output records if the value of propertyp1
equalsv1
and the value of either propertyp2
orp3
isv2
-
fcli ssc artifact list --appversion MyApp:main -q 'scanTypes matches "\bSCA\b"'
Only output artifacts containing a Fortify SCA scan (matching the whole wordSCA
againstscanTypes
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 abuildLabel
that equalsmyLabel
-
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
isnull
):
fcli ... list -q 'prop1==null || prop1 matches "value1|value2"'
-
Add null-check (exclude all records for which
prop
isnull
):
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 aliasrm
, you will need to useFCLI_DEFAULT_..._DELETE_...
and notFCLI_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 useFCLI_DEFAULT_..._ABC
and notFCLI_DEFAULT_..._AB
orFCLI_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 becomeATTRIBUTE_DEFINITION_ID
, andHOST:PORT
will becomeHOST_PORT
.
Although powerful, these environment variables for providing default option and parameter values should be used with some care to avoid unexpected results:
-
Obviously command option requirements should be respected; supplying default values for exclusive options may result in errors or unexpected behavior
-
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:
-
Visual Studio Code: Red Hat YAML plugin
-
Eclipse: Wild Web Developer
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 anyfcli * 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 tostring:<public key contents>
. You can use CI/CD secrets/variables to set theFCLI_DEFAULT_PUBKEY
to a value like this. For testing, you can use abash
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
andcheck-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 usingjava -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