Skip to content

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.

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.

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.

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.

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.