Three questions worth asking first
You have it connected. These three questions are the ones worth asking first, not because they are impressive but because each one exercises a different part of the tool surface, and together they show you where the seams are.
Ask them of a lab appliance the first time through.
“What is on this firewall?”
Section titled ““What is on this firewall?””Start wide. Ask the model to describe the appliance and its network:
Give me an overview of this firewall — what it is, what interfaces it has, and what VLANs are configured.
Three calls happen: get_system_status, list_interfaces, and list_vlans.
Two things in the answer are worth looking at closely.
The interface list is shorter than the one in the web UI. FortiOS generates
bookkeeping interfaces alongside real ones — a quarantine interface for every
wireless VAP, an SSL-VPN tunnel root — and those are hidden. hidden_internal
names them rather than counting them, so you can see exactly what was left
out. If you want them included, ask for internal interfaces and the model
passes include_internal.
Worth knowing that ssl.root is hidden by that rule and is a genuine policy
endpoint, so a policy can name an interface the default list omits.
The interface addresses are host addresses, not networks. An interface reported
as 10.20.30.1/24 really does have .1 on it. That sounds too obvious to
mention until you know that FortiOS writes an interface address and a subnet
object in the identical format, and that
collapsing one of them to its network
is a mistake with no symptom.
“What is 192.168.1.47?”
Section titled ““What is 192.168.1.47?””Pick an address you can see on the network and ask who has it. On a lab box, find one first with show me the current DHCP leases.
What is 10.20.30.84?
This is find_device, and it is the tool that shows most clearly why the
surface is shaped the way it is. One call reads three FortiOS endpoints — the
wireless client list, the DHCP lease table, and the ARP table — and merges them
by MAC into one record:
{ "mac": "aa:bb:cc:dd:ee:01", "seen_in": ["dhcp", "arp", "wifi"], "ip": "10.20.30.84", "hostname": "kevins-laptop", "interface": "vlan30", "ssid": "office", "signal_dbm": -54, "wireless": true}seen_in is the field to read first. A device in all three is a wireless
client with a lease that the appliance is actively talking to. A device in
arp only is statically addressed, or its lease came from a DHCP server that
is not this firewall — either way, it is present and the appliance knows about
it.
The join is by MAC, and the three endpoints disagree about MAC casing. That is why the tool exists rather than the model doing it: a naive comparison across those endpoints matches nothing and quietly returns three partial records that look like three separate devices.
“Is this object safe to delete?”
Section titled ““Is this object safe to delete?””Pick an address object from list_address_objects and ask:
Is the address object DMZ-SERVERS safe to delete?
This is find_references, and it is the question that precedes every
configuration change on a firewall. The answer comes from the appliance’s own
reference lookup, the same one behind the reference counter in the web UI.
{ "object": "DMZ-SERVERS", "verdict": "referenced", "resolved_as": ["address"], "total_references": 3, "candidate_tables": 74, "references": [ { "table": "firewall.policy", "object": "9", "attribute": "dstaddr" }, { "table": "firewall.addrgrp", "object": "ALL-SERVERS", "attribute": "member" } ], "sources_checked": { "object_usage": "ok", "policies": "ok", "routes": "ok" }, "safe_to_delete": false, "policies": [ { "id": 9, "name": "block-legacy-smb", "enabled": true, "action": "deny", "referenced_as": ["destination"] }, { "id": 12, "name": "dmz-mgmt", "enabled": false, "action": "accept", "referenced_as": ["destination", "source"] } ], "groups": [{ "name": "ALL-SERVERS", "kind": "address_group" }], "vips": [], "routes": []}candidate_tables: 74 is the number worth pausing on. That is how many tables
could hold a reference to an address object on this firmware, and it is why the
tool asks the appliance instead of checking a few tables by hand and hoping.
Notice policy 12: it is disabled. It still counts as a reference, because a disabled policy is a policy somebody intends to turn back on, and deleting the object it points at turns re-enabling it into a surprise.
Now try it with a deliberate typo — DMZ-SERVRES. The verdict comes back
object_not_found and there is no safe_to_delete key at all, because the
question was about a name rather than an object. Without that verdict a
misspelling would report zero references and a confident yes.
Three of the five verdicts omit safe_to_delete for reasons like that, and
they are normal outcomes rather than errors — especially with a correctly
least-privileged token.
What each verdict means.
Where to go next
Section titled “Where to go next”You have now used all three kinds of tool: a configuration read, a live-state read, and a cross-referencing read.
Reading a ruleset is the next thing most people want, and it is the one where evaluation order starts to matter. The tool reference is the complete surface when you want to know what else is there.