Which gates stand open, and who told them to.
Declare what each host is allowed to expose. Then read the effective
firewalld ruleset, diff it against the declaration, and reconcile
the difference with per-host confirmation.
“And the rule was added for one afternoon, and the afternoon was in 2021.” Findings 4:9 — nobody remembers, and nobody dares remove it
A firewall is not a state, it is an accumulation. Every rule was added by someone reasonable, for a reason that was true at the time, and almost none were ever taken out. The question is not whether thy rules are wrong. It is whether anyone still knows why they are there.
web01.hostname.loc · default zone · click a gate to shut it
Try the first one. It will refuse, and on thy real fleet it refuses too
— unless thou passest --force, which exists, and which thou
shouldst think about before using.
Three verbs. Two of them only look.
discover — read-only. Connects over SSH, escalates with
sudo, and reads the effective firewalld
configuration for each host's default zone: allowed services and ports, in
both the runtime and the permanent configuration. It diffs that against thy
policy and writes firewall_plan.json plus a workbook.
apply — takes the plan and reconciles, per host, with
confirmation. It writes the permanent rules first, then reloads and
verifies the result, and records what changed in
firewall_results.json.
report — re-renders an existing plan to Excel without touching a single host. For the second meeting about the same spreadsheet.
“Runtime but not permanent” is the quiet one. Those rules are working today and will vanish at the next reboot, and nothing will tell thee when they do.
firewalld is the primary backend and the only one apply
supports. On a host without it — or with --backend nftables
— discover falls back to dumping the nftables ruleset so
thou canst at least see it. It does not diff or reconcile that, and it says so rather
than skipping the host in silence.
One file thou ownest, committed to a repository, defensible in a meeting
A JSON file — or YAML, if PyYAML is installed. Groups hold
shared allow-lists, hosts may name a group and add their own, and optional defaults apply
to any host not listed.
A host's effective allow-list is the union of the defaults, its group,
and its own entry. A port written without a protocol is taken as /tcp.
A host absent from the policy, with no defaults to fall back on, is treated as unmanaged. Its extra rules are reported so thou canst see them, and never removed. Silence in a policy file means “I have not decided about this host yet”, not “strip it”, and the tool refuses to read it the second way.
A guard thou canst override, and a moment's thought before thou dost
Every fleet engineer has, exactly once, dropped their own SSH session with a firewall rule and then discovered that the console access they were sure existed does not. It is a very quiet thirty seconds.
Any change that would drop thy control SSH access is blocked, and the
blocked items are listed in the Policy Drift sheet so thou knowest exactly what was held
back and why. --force disables the guard. It exists because
occasionally thou really art migrating the SSH port and thou dost have console access
— but it is a flag thou shouldst have to type on purpose.
If SSH does not run on 22, tell the guard which port to protect with
--ssh-port 2222/tcp. A guard defending the wrong door is worse
than no guard, because thou wilt trust it.
Permanent first, then reload, then verify. The change is written to the permanent configuration, firewalld is reloaded, and the result is read back. An apply that reported success without the rule landing is a failure, not a pass.
Per host, by default. Eighty hosts is eighty decisions.
-y / --yes skips the prompts for automation,
and like --force it is there because sometimes thou needest it
— but the default is to stop and ask, so thou canst halt at host nine when something
looks wrong rather than finding out at host eighty.
A note on scope, so nothing surprises thee: version one reconciles services and ports on the default zone. Rich rules, sources, interfaces and multi-zone arrangements are read and reported, but never modified.
Six sheets, and the interesting ones are not the first two
Policy Drift is the working sheet: every service and port to add or remove, plus anything the SSH guard blocked. Effective Rules puts the runtime services and ports next to what the policy allows, side by side, which is the view that settles arguments. Runtime vs Permanent names the rules that exist in one and not the other — the ones that will quietly change behaviour at the next reboot.
The Summary sheet carries, per host, the backend, the zone, the change count, the blocked count, whether runtime and permanent agree, and whether the host is managed at all. That last column is worth reading first.
Describe, then look, then reconcile — in that order
Auth flags match every other book: keys or agent by default,
--ask-ssh-pass for password login,
--sudo-pass-same-as-ssh for sudo. Passwords travel by stdin or the
SSHPASS environment variable, never argv. Sudo is needed for
firewall-cmd.
Breaking the fourth wall, briefly
A real tool, written by a real sysadmin who inherited a fleet whose firewall rules had been accumulating since before he arrived, and could not find one person who could explain port 8080. Agentless, MIT licensed.
It talks to firewalld through firewall-cmd,
because that is the interface RHEL supports, and hand-written nft
rules are how thou endest up with a fleet nobody else can maintain. Hosts without firewalld
are reported as such rather than quietly skipped.
It writes an xlsx, and it never writes a formula into one. Everything a host reports is
written as text, so a compromised server cannot hide a payload in a zone name and have it
fire when thou openest the report. Same as its elder siblings, through the same
xlsx_safe module. That part is still not a joke.
Built by vK, who has been paged at 03:00 and did not enjoy it. Companion to linux-audit, which examines, and linux-drift, which notices when the gates move again. Its plans can also be handed to linux-apply, which drops any removal of the ssh service before it runs a thing.
Kneel also at the parish and read at the scriptorium. The Cluster abides. The Loop reconciles. The gate, once opened, is rarely shut.
Nothing here works alone, and neither shouldst thou
The fleet is one testament in several books. Each does one job, writes a report thou canst hand to anyone, and refuses to be clever with thy servers.