Security: Remove hardcoded credentials, enforcing env vars

This commit is contained in:
Gemini Agent
2025-12-04 05:24:36 +00:00
parent 76dffc4c0d
commit 27b7187f3a
4 changed files with 97 additions and 96 deletions

46
sync.py
View File

@@ -3,17 +3,24 @@ import os
import time
import sys
# --- KONFIGURATION (Via Environment Variables) ---
# Falls keine ENV-Vars gesetzt sind, werden die alten Hardcoded-Werte als Fallback genutzt.
NETBOX_URL = os.getenv("NETBOX_URL", "http://172.30.242.99")
TOKEN = os.getenv("NETBOX_TOKEN", "0b740520aeef964cfd2ca34b82a472a271d51649")
def log(msg):
"""Ungepufferte Ausgabe für Docker Logs"""
print(msg, flush=True)
# --- KONFIGURATION ---
# Pflichtfelder - Abbruch wenn nicht gesetzt
NETBOX_URL = os.getenv("NETBOX_URL")
TOKEN = os.getenv("NETBOX_TOKEN")
if not NETBOX_URL or not TOKEN:
log("FATAL ERROR: Environment variables NETBOX_URL and NETBOX_TOKEN are required.")
log("Please provide them via -e flag or .env file.")
sys.exit(1)
# Optionale Konfiguration mit Defaults
ZONE_NAME = os.getenv("ZONE_NAME", "klenzel.net")
REVERSE_ZONE_NAME = os.getenv("REVERSE_ZONE_NAME", "172.in-addr.arpa")
# Interval in Sekunden
REFRESH_INTERVAL = int(os.getenv("REFRESH_INTERVAL", "600"))
OUTPUT_FILE_FWD = os.getenv("OUTPUT_FILE_FWD", "/zones/db.klenzel.net")
OUTPUT_FILE_REV = os.getenv("OUTPUT_FILE_REV", "/zones/db.reverse.arpa")
DEFAULT_TTL = os.getenv("DEFAULT_TTL", "3600")
@@ -21,18 +28,13 @@ DEFAULT_TTL = os.getenv("DEFAULT_TTL", "3600")
# Fallback Konfiguration (wenn KEIN NS in NetBox gefunden wird)
FALLBACK_NS_HOSTNAME = os.getenv("FALLBACK_NS_HOSTNAME", "fks-01-cl-cdns")
FALLBACK_NS_IP = os.getenv("FALLBACK_NS_IP", "172.25.16.152")
# ---------------------
HEADERS = {'Authorization': f'Token {TOKEN}', 'Accept': 'application/json'}
def log(msg):
"""Ungepufferte Ausgabe für Docker Logs"""
print(msg, flush=True)
def fetch_ipam_data():
"""
Holt alle aktiven IPs mit DNS-Namen aus NetBox.
Wirft eine Exception, wenn NetBox nicht erreichbar ist (kein try/except hier!).
Wirft eine Exception, wenn NetBox nicht erreichbar ist.
"""
url = f"{NETBOX_URL}/api/ipam/ip-addresses/?status=active&dns_name__n=&limit=0"
log(f"Abruf IPAM: {url}")
@@ -114,7 +116,6 @@ def get_ns_config(plugin_records, all_records):
def generate_zone_file_fwd(ipam_data, plugin_records):
"""Erstellt die Forward-Zone"""
# Daten aufbereiten
ipam_records = []
for ip in ipam_data:
dns_name = ip.get('dns_name', '')
@@ -133,7 +134,6 @@ def generate_zone_file_fwd(ipam_data, plugin_records):
all_records = plugin_records + ipam_records
# Header-Logik
primary_ns, extra_headers = get_ns_config(plugin_records, all_records)
serial = int(time.time())
@@ -152,7 +152,6 @@ def generate_zone_file_fwd(ipam_data, plugin_records):
header.extend(extra_headers)
header.append("")
# Schreiben
with open(OUTPUT_FILE_FWD, "w") as f:
f.write("\n".join(header))
f.write("\n; --- Records ---\n")
@@ -207,11 +206,10 @@ def generate_zone_file_rev(ipam_data, plugin_records):
log(f"SUCCESS: Reverse Zone geschrieben ({len(ptr_records)} Records).")
if __name__ == "__main__":
# Kurzer Check ob Zielordner existiert
if not os.path.exists(os.path.dirname(OUTPUT_FILE_FWD)):
log(f"FATAL: Verzeichnis {os.path.dirname(OUTPUT_FILE_FWD)} fehlt!")
time.sleep(30)
exit(1)
time.sleep(5)
sys.exit(1)
log(f"--- CoreDNS Sync startet ---")
log(f"NetBox URL: {NETBOX_URL}")
@@ -221,22 +219,14 @@ if __name__ == "__main__":
log(f"\n--- Sync Start: {time.ctime()} ---")
try:
# Schritt 1: Daten holen (wirft Exception bei Fehler)
# Wir holen BEIDE Datensätze, bevor wir irgendetwas schreiben.
# Wenn einer fehlschlägt, bricht der ganze Block ab.
ipam_data = fetch_ipam_data()
plugin_records = fetch_plugin_records()
# Schritt 2: Zonen schreiben
# Wird nur erreicht, wenn fetch_ipam_data UND fetch_plugin_records erfolgreich waren
generate_zone_file_fwd(ipam_data, plugin_records)
generate_zone_file_rev(ipam_data, plugin_records)
except Exception as e:
# Sicherheits-Logik: Bei JEDEM Fehler (Netzwerk, HTTP 500, Parse-Error)
# fangen wir hier ab und schreiben KEINE Dateien.
# Die alten Dateien bleiben erhalten -> CoreDNS liefert weiter die alten Daten (kein NXDOMAIN).
log(f"CRITICAL ERROR: Sync abgebrochen! Behalte alte Zone-Files. Grund: {e}")
log(f"Schlafe {REFRESH_INTERVAL} Sekunden...")
time.sleep(REFRESH_INTERVAL)
time.sleep(REFRESH_INTERVAL)