8.1 KiB
#012 M7 – Platzhalter, Namensregeln, Escaping
Status: erledigt Meilenstein: v0.1.0 Labels: phase-1, backend, security Geschätzt: 8 h Tatsächlich: 2 h 30 min
Ziel
Reine, framework-freie Service-Schicht mit dichter Testabdeckung. Hier entstehen die fertigen PowerShell-Befehle, die der Techniker kopiert — und hier darf nichts schiefgehen, weder beim Escaping noch beim generierten Passwort.
Aufgaben
- Platzhalter-Auflösung
{{key}}in Schritt-Titel, Hilfetext und Befehlstext - Eingebaut aus Gerät und Lauf:
{{hostname}},{{seriennummer}},{{inventarnummer}},{{ticket}},{{datum}},{{techniker}}; im ModusDIENSTLEISTUNGzusätzlich{{kunde}}und{{kundenkuerzel}}, im ModusINTERNleer - Eingebaut aus dem Mitarbeiter:
{{mitarbeiter}}(Alias{{benutzer}}),{{vorname}},{{nachname}},{{upn}},{{sam}},{{mail}},{{abteilung}},{{titel}},{{vorgesetzter}},{{vorgesetzter_sam}},{{dn}},{{ou}} - Aus der gewählten Abteilung:
{{ou}}falls nicht vom Mitarbeiter,{{gruppen}}kommagetrennt {{ou}}eines synchronisierten Mitarbeiters ist der Eltern-Container seinesdn(alles nach dem ersten Komma)- Dazu die in der Vorlage definierten Variablen; unbekannte Platzhalter bleiben sichtbar stehen
{{generiertes_passwort}}: 20 Zeichen aus Groß, Klein, Ziffern und Sonderzeichen ohne verwechselbare Zeichen, je Anzeige neu erzeugt, nie gespeichert; Hinweis „Passwort sofort in den Passwortmanager übernehmen“; in der Druckansicht[Passwort – nicht gespeichert]- Namensregeln (
Einstellung.namensregelnglobal, im ModusDIENSTLEISTUNGzusätzlichKunde.namensregelnmit Fallback):upn,sam(höchstens 20 Zeichen),mail,hostname - Transliteration (ä→ae, ö→oe, ü→ue, ß→ss, Akzente entfernt), Kleinschreibung, Leerzeichen entfernt,
{nnn}-Zähler,{v}für den ersten Buchstaben des Vornamens,{kundenkuerzel} - Shell-Escaping je Shell: PowerShell (doppelte Anführungszeichen verdoppeln, Backtick maskieren), Bash, Cmd
- HTML-Escaping ersetzter Werte; Markdown im Hilfetext sicher gerendert, kein rohes HTML
- „Alle Befehle als Skript kopieren“ je Abschnitt: alle
BEFEHL-Schritte in Reihenfolge, getrennt durch Leerzeilen, je mit# Schritt: <Titel>davor, Zeilenumbruch passend zur Shell
Akzeptanzkriterien
- Test: „Jörg Müller-Lüdenscheid“ ergibt
joerg.mueller-luedenscheid@firma.deundjmuellerluedensch(17 Zeichen — siehe unten, die Klammer im ursprünglichen Text war falsch) - Test:
{{generiertes_passwort}}erscheint im angezeigten Befehl, steht aber nicht inSchrittergebnis,Kommentar,Protokolloder der Druckansicht; zwei Aufrufe liefern verschiedene Passwörter - Test: ein Wert mit
"und`wird für PowerShell korrekt maskiert und bricht den Befehl nicht - Test: unbekannte Platzhalter bleiben als
{{key}}stehen - Test:
{{ou}}wird ausCN=Maria Huber,OU=Buchhaltung,OU=Benutzer,DC=firma,DC=localzuOU=Buchhaltung,OU=Benutzer,DC=firma,DC=local - Test: Skript-Kopie liefert die Befehle in Abschnittsreihenfolge mit Kommentarzeilen
- Test: im Modus
INTERNsind{{kunde}}und{{kundenkuerzel}}leer - Test: ein Wert mit
<script>landet HTML-escaped in der Anzeige
Beim Bauen aufgefallen
- PowerShell liest auch typografische Anführungszeichen als Begrenzer.
“,”und„beenden eine"…"-Zeichenkette genauso wie",‘,’,‚und‛eine'…'-Zeichenkette. Die Maskierung kannte nur das ASCII-Zeichen. Ein Abteilungsname, den jemand aus Word kopiert — Word wandelt"von selbst in“/”—, führte damit fremden Code auf dem Domänencontroller aus. Der Review hat es nicht gelesen, sondern gemessen: er hat sich PowerShell 7 in einem Container geholt und die Markierungsdatei entstehen lassen. Behoben und mit demselben Aufbau gegengeprüft: alle Werte kommen unverändert an, nichts wird ausgeführt. - Der pwsh-Test hat sich still übersprungen — dieselbe Falle, die
tests/helpers/db.tsfür die Datenbank längst zugemacht hat: ein stilles Überspringen sieht genauso grün aus wie ein bestandener Lauf. Er nimmt jetzt das Container-Abbild, wenn keinpwshda ist, und bricht in CI ab, statt zu schweigen. - Zwei verschiedene Passwörter in einer Antwort.
befehleDesLaufshat jeden Schritt zweimal gefüllt — einmal für die Anzeige, einmal für das Skript —, und weil das Passwort bei jedem Füllen neu entsteht, standen auf dem Bildschirm und in der Kopie verschiedene. Der Techniker legt das Konto mit dem einen an und nennt dem Benutzer das andere; weil nichts gespeichert wird, ist es danach unwiederbringlich. - Eine Vorlagenvariable konnte jeden eingebauten Platzhalter überschreiben. Eine Variable
technikerließ einen Befehl mit fremdem Namen unterschreiben, eine Variablekundeholte im Modus Intern die Kundenebene zurück, die es dort ausdrücklich nicht gibt. Gesperrt sind jetzt genau fünf Namen; alles andere bleibt erlaubt, weil eine Onboarding-Vorlage nachupn,samundmailfragen können muss — die Person steht ja noch nicht im Verzeichnis. - Die tragende Annahme der Maskierung hat niemand geprüft. Sie gilt nur, wenn der Platzhalter
in der Vorlage in Anführungszeichen steht;
Write-Host {{vorname}}lässt sich nicht sicher füllen. Das stand als Kommentar da und wurde nirgends eingelöst — der Review hat mit$(touch …)eine Datei entstehen lassen. Jetzt wird es geprüft und der Schritt abgewiesen. - Ich bin selbst in die Falle getappt, die ich in #010 repariert habe:
$'ist inString.replaceAllein Rückverweis auf alles hinter dem Treffer. Auserste\nzweitewurdeerste'zweite\n''zweite— ein Befehl, der nicht mehr zugeht. Gefunden hat es mein eigener Test, der gegen echtes Bash läuft. - Meine erste HTML-Maskierung war doppelt gemoppelt. React maskiert Textknoten selbst; eine zweite Maskierung hätte „Forschung & Entwicklung“ sichtbar gemacht. Der Beweis für das Akzeptanzkriterium steht jetzt am gerenderten HTML statt in einer eigenen Funktion.
{{ou}}bei einem maskierten Backslash im DN.CN=X\\,OU=Yist ein literaler Backslash im Wert, das Komma ist der Trenner — die Vorausschau hielt es für maskiert, lieferte nichts, und der Aufrufer fiel still auf die Ziel-OU der Abteilung zurück. Das Konto wäre in der falschen OU gelandet.- Hostnamen, die Windows ablehnt: ein Nachname „Con“ reichte, damit die Regel
CONvorschlägt — das ist die MS-DOS-Konsole. Reservierte Gerätenamen und rein numerische Namen liefern jetzt keinen Vorschlag. !ist aus dem Passwort geflogen, und ein Passwort fängt nie mit= + - @an: bei eingeschalteter verzögerter Ersetzung frisstcmd.exedas!still, und die vier anderen liest eine Tabellenkalkulation am Zellenanfang als Formel.
Eine Entscheidung, die den Auftragstext korrigiert
Das Akzeptanzkriterium nennt jmuellerluedensch und setzt in Klammern „auf 20 Zeichen gekürzt“.
Der Name hat 17 Zeichen, und beides zusammen geht nur mit zwei Regeln, die so jetzt im Code
stehen: der Bindestrich fällt im sam weg, und eine Regel ohne eigenen {nnn} hält drei Stellen
für die spätere Unterscheidung frei (20 − 3 = 17). Der Vorrat wird immer zurückgehalten, auch
solange der Name frei ist — sonst hieße derselbe Mensch jmuellerluedenscheid, solange er der
Erste ist, und jmuellerluedensch2, sobald ein Zweiter dazukommt. Ein einmal notierter
Anmeldename muss auch morgen noch aus der Regel herausfallen.
Offen geblieben
- Cmd ist nur begründet, nicht gemessen. Es gibt hier kein Windows. Die Ablehnung von
", CR, LF und Null-Byte und die Bewertung von%und!stehen als Begründung im Code — mit dem ausdrücklichen Hinweis, was daran Annahme ist. - Kein Aufrufer. Dieser Meilenstein hat keine Oberfläche; die Funktionen werden von #013
(Abarbeitung) und #014 (Geräteseite) gerufen. Der Hinweis „Passwort sofort in den
Passwortmanager übernehmen“ und die Druckansicht
[Passwort – nicht gespeichert]sind damit vorbereitet, aber noch nirgends zu sehen.