123 lines
5.1 KiB
PHP
123 lines
5.1 KiB
PHP
<?php
|
|
|
|
namespace App\Provisioning\Steps\Customer;
|
|
|
|
use App\Models\ProvisioningRun;
|
|
use App\Provisioning\StepResult;
|
|
use App\Services\Mail\GuestMailConfig;
|
|
use App\Services\Proxmox\ProxmoxClient;
|
|
use App\Support\NextcloudOcc;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
/**
|
|
* Bringt der Nextcloud eines Kunden bei, Mail zu verschicken.
|
|
*
|
|
* Bis hierher konnte sie es NICHT — weder die Bereitstellung noch die
|
|
* Compose-Datei der Vorlage setzten je einen Versand. Damit verschickte jede
|
|
* Kundeninstanz gar nichts: keine Freigabe-Benachrichtigung, keine
|
|
* Aktivitaetsmeldung, kein "Passwort vergessen". Still, ohne Fehlermeldung.
|
|
*
|
|
* Das ist die Voraussetzung fuer die Mitarbeiterverwaltung: die Einladung an
|
|
* einen Mitarbeiter verschickt NEXTCLOUD, nicht CluPilot — nur so entsteht
|
|
* das Passwort dort, wo niemand sonst es zu sehen bekommt.
|
|
*
|
|
* Ohne Server oder Absenderpostfach wird NICHTS geschrieben. Eine halb
|
|
* eingetragene Mailkonfiguration waere schlimmer als keine.
|
|
*
|
|
* Das ist aber KEIN Grund, den Lauf scheitern zu lassen: dieser Schritt steht
|
|
* in der PFLICHT-Pipeline `customer`, und ein Kunde, der bezahlt hat, bekommt
|
|
* seine Cloud auch dann, wenn der Mailversand noch nicht eingerichtet ist —
|
|
* genau wie RegisterMonitoring die Bereitstellung nie an einer nicht
|
|
* erreichbaren Ueberwachung scheitern laesst (siehe deren Kopfkommentar).
|
|
* Mailversand ist hier dieselbe Nebenfunktion: fehlt er, funktioniert die
|
|
* Cloud vollstaendig, nur Einladungen und Freigabe-Benachrichtigungen gehen
|
|
* nicht. Der Schritt geht in diesem Fall mit `advance()` weiter und
|
|
* protokolliert den Grund per `Log::warning`, damit der Betreiber es findet;
|
|
* nachgeholt wird es ueber `clupilot:configure-instance-mail` (Aufgabe 4),
|
|
* sobald Server und Postfach stehen.
|
|
*
|
|
* Nicht eingerichtet ist etwas anderes als kaputt: sobald Server und Postfach
|
|
* da sind, wird geschrieben, und ein Fehler beim Schreiben selbst (occ liefert
|
|
* einen Fehlercode, der Gast antwortet nicht) bleibt ein Fehlschlag wie jeder
|
|
* andere Gastbefehl in dieser Pipeline — CustomerStep::guest() wirft dafuer,
|
|
* und der Runner macht daraus einen Retry.
|
|
*
|
|
* WO DAS SMTP-PASSWORT UEBERALL SICHTBAR IST — ehrlich aufgeschrieben, weil
|
|
* ein erster Entwurf es zu verstecken versuchte und das Verstecken nichts
|
|
* brachte:
|
|
*
|
|
* - im Argv des `/bin/sh -c`, das der Gastagent fuer diesen Aufruf startet
|
|
* (guestExec baut die ganze Zeile so). Debians `dash` behaelt diesen
|
|
* Prozess fuer die volle Dauer des Aufrufs;
|
|
* - im Argv von `php occ` im Container;
|
|
* - und DAUERHAFT im Klartext in /opt/nextcloud … config/config.php, wo
|
|
* Nextcloud es selbst ablegt.
|
|
*
|
|
* Der dritte Punkt erledigt die ersten beiden: wer die Datei lesen kann, muss
|
|
* gar nicht erst in eine Prozessliste schauen. Ein Versteck, das dieselbe
|
|
* Person nicht aussperrt, ist keines — und ein Kommentar, der eines
|
|
* behauptet, haelt den Naechsten vom Nachsehen ab.
|
|
*
|
|
* Die Eingrenzung liegt deshalb in der Infrastruktur, nicht hier: das
|
|
* Versandkonto kann nur senden, der Versandport nimmt nur die eigenen
|
|
* Hostadressen an, und der Mailserver drosselt je Konto. Was hier gilt und
|
|
* geprueft wird, ist etwas anderes: der Wert wird maskiert, damit er keinen
|
|
* zweiten Befehl starten kann.
|
|
*/
|
|
class ConfigureInstanceMail extends CustomerStep
|
|
{
|
|
public function __construct(private ProxmoxClient $pve) {}
|
|
|
|
public function key(): string
|
|
{
|
|
return 'configure_instance_mail';
|
|
}
|
|
|
|
public function maxDuration(): int
|
|
{
|
|
return 120;
|
|
}
|
|
|
|
public function execute(ProvisioningRun $run): StepResult
|
|
{
|
|
$instance = $this->instance($run);
|
|
|
|
if ($instance === null) {
|
|
return StepResult::fail('instance_missing');
|
|
}
|
|
|
|
$config = GuestMailConfig::for($instance);
|
|
|
|
if (! $config->available()) {
|
|
// Nicht eingerichtet, nicht kaputt — siehe Kopfkommentar. Die Cloud
|
|
// wird trotzdem ausgeliefert; der Grund geht ins Log, nicht in
|
|
// einen gescheiterten Lauf.
|
|
Log::warning('Mailversand fuer Instanz uebersprungen (nicht eingerichtet)', [
|
|
'instance' => $instance->uuid,
|
|
'reason' => $config->problem() ?? 'mail_unavailable',
|
|
]);
|
|
|
|
return StepResult::advance();
|
|
}
|
|
|
|
$pve = $this->pve->forHost($instance->host);
|
|
|
|
// Der Schluessel ist ein fester occ-Name aus GuestMailConfig::values(),
|
|
// keine Benutzereingabe — genauso unmaskiert wie 'files default_quota'
|
|
// in ApplyStorageQuota. Maskiert wird nur der WERT, siehe Kopfkommentar.
|
|
foreach ($config->values() as $schluessel => $wert) {
|
|
$this->guest($pve, $run, NextcloudOcc::command(
|
|
'config:system:set '.$schluessel.' --value='.escapeshellarg($wert)
|
|
));
|
|
}
|
|
|
|
// Das Passwort wie jeder andere Wert. Verstecken laesst es sich auf
|
|
// dieser Maschine nicht — siehe Kopfkommentar.
|
|
$this->guest($pve, $run, NextcloudOcc::command(
|
|
'config:system:set mail_smtppassword --value='.escapeshellarg($config->password())
|
|
));
|
|
|
|
return StepResult::advance();
|
|
}
|
|
}
|