Skip to content

Commit 7cf279f

Browse files
committed
Fix parser bugs, optimize Layer 3 subnet analysis, improve scripting & EOF menu safety
1 parent 0e6f371 commit 7cf279f

10 files changed

Lines changed: 1432 additions & 262 deletions

File tree

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ __pycache__/
66
# Local outputs & logs
77
raw_logs/
88
backups/
9+
deliverables/
910
nmap_results.xml
1011
failed_hosts.json
1112
asset_inventory.csv
@@ -17,8 +18,10 @@ migration_cabling_matrix.csv
1718
cisco_to_target_translation.md
1819
migration_config_variables.json
1920
migration_verification_report.md
20-
*.json
2121
oui.txt
22+
*.log
23+
*.cfg
24+
*.json
2225

2326
# OS specific files
2427
.DS_Store

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,14 @@ This shell will guide you through checking requirements, installing dependencies
7272

7373
---
7474

75+
## 📚 Documentation
76+
77+
Detailed guides and manuals are available in the `docs/` directory:
78+
* **[Junior Network Engineer Quick-Start Guide](docs/junior_engineer_guide.md)**: Walks through basic menu operations, using the simulated demo scan mode, and reading generated topology diagrams and reports.
79+
* **[Advanced Scripting & Automation Guide](docs/scripting_guide.md)**: Outlines command-line flags, environment variable parameterization, and integration scripts to run the crawler programmatically in cron jobs or CI/CD pipelines.
80+
81+
---
82+
7583
### Manual CLI Execution (Alternative)
7684

7785
If you prefer to run the scripts manually, follow these steps:

cisco_crawler.py

Lines changed: 223 additions & 75 deletions
Large diffs are not rendered by default.

docs/junior_engineer_guide.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# Cisco Switch Docu-Crawler - Junior Network Engineer Quick-Start Guide
2+
3+
Welcome to the **Cisco Switch Docu-Crawler**! This tool is designed to automate the discovery, auditing, configuration backup, and migration mapping of Cisco network switches and routers (supporting Cisco IOS, IOS-XE, NX-OS, and IOS-XR).
4+
5+
This guide is designed to help you get up to speed with running the tool safely and interpreting the generated outputs.
6+
7+
---
8+
9+
## 🚀 Running the Operator Shell
10+
11+
To make execution easy and consistent, the tool provides operator menus for both Unix/Linux and Windows platforms. These scripts check system requirements (like Python 3, pip, and Nmap) and install necessary packages automatically.
12+
13+
### On Unix/Linux/macOS:
14+
Open your terminal and run the shell script bootstrapper:
15+
```bash
16+
./run.sh
17+
```
18+
19+
### On Windows (PowerShell):
20+
Double-click `run.bat` or run it from a PowerShell window:
21+
```powershell
22+
PowerShell.exe -ExecutionPolicy Bypass -File .\run.ps1
23+
```
24+
25+
---
26+
27+
## 📋 Operations Menu: Step-by-Step
28+
29+
When you launch the script, you are presented with the **Operations Menu**:
30+
31+
```
32+
Operations Menu:
33+
1) Initialize Environment (Install Python packages)
34+
2) Run a New Discovery Scan
35+
3) Run Simulated Discovery (Demo Mode)
36+
4) List Current Backups
37+
5) Advanced Options Menu
38+
6) Exit
39+
```
40+
41+
### Step 1: Initialize Environment (Option 1)
42+
Run this the first time you clone the repository or set up a new machine. It ensures that the required Python libraries (like `netmiko` and `netaddr`) are installed and up-to-date.
43+
44+
### Step 2: Run Simulated Discovery (Option 3 - Highly Recommended First Step)
45+
Before scanning a live network, run a simulation.
46+
* **Safe Dry-Run**: It does not make any real network connections.
47+
* It uses mock switches (spanning different Cisco models like WS-C3850, WS-C2960X, and ISR4431) to generate a full set of deliverables.
48+
* **Purpose**: Allows you to check the report formatting and understand what the tool collects without any risk of affecting production systems.
49+
50+
### Step 3: Run a New Discovery Scan (Option 2)
51+
When you are ready to scan the live network:
52+
1. **Subnets Input**: The script will prompt you for target subnets (e.g. `192.168.1.0/24`). You can enter a single subnet or multiple subnets separated by commas.
53+
2. **Credentials Input**: Provide the SSH/Telnet username and password.
54+
* **AAA Lockout Prevention**: The crawler is built to gracefully halt retries if it hits a `NetmikoAuthenticationException` (authentication error). This prevents the crawler from locking out operator credentials in TACACS+/RADIUS AAA servers.
55+
3. **Scan Execution**: The tool will scan the subnets to locate active switches, validate login credentials, and crawl configuration details concurrently.
56+
57+
---
58+
59+
## 🛠️ Advanced Options Menu (Option 5)
60+
61+
Advanced operations are grouped under the **Advanced Options Menu** to prevent accidental misconfigurations:
62+
63+
* **Save/Compare Baselines**: Allows saving the running network state to a JSON file and comparing it later to detect changes (like new routes, modified neighbors, or interfaces going down).
64+
* **Retry/Resume**: Loads `failed_hosts.json` from a previous run to retry only the hosts that failed to connect, saving time.
65+
* **Crawler Customizations**:
66+
* **Thread Count**: Defaults to `10`. Raising this too high (e.g. `50+`) on older network platforms can saturate switch CPU control planes. Keep it low for safety.
67+
* **Connection Timeout**: The socket wait duration (default `10` seconds). Useful to raise only when scanning across high-latency WAN links.
68+
* **Telnet Fallback**: Toggles Telnet fallback. Toggling this off enforces SSH-only connections.
69+
70+
---
71+
72+
## 📁 Understanding the Deliverables
73+
74+
Every successful crawl creates a new folder under `deliverables/run_<timestamp>/`. The contents are organized as follows:
75+
76+
### 1. `inventory/asset_inventory.csv`
77+
A spreadsheet listing every discovered switch and router. It contains the Hostname, IP, MAC address, Hardware Model, Firmware Version, Serial Number, and Management Method.
78+
79+
### 2. `diagrams/L2_network_diagrams.md`
80+
Contains a **Mermaid.js** physical diagram showing how switches connect.
81+
* **Green Highlighted Nodes**: Represent Spanning Tree (STP) Root Bridges.
82+
* **Dashed Red Lines**: Represent active blocking ports (`BLK`) where STP is actively breaking topology loops.
83+
* **Solid Lines**: Forwarding connections (line thickness corresponds to link speed).
84+
85+
### 3. `diagrams/L3_network_diagrams.md`
86+
Contains a logical diagram mapping IP networks, SVIs (Switched Virtual Interfaces), Loopbacks, and default routing boundaries.
87+
88+
### 4. `analysis/network_analysis_report.md`
89+
An audit report highlighting issues:
90+
* Physical Layer: Speed/duplex mismatches, input/output packet errors, and CRC checksum issues.
91+
* Layer 2 Spanning Tree: STP Disabled switches (which present loop risks) and blocking ports list.
92+
* Layer 3 Subnet Conflicts: Flags **IP Address Conflicts** (same IP on two different switches) and **Subnet Overlaps** (overlapping routing ranges).
93+
* Services Audit: Flags missing NTP, DNS, or AAA security configurations.
94+
95+
### 5. `migration/`
96+
Contains configuration mapping variables (`migration_config_variables.json`), physical patching details (`migration_cabling_matrix.csv`), and translation guidelines (`cisco_to_target_translation.md`) to assist in planning migrations.

docs/scripting_guide.md

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
# Cisco Switch Docu-Crawler - Advanced Scripting & Integration Guide
2+
3+
The **Cisco Switch Docu-Crawler** is designed to be fully scriptable. This guide explains how to integrate the crawler into automated environments (such as cron jobs, Ansible playbooks, CI/CD pipelines, or custom Python orchestration scripts) by leveraging environment variables, CLI flags, and structured output files.
4+
5+
---
6+
7+
## 🔐 Credentials Automation
8+
9+
To run the crawler non-interactively without prompting for input, you can pass credentials using environment variables:
10+
11+
| Variable | Description |
12+
| --- | --- |
13+
| `CRAWLER_USER` or `CRAWLER_USERNAME` | SSH/Telnet Login Username |
14+
| `CRAWLER_PASSWORD` | SSH/Telnet Login Password |
15+
| `CRAWLER_SECRET` or `CRAWLER_ENABLE_SECRET` | Cisco Privileged EXEC Enable Secret |
16+
17+
### Bash Example:
18+
```bash
19+
export CRAWLER_USER="admin"
20+
export CRAWLER_PASSWORD="SecureLogin123"
21+
export CRAWLER_SECRET="SecureEnable123"
22+
23+
python3 cisco_crawler.py --subnets 10.0.1.0/24,10.0.2.0/24 --disable-telnet
24+
```
25+
26+
---
27+
28+
## ⚙️ CLI Reference Table
29+
30+
The `cisco_crawler.py` command line supports the following flags:
31+
32+
| Argument | Type | Default | Description |
33+
| --- | --- | --- | --- |
34+
| `--subnets` | string | *Local subnet* | Comma-separated target networks to scan (e.g. `10.0.0.0/24,192.168.1.0/24`) |
35+
| `--simulate` | flag | `False` | Run simulated scan & crawl (uses local mock switches without network traffic) |
36+
| `--disable-telnet` | flag | `False` | Disables Telnet connections and restricts connection protocol to SSH-only |
37+
| `--threads` | integer | `10` | Number of concurrent workers for switch scanning and crawls |
38+
| `--timeout` | integer | `10` | Connection and socket read timeout in seconds |
39+
| `--retry` | string | `None` | Path to `failed_hosts.json` to retry only previously failed targets |
40+
| `--baseline` | string | `None` | Filepath to save the collected network operational state (for baseline auditing) |
41+
| `--compare` | string | `None` | Filepath to a baseline JSON to compare the current network state against |
42+
| `--verbose` or `-v` | flag | `False` | Enable detailed debug logs printed to standard output |
43+
44+
---
45+
46+
## 🐍 Custom Python Integration Examples
47+
48+
### Example 1: Nightly Automation Script (subprocess)
49+
This script runs the crawler, automatically passing subnets and credentials via the process environment, and exits with a status code.
50+
51+
```python
52+
import subprocess
53+
import os
54+
import sys
55+
56+
def run_nightly_backup():
57+
print("[*] Starting scheduled backup run...")
58+
59+
# Configure run environment
60+
env = os.environ.copy()
61+
env["CRAWLER_USER"] = "admin"
62+
env["CRAWLER_PASSWORD"] = "SecurePassword123"
63+
env["CRAWLER_SECRET"] = "SecureEnableSecret123"
64+
65+
# Call crawler process
66+
cmd = [
67+
"python3", "cisco_crawler.py",
68+
"--subnets", "192.168.1.0/24",
69+
"--disable-telnet",
70+
"--threads", "15",
71+
"--timeout", "8"
72+
]
73+
74+
result = subprocess.run(cmd, env=env, capture_output=True, text=True)
75+
76+
if result.returncode == 0:
77+
print("[+] Crawler completed successfully!")
78+
print(result.stdout)
79+
else:
80+
print("[!] Crawler execution failed!", file=sys.stderr)
81+
print(result.stderr, file=sys.stderr)
82+
sys.exit(result.returncode)
83+
84+
if __name__ == "__main__":
85+
run_nightly_backup()
86+
```
87+
88+
### Example 2: Parsing Config Variables JSON
89+
You can parse the structured JSON variables output file (`migration_config_variables.json`) inside your own automation scripts to build inventory assets or populate CMDBs.
90+
91+
```python
92+
import json
93+
import glob
94+
import os
95+
96+
def load_latest_device_variables():
97+
# Locate the most recent run deliverables directory
98+
runs = glob.glob("deliverables/run_*")
99+
if not runs:
100+
print("No crawler runs found.")
101+
return
102+
103+
latest_run = max(runs, key=os.path.getmtime)
104+
vars_file = os.path.join(latest_run, "migration", "migration_config_variables.json")
105+
106+
if not os.path.exists(vars_file):
107+
print(f"Variables JSON not found in: {latest_run}")
108+
return
109+
110+
with open(vars_file, "r") as f:
111+
devices = json.load(f)
112+
113+
print(f"--- Decoupled Configuration Parameters ({latest_run}) ---")
114+
for hostname, config in devices.items():
115+
print(f"\nDevice: {hostname}")
116+
print(f" Management IP: {config.get('management_ip')}")
117+
print(f" Model: {config.get('model')}")
118+
print(f" DNS Servers: {', '.join(config.get('dns_servers', []))}")
119+
print(f" NTP Servers: {', '.join(config.get('ntp_servers', []))}")
120+
print(f" L3 Interfaces:")
121+
for intf in config.get("l3_interfaces", []):
122+
print(f" - {intf.get('interface')}: {intf.get('ip_address')} (Subnet: {intf.get('subnet')})")
123+
124+
if __name__ == "__main__":
125+
load_latest_device_variables()
126+
```
127+
128+
### Example 3: Running a Configuration State Baseline Audit
129+
This example automates baseline checks, saving the baseline config and raising alerts if the state changes in a future run.
130+
131+
```python
132+
import subprocess
133+
import os
134+
import sys
135+
136+
def check_network_baseline():
137+
baseline_path = "backups/production_baseline.json"
138+
env = os.environ.copy()
139+
env["CRAWLER_USER"] = "admin"
140+
env["CRAWLER_PASSWORD"] = "SecurePassword123"
141+
env["CRAWLER_SECRET"] = "SecureEnableSecret123"
142+
143+
# 1. Create baseline if it doesn't exist
144+
if not os.path.exists(baseline_path):
145+
print(f"[*] Baseline not found. Generating new baseline file at {baseline_path}...")
146+
cmd = ["python3", "cisco_crawler.py", "--subnets", "192.168.1.0/24", "--baseline", baseline_path]
147+
subprocess.run(cmd, env=env, check=True)
148+
print("[+] Baseline successfully saved.")
149+
return
150+
151+
# 2. Compare current network state against the baseline
152+
print("[*] Comparing current network state against baseline...")
153+
cmd = ["python3", "cisco_crawler.py", "--subnets", "192.168.1.0/24", "--compare", baseline_path]
154+
result = subprocess.run(cmd, env=env, capture_output=True, text=True)
155+
156+
# Check output for configuration delta drift
157+
if "State Comparison: CHANGES DETECTED" in result.stdout:
158+
print("[!] WARNING: Network drift detected!")
159+
# Print comparison report details
160+
print(result.stdout)
161+
# Here you could trigger email notifications or slack webhooks
162+
else:
163+
print("[+] Network state is consistent with the baseline.")
164+
165+
if __name__ == "__main__":
166+
check_network_baseline()
167+
```

0 commit comments

Comments
 (0)