feat: add firewall inventory - #6
Conversation
|
Thanks for this, and for the care in the implementation. The typed allowlist, the schema entry, and the secret-leak regression test all match how the rest of the codebase is built. Worth saying up front: this pointed at something I had not registered. My controller has 65 firewall policies and 6 zones sitting behind an API this CLI cannot see at all, and I only went looking because of your PR. The gap you identified is real and I want to close it. My problem is with the endpoint, not the idea. On a UCG-Ultra running Network 10.5.67,
So To be precise about scope: For most commands I would take this and iterate. For a firewall inventory I would rather not: a confident A version I would take reads the v2 policy and zone endpoints, or detects Network 9+ and returns an explicit unsupported error pointing at them. The types here ( If you want to build it I am genuinely interested, and I am happy to dump the shape of the v2 policy and zone responses from my controller to save you the discovery work. |
|
Following up on my own offer rather than leaving it conditional, since you shouldn't have to ask. Here are the v2 shapes from my controller (UCG-Ultra, Network 10.5.67). No obligation attached: I'm posting them because I said I would, and because the discovery work is the tedious part whether you pick this up or I do. Addresses, object IDs and UUIDs below are placeholders, rewritten to the RFC 5737 documentation ranges. Field names, types and presence counts are verbatim. EndpointsNote the singular First gotcha: v2 returns a bare JSON array, not the ZonesAll six are UniFi stock, created by default: {
"_id": "aaaaaaaaaaaaaaaaaaaaaaaa",
"attr_no_edit": false,
"cloud_template": null,
"default_zone": true,
"external_id": "00000000-0000-0000-0000-000000000000",
"name": "Internal",
"network_ids": ["bbbbbbbbbbbbbbbbbbbbbbbb", "cccccccccccccccccccccccc"],
"zone_key": "internal"
}
Policies64 predefined, 1 custom. Policies reference zones by The part that will bite a struct definition. Presence is not uniform across the 65:
So A predefined policy: {
"_id": "dddddddddddddddddddddddd",
"action": "ALLOW",
"connection_state_type": "ALL",
"connection_states": [],
"create_allow_respond": true,
"destination": {
"match_opposite_ports": false,
"matching_target": "ANY",
"port_matching_type": "ANY",
"zone_id": "aaaaaaaaaaaaaaaaaaaaaaaa"
},
"enabled": true,
"hits": 356176922,
"icmp_typename": "ANY",
"icmp_v6_typename": "ANY",
"index": 2147483647,
"ip_version": "BOTH",
"last_hit": 1786739833104,
"logging": false,
"match_ip_sec": false,
"match_opposite_protocol": false,
"name": "Allow All Traffic",
"origin_id": "eeeeeeeeeeeeeeeeeeeeeeee",
"predefined": true,
"protocol": "all",
"schedule": { "mode": "ALWAYS" },
"source": {
"match_opposite_ports": false,
"matching_target": "ANY",
"port_matching_type": "ANY",
"zone_id": "aaaaaaaaaaaaaaaaaaaaaaaa"
}
}The custom one, which is where the {
"_id": "ffffffffffffffffffffffff",
"action": "ALLOW",
"connection_state_type": "ALL",
"connection_states": [],
"create_allow_respond": false,
"destination": {
"ips": ["192.0.2.25"],
"match_opposite_ips": false,
"match_opposite_ports": false,
"matching_target": "IP",
"matching_target_type": "SPECIFIC",
"port": "8006",
"port_matching_type": "SPECIFIC",
"zone_id": "aaaaaaaaaaaaaaaaaaaaaaaa"
},
"enabled": true,
"icmp_typename": "ANY",
"icmp_v6_typename": "ANY",
"index": 10000,
"ip_version": "IPV4",
"logging": false,
"match_ip_sec": false,
"match_ip_sec_type": "MATCH_IP_SEC",
"match_opposite_protocol": false,
"name": "Allow Proxy to Host",
"predefined": false,
"protocol": "tcp",
"schedule": { "mode": "ALWAYS", "repeat_on_days": [], "time_all_day": false },
"source": {
"ips": ["198.51.100.210"],
"match_mac": false,
"match_opposite_ips": false,
"match_opposite_ports": false,
"matching_target": "IP",
"matching_target_type": "SPECIFIC",
"port_matching_type": "ANY",
"zone_id": "aaaaaaaaaaaaaaaaaaaaaaaa"
}
}One design note I'd have an opinion on: 64 of 65 being predefined means a bare On this PRYour branch is still live on your fork, so reopening this or opening a fresh one are both fine by me, whichever you prefer. There's genuinely no expectation either way, and if you'd rather not take on a rewrite, say so and I'll build it, with the gap credited to your report here. I don't have a pre-9 controller, so if the legacy endpoint your original version reads is still populated on yours, I'd be interested to know. It would mean a complete implementation needs both paths rather than a straight replacement. |
What
Add read-only
unifi firewall rulesandunifi firewall groupscommands with text, JSON, and schema support.Why
Firewall policy currently requires controller UI inspection. These commands make policy audits and automation possible through the CLI.
Safety
Both legacy resources are decoded into narrow typed records. Unknown vendor fields are discarded; regression fixtures inject secret-like fields and verify they never appear in command output.
Checks
env -u UNIFI_API_KEY -u UNIFI_HOST make check