This script does it for group policy firewall rules. It was called mgp.py.
#!/usr/bin/env python3
#
# mgp lets you export the firewall rules from a group policy to a CSV file,
# and import firewall rules into a group policy.
#
# Installation:
# mfw uses dotenv to safely store your credentials. Create a file called .meraki.env
# in your home directory. For Linux this is typically /home/username. For Windows this
# is typically
# c:\users\<username>.
# Into .meraki.env put this line:
# MERAKI_DASHBOARD_API_KEY=<your API key>
# If you don't have an API key yet then follow the instructions on this page:
# https://documentation.meraki.com/zGeneral_Administration/Other_Topics/The_Cisco_Meraki_Dashboard_API
#
# Prior to running this script you'll need Python 3.x installed and you'll need to run the below
# commands to install the extra components required.
# pip3 install argparse
# pip3 install meraki
# pip3 install -U meraki
# pip3 install -U python-dotenv
#
# If you are using the script on Linux I would suggest marking it executable to make running
# it simpler.
# chmod +x mfw.py
#
# Usage:
# To export the current rules (or a set of previously imported rules):
# mfw.py -o "Your org name" -n "Your network name" -g "Group Policy Name" export rules.csv
# To import rules and append them to what is already in the dashboard:
# mfw.py -o "Your org name" -n "Your network name" -g "Group Policy Name" import rules.csv
#
# rules.csv might look like:
# Comment,Policy,Protocol,Source Port,Source CIDR,Destination Port,Destination CIDR,Syslog Enabled
# General Comment,allow,udp,Any,192.168.73.1/32,web,google,False
# ,deny,tcp,Any,192.168.73.2/32,80,google.com,False
#
# The script does not do any checking on the format of the files, so if you get an error from
# the meraki API during import you have put something in a format that the API does not like.
# You could try creating some of the rules in the dashboard and exporting them to see how they should
# look.
# You could try breaking up the rules you are importing into smaller files until you locate the rule
# with the error.
# Common things to look out for are to make sure all addresses are in prefix notation. You can't just
# have an IP address on its own.
#
# History:
# When: Who: What:
# 10/03/2023 PID Completed original.
import os,argparse,meraki,csv
# Load global and local Meraki settings such as MERAKI_DASHBOARD_API_KEY
from dotenv import load_dotenv
load_dotenv()
load_dotenv(dotenv_path=os.path.join(os.path.expanduser("~"),".meraki.env"))
dashboard = meraki.DashboardAPI(
output_log=False,
print_console=False
)
# This function retrieves the netId
def getNetId(orgName,netName):
orgId=None
netId=None
# Search for the org
for org in dashboard.organizations.getOrganizations():
if org['name'] == orgName:
orgId=org['id']
break;
if orgId == None:
print("Invalid organization name supplied: "+orgName)
exit(-1)
# Search for the network
for net in dashboard.organizations.getOrganizationNetworks(orgId):
if net['name'] == netName:
netId=net['id']
break;
# If no network, search for a template
if netId == None:
for net in dashboard.organizations.getOrganizationConfigTemplates(orgId):
if net['name'] == netName:
netId=net['id']
break;
# Nothing found matching at all
if netId == None:
print("Invalid network name supplied: "+netName)
exit(-1)
return netId
# Retrieve the group policy object
def getGroupPolicy(networkId,groupPolicyName):
# Loop through the user defined network group policies looking for the correct one
policies=dashboard.networks.getNetworkGroupPolicies(networkId)
for policy in policies:
if policy['name'] == groupPolicyName:
return(policy)
print(f"Group policy {groupPolicyName} not found in network")
exit(-1)
# Save the appliance layer 3 rules to a local file
def exportFirewallRules(gp,csvHandle):
csv_rules=csv.writer(csvHandle, dialect='excel')
csv_rules.writerow(["Policy", "Protocol", "Destination", "Port", "Comment"])
# Load firewall rules from here
firewallAndTrafficShaping=gp['firewallAndTrafficShaping']
if firewallAndTrafficShaping['settings'] != 'custom':
print("The group policy does not have any custom firewall rules")
exit(-1)
# Loop through the rules and export
for rule in firewallAndTrafficShaping['l3FirewallRules']:
csv_rules.writerow([rule["policy"],rule["protocol"],rule['destCidr'],rule['destPort'],rule['comment']])
# Load the firewall rules from local files and apply them to the Meraki Dashboard network
def importFirewallRules(netId,gp,csvHandle):
l3FirewallRules=[]
csv_rules=csv.reader(csvHandle, dialect='excel')
# Read in all the rules
next(csv_rules) # Skip the header
for row in csv_rules:
if len(row)==5:
l3FirewallRules.append({'policy':row[0],'protocol':row[1],'destCidr':row[2],'destPort':row[3],'comment':row[4]})
# Specify we are using custom firewall rules
gp['firewallAndTrafficShaping']['settings']='custom'
gp['firewallAndTrafficShaping']['l3FirewallRules']=l3FirewallRules
dashboard.networks.updateNetworkGroupPolicy(netId,gp['groupPolicyId'],firewallAndTrafficShaping=gp['firewallAndTrafficShaping'])
def main():
# Meraki parameters
orgName=None
netName=None
gpName=None
netId=None
text="""
mfw.py ...
In your home diretory you should have a .meraki.env file containing MERAKI_DASHBOARD_API_KEY=<your API key>
"""
parser = argparse.ArgumentParser(description = text)
parser.add_argument("-o", "--orgName", help="Meraki org name")
parser.add_argument("-n", "--netName", help="Meraki network name")
parser.add_argument("-g", "--groupPolicyName", help="Meraki group policy name")
subparsers = parser.add_subparsers(dest="command", required=True, help='sub-command help')
parser_a = subparsers.add_parser('export', help='Exports rules and objects to local files')
parser_a.add_argument("csv", help="CSV file of access list rules",type=argparse.FileType('w'))
parser_a = subparsers.add_parser('import', help='Imports rules and objects to the Meraki Dashboard from local files')
parser_a.add_argument("csv", help="CSV file of access list rules",type=argparse.FileType('r'))
args=parser.parse_args()
orgName=os.getenv("orgName")
netName=os.getenv("netName")
if args.orgName: orgName=args.orgName
if args.netName: netName=args.netName
if args.groupPolicyName: gpName=args.groupPolicyName
if not os.getenv("MERAKI_DASHBOARD_API_KEY"):
print("MERAKI_DASHBOARD_API_KEY must be defined in .meraki.env in your home directory or in .env in the current directory")
exit(-1)
if not orgName:
print("orgName must be defined on the command line, in .meraki.env in your home directory or in .env in the current directory")
exit(-1)
if not netName:
print("netName must be defined on the command line, in .meraki.env in your home directory or in .env in the current directory")
exit(-1)
netId=getNetId(orgName,netName)
groupPolicy=getGroupPolicy(netId,gpName)
if args.command == "export": exportFirewallRules(groupPolicy,args.csv)
elif args.command == "import": importFirewallRules(netId,groupPolicy,args.csv)
args.csv.close()
main()