Meraki Firewall Changes

Bonzo
Comes here often

Meraki Firewall Changes

Hi folks!

We just got started with Meraki and had to check the change log for L3 outbound firewall rule changes today.
To our suprise, the log entries contained the old and new value of the first 4096 characters of the complete ruleset making it extremely difficult to see any changes and impossible when the rule is further down the ruleset.
The CSV export linked on the page just shows the same dataset.


How are others tracking changes? I am currently doing this through a manual process and it has to be a better option.

 

Any good 3rd party tools out there ?


Any plans on the roadmap to fix this?

3 REPLIES 3
RaphaelL
Kind of a big deal
Kind of a big deal

I can't find my other post , but this is a real issue that we are all facing.

 

I don't have concrete answers for your answer. But I don't think that we are going to have a 'fix' for that.

PhilipDAth
Kind of a big deal
Kind of a big deal

Not a great solution - but I have customers that use a script for doing this.  One to export all the rules (which they do before any changes), and one to import rules.  It also makes rolling back/forward easy.

PhilipDAth
Kind of a big deal
Kind of a big deal

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()

 

Get notified when there are additional replies to this discussion.
Welcome to the Meraki Community!
To start contributing, simply sign in with your Cisco account. If you don't yet have a Cisco account, you can sign up.
Labels