-
Notifications
You must be signed in to change notification settings - Fork 5
/
cisco_meraki_fw_ap_rules_api.py
324 lines (300 loc) · 12.7 KB
/
cisco_meraki_fw_ap_rules_api.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
###
### Cisco Meraki Firewall AP Rules API - robert@nigma.org
###
#!/usr/bin/env python
# Table layout
from tabulate import tabulate
# Progress bar
from tqdm import tqdm
import json
import requests
import sys
import os
import csv
import argparse
# Main Function
def main():
if meraki_debug == "1":
print("Debug enabled")
print("Args: %s" % args)
# If using arg --list-network, then print a table with all the network ssid associated with this Meraki API Token
if args.list_networks is True:
list_networks = meraki_list_networks()
global fw_ap_list
global fw_ap_list_raw
global fw_ap_list_upload
print("")
print("- List Firewall rules (AP) -")
fw_ap_list = meraki_ap_fw_rules("pre")
# Import Firewall rules from CSV file, if using arg --csv
if args.csv:
print("- Importing CSV file %s -" % args.csv)
print("")
fw_ap_list_upload = meraki_ap_fw_rules_import_csv(args.csv)
print("")
# User input for override the firewall rules
else:
print("- Add your new firewall rule below (end by double hitting ENTER or exit through Ctrl-C) =>")
lines = []
try:
while True:
line = input()
if line.lower() == "exit":
sys.exit("- User typed 'exit', exiting... -")
if line:
lines.append(line)
else:
break
except KeyboardInterrupt:
print("")
sys.exit("- User pressed CTRL-C, exiting... -")
if len(lines) == 0:
sys.exit("- No input for Firewall rules, exiting... -")
for item in lines:
# Split by , (csv support)
fw_ap_list_upload.append(item.split(","))
# Assume Yes based on arg
if args.yes:
print("- Do you want to update the firewall rules with your input? (exit by pressing CTRL-C) => yes")
print("- We'll send the data now... -")
print(tabulate(fw_ap_list_upload,headers=['Policy','Protocol','Destination','Port','Comment'],tablefmt="rst"))
# Creating the JSON Payload
fw_ap_list_upload_json = {}
fw_ap_list_upload_json["rules"] = []
for item in fw_ap_list_upload:
if item[2] != "Local LAN" and item[2] != "Any":
fw_ap_list_upload_json["rules"].append({"comment": item[4],"policy": item[0],"protocol": item[1],"destPort": item[3],"destCidr": item[2]})
if meraki_debug == "1":
print("JSON Payload")
print(fw_ap_list_upload_json)
print("")
url = "/networks/%s/ssids/%s/l3FirewallRules" % (args.network,args.ssid)
send_data = meraki_put(url,meraki_api_key,fw_ap_list_upload_json)
else:
# Verify CSV import or user input
try:
while True:
confirm_input = input("- Do you want to update the firewall rules with your input? (exit by pressing CTRL-C) => ")
confirm_input = confirm_input.lstrip() # Ignore leading space
if confirm_input == 'yes' or confirm_input == "y":
print("- We'll send the data now... -")
print(tabulate(fw_ap_list_upload,headers=['Policy','Protocol','Destination','Port','Comment'],tablefmt="rst"))
# Creating the JSON Payload
fw_ap_list_upload_json = {}
fw_ap_list_upload_json["rules"] = []
for item in fw_ap_list_upload:
if item[2] != "Local LAN" and item[2] != "Any":
fw_ap_list_upload_json["rules"].append({"comment": item[4],"policy": item[0],"protocol": item[1],"destPort": item[3],"destCidr": item[2]})
if meraki_debug == "1":
print("JSON Payload")
print(fw_ap_list_upload_json)
print("")
url = "/networks/%s/ssids/%s/l3FirewallRules" % (args.network,args.ssid)
send_data = meraki_put(url,meraki_api_key,fw_ap_list_upload_json)
break
else:
sys.exit("- User typed something else then 'yes' or 'y' - exiting... -")
except KeyboardInterrupt:
print("")
sys.exit("- User pressed CTRL-C, exiting... -")
sys.exit(" - Done, exiting... -")
# Meraki REST API Call - GET
def meraki_requests(url,meraki_api_key,error_handle):
url = "https://dashboard.meraki.com/api/v0%s" % url
if meraki_debug == "1":
print("GET: %s" % url)
querystring = {}
headers = {
'x-cisco-meraki-api-key': meraki_api_key,
'content-type': "application/json",
'cache-control': "no-cache",
}
response = requests.request("GET", url, headers=headers, params=querystring)
if response.status_code == 200:
json_data = json.loads(response.text)
return json_data
else:
if meraki_debug == "1":
print(response.text)
if error_handle == "enable":
sys.exit("Failed: Code %s" % response.status_code)
# Meraki REST API Call - PUT
def meraki_put(url,meraki_api_key,payload):
url = "https://dashboard.meraki.com/api/v0%s" % url
if meraki_debug == "1":
print("POST: %s" % url)
global fw_ap_list
global fw_ap_list_raw
global fw_ap_list_upload
global fw_ap_list_upload_json
payload = json.dumps(payload)
headers = {
'x-cisco-meraki-api-key': meraki_api_key,
'content-type': "application/json",
'cache-control': "no-cache",
}
response = requests.request("PUT", url, data=payload, headers=headers)
if response.status_code == 200:
json_data = json.loads(response.text)
# Reset global vars as firewalls are now updated
fw_ap_list=[]
fw_ap_list_raw=[]
fw_ap_list_upload=[]
fw_ap_list_upload_json=[]
print("")
print("- Successful... Display new FW rules table -")
print("")
if meraki_debug == "1":
print(response.text)
print("")
# Prints the FW table again
meraki_ap_fw_rules("post")
return json_data
else:
if meraki_debug == "1":
print(response.text)
sys.exit("Failed: Code %s" % response.status_code)
# List all Firewall Rules
def meraki_ap_fw_rules(status):
json_fw_ap_list = meraki_requests("/networks/%s/ssids/%s/l3FirewallRules" % (args.network,args.ssid),meraki_api_key, "enable")
global fw_ap_list
for item in json_fw_ap_list:
fw_ap_list_raw.append([item["policy"]+','+item["protocol"]+','+item["destCidr"]+','+item["destPort"]+','+item["comment"]])
fw_ap_list.append([item["policy"],item["protocol"],item["destCidr"],item["destPort"],item["comment"]])
print(tabulate(fw_ap_list,headers=['Policy','Protocol','Destination','Port','Comment'],tablefmt="rst"))
if status == "pre":
print("")
print(tabulate(fw_ap_list_raw,headers=['- Copy paste output (use as template) -'],tablefmt="rst"))
print("")
return fw_ap_list
# Import CSV file
def meraki_ap_fw_rules_import_csv(filename):
fw_ap_import_csv_list = []
try:
with open(filename) as csvfile:
fw_ap_import_csv = csv.reader(csvfile, delimiter=',')
key=0
for item in fw_ap_import_csv:
if key != 0:
print(item)
fw_ap_import_csv_list.append(item)
if len(item) < 5:
key +=1
print("")
sys.exit("- Error: Row %s isn't correct, exiting... -" % key)
key +=1
return fw_ap_import_csv_list
except FileNotFoundError:
sys.exit("- Error: CSV file not found %s, exiting... -" % filename)
def meraki_list_networks():
org_list = meraki_org()
print("- Gathering all the networks from %s organizations -" % len(org_list))
with tqdm(desc='Progess',total=(len(org_list))) as pbar:
# Loop through every Org
for item in org_list:
url = "/organizations/%s/networks" % item[0]
# Get all the networks based on Org
json_data_network = meraki_org_networks(item[0])
if json_data_network:
if meraki_debug == "1":
print("API Enabled")
else:
if meraki_debug == "1":
print("Network ID %s" % item[0])
print("API Access Disabled")
pbar.update(1)
if meraki_debug == "1":
print(tabulate(networks_list,headers=['Network ID','Network Name',"Org ID"],tablefmt="rst"))
print("- Creating a table with all the SSID from %s networks in %s organizations -" % (len(networks_list), len(org_list)))
with tqdm(desc='Progess',total=(len(networks_list))) as pbar:
# Loop through every network
for item in networks_list:
pbar.update(1)
# Get SSID data from Network ID
json_data_networks_ssid = meraki_org_networks_ssid(item[0],item[1],item[2])
print("")
print(tabulate(networks_list_ssid,headers=['Network ID','Network Name',"Organization ID","SSID","Number","Status"],tablefmt="rst"))
print("")
sys.exit("- Done, exiting... -")
# List all org id
def meraki_org():
json_data_org = meraki_requests("/organizations/",meraki_api_key, "enable")
org_list=[]
for item in json_data_org:
org_list.append([item["id"],item["name"]])
if meraki_debug == "1":
print(tabulate(org_list,headers=['Org ID','Name'],tablefmt="rst"))
return org_list
# List all the network id with org id
def meraki_org_networks(network_id):
url = "/organizations/%s/networks" % network_id
json_data_networks = meraki_requests(url,meraki_api_key,"disable")
global networks_list
if json_data_networks:
for item in json_data_networks:
networks_list.append([item["id"],item["name"],item["organizationId"]])
if meraki_debug == "1":
print(tabulate(networks_list,headers=['Network ID','Network Name',"Org ID"],tablefmt="rst"))
return networks_list
# List all SSID on network id with org id
def meraki_org_networks_ssid(network_id,network_name,org_id):
url = "/networks/%s/ssids" % network_id
json_data_networks_ssid = meraki_requests(url,meraki_api_key,"disable")
global networks_list_ssid
if json_data_networks_ssid:
for item in json_data_networks_ssid:
if item["enabled"] is True:
item["enabled"] = "Enabled"
if item["enabled"] is False:
item["enabled"] = "Disabled"
networks_list_ssid.append([network_id,network_name,org_id,item["name"],item["number"],item["enabled"]])
if meraki_debug == "1":
print(tabulate(networks_list_ssid,headers=['Network ID','Network Name',"Organization ID","SSID","Number","Status"],tablefmt="rst"))
return networks_list
# Start script if running as standalone
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Cisco Meraki Firewall AP Rules API - Help section')
parser.add_argument('--token',
help='Meraki token (if not using ENV)')
parser.add_argument('--list-networks', action='store_true',
help='List all the Network id and Org id associated with your API token')
parser.add_argument('--network',
help='Network id (Wireless/Templates)')
parser.add_argument('--ssid',
help='SSID id (0-14)')
parser.add_argument('--csv',
help='Import rules from CSV file')
parser.add_argument('--yes', action='store_true',
help='Assume Yes to all queries and do not prompt')
parser.add_argument('--debug', action='store_true',
help='Debug JSON Payload or when listing networks')
# If args are missing, print help
if len(sys.argv[1:])==0:
parser.print_help()
parser.exit()
args = parser.parse_args()
# No point to assume yes on all queries if user hasn't imported firewall rules
if args.yes and args.csv is None:
parser.error("--yes requires --csv")
if args.token:
os.environ['MERAKI_TOKEN'] = args.token
if 'MERAKI_TOKEN' in os.environ:
meraki_api_key = os.environ['MERAKI_TOKEN']
else:
try:
meraki_api_key
except:
parser.error("--token required if MERAKI_TOKEN isn't set")
if 'MERAKI_DEBUG' in os.environ:
meraki_api_key = os.environ['DEBUG']
else:
meraki_debug = "0"
if args.debug:
meraki_debug = "1"
# Create global variables
networks_list=[]
networks_list_ssid=[]
fw_ap_list=[]
fw_ap_list_raw=[]
fw_ap_list_upload=[]
main()