-
Notifications
You must be signed in to change notification settings - Fork 5
utilities script.py
This utility executes custom commands as defined in provided XML file.
The XML file can contain simple or more complex commands, it can conditionally execute some parts based on remote FortiOS version, run internal parses and use their results, save and operated based on user define parameters, etc.
This utility also has a simple GUI interface called scriptgui.py
and located in auxi
folder.
The output file can be either analysed programatically or it can be converted to easily readable SSH session-like output with script_to_plain.py auxiliary program. When passing the outputs to support, always use the original compressed file.
Besides the standard command line parameters that most utilities share, following local commands are recognized:
-
--list
Checks what cycle names are available in the file referenced by--script
option and shown a simple description as specified within the file. -
--cycle
Runs the cycle specified by its name. This option can be used multiple times to run more different cycles (sequentially). If--cycle-time
option is also used (see bellow), this time is counted for all cycles together.
-
--script
Path to the XML script to process. If the path is simple filesystem path, that file is loaded directly. It can also be a URL, in which case this is first downloaded and then executed in the same way as if it was a local file.Example of a local file can be "/home/user/myscript.xml" for Linux-based systems or "c:\users\user\desktop\myscript.xml" when running on Windows.
For URLs, at least HTTP and HTTPs protocols are supported (HTTPs is strongly recommended due to sensitive nature of the script - the commands are not restricted anyhow). There are some URL that are usable by anybody:
- https://scripts.fortidebug.com/global/latest.xml - Contains general troubleshooting commands for many different subsystems on FortiOS. It automatically redirects to the latest version.
-
--output
If used, the output of each command is appended to the specified file. The format of the file is "JSON Line". See the "Output file" section for detailed format description.This option should be used most of the time when you plan to analyse the commands output later (like when sending the output file to the support).
-
--compress
By default the--output
file is compressed using bzip2 algorithm. This option specifies the number of outputs to be buffered before they are compressed and written to the output file. By default it is saved every 10 outputs and the resulting file is about 20 % of the uncompressed file. To disable compression completely use 0.If the program is terminated nicely (using CTRL+c, also on Windows - closing the window does not work correctly), the latest buffer is also saved. However, if the program crashes for some reason, the unsaved data is lost, so set the number reasonably.
-
--cycle-time
Minimal time (in seconds) one big cycle can run. If the cycle finished before this time, the next cycle will be delayed until the rest of the--cycle-time
passes. If the last cycle took more time than this minimum, the next cycle is started immediately. -
--profile
Specifies the profile name to use. Each profile must be defined inside the XML file. Each cycle definition has the default profile name for the cycle, but this option can be used force different profile.Profile contains the "administrative" parameters for the cycle, like the delay between subsequent commands.
-
--param
The command definition can use some parameters. Some are defined automatically when the script is running, but it is possible to also specify the parameters manually. This option can be specified multiple times to set different parameters.It can be useful for example when the script focuses on specific network interface, but it is unknown which interface it should be when the script is being written.
Following formats are recognized:
-
s:name:value
Parameter called "name" will have the simple string "value". Example: "s:test:value". -
l:name:delimiter:value1,value2,...
Parameter called "name" will be a list of strings. The delimiter is used to control how to split the values. For example "l:test:,:v1,v2,v3" means that the parameter "test" will contain values "v1", "v2" and "v3".
-
-
--quiet
By default (without using this option) the output of each command is written to the standard program output. This is mainly to see the progress of the script and it is not meant for saving the output (see--output
option). If--quiet
is specified, output of the commands will not be shown and only debug and error messages will be printed on the console.
Security is extremely important when dealing with this utility, because there is no restriction of what the commands in XML script file can do.
For the XML script files on your local disk it is up to you to verify their contents or trust the source you got the file from.
However, for the XML files referenced by the URL, this might not be safe enough. Hence by default all the URL files must be digitally signed and the signature must match the public key specified by --public-key
command line option. If there is a problem with the signature, the file is refused.
There is one public key distributed with this project (in pubkeys/default.pem
) and it is used automatically if no --public-key
option is used. All the URL XML scripts officially distributed by this project are signed with the corresponding private key and you will have no problems running them.
If you really don't care about the security of your FortiGate and you are prepared to deal with consequences, there is an option --ignore-signature
that will disable this check. Consider yourself warned!
To learn more about how the signature is verified and how to sign your own XML script files, check the sign.py wiki page.
The output is always appended (ie. it is never automatically truncated). The format is "JSON Lines", meaning that each command output is a separate JSON structure on its own line.
The structure contains a hash array with following elements:
-
command
Full command that was executed (including inline replacements and parameters). -
context
The context in which the command was executed, can be:-
null
when executed in global context -
""
(empty) when executed in management VDOM -
"vdom name"
when executed in a specific VDOM
-
-
output
Output of the command. If the command was a simple FortiOS command, this is the text output received on terminal.If the internal parser was called, the output is a JSON structure containing the data as received from the parser. Parsers are used to run one or more commands on the background and calculate some parser-specific results (for example extract multiple similar parts of the command output and prepare some kind of summary).
-
time
Time when the command was executed.This can either be time on the FortiGate device (default) or the local time on the computer running the script (see
--time-source
option shared by most of the utilities). The time format can also vary as specified by the shared option--time-format
(by default it is human readable timestamp with the UTC offset). -
parameters
Hash array of the parameters at the time the command was executed. Be aware that only parameters with name starting with>
character are saved (without the>
character).The main reason for this element is to save some specific device state when the command was executed. For example when some command output depends on previously executed commands. The parameter usually has to be set manually in the XML script and its meaning is not standardised.
-
connected_on
Unix timestamp on the local computer when the connection to the FortiGate was established. -
nonce
Random number generated when the connection to the FortiGate is established. -
info
Hash array containing the information about the type of the element that was used to execute the command. It has at leasttype
entry, and depending on its value, other entries might be present:-
simple
Element <simple> was used. No other entries in the hash are saved. -
continuous
Element <continuous> was used. There should be alsocontinuous_index
starting at 0 and increasing with each continuous output of the same command. -
parser
Element <parser> was used. There should also beparser_name
andparser_input
to show what were the input parameters for the parser. -
automatic
The command was run internally by the system to retrieve some necessary information.
-
After each successful connection to the FortiGate, couple of commands are executed to retrieve information about the current state (get system status
, get system performance status
, and uptime). This is not printed to standard output.
Special record in the same format of standard record is created to the output file. The command field is null
and parameter automatic
is true
.
In the output
field, the structure is saved with following entries:
-
internal_commands
The array of the outputs from commands mentioned above (in the format of standard entry described above). -
flags
Used to describe operation parameters of the script. Currently following flags are saved:-
time_source
Value of--time-source
option used when the script was started. -
time_format
Value of--time-format
option used when the script was started. -
filename
Script file or URL specified on the command line. -
real_filename
Script final URL after all redirections. -
version
FortiDebug application version used to collect this output.
-
-
info
Information about the FortiGate, besides some operational fields, following are saved:-
hostname
Hostname as configured on the device. -
vdoms_enabled
True if user VDOMs are enabled on the device. -
mgmt_vdom
Name of the management VDOM. -
device
Full human readable FortiGate model name. -
serial
Serial number of the device. -
connected_on
Unix timestamp when the SSH session was established. -
nonce
Random number generated when the SSH sessions is established. -
version
Hash containing following elements:-
major
FortiOS major version -
minor
FortiOS minor version -
patch
FortiOS patch number -
build
FortiOS build number -
compilation
FortiOS compilation number
-
-
The same nonce
and connected_on
fields are saved in every structure of the standard command output and can be used to match with this special information structure.
The top level element must be <fortidebug_scriptfile>
with mandatory version
attribute. In order to be able to execute the script, the FortiDebug system must be of the same version or newer. The FortiDebug version is saved in VERSION.txt
file in its root directory and it is increased every time a new feature is implemented.
-
<profiles>
Specifies a list of profiles that can be either associated with each cycle in its definition, or overridden by the command line option. Profiles control the operational parameters of the cycle.There is the built-in "default" profile that is used in case the cycle specifies no profile name or the profile it specified does not exist.
Following are the options currently configurable:
-
<intercommand_sleep>
Delay in seconds (can be decimal number) between subsequent commands. This is implemented to prevent overloading the FortiGate with too much commands. The default value is 0.5 seconds.
Example of custom profile called "myprofile" with reduced delay:
<profiles> <profile name="mmyprofile"> <intercommand_sleep>0.1</intercommand_sleep> </profile> </profiles>
-
-
<plists>
Parameter list name can be specified by each cycle. This is a space where the runtime parameters are stored during the cycle lifetime, but there can be also some parameters prepared before the cycle is started. This can be done either by defining it inside this parameter list element or by command line option. Command line option overwrites the parameters specified in the XML file.This can be used for example when writing XML scripts to troubleshoot one network interface when the interface name is unknown in advance. In that case, the parameter such as "iface" can be defined and used in the cycle instead of the real interface name (as
${iface}
). The person running the script then uses the--param
command line option to select the right interface name.Example with "iface" parameter and default value "port3":
<plists> <parameters name="main"> <param name="iface" value="port3"/> </parameters> </plists>
In the cycle the command can look like following. Any occurrence of
${param}
will be replaced by the value of the parameter:<simple> diagnose hardware deviceinfo nic ${iface} </simple>
And to overwrite it on command line use
--param s:iface:port5
option.
-
<cycles>
Contains definitions of the commands to be executed on the device (aka "cycle").Each cycle is specified in its own
<cycle>
child element with at least the "name" attribute. Following attributes are recognized:-
name
Name of the cycle. Mandatory. Used on command line to start the right cycle. -
desc
Description of the cycle. Is is printed when user runs the utility with--list
option. -
profile
Profile name to apply when running the cycle. Can be overridden on command line with--profile
option. If not specified, built-in "default" is used. -
parameters
Parameter list name to apply when running the cycle. If not specified, empty list is created.
Child elements of the
<cycle>
element control the flow of the script and the commands to be executed.Example of a cycle called "mycycle" with profile and parameter list, running just one simple command:
<cycles> <cycle name="mycycle" desc="Documentation example cycle" profile="main" parameters="main"> <simple> get system performance status </simple> </cycle> </cycles>
-
Please see the dedicated wiki page for cycle command elements.
Following example uses the sample script, that runs get sys stat
, get sys perf stat
, diagnose firewall packet distribution
and diagnose snmp ip frags
.
<fortidebug_scriptfile version="1">
<cycles>
<cycle name="test" desc="Very simple testing cycle.">
<echo>This is a simple testing cycle.</echo>
<simple context="global" >get system status </simple>
<simple context="global" >get system performance status </simple>
<simple context="mgmt_vdom">diagnose firewall packet distribution</simple>
<simple context="mgmt_vdom">diagnose snmp ip frags </simple>
</cycle>
</cycles>
</fortidebug_scriptfile>
$ ./script.py --host 10.0.0.1 --script ../samples/simplest.xml --list
test : Very simple testing cycle.
$ ./script.py --host 10.109.16.179 --script ../samples/simplest.xml --cycle test
[2018-09-13 20:03:14+02:00] (script) >>> This is a simple testing cycle.
[2018-09-13 20:03:14+02:00] (script) <<< get system status
[2018-09-13 20:03:14+02:00] (script) Version: FortiGate-1500D v5.6.0,build3404,180828 (GA)
[2018-09-13 20:03:14+02:00] (script) Virus-DB: 62.00176(2018-09-13 07:28)
[2018-09-13 20:03:14+02:00] (script) Extended DB: 1.00000(2012-10-17 15:46)
[...]
[2018-09-13 20:03:15+02:00] (script) <<< get system performance status
[2018-09-13 20:03:15+02:00] (script) CPU states: 0% user 1% system 0% nice 99% idle 0% iowait 0% irq 0% softirq
[2018-09-13 20:03:15+02:00] (script) CPU0 states: 0% user 1% system 0% nice 99% idle 0% iowait 0% irq 0% softirq
[2018-09-13 20:03:15+02:00] (script) CPU1 states: 0% user 0% system 0% nice 100% idle 0% iowait 0% irq 0% softirq
[...]
[2018-09-13 20:03:16+02:00] (script) <<< diagnose firewall packet distribution
[2018-09-13 20:03:16+02:00] (script) getting packet distribution statistics...
[2018-09-13 20:03:16+02:00] (script) 0 bytes - 63 bytes: 7491100 packets
[2018-09-13 20:03:16+02:00] (script) 64 bytes - 127 bytes: 1406786 packets
[...]
[2018-09-13 20:03:17+02:00] (script) <<< diagnose snmp ip frags
[2018-09-13 20:03:17+02:00] (script) ReasmTimeout = 0
[2018-09-13 20:03:17+02:00] (script) ReasmReqds = 0
[...]
[2018-09-13 20:03:44+02:00] (script) >>> This is a simple testing cycle.
[2018-09-13 20:03:44+02:00] (script) <<< get system status
[2018-09-13 20:03:44+02:00] (script) Version: FortiGate-1500D v5.6.0,build3404,180828 (GA)
[2018-09-13 20:03:44+02:00] (script) Virus-DB: 62.00176(2018-09-13 07:28)
[...]
[2018-09-13 20:03:45+02:00] (script) <<< get system performance status
[2018-09-13 20:03:45+02:00] (script) CPU states: 0% user 1% system 0% nice 99% idle 0% iowait 0% irq 0% softirq
[2018-09-13 20:03:45+02:00] (script) CPU0 states: 0% user 3% system 0% nice 97% idle 0% iowait 0% irq 0% softirq
[...]
[2018-09-13 20:03:46+02:00] (script) <<< diagnose firewall packet distribution
[2018-09-13 20:03:46+02:00] (script) getting packet distribution statistics...
[2018-09-13 20:03:46+02:00] (script) 0 bytes - 63 bytes: 7491360 packets
[2018-09-13 20:03:46+02:00] (script) 64 bytes - 127 bytes: 1406872 packets
[...]
[2018-09-13 20:03:47+02:00] (script) <<< diagnose snmp ip frags
[2018-09-13 20:03:47+02:00] (script) ReasmTimeout = 0
[2018-09-13 20:03:47+02:00] (script) ReasmReqds = 0
[...]
-
How do I know what commands will be executed on my device?
You can open the script file in your favourite XML editor (built-in XML viewer in Chrome or Firefox will do well). If you got the URL, you can download it first. The syntax is quite self-explanatory and you can refer to XML script file format section if you have any doubts.
-
How to read the compressed output file on Windows?
The output file is bzip2 compressed text file with JSON Lines structure. You can install any utility that supports this format to decompress it and then open in a text editor. The one that was tested is https://www.7-zip.org/.
-
How do I use the internal plotter tool to generate graphs from collected data?
Until the plotter can recognise this new format, use script_to_plain.py to generate an SSH session-like text output that the plotter can work with.