# RDP

# Version_0.5 xfreerdp - Skript

# RDP-Launcher mit `xfreerdp3` – Schnellstart &amp; Nutzung

<div id="bkmrk-quickstart%3A-schritt-" style="background: #e3f2fd; border-left: 4px solid #1976d2; padding: 1em; margin-bottom: 1em;">**Quickstart: Schritt für Schritt (wenn `venv` schon existiert)**1. **Terminal öffnen**  
    <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>T</kbd>
2. **In Projektordner wechseln**  
    `cd ~/rdp-launcher`
3. **Virtuelle Umgebung aktivieren**  
    `source .venv/bin/activate`  
    (Bei jedem neuen Terminal nötig!)
4. **Launcher starten**  
    `./xfreerdp_launcher.py`   
    <span style="color: #666;">(Falls nicht ausführbar: `chmod +x xfreerdp_launcher.py` nur 1x nötig)</span>   
    <span style="color: #666;">Oder per Python:  
    `python3 xfreerdp_launcher.py`</span>
5. **Menü nutzen, Standort &amp; Server auswählen**
6. **Erste Passwortabfrage** – wird sicher im Keyring gespeichert

</div>Diese Anleitung richtet sich an absolute Einsteiger und führt dich in wenigen Schritten zur ersten RDP-Sitzung.  
**Bitte arbeite jeden Schritt der Reihe nach ab.**

---

## 1. Voraussetzungen prüfen (nur 1x nötig)

1. **Python &amp; Pip:**```
    python3 --version
    pip3 --version
    ```
    
    **Fehlt was?**  
    `sudo apt updatesudo apt install python3 python3-pip python3-venv`
2. **xfreerdp3 installieren:**```
    sudo apt install freerdp3-x11
    ```
3. **Keyring-Backend?** (Gnome, KDE etc: schon dabei)

---

## 2. Projektordner &amp; venv erstellen (nur 1x nötig)

1. **Ordner anlegen &amp; wechseln:**```
    mkdir -p ~/rdp-launcher
    cd ~/rdp-launcher
    ```
2. **Virtuelle Umgebung erstellen:**```
    python3 -m venv .venv
    ```
3. **venv aktivieren:**```
    source .venv/bin/activate
    ```
4. **Abhängigkeit installieren:**```
    pip install keyring
    ```

<div id="bkmrk-tipp%3A-immer-zuerst-s" style="background: #fffbdd; border-left: 4px solid #f7d26c; padding: 1em;">**Tipp:** Immer zuerst `source .venv/bin/activate` ausführen, bevor du arbeitest!</div>---

## 3. Python-Skript anlegen

Speichere folgendes als `xfreerdp_launcher.py` im Projektordner:

<details id="bkmrk-%E2%96%B6-python-code-anzeig"><summary>**▶ Python-Code anzeigen / ausklappen**</summary>

```python
#!/usr/bin/env python3
"""
xfreerdp_launcher.py – RDP-Launcher mit TUI und Keyring-Support

Features:
- Übersichtliche, farbige Menüführung (TUI)
- Passwörter sicher im System-Keyring gespeichert
- Automatisches Neuladen der Konfiguration bei Änderungen
- Voll kompatibel mit xfreerdp3-Parametern

Benötigt:
- Python ≥ 3.9
- keyring (pip install keyring)
- config.json im selben Ordner
"""

import argparse
import json
import subprocess
import sys
import os
from pathlib import Path
from getpass import getpass
import keyring

CONFIG_FILE = Path("./config.json").resolve()
SERVICE = "xfreerdp_launcher"

def farbig(text, farbe="reset"):
    farben = {
        "reset": "\033[0m", "bold": "\033[1m", "red": "\033[31m",
        "green": "\033[32m", "yellow": "\033[33m", "blue": "\033[34m",
        "magenta": "\033[35m", "cyan": "\033[36m", "gray": "\033[90m",
        "bright_red": "\033[91m", "bright_green": "\033[92m",
        "bright_yellow": "\033[93m", "bright_blue": "\033[94m",
        "bright_magenta": "\033[95m", "bright_cyan": "\033[96m",
        "bright_white": "\033[97m"
    }
    return f"{farben.get(farbe, '')}{text}{farben['reset']}"

def lade_config():
    try:
        return json.loads(CONFIG_FILE.read_text())
    except Exception as e:
        print(farbig(f"⚠️  Fehler in config.json: {e}", "red"))
        return {}

def passwort_holen(cred_alias, domain, user):
    cred_id = f"{cred_alias}|{domain}|{user}"
    pw = keyring.get_password(SERVICE, cred_id)
    if pw is None:
        pw = getpass(f"Passwort für {user}@{domain}: ")
        if not pw:
            sys.exit("Abbruch – kein Passwort eingegeben.")
        keyring.set_password(SERVICE, cred_id, pw)
        print(farbig("Passwort gespeichert.", "green"))
    return pw

def rdp_starten(ip, domain, user, pw, extra_args):
    cmd = [
        "xfreerdp3",
        f"/u:{user}", f"/d:{domain}", f"/v:{ip}",
        "/dynamic-resolution", "/clipboard", "/cert:ignore",
        f"/p:{pw}"
    ] + extra_args
    try:
        subprocess.Popen(cmd)
    except Exception as e:
        print(farbig(f"Fehler beim Start: {e}", "red"))

def host_verbinden(entry, creds, default_cred, extra_args):
    cred = entry.get("cred", default_cred)
    profile = creds.get(cred)
    if not profile:
        print(farbig(f"Credential '{cred}' fehlt!", "red"))
        input("⏎ Weiter...")
        return
    pw = passwort_holen(cred, profile["domain"], profile["user"])
    rdp_starten(entry["host"], profile["domain"], profile["user"], pw, extra_args)
    print(farbig(f"Sitzung zu {entry['alias']} gestartet.", "cyan"))
    input("⏎ Weiter...")

def menue(section, creds, default_cred, extra_args, path="", offene=set()):
    is_root = (path == "")
    while True:
        config = lade_config()
        groups = config.get("groups", {})
        credentials = config.get("credentials", {})
        default = config.get("default_cred", default_cred)
        if is_root:
            section = {"groups": groups}
        creds = credentials
        default_cred = default

        os.system("clear")
        print(farbig(f"=== RDP-Menü {path} ===\n", "bold"))
        groups = section.get("groups", {})
        hosts = section.get("hosts", [])
        index = {}
        i = 1
        if is_root:
            for name, content in groups.items():
                print(f" {i:2}) {farbig(name, content.get('color', 'reset'))} →")
                index[str(i)] = ("group", content, f"{path}/{name}")
                i += 1
        else:
            for h in hosts:
                alias = h["alias"]
                mark = farbig("✅", "green") if alias in offene else "  "
                print(f" {i:2}) {farbig(alias, h.get('color', 'reset'))} – {h['host']} {mark}")
                index[str(i)] = ("host", h)
                i += 1

        print("\n  b) Zurück")
        print("  q) Beenden")
        sel = input(farbig("Auswahl: ", "bold")).strip()
        if sel == "q":
            sys.exit("Beende Launcher.")
        elif sel == "b":
            return
        elif sel in index:
            typ, eintrag, *rest = index[sel]
            if typ == "group":
                menue({"hosts": eintrag.get("hosts", [])}, creds, default_cred, extra_args, rest[0], offene)
            elif typ == "host":
                offene.add(eintrag["alias"])
                host_verbinden(eintrag, creds, default_cred, extra_args)
        else:
            print(farbig("Ungültige Auswahl.", "red"))
            input("⏎ Weiter...")

def main():
    parser = argparse.ArgumentParser(description="xfreerdp Launcher mit Keyring")
    parser.add_argument("freerdp_args", nargs=argparse.REMAINDER, help="zusätzliche xfreerdp3-Parameter")
    args = parser.parse_args()
    offene = set()
    while True:
        config = lade_config()
        creds = config.get("credentials", {})
        default = config.get("default_cred", "")
        groups = config.get("groups")
        if not groups:
            print(farbig("⚠️  Keine Gruppen in config.json.", "yellow"))
            input("⏎ Weiter...")
            continue
        menue({"groups": groups}, creds, default, args.freerdp_args, "", offene)

if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("\n[Abbruch]")

```

</details>---

## 4. Beispiel `config.json`

Erstelle im selben Ordner eine Datei `config.json` mit folgendem Inhalt:

<details id="bkmrk-%E2%96%B6-beispiel-konfigura"><summary>**▶ Beispiel-Konfiguration anzeigen / ausklappen**</summary>

```json
{
  "default_cred": "user1",
  "credentials": {
    "user1": { "domain": "FIRMENNETZ", "user": "max.mustermann" },
    "user2": { "domain": "INTRANET",   "user": "maria.musterfrau" }
  },
  "groups": {
    "Standort_A": {
      "color": "bright_blue",
      "hosts": [
        { "alias": "Server-A1", "host": "10.0.10.11", "color": "bright_green",  "cred": "user1" },
        { "alias": "Server-A2", "host": "10.0.10.12", "color": "bright_magenta","cred": "user2" }
      ]
    },
    "Standort_B": {
      "color": "bright_yellow",
      "hosts": [
        { "alias": "Server-B1", "host": "10.0.20.21", "color": "bright_cyan",   "cred": "user1" },
        { "alias": "Server-B2", "host": "10.0.20.22", "color": "bright_red",    "cred": "user2" }
      ]
    }
  }
}

```

</details>IP-Adressen, Farben etc. kannst du jederzeit anpassen!

---

## 5. Alles ausführen – Zusammengefasst

- **Terminal öffnen** → `cd ~/rdp-launcher`
- **venv aktivieren** → `source .venv/bin/activate`
- **Launcher starten** → `./xfreerdp_launcher.py`
- Durch das Menü klicken: **Standort → Server → Passwort**
- Passwort wird einmalig abgefragt &amp; im Keyring gespeichert
- **Zum Beenden:** <kbd>q</kbd> eingeben

<div id="bkmrk-mini-quickstart%3Actrl" style="background: #e8f5e9; border-left: 4px solid #4caf50; padding: 1em;">**Mini-Quickstart:**  
`Ctrl+Alt+T  cd ~/rdp-launcher  source .venv/bin/activate  ./xfreerdp_launcher.py`</div>---