I recently had a project where we had the chance to convert a Palo Alto ruleset to an Azure Firewall Policy. I had recently created a script to generate a Firewall Policy for Microsoft 365 endpoints, so the challenge was using that work as a basis to generate an Azure Firewall Policy out of the Palo Alto ruleset. TL;DR: here you have the pa2azfw.py tool. Achievement unlocked!
Unfortunately we were not ablet to generate a single JSON file covering the whole Palo Alto policy, which would have been ideal, so we worked with Panorama’s functionality to export part of the config to CSV format. We generated four CSV files, for which you can see simplified examples in the GitHub repo:
The challenge was interpreting these files and removing the ambiguity that the CSV format generates. For example, a policy source can be a single IPv4 address, a single IPv6 address, or an address group, so I had to write some logic to resolve those gray areas.
When run without output generation and in debug mode (log level 7), the script will search for all CSV files in the current directory and it will try to make sense of them, dynamically discovering whether they contain address groups, services, service groups or policies:
❯ python3 ./pa2azfw.py --log-level 7 --use-ip-groups DEBUG: searching for CSV files in folder '/mnt/c/Users/erjos/Repos/azure-firewall-rules-scripts'... DEBUG: CSV file pa_address_groups.csv found DEBUG: CSV file pa_policies.csv found DEBUG: CSV file pa_services.csv found DEBUG: CSV file pa_service_groups.csv found DEBUG: file pa_address_groups.csv seems to contain address groups DEBUG: skipping line '['\n']' DEBUG: file pa_policies.csv seems to contain policies DEBUG: file pa_services.csv seems to contain services DEBUG: file pa_service_groups.csv seems to contain service groups INFO: 4 services retrieved out of 1 files INFO: 1 service groups retrieved out of 1 files INFO: 3 address groups retrieved out of 1 files INFO: 3 rules retrieved out of 1 files DEBUG: 3 IP groups would be kept, minimum member count of these groups is 2, maximum is 2 DEBUG: 3 rules analized: 0 app rules, 0 FQDN-based net rules and 3 IP-based net rules DEBUG: 0 disabled rules, 3 allow rules and 0 deny rules
The script will generate an ARM template that contains either a full Azure Policy with a Rule Collection Group containing the translated rules, or just the Rule Collection Group that you can deploy to an existing policy. To generate the policy you just specify
JSON as the output format, optionally the flag
--pretty to make it more human readable, and redirect to a file:
python3 ./pa2azfw.py --log-level 4 --output json --use-ip-groups --pretty >pa-policy.json
You can see the output out of the sample files in the repo: pa-policy.json.
The Azure Firewall Policy
When deploying the previously generated pa-policy.json into Azure, the Address Groups will be transformed into Azure IP Groups:
More interestingly, the policies will be transformed into Azure Firewall network rules that leverage the previously created address groups. The services and service groups will be expanded into the corresponding protocol and port fields for each rule, since there is not an equivalent concept in Azure.
Can I use this?
Absolutely! However, please proceed with caution: I have tested this only with this one policy, so your Palo Alto ruleset might include artifacts that escape the script logic, or you might run a different Palo Alto software version that generates a different CSV format.
If you give it a try and it works I would love to hear about it, and if it doesn’t work for you I would love even more to hear about it.
In any case, please have a close look at the resulting Azure Firewall Policy, as well as at the errors and warnings that the script generates to make sure that you are not leaving out any rule.
Thanks for reading, and happy firewalling!
2 thoughts on “Importing Palo Alto policies to Azure Firewall”
This is very helpful. As I’m working on a project to move from a Fortinet to Azure Firewall I wonder how to get the same format as you use in your example from the exported Fortinet config that contains entries like this:
set name “Blacklist”
set uuid ***
set srcintf “WAN”
set dstintf “LAN”
set srcaddr “BLACKLIST-HOST-220.127.116.11”
set dstaddr “all”
set schedule “always”
set service “ALL”
set logtraffic all
Hey Michiel thanks for reading! Some time ago I did something similar for a Fortinet config, but as you can see in https://github.com/erjosito/azure-firewall-rules-scripts/blob/master/fortigate_test.txt the format that the customer gave me was different than yours. That being said, the finite state machine I implemented at the time might be reused for this, you can see the script in https://github.com/erjosito/azure-firewall-rules-scripts/blob/master/read_fortigate_config.py.
If you want I can try to help you with this, feel free to reach out to me in my email address firstname.lastname@example.org