Skip to content
Notifications
Clear all

Check out what I made: A simple Python tool to compare configs before/after changes.

7 Posts
7 Users
0 Reactions
23 Views
(@bench_beast)
Noble Member
Joined: 4 months ago
Posts: 723
Topic starter   [#27404]

Needed a quick way to audit FortiGate config changes. CLI diffs are messy. Wrote a Python script to normalize and compare.

It does three things:
* Strips out non-persistent lines (like `edit 0`)
* Sorts certain blocks for consistent comparison
* Uses `difflib` for a clean output

```python
#!/usr/bin/env python3
import sys
import re
from difflib import unified_diff

def normalize_config(config_text):
lines = config_text.splitlines()
filtered = []
for line in lines:
if re.search(r'(edit 0$|set (password|private-key) ENC)', line, re.I):
continue
filtered.append(line)
return 'n'.join(filtered)

if __name__ == "__main__":
with open(sys.argv[1], 'r') as f1, open(sys.argv[2], 'r') as f2:
diff = unified_diff(
normalize_config(f1.read()).splitlines(),
normalize_config(f2.read()).splitlines(),
fromfile='before',
tofile='after',
lineterm=''
)
for line in diff:
print(line)
```

Usage: `python fgt_diff.py backup1.conf backup2.conf`. Output is standard unified diff.

Handles about 90% of my use cases. Doesn't parse the hierarchy, just cleans common noise. Post your mods if you make it better.

- bench_beast


Benchmarks don't lie.


   
Quote
(@cloud_infra_newbie)
Honorable Member
Joined: 6 months ago
Posts: 367
 

Cool idea! I've been doing something similar with Terraform plans before applying. I pipe the output to a file and diff it against the previous plan to see what's really changing.

Do you ever run into issues with lines that look different but mean the same thing? Like interface reordering?



   
ReplyQuote
(@finops_auditor_ray)
Honorable Member
Joined: 6 months ago
Posts: 467
 

You're filtering out `edit 0` lines. That's a dangerous assumption. What if your config legitimately has an object with index 0 that you *did* modify? You'll miss that change in the diff.

The password/private-key filter is solid though. That's the kind of noise you actually want gone.

Show me a diff from this script on a real config change. I need to see the before/after configs and your script's output to believe it's reliable.


show me the bill


   
ReplyQuote
(@integration_ian)
Honorable Member
Joined: 5 months ago
Posts: 396
 

You're right that filtering `edit 0` is dangerous. That's a brittle, text-based assumption.

If you're going to parse configs, you need to understand the hierarchy. A better approach is to parse blocks, track parents, and then compare objects. Your script will fail silently on meaningful changes.

Since you're already in Python, consider using a proper lib to parse the config into objects before diffing. Or use the FortiGate API to pull structured configs and compare JSON - that's how I'd do it in a middleware workflow. Text diffs are a last resort.


Integration is not a project, it's a lifestyle.


   
ReplyQuote
(@benjislack)
Reputable Member
Joined: 2 months ago
Posts: 244
 

JSON from the API is just another text dump, you still have to parse it. It just moves the complexity around. The real problem is trusting any automated diff with network configs. If your change is critical, you need to read the full before and after config yourself. Every diff tool gives you a false sense of security.

> A better approach is to parse blocks, track parents, and then compare objects.

You're describing building a custom parser for a vendor-specific format. That's a huge maintenance sink. At that point you're better off buying a real config management product, even if it's expensive. This whole "quick script" thing is a trap.


your mileage will vary


   
ReplyQuote
(@cloud_cost_hawk)
Reputable Member
Joined: 3 months ago
Posts: 250
 

Filtering out `edit 0` lines will definitely miss real changes. I've seen firewall configs where the first object in a sequence was legitimately modified. Your script will show a clean diff while the actual config is broken.

But I get the desire to clean up noise. The password filter is good, but you need to go further. You should also strip out timestamps, auto-generated comments, and UUIDs that change on every export. Those create massive, meaningless diffs.

If you're going to stick with text diffs, at least make the filter a configurable list of regex patterns. That way when it silently fails, you can point to the config file and say "you were warned."


cost optimization, not cost cutting


   
ReplyQuote
(@gregm)
Honorable Member
Joined: 3 months ago
Posts: 424
 

The configurable regex list is just a way to document your own blind spots. You think you're building a warning system, but you're really creating a checklist for failure - "did we remember to add every possible dynamic field to the ignore list?"

You're spot on about timestamps and UUIDs, but the moment you start filtering those, you've admitted the text diff is useless for anything beyond basic sanity checking. Real config changes often involve those "noise" fields in ways that matter, like a timestamp that triggers a scheduled rule. Filter it out and you've missed the point of the change entirely.

This whole approach is polishing a brick.


Trust but verify


   
ReplyQuote