I did this for a customer, and used the API command on the management server:
FROM_DATE=$(date -d "90 days ago" +"%Y-%m-%d")
TO_DATE=$(date +"%Y-%m-%d")
JSON_FILE="firewall_rules.last_90_days.json"
CSV_FILE="firewall_rules.last_90_days.csv"
export MGMT_CLI_FORMAT=json
TOTAL_RULES=$(mgmt_cli -r true show-access-rulebase name Network package Standard limit 1 details-level uid | jq '.total')
mgmt_cli -r true show-access-rulebase name Network package Standard show-hits true hits-settings.from-date ${FROM_DATE} hits-settings.to-date ${TO_DATE} use-object-dictionary true limit ${TOTAL_RULES} > ${JSON_FILE}
echo '"Rule Number","Source","Destination","VPN","Service","Rule Action","Install On"' |tee ${CSV_FILE}
for rule in $(jq -r '.rulebase[] |
select(.type=="access-rule"), select(.type=="access-section").rulebase[] |
select(.enabled) |
select(.hits.value == 0)."rule-number"|@text' ${JSON_FILE})
do
jq --arg rule $rule '( [ ."objects-dictionary"[] | { key:.uid, value:.name } ] | from_entries ) as $objs |
.rulebase[]| select(.type=="access-rule"),select(.type=="access-section").rulebase[] |
select((."rule-number"|@text)==$rule) |
[ ( [ ."rule-number"|@text ]|@csv ),
( [ $objs[."source"[]] ]|@csv),
( [$objs[."destination"[]] ]|@csv),
( [ $objs[."vpn"[]] ]|@csv ),
( [ $objs[."service"[]] ]|@csv ),
( [ $objs[."action"] ]|@csv ),
( [ $objs[."install-on"[] ] ]|@csv )
] |@csv
' < ${JSON_FILE}
done |\
sed -e 's@\\"\\"@@g' -e 's@\\"@"@g' -e 's/^""/"/g' -e 's/""$/"/g' |tee -a ${CSV_FILE}
echo
The CSV file has a list of the rules with zero hits. Use however you wish. Adjust numbers in the script however you want.
# cat firewall_rules.last_90_days.csv
"number","source","destination","vpn","service","action","install on"
"1","obj1,obj2","obj1,obj2","Any","Any","Accept","gateway"
"28","obj3","obj4","Any","http","Accept","gateway2"