mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-11 21:54:56 +03:00
27c6414ca5
Complete skill folder anatomy across all cybersecurity skills: - scripts/agent.py: 80-150 line Python agents using real libraries (impacket, boto3, azure-mgmt-*, kubernetes, pefile, yara, scapy, shodan, stix2, etc.) - references/api-reference.md: real API documentation with method signatures - LICENSE: MIT license for all skill folders
205 lines
7.0 KiB
Python
205 lines
7.0 KiB
Python
#!/usr/bin/env python3
|
|
"""VLAN Network Segmentation Agent - Configures and audits VLAN segmentation on managed switches."""
|
|
|
|
import json
|
|
import logging
|
|
import argparse
|
|
from datetime import datetime
|
|
|
|
from netmiko import ConnectHandler
|
|
from napalm import get_network_driver
|
|
|
|
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def connect_netmiko(host, username, password, device_type="cisco_ios"):
|
|
"""Establish SSH connection to network device via Netmiko."""
|
|
device = {
|
|
"device_type": device_type,
|
|
"host": host,
|
|
"username": username,
|
|
"password": password,
|
|
"timeout": 30,
|
|
}
|
|
conn = ConnectHandler(**device)
|
|
logger.info("Connected to %s (%s)", host, device_type)
|
|
return conn
|
|
|
|
|
|
def get_vlan_config(conn):
|
|
"""Retrieve current VLAN configuration from the switch."""
|
|
output = conn.send_command("show vlan brief", use_textfsm=True)
|
|
if isinstance(output, list):
|
|
vlans = []
|
|
for entry in output:
|
|
vlans.append({
|
|
"vlan_id": entry.get("vlan_id", ""),
|
|
"name": entry.get("name", ""),
|
|
"status": entry.get("status", ""),
|
|
"interfaces": entry.get("interfaces", []),
|
|
})
|
|
logger.info("Retrieved %d VLANs", len(vlans))
|
|
return vlans
|
|
return []
|
|
|
|
|
|
def create_vlan(conn, vlan_id, vlan_name):
|
|
"""Create a new VLAN on the switch."""
|
|
commands = [
|
|
f"vlan {vlan_id}",
|
|
f"name {vlan_name}",
|
|
]
|
|
output = conn.send_config_set(commands)
|
|
logger.info("Created VLAN %s (%s)", vlan_id, vlan_name)
|
|
return output
|
|
|
|
|
|
def configure_access_port(conn, interface, vlan_id):
|
|
"""Configure a switch port as an access port in a specific VLAN."""
|
|
commands = [
|
|
f"interface {interface}",
|
|
"switchport mode access",
|
|
f"switchport access vlan {vlan_id}",
|
|
"switchport port-security",
|
|
"switchport port-security maximum 2",
|
|
"switchport port-security violation restrict",
|
|
"spanning-tree portfast",
|
|
"spanning-tree bpduguard enable",
|
|
]
|
|
output = conn.send_config_set(commands)
|
|
logger.info("Configured %s as access port in VLAN %s", interface, vlan_id)
|
|
return output
|
|
|
|
|
|
def configure_trunk_port(conn, interface, allowed_vlans):
|
|
"""Configure a switch port as a trunk port with specific allowed VLANs."""
|
|
vlan_list = ",".join(str(v) for v in allowed_vlans)
|
|
commands = [
|
|
f"interface {interface}",
|
|
"switchport mode trunk",
|
|
"switchport trunk encapsulation dot1q",
|
|
f"switchport trunk allowed vlan {vlan_list}",
|
|
"switchport trunk native vlan 999",
|
|
"switchport nonegotiate",
|
|
]
|
|
output = conn.send_config_set(commands)
|
|
logger.info("Configured %s as trunk with VLANs %s", interface, vlan_list)
|
|
return output
|
|
|
|
|
|
def harden_unused_ports(conn, interfaces):
|
|
"""Shut down and assign unused ports to a quarantine VLAN."""
|
|
commands = []
|
|
for iface in interfaces:
|
|
commands.extend([
|
|
f"interface {iface}",
|
|
"switchport mode access",
|
|
"switchport access vlan 999",
|
|
"shutdown",
|
|
])
|
|
output = conn.send_config_set(commands)
|
|
logger.info("Hardened %d unused ports", len(interfaces))
|
|
return output
|
|
|
|
|
|
def configure_inter_vlan_acl(conn, acl_name, rules):
|
|
"""Configure access control lists for inter-VLAN routing."""
|
|
commands = [f"ip access-list extended {acl_name}"]
|
|
for rule in rules:
|
|
commands.append(rule)
|
|
output = conn.send_config_set(commands)
|
|
logger.info("Configured ACL %s with %d rules", acl_name, len(rules))
|
|
return output
|
|
|
|
|
|
def audit_vlan_security(conn):
|
|
"""Audit VLAN configuration for common security issues."""
|
|
findings = []
|
|
vlan_output = conn.send_command("show vlan brief")
|
|
if "VLAN0001" in vlan_output:
|
|
trunk_output = conn.send_command("show interfaces trunk")
|
|
if "1" in trunk_output:
|
|
findings.append({
|
|
"check": "Native VLAN",
|
|
"finding": "Default VLAN 1 may be used as native VLAN on trunks",
|
|
"severity": "Medium",
|
|
"remediation": "Change native VLAN to unused VLAN (e.g., 999)",
|
|
})
|
|
|
|
port_output = conn.send_command("show interfaces status")
|
|
if "notconnect" in port_output.lower():
|
|
findings.append({
|
|
"check": "Unused Ports",
|
|
"finding": "Ports in notconnect state may not be hardened",
|
|
"severity": "Low",
|
|
"remediation": "Assign to quarantine VLAN and shut down",
|
|
})
|
|
|
|
dtp_output = conn.send_command("show dtp")
|
|
if "DESIRABLE" in dtp_output or "AUTO" in dtp_output:
|
|
findings.append({
|
|
"check": "DTP Negotiation",
|
|
"finding": "DTP negotiation enabled - VLAN hopping risk",
|
|
"severity": "High",
|
|
"remediation": "Set all access ports to 'switchport nonegotiate'",
|
|
})
|
|
|
|
logger.info("Security audit: %d findings", len(findings))
|
|
return findings
|
|
|
|
|
|
def get_napalm_config(host, username, password, driver="ios"):
|
|
"""Retrieve device configuration using NAPALM for multi-vendor support."""
|
|
Driver = get_network_driver(driver)
|
|
device = Driver(host, username, password, timeout=30)
|
|
device.open()
|
|
facts = device.get_facts()
|
|
interfaces = device.get_interfaces()
|
|
vlans = device.get_vlans()
|
|
device.close()
|
|
return {"facts": facts, "interfaces": interfaces, "vlans": vlans}
|
|
|
|
|
|
def generate_report(host, vlans, audit_findings, actions):
|
|
"""Generate VLAN segmentation audit report."""
|
|
report = {
|
|
"device": host,
|
|
"timestamp": datetime.utcnow().isoformat(),
|
|
"vlans": vlans,
|
|
"security_findings": audit_findings,
|
|
"configuration_actions": actions,
|
|
}
|
|
print(f"VLAN SEGMENTATION REPORT: {len(vlans)} VLANs, {len(audit_findings)} findings")
|
|
return report
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="VLAN Network Segmentation Agent")
|
|
parser.add_argument("--host", required=True, help="Switch management IP")
|
|
parser.add_argument("--username", required=True, help="SSH username")
|
|
parser.add_argument("--password", required=True, help="SSH password")
|
|
parser.add_argument("--device-type", default="cisco_ios", help="Netmiko device type")
|
|
parser.add_argument("--audit-only", action="store_true", help="Audit without changes")
|
|
parser.add_argument("--output", default="vlan_report.json")
|
|
args = parser.parse_args()
|
|
|
|
conn = connect_netmiko(args.host, args.username, args.password, args.device_type)
|
|
vlans = get_vlan_config(conn)
|
|
findings = audit_vlan_security(conn)
|
|
|
|
actions = []
|
|
if not args.audit_only:
|
|
logger.info("Audit-only mode not set - configuration changes require explicit commands")
|
|
|
|
report = generate_report(args.host, vlans, findings, actions)
|
|
conn.disconnect()
|
|
|
|
with open(args.output, "w") as f:
|
|
json.dump(report, f, indent=2)
|
|
logger.info("Report saved to %s", args.output)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|