mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-05 15:29:01 +03:00
Add folder anatomy (scripts/agent.py + references/api-reference.md) for 648 cybersecurity skills
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
This commit is contained in:
@@ -0,0 +1,204 @@
|
||||
#!/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()
|
||||
Reference in New Issue
Block a user