diff --git a/agent.py b/agent.py index b45e854..0662598 100644 --- a/agent.py +++ b/agent.py @@ -18,6 +18,9 @@ ANODE_URL = os.environ.get("TUXFLOTTE_ANODE_URL", "https://anode.tuxflotte.de") CREDENTIALS_PATH = os.environ.get( "TUXFLOTTE_AGENT_CREDENTIALS", "/etc/tuxflotte/agent.credentials" ) +# Nachweis beim Bootstrap (27.10.2026, platform-docs +# roadmap/agent-zugang-haertung.md), legt postinstall.sh ab, nur root lesbar. +FINGERPRINT_PATH = "/etc/tuxflotte/device_fingerprint" FALLBACK_INTERVAL_SECONDS = 60 # Jitter (26.08.2026-Planung): nur auf "grosse" Intervalle (Standard 6h) # anwenden, nicht auf den kurzen Debug-Modus (60s) oder den Fallback-Retry @@ -131,14 +134,25 @@ def api_request(path, agent_secret, body): def bootstrap(device_id): """ Holt ein frisches agent_secret über /api/v1/agent/bootstrap. Braucht - keinen Authorization-Header (der Endpoint kannte von Anfang an keine - andere Authentifizierung als die device_id, siehe provisioning-server - app.py) - macht sich zunutze, dass so ein Re-Bootstrap nach einer - Reprovisionierung im Kundenportal möglich ist, ohne physisch am Gerät - etwas tun zu müssen. + keinen Authorization-Header - macht sich zunutze, dass so ein + Re-Bootstrap nach einer Reprovisionierung im Kundenportal möglich ist, + ohne physisch am Gerät etwas tun zu müssen. Als Nachweis geht seit + 27.10.2026 der Fingerprint mit; die device_id allein genügte vorher + jedem, der sie kannte. """ - data = json.dumps({"device_id": device_id}).encode("utf-8") + body = {"device_id": device_id} + + try: + with open(FINGERPRINT_PATH, "r", encoding="utf-8") as f: + fingerprint = f.read().strip() + except OSError as exc: + log(f"Fingerprint nicht lesbar ({exc}), Bootstrap ohne Nachweis.") + else: + if fingerprint: + body["device_fingerprint"] = fingerprint + + data = json.dumps(body).encode("utf-8") req = urllib.request.Request( ANODE_URL + "/api/v1/agent/bootstrap",