From 5753e231249146c3e694d933ce5943a40c223e0b Mon Sep 17 00:00:00 2001 From: boban Date: Sat, 18 Oct 2025 11:06:26 +0200 Subject: [PATCH] Domain Create Modal anpassen Fehler auf Null --- app/Jobs/InstallDkimKey.php | 64 ++++++++++++++----- .../Ui/Domain/Modal/DomainCreateModal.php | 19 +----- app/Services/DkimService.php | 2 +- 3 files changed, 51 insertions(+), 34 deletions(-) diff --git a/app/Jobs/InstallDkimKey.php b/app/Jobs/InstallDkimKey.php index e94f550..624afb8 100644 --- a/app/Jobs/InstallDkimKey.php +++ b/app/Jobs/InstallDkimKey.php @@ -9,6 +9,8 @@ use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; +use Illuminate\Support\Facades\Log; +use Symfony\Component\Process\Process; class InstallDkimKey implements ShouldQueue { @@ -19,6 +21,7 @@ class InstallDkimKey implements ShouldQueue public int $dkimKeyId, public string $privPath, public string $dnsTxtContent, + public string $selector = 'mwl1', ) {} public function handle(): void @@ -26,27 +29,58 @@ class InstallDkimKey implements ShouldQueue $domain = Domain::findOrFail($this->domainId); $dk = DkimKey::findOrFail($this->dkimKeyId); - $domainName = $domain->domain; // z.B. example.com - $selector = $dk->selector; // z.B. mwl1 + // ABSOLUTER, kanonischer Pfad (falls irgendwo ../ o.ä. reinkommt) + $priv = realpath($this->privPath) ?: $this->privPath; - // TXT temporär für Helper speichern (optional, damit /etc/mailwolt/dns gefüllt wird) + if (!is_readable($priv)) { + throw new \RuntimeException("DKIM private key missing or unreadable: {$priv}"); + } + + // TXT in Tempfile schreiben (damit der Helper optional nach /etc/mailwolt/dns kopieren kann) $tmpTxt = tempnam(sys_get_temp_dir(), 'dkim_txt_'); - file_put_contents($tmpTxt, $this->dnsTxtContent); + if ($tmpTxt === false) { + throw new \RuntimeException('Failed to create temporary TXT file for DKIM.'); + } + file_put_contents($tmpTxt, (string)$this->dnsTxtContent); - // Root-Helper aufrufen (sudoers hast du im Installer angelegt) - $cmd = sprintf( - 'sudo /usr/local/sbin/mailwolt-install-dkim %s %s %s %s', - escapeshellarg($domainName), - escapeshellarg($selector), - escapeshellarg($this->privPath), - escapeshellarg($tmpTxt) - ); + // sudo-Helper aufrufen + $cmd = [ + 'sudo', '/usr/local/sbin/mailwolt-install-dkim', + $domain->domain, // DOMAIN + $dk->selector, // SELECTOR + $priv, // Private PEM (absolut) + $tmpTxt, // TXT-Content-Datei + ]; + + $proc = new Process($cmd, base_path()); + $proc->setTimeout(60); // OpenDKIM/IO kann auf langsamen Platten mal dauern + $proc->run(); - exec($cmd, $out, $rc); @unlink($tmpTxt); - if ($rc !== 0) { - throw new \RuntimeException("mailwolt-install-dkim failed (rc={$rc})"); + if (!$proc->isSuccessful()) { + $exit = $proc->getExitCode(); + $out = trim($proc->getOutput()); + $err = trim($proc->getErrorOutput()); + + Log::error('DKIM install failed', [ + 'domain' => $domain->domain, + 'selector' => $dk->selector, + 'priv' => $priv, + 'exit' => $exit, + 'out' => $out, + 'err' => $err, + ]); + + throw new \RuntimeException( + "mailwolt-install-dkim failed (rc={$exit})\nSTDOUT: {$out}\nSTDERR: {$err}" + ); } + + Log::info('DKIM installed', [ + 'domain' => $domain->domain, + 'selector' => $dk->selector, + 'priv' => $priv, + ]); } } diff --git a/app/Livewire/Ui/Domain/Modal/DomainCreateModal.php b/app/Livewire/Ui/Domain/Modal/DomainCreateModal.php index 926e03d..79d146a 100644 --- a/app/Livewire/Ui/Domain/Modal/DomainCreateModal.php +++ b/app/Livewire/Ui/Domain/Modal/DomainCreateModal.php @@ -54,7 +54,7 @@ class DomainCreateModal extends ModalComponent $this->max_aliases = (int)config('mailpool.defaults.max_aliases', 400); $this->max_mailboxes = (int)config('mailpool.defaults.max_mailboxes', 10); $this->default_quota_mb = (int)config('mailpool.defaults.default_quota_mb', 3072); - $this->max_quota_per_mailbox_mb = config('mailpool.defaults.max_quota_per_mailbox_mb'); // kann null sein + $this->max_quota_per_mailbox_mb = config('mailpool.defaults.max_quota_per_mailbox_mb', 3072); $this->total_quota_mb = (int)config('mailpool.defaults.total_quota_mb', 10240); $this->dkim_selector = (string)config('mailpool.defaults.dkim_selector', 'dkim'); @@ -269,23 +269,6 @@ class DomainCreateModal extends ModalComponent 'rate_limit_override' => $this->rate_limit_override, ]); - // DKIM + DNS - $dkim = app(DkimService::class)->generateForDomain($domain, $this->dkim_bits, $this->dkim_selector); - - $dk = DkimKey::create([ - 'domain_id' => $domain->id, - 'selector' => $dkim['selector'], - 'private_key_pem' => $dkim['private_pem'], - 'public_key_txt' => preg_replace('/^v=DKIM1; k=rsa; p=/', '', $dkim['dns_txt']), - 'is_active' => true, - ]); - - dispatch(new InstallDkimKey( - domainId: $domain->id, - dkimKeyId: $dk->id, - privPath: $dkim['priv_path'], - dnsTxtContent: $dkim['dns_txt'] - )); app(DnsRecordService::class)->provision( $domain, diff --git a/app/Services/DkimService.php b/app/Services/DkimService.php index 5ff3848..0d81cdd 100644 --- a/app/Services/DkimService.php +++ b/app/Services/DkimService.php @@ -17,7 +17,7 @@ class DkimService $selKey = $this->safeKey($selector, 32); $disk = Storage::disk('local'); - $baseRel = "dkim/{$dirKey}"; + $baseRel = "private/dkim/{$dirKey}"; $privRel = "{$baseRel}/{$selKey}.pem"; $pubRel = "{$baseRel}/{$selKey}.pub";