commandExpandingEnv zurueckgenommen — sie schuetzte vor nichts

Die Methode sollte das SMTP-Passwort aus der Prozessliste der Kunden-VM
halten. Nachgerechnet: guestExec faehrt die ganze Zeile als /bin/sh -c, die
innere Shell setzt den Wert vor dem exec ein, und Nextcloud legt ihn danach
ohnehin im Klartext in config.php ab. Eingespart wurde einzig das Argv des
docker-Aufrufs, auf einer Maschine, die den Wert an zwei anderen Stellen
zeigt.

Ein Versteck, das dieselbe Person nicht aussperrt, die den Ablageort lesen
kann, ist keines — und ein Kommentar, der Schutz behauptet, haelt den
Naechsten vom Nachsehen ab.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
feat/versandtakt
nexxo 2026-08-03 19:46:44 +02:00
parent 62e69ecde2
commit 58b82aa8a2
2 changed files with 0 additions and 72 deletions

View File

@ -72,49 +72,4 @@ final class NextcloudOcc
{
return 'cd '.self::DIRECTORY.' && docker compose exec -T -u '.self::USER.' app '.$arguments;
}
/**
* Wie command(), aber der Wert wird erst von der Shell IM Container
* eingesetzt.
*
* command() taugt fuer `--password-from-env`, wo occ selbst die
* Umgebungsvariable liest. `config:system:set` kann das nicht: es will den
* Wert als Argument.
*
* Ohne diese Methode staende der Wert an drei Stellen: im Argv der
* VM-Shell (wo HttpProxmoxClient::guestExec() die ganze Zeichenkette als
* ['/bin/sh', '-c', $command] uebergibt), im Argv des docker-Aufrufs, und
* im Argv von `php occ` im Container. Mit dieser Methode reist der Wert
* als Umgebungsvariable in den Container und wird erst dort von der `sh`
* eingesetzt der Gewinn ist, dass er nicht im Prozessabbild DES
* CONTAINERS steht, wo jeder Nextcloud-Prozess und jeder, der sich
* hineinhängt, ihn aus der Umgebung auslesen kann.
*
* Der Wert bleibt im Argv der VM-Shell sichtbar, fuer die Dauer des
* Aufrufs: Debians `dash` (die Standard-Shell in den Kunden-VMs)
* optimiert den Elternprozess nicht weg, wie `bash` es täte.
*
* EHRLICHERWEISE ist das Hygiene, kein Schutz: Nextcloud legt
* `mail_smtppassword` anschliessend im Klartext in config/config.php ab.
* Wer auf der Maschine eine Shell hat, liest es dort. Die eigentliche
* Eingrenzung liegt woanders das Versandkonto kann nur senden, und der
* Versandport nimmt nur die eigenen Hostadressen an. Diese Methode senkt
* die Gelegenheit, sie beseitigt sie nicht.
*
* @param array<string, string> $env
*/
public static function commandExpandingEnv(string $arguments, array $env): string
{
$assignments = '';
$forwards = '';
foreach ($env as $name => $value) {
$assignments .= $name.'='.escapeshellarg($value).' ';
$forwards .= '-e '.$name.' ';
}
return 'cd '.self::DIRECTORY.' && '.$assignments
.'docker compose exec -T -u '.self::USER.' '.$forwards
.'app sh -c '.escapeshellarg('php occ '.$arguments);
}
}

View File

@ -1,27 +0,0 @@
<?php // tests/Feature/NextcloudOccTest.php
use App\Support\NextcloudOcc;
it('haelt den Wert aus dem occ-Aufruf heraus', function () {
$befehl = NextcloudOcc::commandExpandingEnv(
'config:system:set mail_smtppassword --value="$CLUPILOT_SMTP_PW"',
['CLUPILOT_SMTP_PW' => 'geheim'],
);
// Der Wert steht als Zuweisung VOR dem docker-Aufruf (die aeussere Shell
// reicht ihn durch), aber der occ-Aufruf selbst (ab `sh -c`) traegt nur
// den VARIABLENNAMEN. Damit sitzt das Geheimnis nicht im Argv des
// Containers.
expect($befehl)->toContain("CLUPILOT_SMTP_PW='geheim'")
->and($befehl)->toContain('-e CLUPILOT_SMTP_PW')
->and($befehl)->toContain('sh -c')
// Entscheidend: ab `sh -c` (der Innenteil des Containers) steht nur der Name.
->and(substr($befehl, strpos($befehl, 'sh -c')))->not->toContain('geheim');
});
it('haelt sich an dasselbe Verzeichnis und denselben Benutzer wie command()', function () {
$befehl = NextcloudOcc::commandExpandingEnv('status', []);
expect($befehl)->toStartWith('cd '.NextcloudOcc::DIRECTORY)
->and($befehl)->toContain('-u '.NextcloudOcc::USER);
});