Anpassen der Tlsa Record erstellung

main
boban 2025-10-17 03:00:20 +02:00
parent 93c541e3e7
commit c2dab0a56b
1 changed files with 165 additions and 8 deletions

View File

@ -6,6 +6,9 @@ namespace Database\Seeders;
use App\Models\DkimKey;
use App\Models\Domain;
use App\Models\MailUser;
use App\Models\TlsaRecord;
// ← NEU: fürs exists()
use App\Services\DnsRecordService;
use App\Services\TlsaService;
use Illuminate\Database\Seeder;
@ -21,11 +24,11 @@ class SystemDomainSeeder extends Seeder
return;
}
$mtaSub = env('MTA_SUB', 'mx') ?: 'mx'; // z.B. mx
$serverFqdn = "{$mtaSub}.{$platformBase}"; // z.B. mx.nexlab.at
$mtaSub = env('MTA_SUB', 'mx') ?: 'mx'; // z.B. mx
$serverFqdn = "{$mtaSub}.{$platformBase}"; // z.B. mx.nexlab.at
$systemSub = config('mailpool.platform_system_zone') ?: 'sysmail'; // z.B. sysmail
$systemFqdn = "{$systemSub}.{$platformBase}"; // z.B. sysmail.nexlab.at
$systemSub = config('mailpool.platform_system_zone') ?: 'sysmail';
$systemFqdn = "{$systemSub}.{$platformBase}"; // z.B. sysmail.nexlab.at
// =========================================================================
// 1) MAILSERVER-DOMAIN zuerst (mx.<BASE_DOMAIN>), is_server = true
@ -41,9 +44,14 @@ class SystemDomainSeeder extends Seeder
$this->command->info("Server-Host markiert: {$serverDomain->domain}");
}
// TLSA (3 1 1) nur in Laravel erzeugen/aktualisieren (falls LE-Zert bereits da ist)
if (! $serverDomain->tlsa()->exists()) {
$tlsa = app(\App\Services\TlsaService::class)->refreshForServerDomain($serverDomain);
// --- TLSA (3 1 1) prüfen/erzeugen (nur wenn LE-Zert schon da ist) -----
$hasTlsa = TlsaRecord::where('domain_id', $serverDomain->id)
->where('host', $serverFqdn)
->where('service', '_25._tcp')
->exists();
if (!$hasTlsa) {
$tlsa = app(TlsaService::class)->refreshForServerDomain($serverDomain);
if ($tlsa) {
$this->command->info("TLSA erstellt: _25._tcp.{$tlsa->host} 3 1 1 {$tlsa->hash}");
} else {
@ -119,7 +127,6 @@ class SystemDomainSeeder extends Seeder
openssl_pkey_export($res, $privateKeyPem);
$details = openssl_pkey_get_details($res);
$pubDer = $details['key'];
// Public PEM zu "p=" (reines Base64) normalisieren
$publicTxt = trim(preg_replace('/-----(BEGIN|END) PUBLIC KEY-----|\s+/', '', $pubDer));
return [$privateKeyPem, $publicTxt];
}
@ -148,6 +155,156 @@ class SystemDomainSeeder extends Seeder
}
}
//namespace Database\Seeders;
//
//use App\Models\DkimKey;
//use App\Models\Domain;
//use App\Models\MailUser;
//use App\Services\DnsRecordService;
//use App\Services\TlsaService;
//use Illuminate\Database\Seeder;
//
//class SystemDomainSeeder extends Seeder
//{
// public function run(): void
// {
// // --- Basiswerte aus Config/ENV ---
// $platformBase = config('mailpool.platform_zone', env('BASE_DOMAIN', 'example.com')); // z.B. nexlab.at
// if (!$platformBase || $platformBase === 'example.com') {
// $this->command->warn("BASE_DOMAIN ist 'example.com' Seeder überspringt produktive Einträge.");
// return;
// }
//
// $mtaSub = env('MTA_SUB', 'mx') ?: 'mx'; // z.B. mx
// $serverFqdn = "{$mtaSub}.{$platformBase}"; // z.B. mx.nexlab.at
//
// $systemSub = config('mailpool.platform_system_zone') ?: 'sysmail'; // z.B. sysmail
// $systemFqdn = "{$systemSub}.{$platformBase}"; // z.B. sysmail.nexlab.at
//
// // =========================================================================
// // 1) MAILSERVER-DOMAIN zuerst (mx.<BASE_DOMAIN>), is_server = true
// // =========================================================================
// $serverDomain = Domain::firstOrCreate(
// ['domain' => $serverFqdn],
// ['is_active' => true, 'is_system' => false, 'is_server' => true]
// );
//
// if (!$serverDomain->is_server) {
// $serverDomain->is_server = true;
// $serverDomain->save();
// $this->command->info("Server-Host markiert: {$serverDomain->domain}");
// }
//
// // TLSA (3 1 1) nur in Laravel erzeugen/aktualisieren (falls LE-Zert bereits da ist)
// if (! $serverDomain->tlsa()->exists()) {
// $tlsa = app(\App\Services\TlsaService::class)->refreshForServerDomain($serverDomain);
// if ($tlsa) {
// $this->command->info("TLSA erstellt: _25._tcp.{$tlsa->host} 3 1 1 {$tlsa->hash}");
// } else {
// $this->command->warn("TLSA übersprungen: LE-Zertifikat (noch) nicht vorhanden später erneut seeden.");
// }
// } else {
// $this->command->line("TLSA bereits vorhanden, übersprungen.");
// }
//
// // =========================================================================
// // 2) SYSTEM-DOMAIN danach (sysmail.<BASE_DOMAIN>), is_system = true
// // =========================================================================
// $systemDomain = Domain::firstOrCreate(
// ['domain' => $systemFqdn],
// ['is_active' => true, 'is_system' => true]
// );
//
// // System-Absender (no-reply) ohne Passwort (kein Login)
// MailUser::firstOrCreate(
// ['email' => "no-reply@{$systemFqdn}"],
// [
// 'domain_id' => $systemDomain->id,
// 'localpart' => 'no-reply',
// 'password_hash' => null,
// 'is_active' => true,
// 'is_system' => true,
// 'must_change_pw' => false,
// 'quota_mb' => 0,
// ]
// );
//
// // DKIM Key erzeugen, falls keiner aktiv existiert
// if (!$systemDomain->dkimKeys()->where('is_active', true)->exists()) {
// [$privPem, $pubTxt] = $this->generateDkimKeyPair();
// $selector = 'mwl1'; // frei wählbar, später rotieren
//
// DkimKey::create([
// 'domain_id' => $systemDomain->id,
// 'selector' => $selector,
// 'private_key_pem' => $privPem,
// 'public_key_txt' => $pubTxt,
// 'is_active' => true,
// ]);
//
// $this->command->info("DKIM angelegt: Host = {$selector}._domainkey.{$systemFqdn}");
// }
//
// $dk = $systemDomain->dkimKeys()->where('is_active', true)->latest()->first();
// $dkimTxt = $dk ? "v=DKIM1; k=rsa; p={$dk->public_key_txt}" : null;
//
// app(DnsRecordService::class)->provision(
// $systemDomain,
// dkimSelector: $dk?->selector,
// dkimTxt: $dkimTxt,
// opts: [
// 'dmarc_policy' => 'none',
// 'spf_tail' => '-all',
// // optional: 'ipv4' => $serverIp, 'ipv6' => ...
// ]
// );
//
// $this->command->info("System-Domain '{$systemFqdn}' fertig. SPF/DMARC/DKIM & DNS-Empfehlungen eingetragen.");
// $this->printDnsHints($systemDomain);
// }
//
// /** @return array{0:string privatePem,1:string publicTxt} */
// private function generateDkimKeyPair(): array
// {
// $res = openssl_pkey_new([
// 'private_key_bits' => 2048,
// 'private_key_type' => OPENSSL_KEYTYPE_RSA,
// ]);
// openssl_pkey_export($res, $privateKeyPem);
// $details = openssl_pkey_get_details($res);
// $pubDer = $details['key'];
// // Public PEM zu "p=" (reines Base64) normalisieren
// $publicTxt = trim(preg_replace('/-----(BEGIN|END) PUBLIC KEY-----|\s+/', '', $pubDer));
// return [$privateKeyPem, $publicTxt];
// }
//
// private function printDnsHints(Domain $domain): void
// {
// $base = $domain->domain;
//
// $dkim = $domain->dkimKeys()->where('is_active', true)->latest()->first();
// if ($dkim) {
// $this->command->line(" • DKIM TXT @ {$dkim->selector}._domainkey.{$base}");
// $this->command->line(" v=DKIM1; k=rsa; p={$dkim->public_key_txt}");
// }
//
// $spf = $domain->spf()->where('is_active', true)->latest()->first();
// if ($spf) {
// $this->command->line(" • SPF TXT @ {$base}");
// $this->command->line(" {$spf->record_txt}");
// }
//
// $dmarc = $domain->dmarc()->where('is_active', true)->latest()->first();
// if ($dmarc) {
// $this->command->line(" • DMARC TXT @ _dmarc.{$base}");
// $this->command->line(" " . ($dmarc->record_txt ?? $dmarc->renderTxt()));
// }
// }
//}
//
//----------------------------------------------------------------
//
//namespace Database\Seeders;
//