Skip to content

Commit

Permalink
Upgrade to version 1.4
Browse files Browse the repository at this point in the history
  • Loading branch information
akamura committed Mar 24, 2024
1 parent 5b4b702 commit 965f3b6
Show file tree
Hide file tree
Showing 19 changed files with 1,141 additions and 53 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,17 @@ To achieve the optimal experience, I highly encourage you to download and instal
- pysqlcipher3
- rich
- setuptools
- dnspython
- ipinfo
- scapy
- secrets
- numpy
- ipaddress

## IPinfo.io Token
The Swiss Army Knife tools include the powerful **IP Check** utility that run with IPinfo API, to use the utility you need to generate and save the API token.
You can SignUP for free at [IPinfo.io](https://ipinfo.io/) and from your Dashboard get the **Token**.
When you run the Cisco Meraki CLU choose the menu option **Set IPinfo Token** and paste your API token.

## Clone the repository
```shell
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#**************************************************************************
# App: Cisco Meraki CLU *
# Version: 1.3 *
# Version: 1.4 *
# Author: Matia Zanella *
# Description: Cisco Meraki CLU (Command Line Utility) is an essential *
# tool crafted for Network Administrators managing Meraki *
Expand Down
48 changes: 40 additions & 8 deletions Source code/LINUX_MACOS/opt/akamura/ciscomerakiclu/main.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#**************************************************************************
# App: Cisco Meraki CLU *
# Version: 1.3 *
# Version: 1.4 *
# Author: Matia Zanella *
# Description: Cisco Meraki CLU (Command Line Utility) is an essential *
# tool crafted for Network Administrators managing Meraki *
Expand Down Expand Up @@ -103,14 +103,16 @@ def main_menu(db_password):
term_extra.print_ascii_art()

api_key = meraki_api_manager.get_api_key(db_password)
ipinfo_token = db_creator.get_tools_ipinfo_access_token(db_password)
options = [
"Network wide [under dev]",
"Security & SD-WAN",
"Switch and wireless",
"Environmental [under dev]",
"Organization [under dev]",
"The Swiss Army Knife [under dev]",
"The Swiss Army Knife",
f"{'Edit Cisco Meraki API Key' if api_key else 'Set Cisco Meraki API Key'}",
f"{'Edit IPinfo Token' if ipinfo_token else 'Set IPinfo Token'}",
"Exit the Command Line Utility"
]
current_year = datetime.now().year
Expand All @@ -126,10 +128,12 @@ def main_menu(db_password):
print("└" + "─" * 58 + "┘")

term_extra.print_footer(footer)
choice = input(colored("Choose a menu option [1-8]: ", "cyan"))
choice = input(colored("Choose a menu option [1-9]: ", "cyan"))

if choice.isdigit() and 1 <= int(choice) <= 8:
if choice == '2':
if choice.isdigit() and 1 <= int(choice) <= 9:
if choice == '1':
pass
elif choice == '2':
if api_key:
submenu.submenu_mx(api_key)
else:
Expand All @@ -142,10 +146,17 @@ def main_menu(db_password):
else:
print("Please set the Cisco Meraki API key first.")
input(colored("\nPress Enter to return to the main menu...", "green"))

elif choice == '4':
pass
elif choice == '5':
pass
elif choice == '6':
submenu.swiss_army_knife_submenu(db_password)
elif choice == '7':
manage_api_key(db_password)
elif choice == '8':
manage_ipinfo_token(db_password)
elif choice == '9':
term_extra.clear_screen()
term_extra.print_ascii_art()

Expand All @@ -160,12 +171,27 @@ def main_menu(db_password):
else:
print(colored("Invalid choice. Please try again.", "red"))


def manage_api_key(db_password):
term_extra.clear_screen()
api_key = input("\nEnter the Cisco Meraki API Key: ")
meraki_api_manager.save_api_key(db_password, api_key)

def manage_ipinfo_token(db_password):
term_extra.clear_screen()
current_token = db_creator.get_tools_ipinfo_access_token(db_password)
if current_token:
print(colored(f"Current IPinfo Token: {current_token}", "yellow"))
change = input("Do you want to change it? [yes/no]: ").lower()
if change != 'yes':
return

new_token = input("\nEnter the new IPinfo access token: ")
if new_token:
db_creator.store_tools_ipinfo_access_token(db_password, new_token)
print(colored("\nIPinfo access token saved successfully.", "green"))
else:
print(colored("No token entered. No changes made.", "red"))


# ==================================================
# ERROR handling and logging
Expand All @@ -177,11 +203,17 @@ def manage_api_key(db_password):
os.system('clear')
term_extra.print_ascii_art()
db_password = db_creator.prompt_create_database()
if db_password:
db_creator.update_database_schema(db_password)
else:
os.system('clear')
term_extra.print_ascii_art()
db_password = getpass(colored("\n\nWelcome to Cisco Meraki Command Line Utility!\nThis program contains sensitive information. Please insert your password to continue: ", "green"))
db_creator.verify_database_password(db_password)
if db_creator.verify_database_password(db_password):
db_creator.update_database_schema(db_password)
else:
raise ValueError("Incorrect database password.")

main_menu(db_password)
except Exception as e:
logger.error("An error occurred", exc_info=True)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#**************************************************************************
# App: Cisco Meraki CLU *
# Version: 1.3 *
# Version: 1.4 *
# Author: Matia Zanella *
# Description: Cisco Meraki CLU (Command Line Utility) is an essential *
# tool crafted for Network Administrators managing Meraki *
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#**************************************************************************
# App: Cisco Meraki CLU *
# Version: 1.3 *
# Version: 1.4 *
# Author: Matia Zanella *
# Description: Cisco Meraki CLU (Command Line Utility) is an essential *
# tool crafted for Network Administrators managing Meraki *
Expand Down Expand Up @@ -64,7 +64,7 @@ def display_switch_ports(api_key, serial_number):
print(f"[red]Failed to fetch real-time port statuses/packets: {e}[/red]")

if switch_ports:
table = Table(show_header=True, header_style="green", box=SIMPLE)
table = Table(show_header=True, header_style="bold green", box=SIMPLE)

columns = [
("Port", 5), ("Name", 30), ("Enabled", 5),
Expand Down Expand Up @@ -123,7 +123,7 @@ def display_devices(api_key, network_id, device_type):

if devices:
devices = sorted(devices, key=lambda x: x.get('name', '').lower())
table = Table(show_header=True, header_style="green", box=SIMPLE)
table = Table(show_header=True, header_style="bold green", box=SIMPLE)

priority_columns = ['name', 'mac', 'lanIp', 'serial', 'model']
excluded_columns = ['networkId', 'details', 'lat', 'lng', 'firmware']
Expand Down Expand Up @@ -161,7 +161,7 @@ def display_organization_devices_statuses(api_key, organization_id, network_id):
if devices_statuses:
devices_statuses = [device for device in devices_statuses if device.get('productType') in ["switch", "wireless"]]
devices_statuses = sorted(devices_statuses, key=lambda x: x.get('name', '').lower())
table = Table(show_header=True, header_style="green", box=SIMPLE)
table = Table(show_header=True, header_style="bold green", box=SIMPLE)

priority_columns = ['name', 'serial', 'mac', 'ipType', 'lanIp', 'gateway', 'primaryDns', 'secondaryDns', 'PSU 1', 'PSU 2', 'status', 'lastReportedAt']

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#**************************************************************************
# App: Cisco Meraki CLU *
# Version: 1.3 *
# Version: 1.4 *
# Author: Matia Zanella *
# Description: Cisco Meraki CLU (Command Line Utility) is an essential *
# tool crafted for Network Administrators managing Meraki *
Expand Down Expand Up @@ -67,7 +67,7 @@ def display_firewall_rules(api_key, network_id, organization_id):
term_extra.print_ascii_art()

if rules:
table = Table(show_header=True, header_style="green", box=SIMPLE)
table = Table(show_header=True, header_style="bold green", box=SIMPLE)
priority_columns = ['policy', 'protocol', 'srcPort', 'srcCidr', 'destPort', 'destCidr']
excluded_columns = ['syslogEnabled']
other_columns = [key for key in rules[0].keys() if key not in priority_columns and key not in excluded_columns]
Expand Down Expand Up @@ -96,8 +96,6 @@ def display_firewall_rules(api_key, network_id, organization_id):
input(colored("\nPress Enter to return to the previous menu...", "green"))




# ==================================================
# PROCESS Data Inside Networks (MX Firewall Rules)
# ==================================================
Expand All @@ -106,8 +104,6 @@ def select_mx_network(api_key, organization_id):
if selected_network:
network_name = selected_network['name']
network_id = selected_network['id']

display_firewall_rules(api_key, network_id, organization_id)

downloads_path = str(Path.home() / "Downloads")
current_date = datetime.now().strftime("%Y-%m-%d")
Expand All @@ -117,23 +113,27 @@ def select_mx_network(api_key, organization_id):
while True:
term_extra.clear_screen()
term_extra.print_ascii_art()
header = "MX Firewall Rules Menu"

options = [
"List Firewall Rules",
"Download Firewall Rules CSV",
"Status (under dev)",
"Return to Main Menu"
]
term_extra.print_header(header)
term_extra.print_menu(options)

columns, _ = term_extra.get_terminal_size()
print("-" * columns)

# Description header over the menu
print("\n")
print("┌" + "─" * 58 + "┐")
print("│".ljust(59) + "│")
for index, option in enumerate(options, start=1):
print(f"│ {index}. {option}".ljust(59) + "│")
print("│".ljust(59) + "│")
print("└" + "─" * 58 + "┘")

choice = input(colored("\nChoose a menu option [1-4]: ", "cyan"))

if choice == '1':
display_firewall_rules(api_key, network_id)
display_firewall_rules(api_key, network_id, organization_id)

elif choice == '2':
firewall_rules = meraki_api.get_l3_firewall_rules(api_key, network_id)
Expand All @@ -143,6 +143,7 @@ def select_mx_network(api_key, organization_id):
else:
print("No firewall rules to download.")
choice = input(colored("\nPress Enter to return to the precedent menu...", "green"))

elif choice == '3':
pass
elif choice == '4':
break
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#**************************************************************************
# App: Cisco Meraki CLU *
# Version: 1.4 *
# Author: Matia Zanella *
# Description: Cisco Meraki CLU (Command Line Utility) is an essential *
# tool crafted for Network Administrators managing Meraki *
# Github: https://github.com/akamura/cisco-meraki-clu/ *
# *
# Icon Author: Cisco Systems, Inc. *
# Icon Author URL: https://meraki.cisco.com/ *
# *
# Copyright (C) 2024 Matia Zanella *
# https://www.matiazanella.com *
# *
# This program is free software; you can redistribute it and/or modify *
# it under the terms of the GNU General Public License as published by *
# the Free Software Foundation; either version 2 of the License, or *
# (at your option) any later version. *
# *
# This program is distributed in the hope that it will be useful, *
# but WITHOUT ANY WARRANTY; without even the implied warranty of *
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
# GNU General Public License for more details. *
# *
# You should have received a copy of the GNU General Public License *
# along with this program; if not, write to the *
# Free Software Foundation, Inc., *
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
#**************************************************************************


# ==================================================
# IMPORT various libraries and modules
# ==================================================
import dns.resolver
import json

from pathlib import Path
from termcolor import colored
from rich.console import Console
from rich.table import Table
from rich.progress import Progress
from rich.box import SIMPLE
from settings import term_extra

def reverse_ip(ip_address):
"""Reverse the IP address for DNSBL queries."""
return '.'.join(ip_address.split('.')[::-1])

def check_dnsbl(ip_address, services, progress):
"""Check if an IP address is listed in the specified DNSBL services."""
reversed_ip = reverse_ip(ip_address)
results = {}

for service_name, service_domain in progress.track(services.items(), description="☕ Time to take a coffee."):
query = f"{reversed_ip}.{service_domain}"
try:
dns.resolver.resolve(query, 'A')
results[service_name] = colored("Listed: YES", "red")
except dns.resolver.NoAnswer:
results[service_name] = colored("Listed: NO [NO ANSWER]", "green")
except dns.resolver.NXDOMAIN:
results[service_name] = colored("Listed: NO", "green")
except Exception as e:
results[service_name] = colored(f"Error: {e}", "yellow")
return results

def main():
term_extra.clear_screen()
term_extra.print_ascii_art()
current_script_path = Path(__file__).parent
dnsbl_json_path = current_script_path / 'dnsbl_services.json'

with open(dnsbl_json_path, "r") as file:
services_to_check = json.load(file)

ip_to_check = input("Please enter an IP address to check: ")

console = Console()
table = Table(show_header=True, header_style="bold green", box=SIMPLE)
table.add_column("Service", style="dim", width=50)
table.add_column("Result")

with Progress() as progress:
results = check_dnsbl(ip_to_check, services_to_check, progress)

for service, result in results.items():
table.add_row(service, result)

console.print(table)
input("Press Enter to return to the submenu...")


if __name__ == "__main__":
main()
Loading

0 comments on commit 965f3b6

Please sign in to comment.