cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
15978
Views
6
Helpful
27
Replies

correct endpoint for firewall rules?

Adrian41
Level 6
Level 6

Hi,

New to API's and coding in general.

I am trying to write a script that adds a new firewall rule to a network (I'm using a test site atm).

However I am getting a 404 error which I assume means my URL is wrong?

I got this from the Meraki reference guide but I'm not sure its correct.

/networks/{network_id}/appliance/firewall/l3firewallRules

Also - I read somewhere that adding a new rule would overwrite all the existing rules! Is that true and if so is there a way to add a rule so that it doesn't effect any existing rules?

Thanks!

import requests
import security
import json


api_key = security.MERAKI_API_KEY
organizationId = security.ORG_ID
network_id = "xxxxxxxxx"

rule = {
'name': 'Test Rule',
'policy': 'deny',
'protocol': 'any',
'srcPort': 'any',
'srcCidr': '1.1.1.1/24',
'dstPort': 'any',
'dstCidr': '0.0.0.0/0',
}


url = f"https://api.meraki.com/api/v1/networks/{network_id}/appliance/firewall/l3firewallRules"


headers = {
'X-Cisco-Meraki-API-Key': api_key,
'Content-Type': 'application/json'
}


response = requests.post(url, headers=headers, data=json.dumps(rule), verify=False)

print(response.status_code)
27 Replies 27

Thanks you!

This put me on the right track. I changed

data=json.dumps(rule)

to

data=rule,


and then changed the rule paramater to this

rule = '''{
"rules": [
{
"comment": "Test Rule.",
"policy": "allow",
"protocol": "tcp",
"destPort": "443",
"destCidr": "192.168.1.0/24",
"srcPort": "Any",
"srcCidr": "Any",
"syslogEnabled": false
}
]
}'''


(slight syntax change)


just my second issue now - this seems to overwrite all the existing rules rather than just add this to the list.

how do I add things without deleting all the others?

aleabrahao
Meraki Community All-Star
Meraki Community All-Star

You can't update, you have to set all rules again when you create a new rule.

I am not a Cisco employee. My suggestions are based on documentation of Meraki best practices and day-to-day experience.

Please, if this post was useful, leave your kudos and mark it as solved.

Raphael_L
Meraki Community All-Star
Meraki Community All-Star

You can't append a rule. You have to push the whole rule base.

So I would suggest doing a GET first , append your modifications , then PUT the whole rule base.

am I going to have to call the existing rules, then add them along with the new rule to the update call and basically re-write all the rules each time?

aleabrahao
Meraki Community All-Star
Meraki Community All-Star

https://developer.cisco.com/codeexchange/github/repo/CiscoSE/AddMerakiMXL3FirewallRuleToNetworks#usecase

https://developer.cisco.com/meraki/build/mx-firewall-control-python-script/

I am not a Cisco employee. My suggestions are based on documentation of Meraki best practices and day-to-day experience.

Please, if this post was useful, leave your kudos and mark it as solved.

Adrian41
Level 6
Level 6

regarding updating the rules and having to get a copy of existing rules and then adding those to the new update request - this is a little terrifying - what if it misses a rule or something, id have no way of checking 😕

I guess I could get it to export a json file after the get request as something I could look at to make sure its all ok right?

Yes. The order of firewall rules is important, and Dashboard can't assume placement. Placing a rule at the end may not actually do anyty, thus it is up to you to place a rule in the correct position.

Another approach to consider is that if you want maintain rules via the API, it may be worth keeping the 'master copy' in a local database, then just write the whole set each time.

Then if you need to check rules, it's an API read and compare against the local copy.

I'm having a problem appending the new rule list to the existing list :(|

I think its because I have created the existing rule list as a dictionary. However if I try to re-write the dictionary as a list (with square brackets [] ) the code stops working. "Invalid syntax"


import requests
import security
import json

# Replace with your Meraki API key and network ID
api_key = security.MERAKI_API_KEY
organizationId = security.ORG_ID
network_id = "xxxxxxxxxxxxxxxxx"



url = f"https://api.meraki.com/api/v1/networks/{network_id}/appliance/firewall/l3FirewallRules"



headers = {
'X-Cisco-Meraki-API-Key': api_key,
'Content-Type': 'application/json'
}


response = requests.get(url, headers=headers, verify=False)

existingrules = response.json()

print(response.status_code)
print(response.text.encode('utf8'))

with open('ExistingRules.json', 'w') as json_file:
json.dump(response.json(), json_file, indent=4)


newrule = '''{
"rules": [
{
"comment": "Test RuleNEW.",
"policy": "deny",
"protocol": "any",
"destPort": "any",
"destCidr": "192.200.1.0/24",
"srcPort": "Any",
"srcCidr": "Any",
"syslogEnabled": false
}
]
}'''

existingrules.append(newrule)

response = requests.put(url, headers=headers, json=existingrules, verify=False)

As mentioned by @dajirku it is probable that appending is not going to behave as you wish.

Usually the last rule in the list is 'allow any-any', if you append a stricter rule it will be ignored as it will be lower in precedence than 'allow any-any'

To add a rule to existingrules, you should be adding an item to the rules array within it, not direct to existingrules.

Have a look at...

https://github.com/CiscoSE/AddMerakiMXL3FirewallRuleToNetworks/blob/master/AddRulesToMXL3Firewall.py

You could do something along the lines of

# Constants
netowrk_id = "xxxx"
TargetComment = "Google DNS"

# Get Rules for network
FirewallRules = dashboard.appliance.getNetworkApplianceFirewallL3FirewallRules(network_id)
# Determine idx where rule should be updated
target_idx = next((idx for idx, item in enumerate(FirewallRules['rules']) if item['comment'] == TargetComment), None)
# Update rule
FirewallRules['rules'][target_idx].update({
    "comment": TargetComment
    "policy": "deny",
    "protocol": "any",
    "destPort": "any",
    "destCidr": "192.200.1.0/24",
    "srcPort": "Any",
    "srcCidr": "Any",
    "syslogEnabled": false
})
# Remove Default Rule entry
FirewallRules['rules'].pop(-1)
# Update Rules
NewSetOfRules = dashboard.appliance.updateNetworkApplianceFirewallL3FirewallRules(
    networkId=network_id,
    rules=FirewallRules['rules']
)

What happens is, that I search through all the elements in FirewallRules for the index of the element with the comment, of the rule I wan't to update.

With the index in hand, I can either update the rule, or use the index to inject a new rule. In the above example I use it to update a specific rule.

Modify it to suit your implementation.

#########
LinkedIn ::: https://blog.rhbirkelund.dk/
Like what you see? - Mark as helpful ## Did it answer your question? - Mark it as a Solution 🙂
All code examples are provided as is. Responsibility for Code execution is solely your own.

thanks. I have a working script now which does a similar thing. It injects the new rule to the existing but the rules are still updated by completely overwriting all existing rules with the list I send in - apparently that's the way it works, rather than just adding in any new items in the index.

It seems to work ok but I found that when you do the GET, the list includes the default allow rule. Then when you go to PUT the updated list - that Allow rule gets added like it was a custom rule so you end up with the default and an extra identical copy.

You get an extra Allow rule every time you do an update. I fixed this by searching the list index for that rule and deleting it (luckily the comment is "default Rule" which is nicely unique) before adding my new rule and sending it back.

Or use the a posteriori knowledge, that the default rule is always at the end of the list and simpy "pop it". 😉

# Remove Default Rule entry
FirewallRules['rules'].pop(-1)
#########
LinkedIn ::: https://blog.rhbirkelund.dk/
Like what you see? - Mark as helpful ## Did it answer your question? - Mark it as a Solution 🙂
All code examples are provided as is. Responsibility for Code execution is solely your own.