Script-Time: Excel2cli

CLI-Commands aus Kunden-Tabellen generieren lassen.

Script-Time: Excel2cli
Photo by Mohammad Rahmani / Unsplash

Immer wieder bekomme ich Aufträge für Firewalls als Excel-Tabelle zugeschickt. Da diese Arbeit zunehmens langweiliger wird, habe ich begonnen diese Tätigkeiten zu automatisieren. Möglicherweise stellt der Kunde bald eine JSON-API zur Verfügung, sodass die Informationen nicht aus der Tabelle in das Script kopiert werden müssen, sondern direkt abgerufen werden können.

Dieses Script, das ursprünglich ein Shellscript war, lieferte ursprünglich Konfigurationen für Barracuda-Firewalls. Da es aber so gut funktioniert hat, habe ich Fortinet und Checkpoint ebenfalls hinzugefügt. Es ist noch nicht ganz vollständig. Routen und Interfaces werden bereits angelegt. Regeln sind auf Fortigate leicht zu realisieren.

Sobald die mgmt_cli von Checkpoint stabil läuft, kann auch hier der Anteil automatisiert werden, der sich sonst nur in der Windows-Applikation klicken lässt.

Die gleiche Art der Verarbeitung funktioniert besonders gut bei Cisco Komponenten. Auch hier können die Felder leicht an entsprechender Stelle in der Konfig platziert werden, die das Script erstellt.

Vielleich ist die Bash-Variante unten für viele besser verständlich.

Manche Firmen gestatten die Erstellung von Software nur durch ihre eigene Software-Abteilung. Doch die dabei entstehenden Lösungen sind meist viel zu umständlich. Hier geht es nur um Folgendes:

In der Exceltabelle befindet sich in jeder Zeile z.B. eine Cluster-Interface-Beschreibung. So weise ich also jeder Variablen das entsprechende Feld aus jeder einzelnen Zeile zu:

Bei der Ausgabe, die man später in die CLI kopieren kann, wird auch berücksichtigt, ob es sich um IPv4 oder IPv6 handelt:

Doch hier nun die Idee:

"""
Tool zur Unterstützung bei der Firewall/Router/Switch-Konfiguration.

Dieses Skript liest Firewall-Regeln, Schnittstellen und Routing-Informationen aus
vordefinierten Zeichenketten und generiert Konfigurationsanweisungen für
verschiedene Firewall-Typen (Check Point und Fortigate).

Es bietet Funktionen zum Parsen der Eingabedaten, zum Generieren von
geräte-spezifischen Befehlen und zur übersichtlichen Darstellung der
Konfigurationsschritte.

Verwendung:
    python3 firewall_tool.py <Auftragsnummer>

Beispiel:
    python3 firewall_tool.py 12345

Die Auftragsnummer wird in die erzeugten Kommentare der Konfigurationsanweisungen
eingefügt.

"""

import ipaddress
import sys
from typing import List, Tuple

# ANSI escape codes für farbige Ausgabe
RESET = "\033[0m"
RED = "\033[1;91m"
GREEN = "\033[1;92m"
YELLOW = "\033[1;93m"
BLUE = "\033[1;94m"
MAGENTA = "\033[1;95m"
CYAN = "\033[1;96m"

def print_banner() -> None:
    """Zeigt ein Banner mit Informationen zum Tool an."""
    print(
        f"""
    {BLUE}#################################################################################{RESET}
    {BLUE}###                                                                          ####{RESET}
    {BLUE}###   {YELLOW}wf_tool{RESET}                                                                ####{RESET}
    {BLUE}###   ====================================================================   ####{RESET}
    {BLUE}###   Version  : 0.9                                                         ####{RESET}
    {BLUE}###   Date     : 07.04.2017                                                  ####{RESET}
    {BLUE}###   Modified : 22.02.2021                                                  ####{RESET}
    {BLUE}###   Author   : Michael Meister                                             ####{RESET}
    {BLUE}###   --------------------------------------------------------------------   ####{RESET}
    {BLUE}###   Purpose :                                                              ####{RESET}
    {BLUE}###   Dieses Tool bietet Unterstützung für die Firewall-Konfiguration.      ####{RESET}
    {BLUE}###                                                                          ####{RESET}
    {BLUE}#################################################################################{RESET}
    """
    )

def print_help() -> None:
    """Zeigt die Hilfe-Nachricht an und beendet das Skript."""
    print_banner()
    sys.exit(0)

# Check für die korrekte Ausführung der Hilfsfunktion
if len(sys.argv) > 1 and sys.argv[1] in ["-h", "-help", "--help"]:
    print_help()

# Firewall-Regeln, Schnittstellen und Routing-Informationen
RULES = """
0	FALSCH	1	Add	fw-ber-f01	rz-ber-1, rz-ber-2	10.232.17.11/24,10.232.17.12/24	keines	kein		10.232.92.2/25-10.232.92.3/25		RZ-TEST BER	NTP	udp/123	Ja					CLOCK/NTP für TFDPS_DB
0	FALSCH	2	Add	fw-ber-f01	rz-ber-1, rz-ber-2	10.226.17.11/24,10.226.17.12/24	keines	kein		10.232.92.2/25-10.232.92.3/25		RZ-TEST BER	NTP	udp/123	Ja					CLOCK/NTP für TFDPS_DP
"""

INTERFACES = """
0	FALSCH	1	port4	fw-ber-f01			10.237.27.144/29	10.237.27.145	1337 (RZ_BER_MUC)	RZ-BER-MUC-Transit
0	FALSCH	2	eth3.s01	fw-muc-c01			10.237.27.152/29	10.237.27.153	1337 (RZ_BER_MUC)	RZ-BER-MUC-Transit
"""

ROUTING = """
0	FALSCH	1	port4.1337	fw-ber-f01	10.10.27.150	10.224.0.0/16	StdWo0113-Berlin113
0	FALSCH	2	port4.1337	fw-ber-f01	10.10.27.150	10.231.83.0/24	StdWo0022-Berlin022
0	FALSCH	3	eth2.1337	fw-muc-c01	10.10.25.30	172.17.201.128/25	RZ_BER
"""

def calculate_subnet_mask(prefix_length: int) -> str:
    """
    Berechnet die Subnetzmaske aus der Präfixlänge.

    Args:
        prefix_length: Die Präfixlänge des Subnetzes.

    Returns:
        Die Subnetzmaske im Format 'xxx.xxx.xxx.xxx'.
    """
    mask = (1 << 32) - (1 << (32 - prefix_length))
    return ".".join(map(str, [(mask >> i) & 255 for i in [24, 16, 8, 0]]))

def calculate_prefix_length(subnet_mask: str) -> int:
    """
    Berechnet die Präfixlänge aus der Subnetzmaske.

    Args:
        subnet_mask: Die Subnetzmaske im Format 'xxx.xxx.xxx.xxx'.

    Returns:
        Die Präfixlänge des Subnetzes.
    """
    binary_mask = "".join(
        [bin(int(x) + 256)[3:] for x in subnet_mask.split(".")]
    )
    return str(binary_mask.rstrip("0")).count("1")

def print_ascii_art(text: str, font: str = "doom") -> None:
    """
    Gibt den Text als ASCII-Art mit pyfiglet aus.

    Args:
        text: Der auszugebende Text.
        font: Die zu verwendende Schriftart (Standard: "doom").
    """
    from pyfiglet import Figlet

    figlet = Figlet(font=font, width=140)
    print(figlet.renderText(text))

def parse_data(data_string: str, delimiter: str = "\t") -> List[List[str]]:
    """
    Parst eine mehrzeilige Zeichenkette in eine Liste von Listen.

    Args:
        data_string: Die zu parsende Zeichenkette.
        delimiter: Das Trennzeichen zwischen den Spalten (Standard: Tabulator).

    Returns:
        Eine Liste von Listen, wobei jede innere Liste eine Zeile der
        Eingabezeichenkette repräsentiert.
    """
    data_lines = data_string.strip().split("\n")
    return [line.split(delimiter) for line in data_lines]

def process_rules(
    firewall_machine: str,
    rules_data: List[List[str]],
    job_number: str,
    device_type: str = "checkpoint",
) -> None:
    """
    Verarbeitet Firewall-Regeln und gibt Konfigurationsanweisungen aus.

    Args:
        firewall_machine: Der Name der Firewall-Maschine.
        rules_data: Die geparsten Firewall-Regeln.
        job_number: Die Auftragsnummer.
        device_type: Der Typ der Firewall-Maschine ("checkpoint" oder "fortigate").
    """

    filtered_rules = [
        rule for rule in rules_data if rule[4] == firewall_machine
    ]

    if not filtered_rules:
        return
    print_ascii_art("Rules")
    print_ascii_art(firewall_machine)

    for rule in filtered_rules:
        (
            rule_number,
            _,
            _,
            action,
            firewall,
            source_hostnames_str,
            source_ips_str,
            snat,
            _,
            destination_ips_str,
            _,
            dnat,
            destination_hostnames_str,
            protocol_name,
            ports_str,
            ops_relevant,
            _,
            rule_name,
            section,
            comment,
        ) = rule

        source_ips = source_ips_str.replace(";", " ").split()
        source_hostnames = (
            source_hostnames_str.replace(",", " ")
            .replace("  ", " ")
            .replace(";", " ")
            .split()
        )
        destination_ips = destination_ips_str.replace(";", " ").split()
        destination_hostnames = (
            destination_hostnames_str.replace(",", " ")
            .replace("  ", " ")
            .replace(";", " ")
            .split()
        )
        ports = ports_str.replace(";", " ").split()

        full_comment = (
            f"{job_number} {'OPS-Relevant' if ops_relevant.lower() == 'ja' else ''} {comment}"
        )

        print(f"\n{'-' * 63}\n")
        if action.lower() == "add":
            print(f"{GREEN}Neue Regel erstellen{RESET}")
        elif action.lower() == "delete":
            print(f"{RED}Regel LÖSCHEN!!!{RESET}")
        elif action.lower() == "change":
            print(f"{YELLOW}Regel ändern{RESET}")
        else:
            print(f"{RED}Unbekannte Aktion: {action}{RESET}")

        print(f"Regelnummer im Auftrag: {rule_number}")
        print("=" * 27)
        print(f"\nFirewall     : {firewall}")
        print(f"Section      : {section}")
        print(f"Rulename     : {rule_name}")
        print(f"Kommentar    : {full_comment}")

        if device_type == "checkpoint":
            print_checkpoint_rule_details(
                source_ips,
                source_hostnames,
                snat,
                destination_ips,
                destination_hostnames,
                dnat,
                protocol_name,
                ports,
                ops_relevant,
                full_comment,
            )
        elif device_type == "fortigate":
            print_fortigate_rule_details(
                rule_name,
                source_hostnames,
                destination_hostnames,
                ports,
                full_comment,
                action,
            )
        else:
            print(f"{RED}Unbekannter Gerätetyp: {device_type}{RESET}")

def print_checkpoint_rule_details(
    source_ips: List[str],
    source_hostnames: List[str],
    snat: str,
    destination_ips: List[str],
    destination_hostnames: List[str],
    dnat: str,
    protocol_name: str,
    ports: List[str],
    ops_relevant: str,
    full_comment: str,
) -> None:
    """
    Gibt Details zu einer Check Point Firewall-Regel aus.

    Args:
        source_ips: Eine Liste der Quell-IP-Adressen.
        source_hostnames: Eine Liste der Quell-Hostnamen.
        snat: Die Quell-NAT-Adresse.
        destination_ips: Eine Liste der Ziel-IP-Adressen.
        destination_hostnames: Eine Liste der Ziel-Hostnamen.
        dnat: Die Ziel-NAT-Adresse.
        protocol_name: Der Name des Protokolls.
        ports: Eine Liste der Ports.
        ops_relevant: Gibt an, ob die Regel OPS-relevant ist.
        full_comment: Der vollständige Kommentar zur Regel.
    """

    print("\nSources      : ")
    if len(source_ips) != len(source_hostnames):
        print(f"{RED}Fehler im Auftrag: Anzahl der Quell-IPs und -Hostnamen stimmt nicht überein{RESET}")
    for i, source_ip in enumerate(source_ips):
        print(f"  {i+1}. \t {source_ip} \t {source_hostnames[i] if i < len(source_hostnames) else ''}")

    if snat:
        print(f"\nExplicit Src : {snat}")

    print("\nDirection      --->")
    print(f"Protokoll    : {protocol_name}")
    print(f"Ports        : {ports}")

    print("\nDestinations : ")
    if len(destination_ips) != len(destination_hostnames):
        print(f"{RED}Fehler im Auftrag: Anzahl der Ziel-IPs und -Hostnamen stimmt nicht überein{RESET}")
    for i, destination_ip in enumerate(destination_ips):
        print(
            f"  {i+1}. \t {destination_ip} \t {destination_hostnames[i] if i < len(destination_hostnames) else ''}"
        )

    if dnat:
        print(f"\nDNAT         : {dnat}")

    print(f"\nOPS Relevant : {ops_relevant}")
    print(f"Kommentar    : {full_comment}")

def print_fortigate_rule_details(
    rule_name: str,
    source_hostnames: List[str],
    destination_hostnames: List[str],
    ports: List[str],
    full_comment: str,
    action: str,
) -> None:
    """
    Gibt Details zu einer Fortigate Firewall-Regel aus.

    Args:
        rule_name: Der Name der Regel.
        source_hostnames: Eine Liste der Quell-Hostnamen.
        destination_hostnames: Eine Liste der Ziel-Hostnamen.
        ports: Eine Liste der Ports.
        full_comment: Der vollständige Kommentar zur Regel.
        action: Die Aktion der Regel (add, delete, change).
    """

    if action.lower() == "add":
        print(f"\nFirewall     : {firewall_machine}")
        print(f"Section      : {section}")
        print(f"Rulename     : {rule_name}")
        print()
        print("edit")
        print(f'set name "{rule_name}"')
        print('set srcintf "any"')
        print('set dstintf "any"')
        print("set action accept")
        print("set srcaddr", end="")
        for source_hostname in source_hostnames:
            print(f' "{source_hostname}"', end="")
        print()
        print("set dstaddr", end="")
        for destination_hostname in destination_hostnames:
            print(f' "{destination_hostname}"', end="")
        print()
        print('set schedule "always"')
        print(f'set service "{ports[0].replace("/", "_") if ports else ""}"')
        print("set utm-status enable")
        print("set inspection-mode proxy")
        print('set av-profile "DFS-AV"')
        print('set ips-sensor "DFS-IPS"')
        print("set logtraffic-start enable")
        print(f'set comments "{full_comment}"')
        print("next")
    elif action.lower() == "delete":
        print(f"delete {rule_name}")
    elif action.lower() == "change":
        print(f"config firewall policy")
        print(f"edit {rule_name}")
        print(f'set comments "{full_comment}"')
        print(f"next")
        print(f"end")
    else:
        print(f"{RED}Unbekannte Aktion: {action}{RESET}")

def process_interfaces(
    firewall_machines: List[str], interfaces_data: List[List[str]]
) -> None:
    """
    Verarbeitet Firewall-Schnittstellen und gibt Konfigurationsanweisungen aus.

    Args:
        firewall_machines: Eine Liste der Firewall-Maschinen.
        interfaces_data: Die geparsten Firewall-Schnittstellen.
    """

    for firewall_machine in firewall_machines:
        print_ascii_art("Interfaces")
        print_ascii_art(firewall_machine + "1")
        print()

        filtered_interfaces = [
            interface
            for interface in interfaces_data
            if interface[4] == firewall_machine
        ]

        for interface in filtered_interfaces:
            (
                _,
                _,
                _,
                interface_name,
                firewall,
                ip_address_1,
                ip_address_2,
                _,
                cluster_ip,
                vlan_comment,
            ) = interface

            vlan = vlan_comment.split(" ")[0].lstrip("0")
            prefix_length = ip_address_1.split("/")[1]
            interface_base = interface_name.split(".")[0]
            delete = "löschen" in vlan_comment.lower()
            
            print_interface_config(
                firewall + "2",
                interface_base,
                vlan,
                ip_address_1 if not delete else ip_address_2,
                prefix_length,
                vlan_comment,
                delete,
            )
        print()

        print_ascii_art("Interfaces")
        print_ascii_art(firewall_machine + "2")
        print()

        for interface in filtered_interfaces:
            (
                _,
                _,
                _,
                interface_name,
                firewall,
                ip_address_1,
                ip_address_2,
                _,
                cluster_ip,
                vlan_comment,
            ) = interface

            vlan = vlan_comment.split(" ")[0].lstrip("0")
            prefix_length = ip_address_2.split("/")[1]
            interface_base = interface_name.split(".")[0]
            delete = "löschen" in vlan_comment.lower()

            print_interface_config(
                firewall + "2",
                interface_base,
                vlan,
                ip_address_2 if not delete else ip_address_1,
                prefix_length,
                vlan_comment,
                delete,
            )

def print_interface_config(
    firewall: str,
    interface_base: str,
    vlan: str,
    ip_address: str,
    prefix_length: str,
    vlan_comment: str,
    delete: bool = False,
) -> None:
    """
    Gibt die Konfigurationsanweisungen für eine Firewall-Schnittstelle aus.

    Args:
        firewall: Der Name der Firewall.
        interface_base: Der Name der Basis-Schnittstelle.
        vlan: Die VLAN-ID.
        ip_address: Die IP-Adresse der Schnittstelle.
        prefix_length: Die Präfixlänge des Subnetzes.
        vlan_comment: Der Kommentar zur VLAN-ID.
        delete: Gibt an, ob die Schnittstelle gelöscht werden soll.
    """

    action = "löschen" if delete else "anlegen"
    ip_type = "ipv4" if "." in ip_address else "ipv6"

    print(f"# {firewall} - {interface_base}.{vlan} {action}:")
    if delete:
        print(
            f"delete interface {interface_base}.{vlan} {ip_type}-address {ip_address} mask-length {prefix_length}"
        )
    else:
        print(f"add interface {interface_base} vlan {vlan}")
        print(f'set interface {interface_base}.{vlan} comments "{vlan_comment}"')
        print(
            f"set interface {interface_base}.{vlan} {ip_type}-address {ip_address} mask-length {prefix_length}"
        )
        print(f"set interface {interface_base}.{vlan} mtu 1500")
        print(f"set interface {interface_base}.{vlan} state on")
        

def process_fortigate_interfaces(
    firewall_machines: List[str], interfaces_data: List[List[str]]
) -> None:
    """
    Verarbeitet Fortigate Firewall-Schnittstellen und gibt Konfigurationsanweisungen aus.

    Args:
        firewall_machines: Eine Liste der Fortigate Firewall-Maschinen.
        interfaces_data: Die geparsten Firewall-Schnittstellen.
    """

    for firewall_machine in firewall_machines:
        print_ascii_art("Interfaces")
        print_ascii_art(firewall_machine)
        print()

        filtered_interfaces = [
            interface
            for interface in interfaces_data
            if interface[4] == firewall_machine
        ]

        for interface in filtered_interfaces:
            (
                _,
                _,
                _,
                interface_name,
                firewall,
                ip_address_1,
                ip_address_2,
                _,
                cluster_ip,
                vlan_comment,
            ) = interface

            vlan = vlan_comment.split(" ")[0].lstrip("0")
            prefix_length = ip_address_1.split("/")[1]
            interface_base = interface_name.split(".")[0]
            delete = "löschen" in vlan_comment.lower()

            if firewall.endswith("-f"):
                print_fortigate_interface_config(
                    firewall,
                    interface_base,
                    vlan,
                    cluster_ip,
                    prefix_length,
                    vlan_comment,
                    delete,
                )

def print_fortigate_interface_config(
    firewall: str,
    interface_base: str,
    vlan: str,
    cluster_ip: str,
    prefix_length: str,
    vlan_comment: str,
    delete: bool = False,
) -> None:
    """
    Gibt die Konfigurationsanweisungen für eine Fortigate Firewall-Schnittstelle aus.

    Args:
        firewall: Der Name der Firewall.
        interface_base: Der Name der Basis-Schnittstelle.
        vlan: Die VLAN-ID.
        cluster_ip: Die Cluster-IP-Adresse.
        prefix_length: Die Präfixlänge des Subnetzes.
        vlan_comment: Der Kommentar zur VLAN-ID.
        delete: Gibt an, ob die Schnittstelle gelöscht werden soll.
    """

    action = "löschen" if delete else "anlegen"
    print(f"# {firewall} - {interface_base}.{vlan} {action}:")
    if delete:
        print(
            f"delete interface {interface_base}.{vlan} ipv4-address {cluster_ip} mask-length {prefix_length}"
        )
    else:
        print("config system interface")
        print(f'edit "{interface_base}.{vlan}"')
        print('set vdom "root"')
        print(f'set description "{vlan_comment}"')
        print("set device-identification enable")
        print("set role lan")
        print(f"set ip {cluster_ip}/{prefix_length}")
        print("set allowaccess ping")
        print(f'set interface "{interface_base}"')
        print(f"set vlanid {vlan}")
        print("next")
        print("end")

def process_routing(
    firewall_machines: List[str], routing_data: List[List[str]], device_type: str
) -> None:
    """
    Verarbeitet Routing-Informationen und gibt Konfigurationsanweisungen aus.

    Args:
        firewall_machines: Eine Liste der Firewall-Maschinen.
        routing_data: Die geparsten Routing-Informationen.
        device_type: Der Typ der Firewall-Maschine ("checkpoint" oder "fortigate").
    """

    for firewall_machine in firewall_machines:
        print_ascii_art("ROUTING")
        if device_type == "checkpoint":
            print_ascii_art(f"{firewall_machine}1 u. {firewall_machine}2")
        else:
            print_ascii_art(firewall_machine)

        filtered_routing_entries = [
            entry for entry in routing_data if entry[4] == firewall_machine
        ]

        for routing_entry in filtered_routing_entries:
            (
                _,
                _,
                _,
                interface,
                firewall,
                gateway,
                network,
                comment,
            ) = routing_entry

            network_address = network.split("/")[0]
            prefix_length = network.split("/")[1]
            delete = "löschen" in comment.lower()

            if device_type == "checkpoint":
                print_checkpoint_routing_config(
                    firewall, network_address, prefix_length, gateway, comment, delete
                )
            elif device_type == "fortigate":
                print_fortigate_routing_config(
                    firewall,
                    network_address,
                    prefix_length,
                    gateway,
                    interface,
                    comment,
                    delete,
                )
            else:
                print(f"{RED}Unbekannter Gerätetyp: {device_type}{RESET}")

def print_checkpoint_routing_config(
    firewall: str,
    network_address: str,
    prefix_length: str,
    gateway: str,
    comment: str,
    delete: bool = False,
) -> None:
    """
    Gibt die Konfigurationsanweisungen für eine Check Point Routing-Regel aus.

    Args:
        firewall: Der Name der Firewall.
        network_address: Die Netzwerkadresse.
        prefix_length: Die Präfixlänge des Subnetzes.
        gateway: Die Gateway-Adresse.
        comment: Der Kommentar zur Routing-Regel.
        delete: Gibt an, ob die Routing-Regel gelöscht werden soll.
    """

    action = "löschen" if delete else "anlegen"
    print(f"# {firewall} - {network_address}/{prefix_length} {action}")
    if delete:
        print(f"set static-route {network_address}/{prefix_length} off")
    else:
        print(f'set static-route {network_address}/{prefix_length} comment "{comment}"')
        print(
            f"set static-route {network_address}/{prefix_length} nexthop gateway address {gateway} on"
        )

def print_fortigate_routing_config(
    firewall: str,
    network_address: str,
    prefix_length: str,
    gateway: str,
    interface: str,
    comment: str,
    delete: bool = False,
) -> None:
    """
    Gibt die Konfigurationsanweisungen für eine Fortigate Routing-Regel aus.

    Args:
        firewall: Der Name der Firewall.
        network_address: Die Netzwerkadresse.
        prefix_length: Die Präfixlänge des Subnetzes.
        gateway: Die Gateway-Adresse.
        interface: Die Schnittstelle.
        comment: Der Kommentar zur Routing-Regel.
        delete: Gibt an, ob die Routing-Regel gelöscht werden soll.
    """

    action = "löschen" if delete else "anlegen"
    print(f"# {firewall} - {network_address}/{prefix_length} {action}")
    if delete:
        print(
            f"keine Ahnung, wie man {network_address}/{prefix_length} über das cli löscht"
        )
    else:
        print("config router static")
        print("edit")
        print(f"set dst {network_address}/{prefix_length}")
        print(f"set gateway {gateway}")
        print(f'set device "{interface}"')
        print(f'set comment "{comment}"')
        print("next")
        print("end")

def process_antispoofing(
    routing_firewall_machines: List[str],
    interfaces_data: List[List[str]],
    routing_data: List[List[str]],
) -> None:
    """
    Verarbeitet Anti-Spoofing-Konfigurationen und gibt Anweisungen aus.

    Args:
        routing_firewall_machines: Eine Liste der Firewall-Maschinen mit Routing-Informationen.
        interfaces_data: Die geparsten Firewall-Schnittstellen.
        routing_data: Die geparsten Routing-Informationen.
    """

    print(
        "\n############################################################################"
    )
    print("#\n#  In der Netzwerktopologie Antispoofing anlegen:\n#")

    for firewall_machine in routing_firewall_machines:
        filtered_interfaces = [
            interface
            for interface in interfaces_data
            if interface[4] == firewall_machine
        ]

        for interface in filtered_interfaces:
            (
                _,
                _,
                _,
                interface_name,
                firewall,
                ip_address_1,
                ip_address_2,
                _,
                cluster_ip,
                vlan_comment,
            ) = interface

            if firewall.endswith("-c"):
                print_ascii_art(firewall_machine)
                vlan = vlan_comment.split(" ")[0].lstrip("0")
                prefix_length = cluster_ip.split("/")[1]
                interface_base = interface_name.split(".")[0]
                delete = "löschen" in vlan_comment.lower()

                print_antispoofing_config(
                    firewall,
                    interface_base,
                    vlan,
                    cluster_ip,
                    ip_address_1,
                    ip_address_2,
                    prefix_length,
                    vlan_comment,
                    routing_data,
                    delete,
                )

def print_antispoofing_config(
    firewall: str,
    interface_base: str,
    vlan: str,
    cluster_ip: str,
    ip_address_1: str,
    ip_address_2: str,
    prefix_length: str,
    vlan_comment: str,
    routing_data: List[List[str]],
    delete: bool = False,
) -> None:
    """
    Gibt die Konfigurationsanweisungen für Anti-Spoofing aus.

    Args:
        firewall: Der Name der Firewall.
        interface_base: Der Name der Basis-Schnittstelle.
        vlan: Die VLAN-ID.
        cluster_ip: Die Cluster-IP-Adresse.
        ip_address_1: Die erste IP-Adresse des Clusters.
        ip_address_2: Die zweite IP-Adresse des Clusters.
        prefix_length: Die Präfixlänge des Subnetzes.
        vlan_comment: Der Kommentar zur VLAN-ID.
        routing_data: Die geparsten Routing-Informationen.
        delete: Gibt an, ob die Anti-Spoofing-Konfiguration gelöscht werden soll.
    """

    action = "löschen" if delete else "anlegen"
    print(f"# {firewall}1 - {interface_base}.{vlan} {action}:")
    if delete:
        print(
            f"# delete interface {interface_base}.{vlan} ipv4-address {cluster_ip} mask-length {prefix_length}"
        )
    else:
        print("#      Auf", firewall, "[ add Interface ]")
        print(f"#        Object-Name: {interface_base}.{vlan}")
        print("#               Type: Cluster")
        print(f"#               IPv4: {cluster_ip}/{prefix_length}")
        print(f"#            Member1: {ip_address_1}/{prefix_length}")
        print(f"#            Member2: {ip_address_2}/{prefix_length}")
        print(
            f"#       Antispoofing: as-ng.{firewall.replace('fw-', '')}-{interface_base}.{vlan}"
        )

        network_address = ipaddress.ip_network(cluster_ip, strict=False)
        network_mask = calculate_subnet_mask(int(prefix_length))
        netname_part = vlan_comment.lower().replace(" ", "_")
        firewall_part = firewall.replace("fw-", "").split("-")[0]
        print(
            f"#                       * fw-n.{firewall_part}-{netname_part} - {network_address}/{network_mask}"
        )

        for routing_entry in routing_data:
            (
                _,
                _,
                _,
                routing_interface,
                _,
                _,
                network,
                netname,
            ) = routing_entry

            if routing_interface == f"{interface_base}.{vlan}":
                routing_network = network.split("/")[0]
                routing_prefix_length = network.split("/")[1]
                routing_netmask = calculate_subnet_mask(int(routing_prefix_length))
                print(
                    f"#                       * {netname.lower().replace(' ', '_')} - {routing_network}/{routing_netmask}"
                )

def main() -> None:
    """
    Hauptfunktion des Skripts.
    """

    if len(sys.argv) < 2:
        print("Bitte Auftragsnummer als Argument angeben.")
        sys.exit(1)

    job_number = sys.argv[1]

    rules_data = parse_data(RULES)
    interfaces_data = parse_data(INTERFACES)
    routing_data = parse_data(ROUTING)

    # Eindeutige Firewall-Maschinen für jeden Datentyp ermitteln
    unique_rule_firewall_machines = sorted(
        list(set([rule[4] for rule in rules_data if rule[4]]))
    )
    unique_interface_firewall_machines = sorted(
        list(set([interface[4] for interface in interfaces_data if interface[4]]))
    )
    unique_routing_firewall_machines = sorted(
        list(set([route[4] for route in routing_data if route[4]]))
    )

    # Verarbeitung der Regeln für Check Point-Firewalls
    checkpoint_machines = [
        fw for fw in unique_rule_firewall_machines if fw.endswith("-c")
    ]
    for firewall_machine in checkpoint_machines:
        process_rules(firewall_machine, rules_data, job_number, "checkpoint")

    # Verarbeitung der Schnittstellen für Check Point-Firewalls
    checkpoint_machines = [
        fw for fw in unique_interface_firewall_machines if fw.endswith("-c")
    ]
    process_interfaces(checkpoint_machines, interfaces_data)

    # Verarbeitung des Routings für Check Point-Firewalls
    checkpoint_machines = [
        fw for fw in unique_routing_firewall_machines if fw.endswith("-c")
    ]
    process_routing(checkpoint_machines, routing_data, "checkpoint")

    # Verarbeitung von Anti-Spoofing für Check Point-Firewalls
    process_antispoofing(
        checkpoint_machines, interfaces_data, routing_data
    )

    # Verarbeitung der Regeln für Fortigate-Firewalls
    fortigate_machines = [
        fw for fw in unique_rule_firewall_machines if fw.endswith("-f")
    ]
    for firewall_machine in fortigate_machines:
        process_rules(firewall_machine, rules_data, job_number, "fortigate")

    # Verarbeitung der Schnittstellen für Fortigate-Firewalls
    fortigate_machines = [
        fw for fw in unique_interface_firewall_machines if fw.endswith("-f")
    ]
    process_fortigate_interfaces(fortigate_machines, interfaces_data)

    # Verarbeitung des Routings für Fortigate-Firewalls
    fortigate_machines = [
        fw for fw in unique_routing_firewall_machines if fw.endswith("-f")
    ]
    process_routing(fortigate_machines, routing_data, "fortigate")

if __name__ == "__main__":
    main()

Die BASH-Version

#!/bin/bash
Help(){
    echo "
    #################################################################################
    ###                                                                          ####
    ###   wf_tool                                                                ####
    ###   ====================================================================   ####
    ###   Version  : 0.9                                                         ####
    ###   Date     : 07.04.2017                                                  ####
    ###   Modified : 22.02.2021                                                  ####
    ###   Author   : Michael Meister                                             ####
    ###   --------------------------------------------------------------------   ####
    ###   Purpose :                                                              ####
    ###   This tool provides help for fw-configuration                           ####
    ###                                                                          ####
    #################################################################################
    "
    exit 0
}
 
[ "$1" = "-h" -o "$1" = "-help" -o "$1" = "--help" ] && Help

####################################################################################################
####################################################################################################
# Export Rules, Interfaces and Routing to Excel, switch to read/write in Excel and paste the
# full lines below:
#
RULES='
0	FALSCH	1	Add	fw-ber-f01	rz-ber-1, rz-ber-2	10.232.17.11/24,10.232.17.12/24	keines	kein		10.232.92.2/25-10.232.92.3/25		RZ-TEST BER	NTP	udp/123	Ja					CLOCK/NTP für TFDPS_DB
0	FALSCH	2	Add	fw-ber-f01	rz-ber-1, rz-ber-2	10.226.17.11/24,10.226.17.12/24	keines	kein		10.232.92.2/25-10.232.92.3/25		RZ-TEST BER	NTP	udp/123	Ja					CLOCK/NTP für TFDPS_DP
'

INTERFACES='
0	FALSCH	1	port4	fw-ber-f01			10.237.27.144/29	10.237.27.145	1337 (RZ_BER_MUC)	RZ-BER-MUC-Transit
0	FALSCH	1	eth3.s01	fw-muc-c01			10.237.27.152/29	10.237.27.153	1337 (RZ_BER_MUC)	RZ-BER-MUC-Transit
'

ROUTING='
0	FALSCH	1	port4.1337	fw-ber-f01	10.10.27.150	10.224.0.0/16	StdWo0113-Berlin113
0	FALSCH	2	port4.1337	fw-ber-f01	10.10.27.150	10.231.83.0/24	StdWo0022-Berlin022
0	FALSCH	3	eth2.1337	fw-muc-c01	10.10.25.30	172.17.201.128/25	RZ_BER
'


####################################################################################################
####################################################################################################

# functions() here:

cdr2mask(){
   # Number of args to shift, 255..255, first non-255 byte, zeroes
   set -- $(( 5 - ($1 / 8) )) 255 255 255 255 $(( (255 << (8 - ($1 % 8))) & 255 )) 0 0 0
   [ $1 -gt 1 ] && shift $1 || shift
   echo ${1-0}.${2-0}.${3-0}.${4-0}
}

mask2cdr ()
{
   # Assumes there's no "255." after a non-255 byte in the mask
   local x=${1##*255.}
   set -- 0^^^128^192^224^240^248^252^254^ $(( (${#1} - ${#x})*2 )) ${x%%.*}
   x=${1%%$3*}
   echo $(( $2 + (${#x}/4) ))
}


cprules(){
#                             _____ _____    _____  _    _ _      ______  _____
#                            / ____|  __ \  |  __ \| |  | | |    |  ____|/ ____|
#                           | |    | |__) | | |__) | |  | | |    | |__  | (___
#                           | |    |  ___/  |  _  /| |  | | |    |  __|  \___ \
#                           | |____| |      | | \ \| |__| | |____| |____ ____) |
#                            \_____|_|      |_|  \_\\____/|______|______|_____/

# Rules first as they can be done without OPSPLAN
#


for MASCHINE in ${MASCHINES}
do
echo
echo
echo "####################################################################################################"
echo "####################################################################################################"
figlet -w 140 -f doom Rules
figlet -w 140 -f doom ${MASCHINE}

echo "$RULES" |
grep "${MASCHINE}" |
sed -e 's/\t/\|/g' |

while read line
	do
	RULENR=$(echo $line | cut -d '|' -f3)
	FIREWALL=$(echo $line | cut -d '|' -f5)
	TODO=$(echo $line | cut -d '|' -f4)
	SOURCEIP=$(echo $line | cut -d '|' -f7 | sed -e 's/[;,]/ /g')
	SNAT=$(echo $line | cut -d '|' -f8)
	SRCHOSTNAMES=$(echo $line | cut -d '|' -f6 | sed -e 's/ *,/,/g;s/, */,/g;s/ /_/g;s/[;,]/ /g')
	DIRECTION="--->" #$(echo $line | cut -d '|' -f X)
	DESTIP=$(echo $line | cut -d '|' -f11 | sed -e 's/[;,]/ /g')
	DNAT=$(echo $line | cut -d '|' -f12)
	DESTHOSTNAMES=$(echo $line | cut -d '|' -f13 | sed -e 's/ *,/,/g;s/, */,/g;s/ /_/g;s/[;,]/ /g')
	PROTONAME=$(echo $line | cut -d '|' -f14 | sed -e 's/[;,]/ /g')
	PORTS=$(echo $line | cut -d '|' -f15 | sed -e 's/[;,]/ /g')
	PAT=$(echo $line | cut -d '|' -f17)
	OPS=$(echo $line | cut -d '|' -f16)
	SECTION=$(echo $line | cut -d '|' -f19)
	RULENAME=$(echo $line | cut -d '|' -f18)
	COMMENT="${AUFTRAG} $( (echo $OPS | grep -qi "ja") && echo OPS-Relevant) $(echo $line | cut -d '|' -f21 | sed -e 's/[;]/ /g;s/ */ /g')"

	# if [[ ${RULENR} > 0 ]]
	# then
		declare -a SOURCEIPS=($SOURCEIP)
		declare -a SOURCENAMES=($SRCHOSTNAMES)
		declare -a DESTIPS=($DESTIP)
		declare -a DESTNAMES=($DESTHOSTNAMES)

		if (echo ${TODO} | grep -q "Add")
			then
				echo
				echo "---------------------------------------------------------------"
				echo "Neue Regel erstellen"
				echo "Regelnummer im Auftrag : ${RULENR}"
				echo "==========================="
				echo
				echo "Firewall     : ${FIREWALL}"
				echo "Section      : ${SECTION}"
				echo "Rulename     : ${RULENAME}"
				echo "Kommentar    : ${COMMENT}"
				echo "Sources      : "
				echo

                [[ $(echo "$SOURCEIP" | wc -w) == $(echo "$SRCHOSTNAMES" | wc -w) ]] || echo Fehler im Auftrag
				for (( i=0; i<${#SOURCEIPS[@]}; i++ ))
					do 
					echo -e "  $(($i+1)). \\t ${SOURCEIPS[$i]} \\t ${SOURCENAMES[$i]}"
				done
				echo
				[ "${SNAT}" ] && echo "Explicit Src : ${SNAT}" && echo
				echo "Direction      ${DIRECTION}"
				echo "Protokoll    : ${PROTONAME}"
				echo "Ports        : ${PORTS}"
				[ "${PAT}" ] && echo "PAT          : ${PAT}"
				echo "Direction      ${DIRECTION}"
				echo
				echo "Destinations : "
				echo
                [[ $(echo "$DESTIPS" | wc -w) == $(echo "$DESTNAMES" | wc -w) ]] || echo Fehler im Auftrag
				for (( i=0; i<${#DESTIPS[@]}; i++ ))
					do echo -e "  $(($i+1)). \\t ${DESTIPS[$i]} \\t ${DESTNAMES[$i]}"
				done
				echo
				[ "${DNAT}" ] && echo "DNAT         : ${DNAT}" && echo
				echo "OPS Relevant : ${OPS}"
				echo "Kommentar    : ${COMMENT}"
		fi
		if (echo ${TODO} | grep -q "Delete")
			then
				echo
				echo "---------------------------------------------------------------"
				echo -e "[1;91mRegel LÖSCHEN!!!\033[0m"
				echo "Regelnummer im Auftrag : ${RULENR}"
				echo "==========================="
				echo
				echo "Firewall     : ${FIREWALL}"
				echo "Section      : ${SECTION}"
				echo "Rulename     : ${RULENAME}"
				echo "Kommentar    : ${COMMENT}"
				echo "Sources      : "
				echo
                [[ $(echo "$SOURCEIPS" | wc -w) == $(echo "$SOURCENAMES" | wc -w) ]] || echo Fehler im Auftrag
				for (( i=0; i<${#SOURCEIPS[@]}; i++ ))
					do echo -e "  $(($i+1)). \\t ${SOURCEIPS[$i]} \\t ${SOURCENAMES[$i]}"
				done
				echo
				[ "${SNAT}" ] && echo "Explicit Src : ${SNAT}" && echo
				echo "Direction      ${DIRECTION}"
				echo "Protokoll    : ${PROTONAME}"
				echo "Ports        : ${PORTS}"
				[ "${PAT}" ] && echo "PAT          : ${PAT}"
				echo "Direction      ${DIRECTION}"
				echo
				echo "Destinations : "
				echo
                [[ $(echo "$DESTIPS" | wc -w) == $(echo "$DESTNAMES" | wc -w) ]] || echo Fehler im Auftrag
				for (( i=0; i<${#DESTIPS[@]}; i++ ))
					do echo -e "  $(($i+1)). \\t ${DESTIPS[$i]} \\t ${DESTNAMES[$i]}"
				done
				echo
				[ "${DNAT}" ] && echo "DNAT         : ${DNAT}" && echo
				echo "OPS Relevant : ${OPS}"
				echo "Kommentar    : ${COMMENT}"
		fi
		if (echo ${TODO} | grep -q "Change")
			then
				echo
				echo "---------------------------------------------------------------"
				echo "Regel ändern"
				echo "Regelnummer im Auftrag : ${RULENR}"
				echo "==========================="
				echo
				echo "Firewall     : ${FIREWALL}"
				echo "Section      : ${SECTION}"
				echo "Rulename     : ${RULENAME}"
				echo "Kommentar    : ${COMMENT}"
				echo "Sources      : "
				echo
				for (( i=0; i<${#SOURCEIPS[@]}; i++ ))
					do echo -e "  $(($i+1)). \\t ${SOURCEIPS[$i]} \\t ${SOURCENAMES[$i]}"
				done
				echo
				[ "${SNAT}" ] && echo "Explicit Src : ${SNAT}" && echo
				echo "Direction      ${DIRECTION}"
				echo "Protokoll    : ${PROTONAME}"
				echo "Ports        : ${PORTS}"
				[ "${PAT}" ] && echo "PAT          : ${PAT}"
				echo "Direction      ${DIRECTION}"
				echo
				echo "Destinations : "
				echo
				for (( i=0; i<${#DESTIPS[@]}; i++ ))
					do echo -e "  $(($i+1)). \\t ${DESTIPS[$i]} \\t ${DESTNAMES[$i]}"
				done
				echo
				[ "${DNAT}" ] && echo "DNAT         : ${DNAT}" && echo
				echo "OPS Relevant : ${OPS}"
				echo -e "Kommentar    : \033[1;31m${COMMENT}\033[0m"
		fi
	# fi
done | sed -e 's/ \//\//g;s/\/\//\//g'

done

}

fortirules(){
#                    ______ ____  _____ _______ _____   _____  _    _ _      ______  _____
#                   |  ____/ __ \|  __ \__   __|_   _| |  __ \| |  | | |    |  ____|/ ____|
#                   | |__ | |  | | |__) | | |    | |   | |__) | |  | | |    | |__  | (___
#                   |  __|| |  | |  _  /  | |    | |   |  _  /| |  | | |    |  __|  \___ \
#                   | |   | |__| | | \ \  | |   _| |_  | | \ \| |__| | |____| |____ ____) |
#                   |_|    \____/|_|  \_\ |_|  |_____| |_|  \_\\____/|______|______|_____/

# Rules first as they can be done without OPSPLAN
#


for MASCHINE in ${MASCHINES}
do
echo
echo
echo "####################################################################################################"
echo "####################################################################################################"
figlet -w 140 -f doom Rules
figlet -w 140 -f doom ${MASCHINE}

echo "$RULES" |
grep "${MASCHINE}" |
sed -e 's/\t/\|/g' |

while read line
	do
	RULENR=$(echo $line | cut -d '|' -f3)
	FIREWALL=$(echo $line | cut -d '|' -f5)
	TODO=$(echo $line | cut -d '|' -f4)
	SOURCEIP=$(echo $line | cut -d '|' -f7 | sed -e 's/[;,]/ /g')
	SNAT=$(echo $line | cut -d '|' -f8)
	SRCHOSTNAMES=$(echo $line | cut -d '|' -f6 | sed -e 's/ *,/,/g;s/, */,/g;s/ /_/g;s/[;,]/ /g')
	DIRECTION="--->" #$(echo $line | cut -d '|' -f X)
	DESTIP=$(echo $line | cut -d '|' -f11 | sed -e 's/[;,]/ /g')
	DNAT=$(echo $line | cut -d '|' -f12)
	DESTHOSTNAMES=$(echo $line | cut -d '|' -f13 | sed -e 's/ *,/,/g;s/, */,/g;s/ /_/g;s/[;,]/ /g')
	PROTONAME=$(echo $line | cut -d '|' -f14 | sed -e 's/[;,]/ /g')
	PORTS=$(echo $line | cut -d '|' -f15 | sed -e 's/[;,]/ /g')
	PAT=$(echo $line | cut -d '|' -f17)
	OPS=$(echo $line | cut -d '|' -f16)
	SECTION=$(echo $line | cut -d '|' -f19)
	RULENAME=$(echo $line | cut -d '|' -f18)
	COMMENT="${AUFTRAG} $( (echo $OPS | grep -qi "ja") && echo OPS-Relevant) $(echo $line | cut -d '|' -f21 | sed -e 's/[;,/]/ /g;s/ */ /g')"

	# if [[ ${RULENR} > 0 ]]
	# then
		declare -a SOURCEIPS=($SOURCEIP)
		declare -a SOURCENAMES=($SRCHOSTNAMES)
		declare -a DESTIPS=($DESTIP)
		declare -a DESTNAMES=($DESTHOSTNAMES)

		if (echo ${TODO} | grep -q "Add")
			then
				echo
				echo "---------------------------------------------------------------"
				echo "Neue Regel erstellen"
				echo "Regelnummer im Auftrag : ${RULENR}"
				echo "==========================="
				echo
				echo "Firewall     : ${FIREWALL}"
				echo "Section      : ${SECTION}"
				echo "Rulename     : ${RULENAME}"
                echo
				# ip=1.1.1.128/25
				# (echo $ip | grep -q "/") && [[ "$( echo $ip | sed -e 's/\/.*//')" == "$(ipcalc $ip | sed -ne '/Network:/{s/Network: *//;s/\/.*//p}')" ]] && echo ist ein Netz || echo ist ein Host
                echo edit
                echo set name \"${RULENAME}\"
                echo set srcintf \"any\"
                echo set dstintf \"any\"
                echo set action accept
                echo -n set srcaddr
                for (( i=0; i<${#SOURCENAMES[@]}; i++ ))
					do 
					echo -n " "\"${SOURCENAMES[$i]}\"
				done
                echo
                echo -n set dstaddr
                for (( i=0; i<${#DESTNAMES[@]}; i++ ))
					do 
					echo -n " "\"${DESTNAMES[$i]}\"
				done
                echo
                echo set schedule \"always\"
                echo set service \"$(echo $PORTS | sed -e 's/\//_/g;s/ /\" \"/g' )\"
                echo set utm-status enable
                echo set inspection-mode proxy
                echo set av-profile \"DS-AV\"
                echo set ips-sensor \"DS-IPS\"
                echo set logtraffic-start enable
                echo set comments \"${COMMENT}\"
                echo next
		fi
		if (echo ${TODO} | grep -q "Delete")
			then
				echo
				echo "---------------------------------------------------------------"
				echo -e "[1;91mRegel LÖSCHEN!!!\033[0m"
				echo "Regelnummer im Auftrag : ${RULENR}"
				echo "==========================="
				echo
				echo "Firewall     : ${FIREWALL}"
				echo "Section      : ${SECTION}"
				echo "Rulename     : ${RULENAME}"
				echo "Sources      : "
				echo
                [[ $(echo "$SOURCEIPS" | wc -w) == $(echo "$SOURCENAMES" | wc -w) ]] || echo Fehler im Auftrag
				for (( i=0; i<${#SOURCEIPS[@]}; i++ ))
					do echo -e "  $(($i+1)). \\t ${SOURCEIPS[$i]} \\t ${SOURCENAMES[$i]}"
				done
				echo
				[ "${SNAT}" ] && echo "Explicit Src : ${SNAT}" && echo
				echo "Direction      ${DIRECTION}"
				echo "Protokoll    : ${PROTONAME}"
				echo "Ports        : ${PORTS}"
				[ "${PAT}" ] && echo "PAT          : ${PAT}"
				echo "Direction      ${DIRECTION}"
				echo
				echo "Destinations : "
				echo
                [[ $(echo "$DESTIPS" | wc -w) == $(echo "$DESTNAMES" | wc -w) ]] || echo Fehler im Auftrag
				for (( i=0; i<${#DESTIPS[@]}; i++ ))
					do echo -e "  $(($i+1)). \\t ${DESTIPS[$i]} \\t ${DESTNAMES[$i]}"
				done
				echo
				[ "${DNAT}" ] && echo "DNAT         : ${DNAT}" && echo
				echo "OPS Relevant : ${OPS}"
				echo "Kommentar    : ${COMMENT}"
		fi
		if (echo ${TODO} | grep -q "Change")
			then
				echo
				echo "---------------------------------------------------------------"
				echo "Regel ändern"
				echo "Regelnummer im Auftrag : ${RULENR}"
				echo "==========================="
				echo
				echo "Firewall     : ${FIREWALL}"
				echo "Section      : ${SECTION}"
				echo "Rulename     : ${RULENAME}"
				echo "Sources      : "
				echo
				for (( i=0; i<${#SOURCEIPS[@]}; i++ ))
					do echo -e "  $(($i+1)). \\t ${SOURCEIPS[$i]} \\t ${SOURCENAMES[$i]}"
				done
				echo
				[ "${SNAT}" ] && echo "Explicit Src : ${SNAT}" && echo
				echo "Direction      ${DIRECTION}"
				echo "Protokoll    : ${PROTONAME}"
				echo "Ports        : ${PORTS}"
				[ "${PAT}" ] && echo "PAT          : ${PAT}"
				echo "Direction      ${DIRECTION}"
				echo
				echo "Destinations : "
				echo
				for (( i=0; i<${#DESTIPS[@]}; i++ ))
					do echo -e "  $(($i+1)). \\t ${DESTIPS[$i]} \\t ${DESTNAMES[$i]}"
				done
				echo
				[ "${DNAT}" ] && echo "DNAT         : ${DNAT}" && echo
				echo "OPS Relevant : ${OPS}"
				echo -e "Kommentar    : \033[1;31m${COMMENT}\033[0m"
		fi
	# fi
done | sed -e 's/ \//\//g;s/\/\//\//g'

done
}

cpinterfaces(){
#             _____ _____    _____ _   _ _______ ______ _____  ______      _____ ______  _____
#            / ____|  __ \  |_   _| \ | |__   __|  ____|  __ \|  ____/\   / ____|  ____|/ ____|
#           | |    | |__) |   | | |  \| |  | |  | |__  | |__) | |__ /  \ | |    | |__  | (___
#           | |    |  ___/    | | | . ` |  | |  |  __| |  _  /|  __/ /\ \| |    |  __|  \___ \
#           | |____| |       _| |_| |\  |  | |  | |____| | \ \| | / ____ \ |____| |____ ____) |
#            \_____|_|      |_____|_| \_|  |_|  |______|_|  \_\_|/_/    \_\_____|______|_____/
#           

for MASCHINE in $MASCHINES
do
echo
echo '############################################################################'
echo '############################################################################'
figlet -w 140 -f doom Interfaces
figlet -w 140 -f doom ${MASCHINE}1
echo

echo -e "$INTERFACES" |
grep "${MASCHINE}" |
sed -e 's/\t/;/g' |
while read line
	do
	firewall=$(echo $line | cut -d ';' -f5 | sed -e 's/ //g')
	interface=$(echo $line | cut -d ';' -f4 | sed -e 's/ //g;s/\..*//')
	vlan=$(echo $line | cut -d ';' -f10 | sed -e 's/ (.*//g;s/ //g;s/^0*//')
	clusterip=$(echo $line | cut -d ';' -f9 | sed -e 's/ //g')
	cp1=$(echo $line | cut -d ';' -f6 | sed -e 's/ //g')
	cp2=$(echo $line | cut -d ';' -f7 | sed -e 's/ //g')
	cdr=$(echo $line | cut -d ';' -f8 | sed -e 's/.*\///;s/ //g')
    # mask=$(cdr2mask $cdr)
	kommentar=$(echo $line | cut -d ';' -f10 | sed -e 's/.*(//g;s/).*//g')

	if (echo $line | grep -qi "löschen")
		then
            echo "# ${firewall}2 - $interface.$vlan löschen:"
			echo delete interface $interface.$vlan ipv4-address $cp1 mask-length $cdr
		else
            echo '#'
            echo "# ${firewall}2 - $interface.$vlan anlegen:"
            echo add interface $interface vlan $vlan
            echo set interface $interface.$vlan comments \"$kommentar\"
            ( echo "$cp1" | grep -q "." ) && echo set interface $interface.$vlan ipv4-address $cp1 mask-length $cdr
            ( echo "$cp1" | grep -q ":" ) && echo set interface $interface.$vlan ipv6-address $cp1 mask-length $cdr
            echo set interface $interface.$vlan mtu 1500
            echo set interface $interface.$vlan state on
	fi
done | sed -e 's/ \//\//;s/\/\//\//'

echo
echo '############################################################################'
echo '############################################################################'
figlet -w 140 -f doom Interfaces
figlet -w 140 -f doom ${MASCHINE}2
echo

echo -e "$INTERFACES" |
grep "${MASCHINE}" |
sed -e 's/\t/;/g' |
while read line
	do
	firewall=$(echo $line | cut -d ';' -f5 | sed -e 's/ //g')
	interface=$(echo $line | cut -d ';' -f4 | sed -e 's/ //g;s/\..*//')
	vlan=$(echo $line | cut -d ';' -f10 | sed -e 's/ (.*//g;s/ //g')
	clusterip=$(echo $line | cut -d ';' -f9 | sed -e 's/ //g')
	cp1=$(echo $line | cut -d ';' -f6 | sed -e 's/ //g')
	cp2=$(echo $line | cut -d ';' -f7 | sed -e 's/ //g')
	cdr=$(echo $line | cut -d ';' -f8 | sed -e 's/.*\///;s/ //g')
    # mask=$(cdr2mask $cdr)
	kommentar=$(echo $line | cut -d ';' -f10 | sed -e 's/.*(//g;s/).*//g')

	if (echo $line | grep -qi "löschen")
		then
            echo "# ${firewall}2 - $interface.$vlan löschen:"
			echo delete interface $interface.$vlan ipv4-address $cp2 mask-length $cdr
		else
            echo '#'
            echo "# ${firewall}2 - $interface.$vlan anlegen:"
            echo add interface $interface vlan $vlan
            echo set interface $interface.$vlan comments \"$kommentar\"
            ( echo "$cp2" | grep -q "." ) && echo set interface $interface.$vlan ipv4-address $cp2 mask-length $cdr
            ( echo "$cp2" | grep -q ":" ) && echo set interface $interface.$vlan ipv6-address $cp2 mask-length $cdr
            echo set interface $interface.$vlan mtu 1500
            echo set interface $interface.$vlan state on
	fi
done | sed -e 's/ \//\//;s/\/\//\//'

done
}


fortiinterfaces(){
#      ______ ____  _____ _______ _____   _____ _   _ _______ ______ _____  ______      _____ ______  _____
#     |  ____/ __ \|  __ \__   __|_   _| |_   _| \ | |__   __|  ____|  __ \|  ____/\   / ____|  ____|/ ____|
#     | |__ | |  | | |__) | | |    | |     | | |  \| |  | |  | |__  | |__) | |__ /  \ | |    | |__  | (___
#     |  __|| |  | |  _  /  | |    | |     | | | . ` |  | |  |  __| |  _  /|  __/ /\ \| |    |  __|  \___ \
#     | |   | |__| | | \ \  | |   _| |_   _| |_| |\  |  | |  | |____| | \ \| | / ____ \ |____| |____ ____) |
#     |_|    \____/|_|  \_\ |_|  |_____| |_____|_| \_|  |_|  |______|_|  \_\_|/_/    \_\_____|______|_____/
#     
for MASCHINE in $MASCHINES
do
echo
echo '############################################################################'
echo '############################################################################'
figlet -w 140 -f doom Interfaces
figlet -w 140 -f doom ${MASCHINE}
echo

echo -e "$INTERFACES" |
grep "${MASCHINE}" |
sed -e 's/\t/;/g' |
while read line
	do
	firewall=$(echo $line | cut -d ';' -f5 | sed -e 's/ //g')
	interface=$(echo $line | cut -d ';' -f4 | sed -e 's/ //g;s/\..*//')
	vlan=$(echo $line | cut -d ';' -f10 | sed -e 's/ (.*//g;s/ //g;s/^0*//')
	clusterip=$(echo $line | cut -d ';' -f9 | sed -e 's/ //g')
	cp1=$(echo $line | cut -d ';' -f6 | sed -e 's/ //g')
	cp2=$(echo $line | cut -d ';' -f7 | sed -e 's/ //g')
	cdr=$(echo $line | cut -d ';' -f8 | sed -e 's/.*\///;s/ //g')
    # mask=$(cdr2mask $cdr)
	kommentar=$(echo $line | cut -d ';' -f10 | sed -e 's/.*(//g;s/).*//g')

	if  ( echo $firewall | grep -Eiq '.*-.*-f' )
	then
		if (echo $line | grep -qi "löschen")
			then
                echo "# ${firewall} - $interface.$vlan löschen:"
				echo delete interface $interface.$vlan ipv4-address $cp1 mask-length $cdr
			else
                echo '#'
                echo "# ${firewall} - $interface.$vlan anlegen:"
                echo config system interface
                echo edit \"$interface.$vlan\"
                echo set vdom \"root\"
                echo set description \"$kommentar\"
                echo set device-identification enable
                echo set role lan
                echo set ip $clusterip/$cdr
                echo set allowaccess ping
                echo set interface \"$interface\"
                echo set vlanid $vlan
                echo next
                echo end
		fi
	fi
done | sed -e 's/ \//\//;s/\/\//\//'

done
}

cprouting(){
#               _____ _____    _____   ____  _    _ _______ _____ _   _  _____
#              / ____|  __ \  |  __ \ / __ \| |  | |__   __|_   _| \ | |/ ____|
#             | |    | |__) | | |__) | |  | | |  | |  | |    | | |  \| | |  __
#             | |    |  ___/  |  _  /| |  | | |  | |  | |    | | | . ` | | |_ |
#             | |____| |      | | \ \| |__| | |__| |  | |   _| |_| |\  | |__| |
#              \_____|_|      |_|  \_\\____/ \____/   |_|  |_____|_| \_|\_____|
#             
for MASCHINE in $MASCHINES
do
echo "####################################################################################################"
echo "####################################################################################################"
figlet -w 140 -f doom ROUTING
figlet -w 140 -f doom ${MASCHINE}1 u. ${MASCHINE}2

echo -e "$ROUTING" |
grep "${MASCHINE}" |
sed -e 's/\t/;/g' |
while read line
	do
	firewall=$(echo $line | cut -d ';' -f5 | sed -e 's/ //g')
	netz=$(echo $line | cut -d ';' -f7 | sed -e 's/ //g;s/\/.*//')
	maske=$(echo $line | cut -d ';' -f7 | sed -e 's/ //g;s/.*\///')
	gateway=$(echo $line | cut -d ';' -f6 | sed -e 's/ //g')
	interface=$(echo $line | cut -d ';' -f4 | sed -e 's/ //g')
	kommentar=$(echo $line | cut -d ';' -f8)

	if [[ $netz ]]
	then
		if (echo $line | grep -qi "löschen")
			then
                echo "# $firewall - ${netz}/${maske}"
				echo set static-route ${netz}/${maske} off
			else
                echo "# $firewall - ${netz}/${maske}"
				echo set static-route ${netz}/${maske} comment \"${kommentar}\"
				echo set static-route ${netz}/${maske} nexthop gateway address ${gateway} on

		fi
	fi
done | sed -e 's/ \//\//;s/\/\//\//'

done

}

fortirouting(){
#       ______ ____  _____ _______ _____   _____   ____  _    _ _______ _____ _   _  _____
#      |  ____/ __ \|  __ \__   __|_   _| |  __ \ / __ \| |  | |__   __|_   _| \ | |/ ____|
#      | |__ | |  | | |__) | | |    | |   | |__) | |  | | |  | |  | |    | | |  \| | |  __
#      |  __|| |  | |  _  /  | |    | |   |  _  /| |  | | |  | |  | |    | | | . ` | | |_ |
#      | |   | |__| | | \ \  | |   _| |_  | | \ \| |__| | |__| |  | |   _| |_| |\  | |__| |
#      |_|    \____/|_|  \_\ |_|  |_____| |_|  \_\\____/ \____/   |_|  |_____|_| \_|\_____|
#      
for MASCHINE in $MASCHINES
do
echo "####################################################################################################"
echo "####################################################################################################"
figlet -w 140 -f doom ROUTING
figlet -w 140 -f doom ${MASCHINE}

echo -e "$ROUTING" |
grep "${MASCHINE}" |
sed -e 's/\t/;/g' |
while read line
	do
	firewall=$(echo $line | cut -d ';' -f5 | sed -e 's/ //g')
	netz=$(echo $line | cut -d ';' -f7 | sed -e 's/ //g;s/\/.*//')
	maske=$(echo $line | cut -d ';' -f7 | sed -e 's/ //g;s/.*\///')
	gateway=$(echo $line | cut -d ';' -f6 | sed -e 's/ //g')
	interface=$(echo $line | cut -d ';' -f4 | sed -e 's/ //g')
	kommentar=$(echo $line | cut -d ';' -f8)


   	if (echo $line | grep -qi "löschen")
   		then
            echo "# $firewall - ${netz}/${maske}"
   			echo keine Ahnung, wie man ${netz}/${maske} über das cli löscht
   		else
            echo "# $firewall - ${netz}/${maske}"
            echo config router static
            echo edit
            echo set dst ${netz}/${maske}
            echo set gateway $gateway
            echo set device \"$interface\"
            echo set comment \"$kommentar\"
            echo next
            echo end
   	fi
   done | sed -e 's/ \//\//;s/\/\//\//'
done
}

antispoofing(){
#                _   _ _______ _____  _____ _____   ____   ____  ______ _____ _   _  _____
#          /\   | \ | |__   __|_   _|/ ____|  __ \ / __ \ / __ \|  ____|_   _| \ | |/ ____|
#         /  \  |  \| |  | |    | | | (___ | |__) | |  | | |  | | |__    | | |  \| | |  __
#        / /\ \ | . ` |  | |    | |  \___ \|  ___/| |  | | |  | |  __|   | | | . ` | | |_ |
#       / ____ \| |\  |  | |   _| |_ ____) | |    | |__| | |__| | |     _| |_| |\  | |__| |
#      /_/    \_\_| \_|  |_|  |_____|_____/|_|     \____/ \____/|_|    |_____|_| \_|\_____|
#      
echo
echo '############################################################################'
echo '#'
echo "#  In der Netzwerktopologie Antispoofing anlegen:"
for MASCHINE in ${ROUTINGFW}
do

echo -e "$INTERFACES" |
grep "$MASCHINE" |
sed -e 's/\t/;/g' |
while read line
	do
	firewall=$(echo $line | cut -d ';' -f5 | sed -e 's/ //g')
	interface=$(echo $line | cut -d ';' -f4 | sed -e 's/ //g;s/\..*//')
	vlan=$(echo $line | cut -d ';' -f10 | sed -e 's/ (.*//g;s/ //g')
	clusterip=$(echo $line | cut -d ';' -f9 | sed -e 's/ //g')
	cp1=$(echo $line | cut -d ';' -f6 | sed -e 's/ //g')
	cp2=$(echo $line | cut -d ';' -f7 | sed -e 's/ //g')
	cdr=$(echo $line | cut -d ';' -f8 | sed -e 's/.*\///;s/ //g')
    # mask=$(cdr2mask $cdr)
	kommentar=$(echo $line | cut -d ';' -f10 | sed -e 's/.*(//g;s/).*//g')

	if  ( echo $firewall | grep -Eiq '.*-.*-c' )
	then
		figlet -w 140 -f doom ${MASCHINE}
		if (echo $line | grep -qi "löschen")
			then
                echo "# ${firewall}1 - $interface.$vlan löschen:"
				echo "# delete interface $interface.$vlan ipv4-address $clusterip mask-length $cdr"
			else
                echo '#'
                echo "#      Auf ${firewall} [ add Interface ]"
                echo "#        Object-Name: $interface.$vlan"
                echo "#               Type: Cluster"
                echo "#               IPv4: $clusterip/$cdr"
                echo "#            Member1: $cp1/$cdr"
                echo "#            Member2: $cp2/$cdr"
                echo "#       Antispoofing: as-ng.${firewall//fw-/}-$interface.$vlan"
				echo "#                       * fw-n.$(echo $firewall | sed -e 's/fw-//;s/-.*//')-$(echo $kommentar | sed 's/.*/\L&/;s/ /_/g') - $(ipcalc $clusterip/$cdr | sed -ne '/Network/{s/\/.*//;s/.* //p}')/$(ipcalc $clusterip/$cdr | sed -ne '/Netmask/{s/ =.*//;s/.* //p}')"
				

				echo -e "$ROUTING" |
				sed -e 's/\t/;/g' |
				while read line
					do
					netz=$(echo $line | cut -d ';' -f7 | sed -e 's/ //g;s/\/.*//')
					maske=$(echo $line | cut -d ';' -f7 | sed -e 's/ //g;s/.*\///')
					cpif=$(echo $line | cut -d ';' -f4 | sed -e 's/ //g')
					netname=$(echo $line | cut -d ';' -f8 | sed 's/.*/\L&/;s/ /_/g')
					
					if [[ "$cpif" == "$interface.$vlan" ]]
					then
						echo "#                       * $netname - ${netz}/$(cdr2mask ${maske})"
					fi
				done | sed -e 's/ \//\//;s/\/\//\//'




		fi
	fi
done | sed -e 's/ \//\//;s/\/\//\//'

done

echo '#'
echo '############################################################################'
echo

}

#           _____ _______       _____ _______   _    _ ______ _____  ______
#          / ____|__   __|/\   |  __ \__   __| | |  | |  ____|  __ \|  ____|
#         | (___    | |  /  \  | |__) | | |    | |__| | |__  | |__) | |__
#          \___ \   | | / /\ \ |  _  /  | |    |  __  |  __| |  _  /|  __|
#          ____) |  | |/ ____ \| | \ \  | |    | |  | | |____| | \ \| |____
#         |_____/   |_/_/    \_\_|  \_\ |_|    |_|  |_|______|_|  \_\______|
#         
####################################################################################################
####################################################################################################

AUFTRAG=$1
INTERFACEFW=$(echo "$INTERFACES" | sed -e 's/\t/\|/g' | cut -d '|' -f5 | grep -vEi "^$" | sort -u)
ROUTINGFW=$(echo "$ROUTING" | sed -e 's/\t/\|/g' | cut -d '|' -f5 | grep -vEi "^$" | sort -u)
RULEFW=$(echo "$RULES" | sed -e 's/\t/\|/g' | cut -d '|' -f5 | grep -vEi "^$" | sort -u)

####################################################################################################
####################################################################################################
#         _____ _    _ ______ _____ _  _______   ____ _____ _   _ _______
#        / ____| |  | |  ____/ ____| |/ /  __ \ / __ \_   _| \ | |__   __|
#       | |    | |__| | |__ | |    | ' /| |__) | |  | || | |  \| |  | |
#       | |    |  __  |  __|| |    |  < |  ___/| |  | || | | . ` |  | |
#       | |____| |  | | |___| |____| . \| |    | |__| || |_| |\  |  | |
#        \_____|_|  |_|______\_____|_|\_\_|     \____/_____|_| \_|  |_|
#       


MASCHINES=$( echo "$RULEFW" | grep -Ei '.*-.*-c' )
[ "${MASCHINES}" ] && cprules

MASCHINES=$( echo "$INTERFACEFW" | grep -Ei '.*-.*-c' )
[ "${MASCHINES}" ] && cpinterfaces

MASCHINES=$( echo "$ROUTINGFW" | grep -Ei '.*-.*-c' )
[ "${MASCHINES}" ] && cprouting

MASCHINES=$( echo "$ROUTINGFW" | grep -Ei '.*-.*-c' )
[ "${MASCHINES}" ] && antispoofing

####################################################################################################
#            ______ ____  _____ _______ _____ _   _ ______ _______
#           |  ____/ __ \|  __ \__   __|_   _| \ | |  ____|__   __|
#           | |__ | |  | | |__) | | |    | | |  \| | |__     | |
#           |  __|| |  | |  _  /  | |    | | | . ` |  __|    | |
#           | |   | |__| | | \ \  | |   _| |_| |\  | |____   | |
#           |_|    \____/|_|  \_\ |_|  |_____|_| \_|______|  |_|
#           
MASCHINES=$( echo "$RULEFW" | grep -Ei '.*-.*-f' )
[ "${MASCHINES}" ] && fortirules

MASCHINES=$( echo "$INTERFACEFW" | grep -Ei '.*-.*-f' )
[ "${MASCHINES}" ] && fortiinterfaces

MASCHINES=$( echo "$ROUTINGFW" | grep -Ei '.*-.*-f' )
[ "${MASCHINES}" ] && fortirouting