Error Messages
Most error messages you will see are regular FortiGate CLI error messages. If you are familiar with the CLI you will likely recognize them.
Other error messages indicate your script encountered problems while executing, such as:
- command parse error: It was not possible to parse this line of your script into a valid FortiGate CLI command. Common causes for this are misspelled keywords or an incorrect command format.
- unknown action: Generally this message indicates the previous line of the script was not executed, especially if the previous line accesses an object such as “config router static”.
- Device XXX failed-1: This usually means there is a problem with the end of the script. XXX is the name of the FortiGate unit the script is to be executed on. If a script has no end statement or that line has an error in it you may see this error message. You may also see this message if the FortiGate unit has not been synchronized by deploying its current configuration.
Troubleshooting Tips
Here are some troubleshooting tips to help locate and fix problems you may experience with your scripts.
- Check the script output. Generally the error messages displayed here will help you locate and fix the problem.
- See the FortiGate CLI Reference for more information on all CLI commands.
- There is a limit to the number of scripts allowed on the FortiManager unit. Try removing an old script before trying to save your current one.
- As mentioned at the start of this chapter, ensure the console more command is disabled on the FortiGate devices where scripts execute. Otherwise a condition may occur where both the FortiGate device and the FortiManager system are waiting for each other to respond until they timeout.
- There should be no punctuation at the start or end of the lines.
- Only whitespace is allowed on the same line as the command. This is useful in lining up end and next commands for quick and easy debugging of the script.
- Keep your scripts short. They are easier to troubleshoot and it gives you more flexibility. You can easily execute a number of scripts after each other.
- Use full command names. For example instead of “set host test” use “set hostname test”. This is required for any scripts that are to be run on the global database. l Use the number sign (#) to comment out a line you suspect contains an error.
Tcl scripts
Tcl is a dynamic scripting language that extends the functionality of CLI scripting. In FortiManager Tcl scripts, the first line of the script is “#!” as it is for standard Tcl scripts.
This guide assumes you are familiar with the Tcl language and regular expressions, and instead focuses on how to use
CLI commands in your Tcl scripts. Where you require more information about Tcl commands than this guide contains, please refer to resources such as the Tcl newsgroup, Tcl reference books, and the official Tcl website at http://www.tcl.tk.
Tcl scripts can do more than just get and set information. The benefits of Tcl come from:
- variables to store information, l loops to repeats commands that are slightly different each time l decisions to compare information from the device
The sample scripts in this section will contain procedures that you can combine to use your scripts. The samples will each focus on one of three areas:
- Tcl variables l Tcl loops l Tcl decisions
Limitations of FortiManager Tcl
FortiManager Tcl executes in a controlled environment. You do not have to know the location of the Tcl interpreter or environment variables to execute your scripts. This also means some of the commands normally found in Tcl are not used in FortiManager Tcl.
Depending on the CLI commands you use in your Tcl scripts, you may not be able to run some scripts on some versions of FortiOS as CLI commands change periodically.
Tcl variables
Variables allow you to store information from the FortiGate device, and use it later in the script. Arrays allow you to easily manage information by storing multiple pieces of data under a variable name. The next script uses an array to store the FortiGate system information.
Example: Save system status information in an array.
Script:
#!
proc get_sys_status aname {
upvar $aname a
puts [exec “# This is an example Tcl script to get the system status of the
FortiGate\n” “# ” 15 ] set input [exec “get system status\n” “# ” 15 ]
# puts $input set linelist [split $input \n]
# puts $linelist foreach line $linelist {
if {![regexp {([^:]+):(.*)} $line dummy key value]} continue
switch -regexp — $key { Version {
regexp {FortiGate-([^ ]+) ([^,]+),build([\d]+),.*} $value dummy a
(platform) a(version) a(build)
}
Serial-Number { set a(serial-number) [string trim $value]
}
Hostname { set a(hostname) [string trim $value]
} }
}
}
get_sys_status status puts “This machine is a $status(platform) platform.” puts “It is running version $status(version) of FortiOS.” puts “The firmware is build# $status(build).” puts “S/N: $status(serial-number)” puts “This machine is called $status(hostname)”
Output:
——- Executing time: 2013-10-21 09:58:06 ——
Starting log (Run on device)
FortiGate-VM64 #
This machine is a VM64 platform.
It is running version v5.0 of FortiOS.
The firmware is build# 0228.
S/N: FGVM02Q105060070
This machine is called FortiGate-VM64
——- The end of log ———-
Variations:
Once the information is in the variable array, you can use it as part of commands you send to the FortiGate device or to make decisions based on the information. For example:
if {$status(version) == 5.0} { # follow the version 5.0 commands
} elseif {$status(version) == 5.0} {
# follow the version 5.0 commands
}
This script introduces the concept of executing CLI commands within Tcl scripts using the following method: set input [exec “get system status\n” “# “]
This command executes the CLI command “get system status” and passes the result into the variable called input. Without the “\n” at the end of the CLI command, the CLI command will not execute to provide output.
In analyzing this script:
- line 1 is the required #! to indicate this is a Tcl script l lines 2-3 open the procedure declaration l lines 4-5 puts the output from the CLI command into a Tcl variable as a string, and breaks it up at each return character into an array of smaller strings l line 6 starts a loop to go through the array of strings
- line 7 loops if the array element is punctuation or continues if its text l line 8 takes the output of line 7’s regular expression command and based on a match, performs one of the actions listed in lines 9 through 17
- lines 9-11 if regular expression matches ‘Version’ then parse the text and store values for the platform, version, and build number in the named array elements
- line 12-14 if regular expression matches ‘Serial-Number’ then store the value in an array element named that after trimming the string down to text only
- lines 15-17 is similar to line 12 except the regular expression is matched against ‘Hostname’ l line 17-19 close the switch decision statement, the for each loop, and the procedure l line 20 calls the procedure with an array name of status l lines 21-25 output the information stored in the status array
Tcl loops
Even though the last script used a loop, that script’s main purpose was storing information in the array. The next script uses a loop to create a preset number of users on the FortiGate device, in this case 10 users. The output is only shown for the first two users due to space considerations.
Example: Create 10 users from usr0001 to usr0010:
Script:
#!
proc do_cmd {cmd} { puts [exec “$cmd\n” “# ” 15]
} set num_users 10 do_cmd “config vdom” do_cmd “edit root” do_cmd “config user local”
for {set i 1} {$i <= $num_users} {incr i} {
set name [format “usr%04d” $i] puts “Adding user: $name” do_cmd “edit $name” do_cmd “set status enable” do_cmd “set type password” do_cmd “next”
} do_cmd “end” do_cmd “end”
do_cmd “config vdom” do_cmd “edit root” do_cmd “show user local”
do_cmd “end”
Output:
View the log of script running on device:FortiGate-VM64
——- Executing time: 2013-10-16 15:27:18 ——
Starting log (Run on device) config vdom
FortiGate-VM64 (vdom) # edit root
current vf=root:0 FortiGate-VM64 (root) # config user local FortiGate-VM64 (local) # Adding user: usr0001 edit usr0001 new entry ‘usr0001’ added FortiGate-VM64 (usr0001) # set status enable FortiGate-VM64 (usr0001) # set type password FortiGate-VM64 (usr0001) # next
FortiGate-VM64 (local) # Adding user: usr0002 edit usr0002 new entry ‘usr0002’ added FortiGate-VM64 (usr0002) # set status enable FortiGate-VM64 (usr0002) # set type password
FortiGate-VM64 (usr0002) # next
Variations:
There are a number of uses for this kind of looping script. One example is to create firewall policies for each interface that deny all non-HTTPS and non-SSH traffic by default. Another example is a scheduled script to loop through the static routing table to check that each entry is still reachable, and if not remove it from the table.
This script loops 10 times creating a new user each time whose name is based on the loop counter. The format command is used to force a four digit number.
In analyzing this script:
- line 1 is the required #! to indicate this is a Tcl script l lines 2-4 open CLI command wrapper procedure l line 5 declares the number of users to create l line 6 gets the FortiGate ready for entering local users l line 7 opens the for loop that will loop ten times l line 8 sets the user name based on the incremented loop counter variable l line 9 is just a comment to the administrator which user is being created l lines 10-13 create and configure the user, leaving the CLI ready for the next user to be added l line 14 ends the for loop l line 15 ends the adding of users in the CLI
- line 16 executes a CLI command to prove the users were added properly
Tcl decisions
Tcl has a number of decision structures that allow you to execute different CLI commands based on what information you discover.
This script is more complex than the previous scripts as it uses two procedures that read FortiGate information, make a decision based on that information, and then executes one of the CLI sub-scripts based on that information.