Zugangsdaten und Proxy-Handling ohne Keepass
This commit is contained in:
@@ -3,6 +3,8 @@ hosting.kdbx
|
||||
|
||||
# Zwischengespeicherte INWX-Session (enthält ein kurzlebiges Session-Cookie)
|
||||
.inwx_session
|
||||
# Anmeldedaten
|
||||
.inwx_credentials
|
||||
|
||||
# Python-venv und Cache
|
||||
venv/
|
||||
|
||||
@@ -1,3 +1,31 @@
|
||||
### Skripte und Funktionen
|
||||
immer zuerst die python Umgebung aktivieren und Proxy setzen
|
||||
`source venv/bin/activate`
|
||||
`export INWX_PROXY="http://proxy.stadt-muenster.de:8080`
|
||||
|
||||
## allgemeine Funktonen, nicht aufrufbar
|
||||
inwx_common.py
|
||||
## Eintrag hinzufügen
|
||||
inwx_add_record.py
|
||||
# Bsp python3 inwx_add_record.py stadt-muenster.eu TXT @ citeq:10
|
||||
|
||||
## Gesamtliste fuer die citeq
|
||||
inwx_domains.py
|
||||
# Bsp pyhton3 inwx_domains.py
|
||||
|
||||
## Abrechnungsliste mit Verwaltungen und Kosten
|
||||
inwx_domains_owner.py
|
||||
# Bsp pyhton3 inwx_domains_owner.py
|
||||
|
||||
## Inhalt einer Domain auflisten
|
||||
inwx_list.py
|
||||
# Bsp python3 inwx_list.py stadt-muenster.eu
|
||||
|
||||
## Listen um Inhaber und Preise der Abrechnung aufzulisten
|
||||
domain_owner
|
||||
domain_price
|
||||
|
||||
### Neuinstallation
|
||||
Um die Library sauber in einer isolierten Umgebung auf deinem neuen Server zu installieren, gehst du in dein Projektverzeichnis und führst diese drei Schritte aus. Das verhindert, dass sich verschiedene Python-Projekte in die Quere kommen.
|
||||
|
||||
### 1. Die Umgebung erstellen
|
||||
@@ -19,7 +47,9 @@ source venv/bin/activate
|
||||
Jetzt kannst du `pip` nutzen. Da die Umgebung aktiv ist, wird die Library **nur** in diesem Ordner installiert und nicht systemweit:
|
||||
|
||||
```bash
|
||||
pip install inwx-domrobot
|
||||
### pip install inwx-domrobot
|
||||
pip install --proxy http://proxy.stadt-muenster.de:8080 inwx-domrobot
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
@@ -30,9 +60,10 @@ Du kannst sofort prüfen, ob alles an der richtigen Stelle gelandet ist:
|
||||
* **Paket-Check:** `pip list` (Hier sollte `inwx-domrobot` auftauchen).
|
||||
* **Pfad-Check:** `which python3` (Sollte den Pfad zu deinem Projektordner anzeigen, nicht `/usr/bin/python3`).
|
||||
|
||||
### Wie geht es weiter?
|
||||
Wenn du fertig bist oder das Terminal schließt, kannst du die Umgebung mit dem Befehl `deactivate` wieder verlassen. Wenn du das Skript später erneut ausführen willst, musst du vorher nur wieder den `source`-Befehl aus Schritt 2 eingeben.
|
||||
|
||||
**Tipp für den neuen Server:** Falls `python3 -m venv` eine Fehlermeldung ausgibt ("venv not found"), musst du das entsprechende System-Paket unter Ubuntu/Debian einmalig nachinstallieren:
|
||||
`sudo apt update && sudo apt install python3-venv -y`
|
||||
### Anmeldedaten
|
||||
siehe .inwx.credentials
|
||||
|
||||
### Proxy Nutzung
|
||||
export INWX_PROXY="http://proxy.stadt-muenster.de:8080"
|
||||
|
||||
|
||||
+3
-3
@@ -1,3 +1,3 @@
|
||||
10 gruppe1
|
||||
20 gruppe2
|
||||
30 gruppe3
|
||||
10 Münster
|
||||
20 Hamm
|
||||
30 Kreis_Warendof
|
||||
|
||||
+10
-1
@@ -1 +1,10 @@
|
||||
de 5,00
|
||||
de 12,90
|
||||
com 13,20
|
||||
ms 19,50
|
||||
eu 13,50
|
||||
schule 16,00
|
||||
digital 17,60
|
||||
info 15,50
|
||||
nrw 16,70
|
||||
net 14,10
|
||||
org 14,00
|
||||
|
||||
+66
-41
@@ -1,15 +1,21 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Gemeinsame Helfer für die INWX-Skripte.
|
||||
|
||||
Kapselt das Laden der Zugangsdaten aus KeePassXC sowie den Login mit
|
||||
Session-Caching: Nach dem ersten Login wird das Session-Cookie von INWX
|
||||
lokal zwischengespeichert. Folgeaufrufe nutzen diese Session wieder und
|
||||
benötigen daher weder das KeePass-Master-Passwort noch einen neuen Login,
|
||||
solange die Session bei INWX noch gültig ist.
|
||||
Kapselt das Laden der Zugangsdaten sowie den Login mit Session-Caching:
|
||||
Nach dem ersten Login wird das Session-Cookie von INWX lokal zwischen-
|
||||
gespeichert. Folgeaufrufe nutzen diese Session wieder und benötigen daher
|
||||
keinen neuen Login, solange die Session bei INWX noch gültig ist.
|
||||
|
||||
Zugangsdaten werden in dieser Reihenfolge gesucht:
|
||||
1. Umgebungsvariablen INWX_USER / INWX_PASSWORD
|
||||
(z.B. gesetzt über eine systemd EnvironmentFile=)
|
||||
2. Credentials-Datei CREDS_FILE_PATH im Format:
|
||||
username=dein_inwx_benutzername
|
||||
password=dein_inwx_passwort
|
||||
Die Datei muss chmod 600 und dem ausführenden Benutzer gehören.
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import requests
|
||||
@@ -23,50 +29,64 @@ except ImportError:
|
||||
# --- KONFIGURATION ---
|
||||
API_URL = 'https://api.domrobot.com'
|
||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
KP_DB_PATH = os.path.join(BASE_DIR, "hosting.kdbx")
|
||||
KP_ENTRY_NAME = "inwx"
|
||||
# HTTP-Proxy für die Verbindung zur INWX-API (optional).
|
||||
# Format: http://proxyhost:port oder mit Auth: http://user:passwort@proxyhost:port
|
||||
# Kann per Umgebungsvariable INWX_PROXY gesetzt werden.
|
||||
PROXY_URL = os.environ.get("INWX_PROXY")
|
||||
# Datei mit den INWX-Zugangsdaten (username=... / password=...).
|
||||
# WICHTIG: chmod 600, nur für den ausführenden Benutzer lesbar!
|
||||
CREDS_FILE_PATH = os.path.join(BASE_DIR, ".inwx_credentials")
|
||||
# Datei mit der zwischengespeicherten Session (enthält nur ein kurzlebiges
|
||||
# Session-Cookie, niemals das Passwort).
|
||||
SESSION_CACHE_PATH = os.path.join(BASE_DIR, ".inwx_session")
|
||||
|
||||
|
||||
def get_creds():
|
||||
"""Holt Benutzername und Passwort aus KeePassXC.
|
||||
|
||||
Das KeePass-Master-Passwort wird interaktiv abgefragt. Ist die
|
||||
Umgebungsvariable KP_PW gesetzt, wird deren Wert stattdessen automatisch
|
||||
an keepassxc-cli übergeben (praktisch in nicht-interaktiven Umgebungen).
|
||||
"""
|
||||
def _check_perms(path):
|
||||
"""Warnt, falls eine Secrets-Datei für Gruppe/Andere lesbar ist."""
|
||||
try:
|
||||
# -s sorgt dafür, dass das Passwort nicht als 'PROTECTED' ausgegeben wird
|
||||
cmd = ["keepassxc-cli", "show", "-s", KP_DB_PATH, KP_ENTRY_NAME]
|
||||
mode = os.stat(path).st_mode
|
||||
if mode & 0o077:
|
||||
print(f"⚠️ {path} ist für andere Benutzer les-/schreibbar! "
|
||||
f"Bitte 'chmod 600 {path}' ausführen.")
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
master_pw = os.environ.get("KP_PW")
|
||||
if master_pw:
|
||||
# Master-Passwort über stdin an keepassxc-cli durchreichen.
|
||||
result = subprocess.run(
|
||||
cmd, input=master_pw + "\n",
|
||||
capture_output=True, text=True,
|
||||
)
|
||||
if result.returncode != 0:
|
||||
print(f"❌ KeePass-Fehler: {result.stderr.strip()}")
|
||||
return None, None
|
||||
output = result.stdout
|
||||
else:
|
||||
# Kein KP_PW gesetzt -> keepassxc-cli fragt interaktiv nach.
|
||||
output = subprocess.check_output(cmd, text=True)
|
||||
|
||||
def get_creds():
|
||||
"""Holt Benutzername und Passwort für die INWX-API.
|
||||
|
||||
Siehe Modul-Docstring für die Reihenfolge der Quellen (ENV, dann Datei).
|
||||
"""
|
||||
env_user = os.environ.get("INWX_USER")
|
||||
env_password = os.environ.get("INWX_PASSWORD")
|
||||
if env_user and env_password:
|
||||
return env_user, env_password
|
||||
|
||||
if not os.path.exists(CREDS_FILE_PATH):
|
||||
print(f"❌ Keine Zugangsdaten gefunden: weder INWX_USER/INWX_PASSWORD "
|
||||
f"gesetzt, noch {CREDS_FILE_PATH} vorhanden.")
|
||||
return None, None
|
||||
|
||||
_check_perms(CREDS_FILE_PATH)
|
||||
|
||||
try:
|
||||
creds = {}
|
||||
for line in output.splitlines():
|
||||
if ":" in line:
|
||||
k, v = line.split(":", 1)
|
||||
with open(CREDS_FILE_PATH, "r") as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if not line or line.startswith("#") or "=" not in line:
|
||||
continue
|
||||
k, v = line.split("=", 1)
|
||||
creds[k.strip().lower()] = v.strip()
|
||||
|
||||
user = creds.get("username") or creds.get("benutzername") or creds.get("user")
|
||||
password = creds.get("password") or creds.get("passwort")
|
||||
user = creds.get("username") or creds.get("user")
|
||||
password = creds.get("password")
|
||||
if not user or not password:
|
||||
print(f"❌ {CREDS_FILE_PATH} enthält keine gültigen username=/password=-Zeilen.")
|
||||
return None, None
|
||||
return user, password
|
||||
except Exception as e:
|
||||
print(f"❌ KeePass-Fehler: {e}")
|
||||
print(f"❌ Fehler beim Lesen von {CREDS_FILE_PATH}: {e}")
|
||||
return None, None
|
||||
|
||||
|
||||
@@ -107,7 +127,7 @@ def _clear_cached_session():
|
||||
|
||||
|
||||
def _do_login(api):
|
||||
"""Frischer Login via KeePass-Zugangsdaten; speichert die Session. True bei Erfolg."""
|
||||
"""Frischer Login mit den konfigurierten Zugangsdaten; speichert die Session. True bei Erfolg."""
|
||||
user, password = get_creds()
|
||||
if not user or not password:
|
||||
return False
|
||||
@@ -129,9 +149,14 @@ def get_client():
|
||||
Nutzt eine zwischengespeicherte Session, falls vorhanden. Ob diese noch
|
||||
gültig ist, wird erst beim ersten echten Aufruf via call_api() geprüft –
|
||||
so sparen wir uns eine zusätzliche Anfrage. Ist keine Session vorhanden,
|
||||
wird sofort via KeePass eingeloggt.
|
||||
wird sofort neu eingeloggt.
|
||||
|
||||
Ist PROXY_URL gesetzt, laufen alle Requests der Session (Login und
|
||||
API-Aufrufe) über diesen HTTP-Proxy.
|
||||
"""
|
||||
api = ApiClient(api_url=API_URL)
|
||||
if PROXY_URL:
|
||||
api.api_session.proxies = {"http": PROXY_URL, "https": PROXY_URL}
|
||||
if _load_cached_cookies(api):
|
||||
print("ℹ️ Verwende zwischengespeicherte Session.")
|
||||
return api
|
||||
@@ -159,8 +184,8 @@ def call_api(api, method, params=None):
|
||||
"""Wie ApiClient.call_api, meldet sich aber bei abgelaufener Session neu an.
|
||||
|
||||
Deutet der Rückgabecode auf eine fehlende/abgelaufene Session hin (siehe
|
||||
_is_auth_error), wird die zwischengespeicherte Session verworfen, via
|
||||
KeePass neu eingeloggt und der Aufruf einmal wiederholt.
|
||||
_is_auth_error), wird die zwischengespeicherte Session verworfen, neu
|
||||
eingeloggt und der Aufruf einmal wiederholt.
|
||||
"""
|
||||
params = params or {}
|
||||
res = api.call_api(method, params)
|
||||
|
||||
Reference in New Issue
Block a user