This commit is contained in:
2025-12-23 12:59:36 +01:00
parent a931f3b3b9
commit 0f35e8a69c
55 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
# Docker run ID
getent group docker | cut -d: -f3

View File

@@ -0,0 +1,17 @@
# Use the official n8n image as a base
FROM n8nio/n8n:latest
# Switch to the root user to install packages
USER root
# Install docker-cli using the apk package manager
RUN apk add --no-cache docker-cli
# Install Python, pip, and required build dependencies
RUN apk add --no-cache python3 py3-pip build-base
# Install required Python packages
RUN pip install netmiko --break-system-packages
# Switch back to the non-privileged node user
USER node

View File

@@ -0,0 +1,82 @@
import json
# A bejövő adatok az n8n-től. A $items() függvénnyel hivatkozunk
# a korábbi node-okra a nevük alapján.
# Cseréld le a 'MySQL_Node_Neve' és 'Élő_Adat_Node_Neve' neveket
# a te munkafolyamatodban lévő node-ok tényleges nevére!
# Például:
# db_clients_items = $items("MySQL Client Fetch")
# live_clients_items = $items("Code (IP Scan Script)")
# Fontos: Ha az n8n Code node-jában futtatod, a $items funkciót közvetlenül használhatod.
# Ha külső szkriptként futtatod az "Execute Command" node-ból, akkor a bemenetet
# másképp kell kezelni (pl. parancssori argumentumként JSON stringet).
# Ez a kód az n8n Code node Python módjához készült.
db_clients_items = $items("MySQL_Node_Neve") # Ezt cseréld a MySQL node-od nevére
live_clients_items = $items("Élő_Adat_Node_Neve") # Ezt cseréld az élő adatokat adó Code node-od nevére
# Hozzuk létre a MAC cím alapján kereshető adathalmazokat
# Ellenőrizzük, hogy a bemeneti lista nem üres-e
db_clients = {}
if db_clients_items:
db_clients = {item.json['mac_address']: item.json for item in db_clients_items}
live_clients = {}
if live_clients_items:
live_clients = {item.json['mac_address']: item.json for item in live_clients_items}
differences = []
# 1. Új kliensek keresése (amik az élő adatokban vannak, de a DB-ben nem)
for mac, client_data in live_clients.items():
if mac not in db_clients:
differences.append({
"change_type": "ÚJ KLIENS",
"client": client_data
})
# 2. Eltávolított kliensek keresése (amik a DB-ben vannak, de az élő adatokban már nem)
for mac, client_data in db_clients.items():
if mac not in live_clients:
differences.append({
"change_type": "ELTÁVOLÍTOTT KLIENS",
"client": client_data
})
# 3. Változások keresése (pl. megváltozott az IP címe)
# Ez egy egyszerűbb példa, ami csak az IP-t figyeli.
# Ha több mezőt is figyelni akarsz, bővítsd ezt a részt.
for mac, live_data in live_clients.items():
if mac in db_clients:
db_data = db_clients[mac]
# Összehasonlítjuk az IP címet és a switch nevét
if live_data.get('ip_address') != db_data.get('ip_address') or \
live_data.get('switch_name') != db_data.get('switch_name') or \
live_data.get('interface') != db_data.get('interface') or \
live_data.get('vlan') != db_data.get('vlan'):
# Gyűjtsük össze a változásokat
changes = {}
if live_data.get('ip_address') != db_data.get('ip_address'):
changes['ip_address'] = {'from': db_data.get('ip_address'), 'to': live_data.get('ip_address')}
if live_data.get('switch_name') != db_data.get('switch_name'):
changes['switch_name'] = {'from': db_data.get('switch_name'), 'to': live_data.get('switch_name')}
if live_data.get('interface') != db_data.get('interface'):
changes['interface'] = {'from': db_data.get('interface'), 'to': live_data.get('interface')}
if live_data.get('vlan') != db_data.get('vlan'):
changes['vlan'] = {'from': db_data.get('vlan'), 'to': live_data.get('vlan')}
differences.append({
"change_type": "MEGVÁLTOZOTT KLIENS",
"client_mac": mac,
"changes": changes,
"current_data": live_data
})
# A 'return' paranccsal adjuk vissza a különbségeket.
# Ha a 'differences' lista üres, a workflow ezen az ágon megáll (ha nincsenek további node-ok,
# amik üres bemenettel is futnak).
return differences

View File

@@ -0,0 +1,24 @@
services:
n8n:
container_name: n8n
build: .
user: "node:1001"
restart: always
ports:
- "127.0.0.1:5678:5678"
environment:
- TZ=Europe/Hamburg
volumes:
- /mnt/c/Tools/docker/n8n:/home/node/.n8n
- /var/run/docker.sock:/var/run/docker.sock:Z
- /mnt/c/Users/i.meszely/Gitea/WPanda/Dev:/home/node/dev
networks:
- shared-network
volumes:
n8n_data:
driver: local
networks:
shared-network:
external: true

View File

@@ -0,0 +1,11 @@
docker run -d \
--name n8n \
--user "node:1001" \
--restart always \
-p 127.0.0.1:5678:5678 \
-e TZ=Europe/Hamburg \
-v /mnt/c/docker/n8n:/home/node/.n8n \
-v /var/run/docker.sock:/var/run/docker.sock \
--network n8n_n8n_network \
--ip 172.20.0.100 \
n8n

View File

@@ -0,0 +1,105 @@
import json
import os
import re
import csv
from datetime import datetime
from netmiko import ConnectHandler
from netmiko.exceptions import NetmikoTimeoutException, NetmikoAuthenticationException
def get_aruba_firmware(host, username, password):
"""
Connects to an Aruba switch, retrieves the hostname and firmware version.
Returns a dictionary with the collected data.
"""
device = {
'device_type': 'aruba_aoscx',
'host': host,
'username': username,
'password': password,
}
print(f"Csatlakozás a(z) {host} eszközhöz...")
try:
with ConnectHandler(**device) as net_connect:
print(f"Sikeres csatlakozás a(z) {host} eszközhöz. Firmware verzió lekérdezése...")
# Hostname lekérdezése a promptból
prompt = net_connect.find_prompt()
switch_hostname = prompt.strip('#> ')
# Firmware verzió lekérdezése
output = net_connect.send_command('show version')
firmware_version = "N/A"
# Reguláris kifejezés a firmware verzió megtalálásához
match = re.search(r"Version\s+:\s+(.*)", output)
if match:
firmware_version = match.group(1).strip()
return {
'switch_name': switch_hostname,
'ip_address': host,
'firmware_version': firmware_version
}
except NetmikoTimeoutException:
print(f"Hiba: Időtúllépés a(z) {host} eszközhöz való csatlakozáskor.")
return {'switch_name': 'N/A', 'ip_address': host, 'firmware_version': 'Timeout'}
except NetmikoAuthenticationException:
print(f"Hiba: Sikertelen hitelesítés a(z) {host} eszközön.")
return {'switch_name': 'N/A', 'ip_address': host, 'firmware_version': 'Auth Failed'}
except Exception as e:
print(f"Váratlan hiba történt a(z) {host} feldolgozása közben: {e}")
return {'switch_name': 'N/A', 'ip_address': host, 'firmware_version': f'Error: {e}'}
if __name__ == "__main__":
# Konfigurációs fájl beolvasása
try:
with open('config.json', 'r') as f:
config = json.load(f)
except FileNotFoundError:
print("Hiba: A 'config.json' fájl nem található.")
exit()
except json.JSONDecodeError:
print("Hiba: A 'config.json' fájl formátuma érvénytelen.")
exit()
SWITCH_IPS = config.get("switch_ips", [])
USERNAME = config.get("username")
PASSWORD = config.get("password")
if not all([SWITCH_IPS, USERNAME, PASSWORD]):
print("Hiba: A 'config.json' fájl hiányos. Tartalmaznia kell 'switch_ips', 'username', és 'password' kulcsokat.")
exit()
# Kimeneti mappa
OUTPUT_DIR = "results"
os.makedirs(OUTPUT_DIR, exist_ok=True)
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
CSV_FILENAME = os.path.join(OUTPUT_DIR, f"aruba_firmware_versions_{timestamp}.csv")
all_switches_firmware = []
for ip in SWITCH_IPS:
print(f"\n--- Feldolgozás: {ip} ---")
firmware_data = get_aruba_firmware(ip, USERNAME, PASSWORD)
if firmware_data:
all_switches_firmware.append(firmware_data)
print(f"Sikeresen lekérdezve: {firmware_data['switch_name']} ({firmware_data['ip_address']}) - Verzió: {firmware_data['firmware_version']}")
if all_switches_firmware:
print(f"\nÖsszesen {len(all_switches_firmware)} switch adat gyűjtve. Mentés a(z) {CSV_FILENAME} fájlba...")
fieldnames = ['switch_name', 'ip_address', 'firmware_version']
try:
with open(CSV_FILENAME, 'w', newline='', encoding='utf-8') as csvfile:
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(all_switches_firmware)
print(f"Sikeres mentés a(z) '{CSV_FILENAME}' fájlba.")
except IOError as e:
print(f"Hiba történt a CSV fájl írása közben: {e}")
else:
print("\nEgyetlen switch-ről sem sikerült adatot gyűjteni.")

View File

@@ -0,0 +1,133 @@
import os
import re
from datetime import datetime
import json
import requests
from netmiko import ConnectHandler
from netmiko.exceptions import NetmikoTimeoutException, NetmikoAuthenticationException
def get_aruba_clients(host, username, password):
"""
Connects to an Aruba switch via SSH, gets hostname and client info,
and returns a list of dictionaries, each representing a client.
"""
device = {
'device_type': 'aruba_aoscx',
'host': host,
'username': username,
'password': password,
}
all_clients_data = []
print(f"Csatlakozás a(z) {host} eszközhöz...")
try:
with ConnectHandler(**device) as net_connect:
print("Sikeres csatlakozás. Adatok lekérdezése...")
prompt = net_connect.find_prompt()
switch_hostname = prompt.strip('#> ')
output = net_connect.send_command('show client ip')
ip_pattern = re.compile(r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$')
if isinstance(output, str):
lines = output.splitlines()
for line in lines[2:]:
columns = line.split()
if len(columns) >= 4:
potential_ip = columns[-1]
if ip_pattern.match(potential_ip):
client_data = {
'switch_name': switch_hostname,
'mac_address': columns[0],
'interface': columns[1],
'vlan': columns[2],
'ip_address': potential_ip,
}
all_clients_data.append(client_data)
return all_clients_data
print("Hiba: A parancs kimenete nem volt a várt formátumban.")
return None
except NetmikoTimeoutException:
print(f"Hiba: Időtúllépés a(z) {host} eszközhöz való csatlakozáskor.")
return None
except NetmikoAuthenticationException:
print(f"Hiba: Sikertelen hitelesítés a(z) {host} eszközön. Ellenőrizd a jelszót.")
return None
except Exception as e:
print(f"Váratlan hiba történt: {e}")
return None
if __name__ == "__main__":
# --- IDE DEFINIÁLD A SWITCH-EK IP CÍMEIT ---
SWITCH_IPS = [
"10.220.1.84", # NET-SW01
"10.220.1.85", # NET-SW02
"10.220.1.86", # NET-SW04
"10.220.1.87", # NET-SW05
"10.220.1.88", # NET-SW06
"10.220.1.90", # NET-SW07
"10.220.1.91", # NET-SW08
"10.220.1.92", # NET-SW09
"10.220.1.93", # NET-SW10
"10.220.1.94", # NET-SW11
"10.220.1.96", # NET-SW13
# "10.220.1.96", # NET-SW14
"10.220.1.99", # NET-SW17
]
USERNAME = os.getenv('ARUBA_USER', 'svc.operator') # Felhasználónév környezeti változóból, alapértelmezett értékkel
if not USERNAME:
print("Hiba: Az ARUBA_USER környezeti változó nincs beállítva.")
exit()
PASSWORD = os.getenv('ARUBA_PASSWORD')
if not PASSWORD:
print("Hiba: Az ARUBA_PASSWORD környezeti változó nincs beállítva.")
exit()
N8N_WEBHOOK_URL = os.getenv('N8N_WEBHOOK_URL')
if not N8N_WEBHOOK_URL:
print("Hiba: Az N8N_WEBHOOK_URL környezeti változó nincs beállítva.")
exit()
all_switches_clients = []
for ip in SWITCH_IPS:
print(f"\n--- Feldolgozás: {ip} ---")
clients_from_one_switch = get_aruba_clients(ip, USERNAME, PASSWORD)
if clients_from_one_switch:
all_switches_clients.extend(clients_from_one_switch)
print(f"Sikeresen lekérdezve {len(clients_from_one_switch)} kliens a(z) {ip} switch-ről.")
else:
print(f"Nem sikerült adatot lekérdezni a(z) {ip} switch-ről.")
if all_switches_clients:
print(f"\nÖsszesen {len(all_switches_clients)} kliens adat gyűjtve. Küldés az n8n webhookra...")
try:
proxies = { 'http': None, 'https': None }
response = requests.post(N8N_WEBHOOK_URL, json=all_switches_clients, proxies=proxies)
response.raise_for_status() # Hibát dob, ha a státuszkód 4xx vagy 5xx
print(f"Sikeresen elküldve {len(all_switches_clients)} kliens adat az n8n webhookra. Státusz: {response.status_code}")
except requests.exceptions.RequestException as e:
print(f"Hiba történt az adatok n8n webhookra küldése közben: {e}")
else:
print("\nEgyetlen switch-ről sem sikerült adatot gyűjteni.")

View File

@@ -0,0 +1,16 @@
import json
# Az n8n az 'items' listában adja át a bejövő adatokat.
# Nekünk az első elem kell, ami az Execute Command kimenete.
input_item = items[0]
# Kivesszük a 'stdout' mezőt, ami a JSON-t tartalmazza szövegként.
stdout_string = input_item.json['stdout']
# A `json.loads()` paranccsal a szöveget átalakítjuk egy Python listává,
# ami dictionary-ket tartalmaz.
switches_list = json.loads(stdout_string)
# Visszaadjuk a listát. Az n8n a Code node kimenetén ezt automatikusan
# szét fogja bontani különálló elemekre (item-ekre).
return switches_list