.env.example belegte S3_ENDPOINT mit der Adresse eines externen
Anbieters. Gedacht war das als Beispiel - in der kopierten .env stand es
aber aktiv, und damit sprach die Anwendung mit einem fremden Host statt
mit dem Objektspeicher nebenan.
Verschaerfend: Die docker-compose.yml hatte laengst einen brauchbaren
Standard, ${S3_ENDPOINT:-http://minio:9000}. Der greift nur bei leerer
Variable - die Beispieldatei hebelte ihn aus. Der Mechanismus, der genau
diesen Fehler verhindern sollte, war durch die Beispieldatei wirkungslos.
Auf dem Livesystem hat das monatelang jede Ablage scheitern lassen, und
die Zugangs-ID des lokalen Speichers ging bei jedem Versuch nach draussen.
Die Zeile ist jetzt auskommentiert, mit einer Erklaerung, wann man sie
braucht.
Nebenbei stand dort SEED_ADMIN_EMAIL mit der Adresse des Betreibers. In
einer mitgelieferten Beispieldatei hat eine persoenliche Adresse nichts
zu suchen - jetzt leer.
Der Test prueft beides und dazu die allgemeine Regel: Kein aktiver Wert
in der Beispieldatei zeigt auf einen fremden Rechner. Er prueft auch,
dass ueberhaupt Zuweisungen gefunden werden - sonst staende er gruen da
und pruefte nichts.
Gegen zwei Mutationen geprueft: Endpunkt wieder aktiv, persoenliche
Adresse wieder eingetragen - beide werden rot.
Refs #45
101 lines
3.8 KiB
TypeScript
101 lines
3.8 KiB
TypeScript
import { readFileSync } from 'node:fs'
|
|
import { describe, expect, it } from 'vitest'
|
|
|
|
/**
|
|
* Die Beispielkonfiguration darf keine Falle enthalten.
|
|
*
|
|
* `.env.example` wird nach `.env` kopiert und dann Zeile für Zeile
|
|
* ausgefüllt. Was schon einen Wert hat, wird dabei leicht überlesen — und
|
|
* genau das ist am 31.08.2026 passiert:
|
|
*
|
|
* S3_ENDPOINT=https://fsn1.your-objectstorage.com
|
|
*
|
|
* Die Zeile war als Beispiel gedacht. Sie stand aber aktiv in der `.env`,
|
|
* und damit sprach die Anwendung monatelang mit einem fremden Anbieter
|
|
* statt mit dem Objektspeicher nebenan. Jede Ablage scheiterte mit
|
|
* `NoSuchBucket`, und die Zugangs-ID des lokalen Speichers ging bei jedem
|
|
* Versuch nach draußen.
|
|
*
|
|
* Verschärfend: Die `docker-compose.yml` hatte längst einen brauchbaren
|
|
* Standard (`${S3_ENDPOINT:-http://minio:9000}`). Der greift aber nur bei
|
|
* leerer Variable — die Beispieldatei hebelte ihn aus. Der Mechanismus,
|
|
* der den Fehler verhindern sollte, war durch die Beispieldatei
|
|
* wirkungslos.
|
|
*
|
|
* Diese Tests halten fest: Ein Wert steht in der Beispieldatei nur, wenn
|
|
* er für die mitgelieferte Zusammenstellung auch richtig ist.
|
|
*/
|
|
|
|
const beispiel = readFileSync('.env.example', 'utf8')
|
|
|
|
/** Alle aktiven Zuweisungen - Kommentarzeilen zählen nicht. */
|
|
function zuweisungen(): [string, string][] {
|
|
return beispiel
|
|
.split('\n')
|
|
.map((zeile) => zeile.trim())
|
|
.filter((zeile) => zeile !== '' && !zeile.startsWith('#'))
|
|
.map((zeile) => {
|
|
const stelle = zeile.indexOf('=')
|
|
return [zeile.slice(0, stelle), zeile.slice(stelle + 1)] as [string, string]
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Rechner, die zur mitgelieferten Zusammenstellung gehören. Alles andere
|
|
* ist ein fremder Host und hat in der Beispieldatei nichts verloren.
|
|
*/
|
|
const EIGENE_HOSTS = ['localhost', '127.0.0.1', '0.0.0.0', 'minio', 'db']
|
|
|
|
describe('Beispielkonfiguration', () => {
|
|
it('zeigt mit keinem aktiven Wert auf einen fremden Host', () => {
|
|
const fremde = zuweisungen()
|
|
.filter(([, wert]) => /https?:\/\//.test(wert))
|
|
.filter(([, wert]) => {
|
|
const treffer = wert.match(/https?:\/\/([^:/"']+)/)
|
|
return treffer ? !EIGENE_HOSTS.includes(treffer[1]!) : false
|
|
})
|
|
.map(([name, wert]) => `${name}=${wert}`)
|
|
|
|
expect(
|
|
fremde,
|
|
'Diese Zeilen zeigen nach draußen. Wer die Datei kopiert und die ' +
|
|
'Zeile übersieht, schickt seine Daten an einen fremden Rechner.',
|
|
).toEqual([])
|
|
})
|
|
|
|
it('lässt S3_ENDPOINT auskommentiert, damit der Compose-Standard greift', () => {
|
|
const aktiv = zuweisungen().some(([name]) => name === 'S3_ENDPOINT')
|
|
|
|
expect(
|
|
aktiv,
|
|
'Mit gesetztem S3_ENDPOINT greift ${S3_ENDPOINT:-http://minio:9000} ' +
|
|
'aus der docker-compose.yml nicht mehr.',
|
|
).toBe(false)
|
|
})
|
|
|
|
it('erklärt trotzdem, wann man S3_ENDPOINT braucht', () => {
|
|
// Auskommentieren allein hilft nicht - dann sucht jemand mit externem
|
|
// Speicher vergeblich nach der Einstellung.
|
|
expect(beispiel).toMatch(/#\s*S3_ENDPOINT=/)
|
|
expect(beispiel).toMatch(/EXTERNER Objektspeicher/)
|
|
})
|
|
|
|
it('enthält keine persönliche E-Mail-Adresse', () => {
|
|
// Stand einmal drin: die Adresse des Betreibers als Vorgabe fuer den
|
|
// Seed. In einer mitgelieferten Beispieldatei hat sie nichts zu suchen.
|
|
const adressen = zuweisungen()
|
|
// Verbindungszeichenfolgen tragen ein "@" vor dem Rechnernamen -
|
|
// das ist keine E-Mail-Adresse.
|
|
.filter(([, wert]) => !wert.includes('://'))
|
|
.filter(([, wert]) => /[\w.+-]+@[\w-]+\.[a-z]{2,}/i.test(wert))
|
|
.filter(([, wert]) => !/example\.(de|com|org)/.test(wert))
|
|
.map(([name, wert]) => `${name}=${wert}`)
|
|
|
|
expect(adressen).toEqual([])
|
|
})
|
|
|
|
it('findet überhaupt Zuweisungen - sonst prüft der Test nichts', () => {
|
|
expect(zuweisungen().length).toBeGreaterThan(15)
|
|
})
|
|
})
|