Files
DogFatherGit 077925ab25 Dreizehn rote Pruefungen, eine Ursache: openssl steht nicht im PATH
DER BEFUND

Im naechtlichen Lauf standen dreizehn Pruefungen mit derselben Zeile
rot:

    [uncaughtException] Error: spawnSync openssl ENOENT

Kein Programmfehler. Die Pruefungen brauchen einen https-Vorbau (der
Sitzungskeks des Hauses ist `secure` und kommt ueber http nicht an),
und dafuer erzeugen sie ein Wegwerf-Zertifikat mit openssl.

GEMESSEN, NICHT VERMUTET

  openssl liegt hier:   C:\Program Files\Git\mingw64\bin\openssl.exe
                        C:\Program Files\Git\usr\bin\openssl.exe
  im System-PATH steht: C:\Program Files\Git\cmd   (nur git.exe)
  im Benutzer-PATH:     nichts mit Git

Wer aus Git Bash startet, erbt die mingw-Pfade und merkt nie etwas.
Die Aufgabenplanung startet `node.exe` DIREKT, ohne Shell -- und
bekommt sie nicht. Bei mir gruen, nachts rot, und der Grund steht
nicht im Code.

Das Schlimmste daran ist nicht der Ausfall: Dreizehn dauerhaft rote
Zeilen in einer Notiz, die Filipe morgens liest, gewoehnen einem das
Hinsehen ab -- und decken dabei die echten Befunde zu.

DIE REPARATUR

`server/helfer-openssl.mjs` sucht openssl erst im PATH (ohne `where`
oder `which` -- beides sind selbst Programme und koennen genauso
fehlen), danach an den Orten, an denen es auf einem Windows-Rechner
mit Git wirklich liegt.

Dazu `zertifikatBauen(schluessel, zertifikat, host)`. Die acht
Aufrufformen im Haus waren identisch bis auf die Variablennamen
(schl/zert, schluesselDatei/zertDatei, zKey/zCrt, sk/zt, key/crt) --
eine Stelle traegt alle neunundzwanzig. Zwei Tage zuvor war eine
davon um ein `-addext` aermer als die anderen; gemerkt hat es
niemand, weil der Browser den fehlenden Alternativnamen erst bei
einer Weiterleitung anmahnt. Eine Stelle kann nicht von sich selbst
abweichen.

KEIN EINTRAG IN DEN SYSTEM-PATH. `mingw64\bin` enthaelt rund hundert
Programme mit Unix-Namen (`find`, `sort`, `link`), die gleichnamige
Windows-Befehle verdecken. Das fuer eine Pruefung zu aendern haette
an ganz anderen Stellen Fehler verursacht, die niemand hierher
zurueckverfolgt.

GEGENPROBE IN BEIDE RICHTUNGEN, mit dem PATH des Nachtlaufs:

  vorher (direkter Aufruf):  ABSTURZ: spawnSync openssl ENOENT
  nachher (ueber den Helfer): Zertifikat gebaut, 1236 Bytes

Und eine echte Pruefung unter denselben Bedingungen:

  PATH ohne mingw64 -> pruef-chat-neu-stelle
  63 Pruefungen, 0 Fehler, 0 Abstuerze

Genau diese Datei stand im Nachtlauf mit ENOENT rot.

EINE WACHE DAGEGEN

pruef-struktur prueft ab jetzt, dass niemand openssl wieder direkt
ruft -- der naechste merkt es dort und nicht erst in einem
Nachtlauf, den niemand liest. Drei Gegenproben.

Beim ersten Anlauf schlug sie auf ihre EIGENEN Probetexte an: Sie
liest alle Serverdateien, und dazu gehoert sie selbst. Die Texte
werden jetzt zusammengesetzt. Derselbe Selbsttreffer ist mir heute
schon zweimal passiert.

DER DRITTE AUSGANG BLEIBT, WO ER HINGEHOERT

`helfer-kachel-echtfarbe.mjs` faengt den Fehler weiterhin ab und
meldet `moeglich: false` mit Grund, statt abzubrechen. Eine
Sicherung abzuschaffen, weil ihr Anlass gerade behoben ist, ist der
Anfang des naechsten stillen Fehlschlags.

NEBENBEI: pruef-community-sicht

Sie war rot mit "ZU VIEL: reaktion.html" -- mein eigener Rueckstand
vom 28.09. Die Reaction steht als Kachel im Community-Bereich; die
Liste war nicht nachgezogen. Jetzt 10 / 0.

Die Liste bleibt bewusst von Hand gepflegt: Sie ist eine ABSICHT,
keine Ableitung. Aus rechte.js gelesen verglichen sich zwei Kopien
derselben Quelle -- immer gruen, nie ein Beweis.

GEPRUEFT
  pruef-struktur         ALLES IN ORDNUNG (mit der neuen Wache)
  pruef-community-sicht  10 / 0
  pruef-chat-neu-stelle  63 / 0  (mit dem PATH des Nachtlaufs)
  pruef-notizen, -teamlage-karten, -werdegang: EXIT 0, keine Abstuerze
  mess-quer              EXIT 0
  29 Dateien: node --check auf allen, kein direkter Aufruf mehr
2026-09-29 16:14:13 +02:00

113 lines
4.6 KiB
JavaScript

/* =====================================================================
helfer-openssl.mjs — wo liegt openssl?
WAS HIER SCHIEFGING (29.09.2026 gemessen):
Im nächtlichen Lauf standen dreizehn Prüfungen mit derselben Zeile
rot:
[uncaughtException] Error: spawnSync openssl ENOENT
Kein Programmfehler. Die Prüfungen brauchen einen https-Vorbau
(der Sitzungskeks des Hauses ist `secure`, über http kommt er nicht
an), und dafür erzeugen sie ein Wegwerf-Zertifikat mit `openssl`.
AUF DIESEM RECHNER LIEGT ES IN Git Bash:
C:\Program Files\Git\mingw64\bin\openssl.exe
C:\Program Files\Git\usr\bin\openssl.exe
Im PATH des Systems steht aber nur `C:\Program Files\Git\cmd` —
dort liegt `git.exe` und sonst nichts. Wer aus Git Bash heraus
startet, erbt die mingw-Pfade und merkt nie etwas. Die
Aufgabenplanung startet `node.exe` direkt, ohne Shell — und
bekommt sie nicht.
Das ist die unangenehmste Sorte Fehler: Bei mir grün, nachts rot,
und der Grund steht nicht im Code. Dreizehn dauerhaft rote Zeilen
in einer Notiz, die Filipe morgens liest, gewöhnen einem das
Hinsehen ab — und decken dabei die echten Befunde zu.
WAS DIESE DATEI TUT: Sie sucht `openssl` zuerst dort, wo es
ohnehin gefunden würde (PATH), und danach an den Orten, an denen
es auf einem Windows-Rechner mit Git tatsächlich liegt. Damit
läuft dieselbe Prüfung in beiden Umgebungen.
WARUM KEIN EINTRAG IN DEN SYSTEM-PATH: `mingw64\bin` enthält rund
hundert Programme mit Unix-Namen (`find`, `sort`, `link` …), die
gleichnamige Windows-Befehle verdecken. Das für eine einzige
Prüfung zu ändern, würde an ganz anderen Stellen Fehler
verursachen, die niemand mehr hierher zurückverfolgt.
===================================================================== */
import { existsSync } from "node:fs";
import { execFileSync } from "node:child_process";
import { delimiter, join } from "node:path";
/* Die Orte, an denen Git für Windows sein openssl ablegt. Beide
kommen vor: `mingw64` bei der 64-Bit-Fassung, `usr` bei der
mitgelieferten Unix-Umgebung. */
const BEKANNTE_ORTE = [
"C:/Program Files/Git/mingw64/bin/openssl.exe",
"C:/Program Files/Git/usr/bin/openssl.exe",
"C:/Program Files (x86)/Git/mingw64/bin/openssl.exe",
"C:/Program Files (x86)/Git/usr/bin/openssl.exe",
"C:/Program Files/OpenSSL-Win64/bin/openssl.exe",
];
let gemerkt = null;
/* IM PATH SUCHEN, OHNE `where` ODER `which` ZU BRAUCHEN. Beide sind
selbst Programme und können genauso fehlen; und `which` gibt es
unter Windows außerhalb von Git Bash gar nicht. */
const imPfad = () => {
const pfade = (process.env.PATH || "").split(delimiter).filter(Boolean);
const namen = process.platform === "win32"
? ["openssl.exe", "openssl.com", "openssl"]
: ["openssl"];
for (const p of pfade) {
for (const n of namen) {
const voll = join(p, n);
if (existsSync(voll)) return voll;
}
}
return null;
};
/* Der Pfad zu openssl — oder ein Abbruch mit Anleitung.
*
* DRITTER AUSGANG: Wird nichts gefunden, ist das weder „in Ordnung"
* noch „das Programm ist kaputt", sondern „konnte nicht nachsehen".
* Der Fehler sagt deshalb, WAS fehlt und WO man es herbekommt —
* `spawnSync openssl ENOENT` sagt nur, dass etwas nicht da war. */
export function opensslPfad() {
if (gemerkt) return gemerkt;
const gefunden = imPfad() || BEKANNTE_ORTE.find((o) => existsSync(o));
if (!gefunden) {
throw new Error(
"openssl ist nicht auffindbar. Es wird fuer den https-Vorbau gebraucht "
+ "(der Sitzungskeks ist `secure` und kommt ueber http nicht an).\n"
+ " Gesucht im PATH und an diesen Orten:\n"
+ BEKANNTE_ORTE.map((o) => " " + o).join("\n")
+ "\n Unter Windows bringt Git fuer Windows es mit; sonst "
+ "https://slproweb.com/products/Win32OpenSSL.html");
}
gemerkt = gefunden;
return gefunden;
}
/* Ein Wegwerf-Zertifikat für einen Hostnamen.
*
* WARUM HIER UND NICHT IN JEDER DATEI: Die Zeile stand
* neunundzwanzigmal fast gleich im Haus. Zwei Tage bevor ich das
* hier schrieb, war eine davon um ein `-addext` ärmer als die
* anderen — gemerkt hat es niemand, weil der Browser den fehlenden
* Alternativnamen erst bei einer Weiterleitung anmahnt. Eine Stelle
* kann nicht von sich selbst abweichen. */
export function zertifikatBauen(schluessel, zertifikat, host, tage = 2) {
execFileSync(opensslPfad(), [
"req", "-x509", "-newkey", "rsa:2048", "-nodes",
"-keyout", schluessel, "-out", zertifikat,
"-days", String(tage), "-subj", `/CN=${host}`,
"-addext", `subjectAltName=DNS:${host}`,
], { stdio: "ignore" });
}