Domain Create Modal anpassen Fehler auf Null
parent
d99913df06
commit
dc9a5fdd48
|
|
@ -1,4 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Services;
|
namespace App\Services;
|
||||||
|
|
||||||
use App\Models\Domain;
|
use App\Models\Domain;
|
||||||
|
|
@ -16,8 +17,8 @@ class TlsaService
|
||||||
private function certCandidates(string $host): array
|
private function certCandidates(string $host): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'/etc/ssl/mail/fullchain.pem', // vom Deploy-Wrapper kopiert (lesbar)
|
'/etc/ssl/mail/fullchain.pem',
|
||||||
"/etc/letsencrypt/live/{$host}/fullchain.pem", // Fallback (meist nicht lesbar)
|
"/etc/letsencrypt/live/{$host}/fullchain.pem",
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -34,42 +35,33 @@ class TlsaService
|
||||||
$cmd = "openssl x509 -in " . escapeshellarg($certPath) . " -noout -pubkey"
|
$cmd = "openssl x509 -in " . escapeshellarg($certPath) . " -noout -pubkey"
|
||||||
. " | openssl pkey -pubin -outform DER"
|
. " | openssl pkey -pubin -outform DER"
|
||||||
. " | openssl dgst -sha256";
|
. " | openssl dgst -sha256";
|
||||||
$out = shell_exec($cmd . ' 2>/dev/null') ?? '';
|
$out = trim(shell_exec($cmd . ' 2>/dev/null') ?? '');
|
||||||
$out = trim($out);
|
|
||||||
if ($out === '') return null;
|
if ($out === '') return null;
|
||||||
|
|
||||||
// Variationen entfernen: "SHA256(stdin)= x", "SHA2-256(stdin)= x"
|
// Akzeptiere "SHA256(stdin)= x" und "SHA2-256(stdin)= x"
|
||||||
$hash = preg_replace('/^SHA2?56\(stdin\)=\s*/i', '', $out);
|
$hash = preg_replace('/^SHA2?-?256\(stdin\)=\s*/i', '', $out);
|
||||||
$hash = preg_replace('/^SHA2?-256\(stdin\)=\s*/i', '', $hash); // falls "SHA2-256"
|
|
||||||
$hash = trim($hash);
|
$hash = trim($hash);
|
||||||
|
|
||||||
return $hash !== '' ? $hash : null;
|
return $hash !== '' ? strtolower($hash) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holt is_server-Domain und schreibt/aktualisiert TLSA (3 1 1) */
|
/** Erzeugt/aktualisiert TLSA (3 1 1) für den aktuellen MX-Host (is_server-Domain). */
|
||||||
public function refreshForMx(string $service = '_25._tcp'): ?TlsaRecord
|
public function refreshForMx(string $service = '_25._tcp'): ?TlsaRecord
|
||||||
{
|
{
|
||||||
$host = $this->resolveMxHost();
|
$host = $this->resolveMxHost();
|
||||||
|
|
||||||
// 1) Server-Domain ermitteln (es darf genau eine mit is_server=true geben)
|
|
||||||
$serverDomain = Domain::where('is_server', true)
|
$serverDomain = Domain::where('is_server', true)
|
||||||
->where('domain', $host) // doppelt absichern: passt zur ENV
|
->where('domain', $host) // Absicherung
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if (!$serverDomain) {
|
if (!$serverDomain) return null;
|
||||||
// Kein is_server Eintrag -> nichts zu tun
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2) Zertifikat finden/lesen
|
|
||||||
$certPath = $this->firstReadableCert($host);
|
$certPath = $this->firstReadableCert($host);
|
||||||
if (!$certPath) return null;
|
if (!$certPath) return null;
|
||||||
|
|
||||||
// 3) Hash berechnen
|
|
||||||
$hash = $this->computeHashFromCertPath($certPath);
|
$hash = $this->computeHashFromCertPath($certPath);
|
||||||
if (!$hash) return null;
|
if (!$hash) return null;
|
||||||
|
|
||||||
// 4) DB schreiben (idempotent)
|
|
||||||
$rec = TlsaRecord::updateOrCreate(
|
$rec = TlsaRecord::updateOrCreate(
|
||||||
['domain_id' => $serverDomain->id, 'host' => $host, 'service' => $service],
|
['domain_id' => $serverDomain->id, 'host' => $host, 'service' => $service],
|
||||||
[
|
[
|
||||||
|
|
@ -81,17 +73,20 @@ class TlsaService
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
// 5) optionale Export-Datei
|
|
||||||
@mkdir('/etc/mailwolt/dns', 0755, true);
|
@mkdir('/etc/mailwolt/dns', 0755, true);
|
||||||
$line = sprintf('%s.%s IN TLSA %d %d %d %s', $service, $host, 3, 1, 1, $hash);
|
$line = sprintf('%s.%s IN TLSA %d %d %d %s', $service, $host, 3, 1, 1, $hash);
|
||||||
@file_put_contents("/etc/mailwolt/dns/{$host}.tlsa.txt", $line . "\n");
|
@file_put_contents("/etc/mailwolt/dns/{$host}.tlsa.txt", $line . "\n");
|
||||||
|
|
||||||
return $rec;
|
return $rec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 🔧 Alias für Seeder-Kompatibilität */
|
||||||
|
public function prefreshForServerDomain(?Domain $unused = null): ?TlsaRecord
|
||||||
|
{
|
||||||
|
return $this->refreshForMx('_25._tcp');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//namespace App\Services;
|
//namespace App\Services;
|
||||||
//
|
//
|
||||||
//use App\Models\Domain;
|
//use App\Models\Domain;
|
||||||
|
|
@ -99,316 +94,436 @@ class TlsaService
|
||||||
//
|
//
|
||||||
//class TlsaService
|
//class TlsaService
|
||||||
//{
|
//{
|
||||||
|
// public function refreshForServerDomain(Domain $serverDomain): ?TlsaRecord
|
||||||
|
// {
|
||||||
|
// // Falls du bereits eine Methode hast, die den Server-TLSA erzeugt:
|
||||||
|
// if (method_exists($this, 'refreshForServer')) {
|
||||||
|
// return $this->refreshForServer();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Minimal-Implementierung (TLSA 3 1 1 aus aktuellem Mail-Zertifikat)
|
||||||
|
// $host = env('MTA_HOST', $serverDomain->mx_host ?? ("mx.".$serverDomain->domain));
|
||||||
|
// $service = '_25._tcp';
|
||||||
|
// $cert = env('MAIL_CERT', "/etc/ssl/mail/fullchain.pem");
|
||||||
|
// $pubkeyDer = trim(shell_exec(
|
||||||
|
// "openssl x509 -in ".escapeshellarg($cert)." -pubkey -noout | ".
|
||||||
|
// "openssl pkey -pubin -outform DER 2>/dev/null | ".
|
||||||
|
// "openssl dgst -sha256 -r | awk '{print \$1}'"
|
||||||
|
// ) ?? '');
|
||||||
|
//
|
||||||
|
// if ($pubkeyDer === '') {
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return TlsaRecord::updateOrCreate(
|
||||||
|
// ['service' => $service, 'host' => $host],
|
||||||
|
// ['usage' => 3, 'selector' => 1, 'matching' => 1, 'hash' => strtolower($pubkeyDer)]
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
//
|
||||||
// public function resolveMxHost(): string
|
// public function resolveMxHost(): string
|
||||||
// {
|
// {
|
||||||
// $base = env('BASE_DOMAIN', 'example.com');
|
// $base = env('BASE_DOMAIN', 'example.com');
|
||||||
// $sub = env('MTA_SUB', 'mx') ?: 'mx';
|
// $sub = env('MTA_SUB', 'mx') ?: 'mx';
|
||||||
// return "{$sub}.{$base}";
|
// return "{$sub}.{$base}";
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// private function certCandidates(string $host): array
|
// private function certCandidates(string $host): array
|
||||||
// {
|
// {
|
||||||
// // bevorzugt die vom Deploy-Hook gesetzten, lesbaren Symlinks
|
// return [
|
||||||
// $candidates = [
|
// '/etc/ssl/mail/fullchain.pem', // vom Deploy-Wrapper kopiert (lesbar)
|
||||||
// '/etc/ssl/mail/fullchain.pem', // MX
|
// "/etc/letsencrypt/live/{$host}/fullchain.pem", // Fallback (meist nicht lesbar)
|
||||||
// "/etc/letsencrypt/live/{$host}/fullchain.pem", // Fallback
|
|
||||||
// ];
|
// ];
|
||||||
// return $candidates;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public function refreshForMx(string $service = '_25._tcp'): ?\App\Models\TlsaRecord
|
|
||||||
// {
|
|
||||||
// $host = $this->resolveMxHost();
|
|
||||||
//
|
|
||||||
// // bevorzugt die als Server markierte Domain
|
|
||||||
// $serverDomain = \App\Models\Domain::where('is_server', true)->first();
|
|
||||||
//
|
|
||||||
// // Fallback: Domain über FQDN (mx.<BASE_DOMAIN>) finden
|
|
||||||
// if (!$serverDomain) {
|
|
||||||
// $serverDomain = \App\Models\Domain::where('domain', $host)->first();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (!$serverDomain) {
|
|
||||||
// // Keine passende Domain in der DB → nichts tun
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return $this->refreshForServerDomain($serverDomain, $service);
|
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// private function firstReadableCert(string $host): ?string
|
// private function firstReadableCert(string $host): ?string
|
||||||
// {
|
// {
|
||||||
// foreach ($this->certCandidates($host) as $path) {
|
// foreach ($this->certCandidates($host) as $p) {
|
||||||
// if (is_file($path) && is_readable($path)) {
|
// if (is_file($p) && is_readable($p)) return $p;
|
||||||
// return $path;
|
|
||||||
// }
|
|
||||||
// }
|
// }
|
||||||
// return null;
|
// return null;
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// public function computeHashFromCert(string $host): ?string
|
// public function computeHashFromCertPath(string $certPath): ?string
|
||||||
// {
|
// {
|
||||||
// $certPath = $this->firstReadableCert($host);
|
// $cmd = "openssl x509 -in " . escapeshellarg($certPath) . " -noout -pubkey"
|
||||||
// if (!$certPath) return null;
|
|
||||||
//
|
|
||||||
// $cmd = "openssl x509 -in ".escapeshellarg($certPath)." -noout -pubkey"
|
|
||||||
// . " | openssl pkey -pubin -outform DER"
|
// . " | openssl pkey -pubin -outform DER"
|
||||||
// . " | openssl dgst -sha256";
|
// . " | openssl dgst -sha256";
|
||||||
// $out = shell_exec($cmd.' 2>/dev/null') ?? '';
|
// $out = shell_exec($cmd . ' 2>/dev/null') ?? '';
|
||||||
// $hash = preg_replace('/^SHA256\(stdin\)=\s*/', '', trim($out));
|
// $out = trim($out);
|
||||||
|
// if ($out === '') return null;
|
||||||
|
//
|
||||||
|
// // Variationen entfernen: "SHA256(stdin)= x", "SHA2-256(stdin)= x"
|
||||||
|
// $hash = preg_replace('/^SHA2?56\(stdin\)=\s*/i', '', $out);
|
||||||
|
// $hash = preg_replace('/^SHA2?-256\(stdin\)=\s*/i', '', $hash); // falls "SHA2-256"
|
||||||
|
// $hash = trim($hash);
|
||||||
|
//
|
||||||
// return $hash !== '' ? $hash : null;
|
// return $hash !== '' ? $hash : null;
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// public function refreshForServerDomain(Domain $serverDomain, string $service = '_25._tcp'): ?TlsaRecord
|
// /** Holt is_server-Domain und schreibt/aktualisiert TLSA (3 1 1) */
|
||||||
|
// public function refreshForMx(string $service = '_25._tcp'): ?TlsaRecord
|
||||||
// {
|
// {
|
||||||
// $host = $this->resolveMxHost();
|
// $host = $this->resolveMxHost();
|
||||||
// $hash = $this->computeHashFromCert($host);
|
|
||||||
// if (!$hash) return null;
|
|
||||||
//
|
//
|
||||||
// $certPath = $this->firstReadableCert($host) ?? '';
|
// // 1) Server-Domain ermitteln (es darf genau eine mit is_server=true geben)
|
||||||
|
// $serverDomain = Domain::where('is_server', true)
|
||||||
|
// ->where('domain', $host) // doppelt absichern: passt zur ENV
|
||||||
|
// ->first();
|
||||||
//
|
//
|
||||||
// $rec = TlsaRecord::updateOrCreate(
|
// if (!$serverDomain) {
|
||||||
// ['domain_id' => $serverDomain->id, 'host' => $host, 'service' => $service],
|
// // Kein is_server Eintrag -> nichts zu tun
|
||||||
// [
|
|
||||||
// 'usage' => 3,
|
|
||||||
// 'selector' => 1,
|
|
||||||
// 'matching' => 1,
|
|
||||||
// 'hash' => $hash,
|
|
||||||
// 'cert_path' => $certPath,
|
|
||||||
// ]
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// @mkdir('/etc/mailwolt/dns', 0755, true);
|
|
||||||
// $line = sprintf('%s.%s IN TLSA %d %d %d %s', $service, $host, 3, 1, 1, $hash);
|
|
||||||
// @file_put_contents("/etc/mailwolt/dns/{$host}.tlsa.txt", $line."\n");
|
|
||||||
//
|
|
||||||
// return $rec;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public function computeHashFromCert(string $host): ?string
|
|
||||||
// {
|
|
||||||
// $certPath = "/etc/letsencrypt/live/{$host}/fullchain.pem";
|
|
||||||
// if (!is_file($certPath)) {
|
|
||||||
// // optional: Log für Debug
|
|
||||||
// logger()->warning("TLSA: Zertifikat nicht gefunden", ['path' => $certPath]);
|
|
||||||
// return null;
|
// return null;
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// $cmd = "openssl x509 -in ".escapeshellarg($certPath)." -noout -pubkey"
|
// // 2) Zertifikat finden/lesen
|
||||||
// . " | openssl pkey -pubin -outform DER"
|
// $certPath = $this->firstReadableCert($host);
|
||||||
// . " | openssl dgst -sha256";
|
// if (!$certPath) return null;
|
||||||
// $out = shell_exec($cmd.' 2>/dev/null') ?? '';
|
|
||||||
// $hash = preg_replace('/^SHA256\(stdin\)=\s*/', '', trim($out));
|
|
||||||
// return $hash !== '' ? $hash : null;
|
|
||||||
// }
|
|
||||||
//
|
//
|
||||||
// /**
|
// // 3) Hash berechnen
|
||||||
// * TLSA (3 1 1) für den MX-Host der übergebenen Domain erzeugen/aktualisieren.
|
// $hash = $this->computeHashFromCertPath($certPath);
|
||||||
// * Host kommt DIREKT aus $serverDomain->domain, nicht aus ENV.
|
// if (!$hash) return null;
|
||||||
// */
|
|
||||||
// public function refreshForServerDomain(Domain $serverDomain, string $service = '_25._tcp'): ?TlsaRecord
|
|
||||||
// {
|
|
||||||
// $host = $serverDomain->domain; // <— wichtig: Domain-Objekt statt ENV
|
|
||||||
// $hash = $this->computeHashFromCert($host);
|
|
||||||
// if (!$hash) {
|
|
||||||
// return null; // Zert (noch) nicht vorhanden
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// $certPath = "/etc/letsencrypt/live/{$host}/fullchain.pem";
|
|
||||||
//
|
//
|
||||||
|
// // 4) DB schreiben (idempotent)
|
||||||
// $rec = TlsaRecord::updateOrCreate(
|
// $rec = TlsaRecord::updateOrCreate(
|
||||||
// ['domain_id' => $serverDomain->id, 'host' => $host, 'service' => $service],
|
// ['domain_id' => $serverDomain->id, 'host' => $host, 'service' => $service],
|
||||||
// [
|
// [
|
||||||
// 'usage' => 3, // DANE-EE
|
// 'usage' => 3,
|
||||||
// 'selector' => 1, // SPKI
|
// 'selector' => 1,
|
||||||
// 'matching' => 1, // SHA-256
|
// 'matching' => 1,
|
||||||
// 'hash' => $hash,
|
// 'hash' => $hash,
|
||||||
// 'cert_path' => $certPath,
|
// 'cert_path' => $certPath,
|
||||||
// ]
|
// ]
|
||||||
// );
|
// );
|
||||||
//
|
//
|
||||||
// // optional: Datei für Export/Debug
|
// // 5) optionale Export-Datei
|
||||||
// @mkdir('/etc/mailwolt/dns', 0755, true);
|
|
||||||
// @file_put_contents("/etc/mailwolt/dns/{$host}.tlsa.txt", sprintf('%s.%s IN TLSA 3 1 1 %s', $service, $host, $hash)."\n");
|
|
||||||
//
|
|
||||||
// return $rec;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public function resolveMxHost(): string
|
|
||||||
// {
|
|
||||||
// $base = env('BASE_DOMAIN', 'example.com');
|
|
||||||
// $sub = env('MTA_SUB', 'mx') ?: 'mx';
|
|
||||||
// return "{$sub}.{$base}";
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public function computeHashFromCert(string $host): ?string
|
|
||||||
// {
|
|
||||||
// $certPath = "/etc/letsencrypt/live/{$host}/fullchain.pem";
|
|
||||||
// if (!is_file($certPath)) return null;
|
|
||||||
//
|
|
||||||
// $cmd = "openssl x509 -in ".escapeshellarg($certPath)." -noout -pubkey"
|
|
||||||
// . " | openssl pkey -pubin -outform DER"
|
|
||||||
// . " | openssl dgst -sha256";
|
|
||||||
// $out = shell_exec($cmd.' 2>/dev/null') ?? '';
|
|
||||||
// $hash = preg_replace('/^SHA256\(stdin\)=\s*/', '', trim($out));
|
|
||||||
// return $hash !== '' ? $hash : null;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Schreibt/aktualisiert TLSA (3 1 1) für den MX-Host in DB
|
|
||||||
// * und legt zusätzlich /etc/mailwolt/dns/<host>.tlsa.txt ab.
|
|
||||||
// */
|
|
||||||
// public function refreshForServerDomain(Domain $serverDomain, string $service = '_25._tcp'): ?TlsaRecord
|
|
||||||
// {
|
|
||||||
// $host = $this->resolveMxHost();
|
|
||||||
// $hash = $this->computeHashFromCert($host);
|
|
||||||
// if (!$hash) {
|
|
||||||
// return null; // Zert (noch) nicht vorhanden
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// $certPath = "/etc/letsencrypt/live/{$host}/fullchain.pem";
|
|
||||||
//
|
|
||||||
// $rec = TlsaRecord::updateOrCreate(
|
|
||||||
// ['domain_id' => $serverDomain->id, 'host' => $host, 'service' => $service],
|
|
||||||
// [
|
|
||||||
// 'usage' => 3, // DANE-EE
|
|
||||||
// 'selector' => 1, // SPKI
|
|
||||||
// 'matching' => 1, // SHA-256
|
|
||||||
// 'hash' => $hash,
|
|
||||||
// 'cert_path' => $certPath,
|
|
||||||
// ]
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// // Optional: TXT-Datei für Export/Debug
|
|
||||||
// @mkdir('/etc/mailwolt/dns', 0755, true);
|
// @mkdir('/etc/mailwolt/dns', 0755, true);
|
||||||
// $line = sprintf('%s.%s IN TLSA %d %d %d %s', $service, $host, 3, 1, 1, $hash);
|
// $line = sprintf('%s.%s IN TLSA %d %d %d %s', $service, $host, 3, 1, 1, $hash);
|
||||||
// @file_put_contents("/etc/mailwolt/dns/{$host}.tlsa.txt", $line."\n");
|
// @file_put_contents("/etc/mailwolt/dns/{$host}.tlsa.txt", $line . "\n");
|
||||||
//
|
|
||||||
// return $rec;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
//class TlsaService
|
|
||||||
//{
|
|
||||||
// public function resolveMtaHost(): string
|
|
||||||
// {
|
|
||||||
// $base = env('BASE_DOMAIN', 'example.com');
|
|
||||||
// $sub = env('MTA_SUB', 'mx') ?: 'mx';
|
|
||||||
// return "{$sub}.{$base}";
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public function computeHashFromCert(string $host): ?string
|
|
||||||
// {
|
|
||||||
// $certPath = "/etc/letsencrypt/live/{$host}/fullchain.pem";
|
|
||||||
// if (!is_file($certPath)) return null;
|
|
||||||
//
|
|
||||||
// $cmd = "openssl x509 -in ".escapeshellarg($certPath)." -noout -pubkey"
|
|
||||||
// . " | openssl pkey -pubin -outform DER"
|
|
||||||
// . " | openssl dgst -sha256";
|
|
||||||
// $out = shell_exec($cmd.' 2>/dev/null') ?? '';
|
|
||||||
// $hash = preg_replace('/^SHA256\(stdin\)=\s*/', '', trim($out));
|
|
||||||
// return $hash !== '' ? $hash : null;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public function refreshForMx(string $service = '_25._tcp'): ?TlsaRecord
|
|
||||||
// {
|
|
||||||
// $host = $this->resolveMtaHost();
|
|
||||||
// $certPath = "/etc/letsencrypt/live/{$host}/fullchain.pem";
|
|
||||||
// $hash = $this->computeHashFromCert($host);
|
|
||||||
// if (!$hash) return null;
|
|
||||||
//
|
|
||||||
// // DB upsert (global, domain_id = null)
|
|
||||||
// $rec = TlsaRecord::updateOrCreate(
|
|
||||||
// ['domain_id' => null, 'host' => $host, 'service' => $service],
|
|
||||||
// [
|
|
||||||
// 'usage' => 3, // DANE-EE
|
|
||||||
// 'selector' => 1, // SPKI
|
|
||||||
// 'matching' => 1, // SHA-256
|
|
||||||
// 'hash' => $hash,
|
|
||||||
// 'cert_path' => $certPath,
|
|
||||||
// ]
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// // Datei – nur aktualisieren, wenn sich der Hash ändert
|
|
||||||
// @mkdir('/etc/mailwolt/dns', 0755, true);
|
|
||||||
// $file = "/etc/mailwolt/dns/{$host}.tlsa.txt";
|
|
||||||
// $newLine = sprintf('%s.%s IN TLSA %d %d %d %s', $service, $host, 3, 1, 1, $hash);
|
|
||||||
//
|
|
||||||
// $needWrite = true;
|
|
||||||
// if (is_file($file)) {
|
|
||||||
// $current = trim((string)file_get_contents($file));
|
|
||||||
// if ($current === $newLine) {
|
|
||||||
// $needWrite = false;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if ($needWrite) {
|
|
||||||
// file_put_contents($file, $newLine."\n");
|
|
||||||
// }
|
|
||||||
//
|
//
|
||||||
// return $rec;
|
// return $rec;
|
||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
//
|
//
|
||||||
//----
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
//namespace App\Services;
|
|
||||||
//
|
//
|
||||||
//use App\Models\TlsaRecord;
|
////namespace App\Services;
|
||||||
|
////
|
||||||
|
////use App\Models\Domain;
|
||||||
|
////use App\Models\TlsaRecord;
|
||||||
|
////
|
||||||
|
////class TlsaService
|
||||||
|
////{
|
||||||
|
//// public function resolveMxHost(): string
|
||||||
|
//// {
|
||||||
|
//// $base = env('BASE_DOMAIN', 'example.com');
|
||||||
|
//// $sub = env('MTA_SUB', 'mx') ?: 'mx';
|
||||||
|
//// return "{$sub}.{$base}";
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// private function certCandidates(string $host): array
|
||||||
|
//// {
|
||||||
|
//// // bevorzugt die vom Deploy-Hook gesetzten, lesbaren Symlinks
|
||||||
|
//// $candidates = [
|
||||||
|
//// '/etc/ssl/mail/fullchain.pem', // MX
|
||||||
|
//// "/etc/letsencrypt/live/{$host}/fullchain.pem", // Fallback
|
||||||
|
//// ];
|
||||||
|
//// return $candidates;
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// public function refreshForMx(string $service = '_25._tcp'): ?\App\Models\TlsaRecord
|
||||||
|
//// {
|
||||||
|
//// $host = $this->resolveMxHost();
|
||||||
|
////
|
||||||
|
//// // bevorzugt die als Server markierte Domain
|
||||||
|
//// $serverDomain = \App\Models\Domain::where('is_server', true)->first();
|
||||||
|
////
|
||||||
|
//// // Fallback: Domain über FQDN (mx.<BASE_DOMAIN>) finden
|
||||||
|
//// if (!$serverDomain) {
|
||||||
|
//// $serverDomain = \App\Models\Domain::where('domain', $host)->first();
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// if (!$serverDomain) {
|
||||||
|
//// // Keine passende Domain in der DB → nichts tun
|
||||||
|
//// return null;
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// return $this->refreshForServerDomain($serverDomain, $service);
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// private function firstReadableCert(string $host): ?string
|
||||||
|
//// {
|
||||||
|
//// foreach ($this->certCandidates($host) as $path) {
|
||||||
|
//// if (is_file($path) && is_readable($path)) {
|
||||||
|
//// return $path;
|
||||||
|
//// }
|
||||||
|
//// }
|
||||||
|
//// return null;
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// public function computeHashFromCert(string $host): ?string
|
||||||
|
//// {
|
||||||
|
//// $certPath = $this->firstReadableCert($host);
|
||||||
|
//// if (!$certPath) return null;
|
||||||
|
////
|
||||||
|
//// $cmd = "openssl x509 -in ".escapeshellarg($certPath)." -noout -pubkey"
|
||||||
|
//// . " | openssl pkey -pubin -outform DER"
|
||||||
|
//// . " | openssl dgst -sha256";
|
||||||
|
//// $out = shell_exec($cmd.' 2>/dev/null') ?? '';
|
||||||
|
//// $hash = preg_replace('/^SHA256\(stdin\)=\s*/', '', trim($out));
|
||||||
|
//// return $hash !== '' ? $hash : null;
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// public function refreshForServerDomain(Domain $serverDomain, string $service = '_25._tcp'): ?TlsaRecord
|
||||||
|
//// {
|
||||||
|
//// $host = $this->resolveMxHost();
|
||||||
|
//// $hash = $this->computeHashFromCert($host);
|
||||||
|
//// if (!$hash) return null;
|
||||||
|
////
|
||||||
|
//// $certPath = $this->firstReadableCert($host) ?? '';
|
||||||
|
////
|
||||||
|
//// $rec = TlsaRecord::updateOrCreate(
|
||||||
|
//// ['domain_id' => $serverDomain->id, 'host' => $host, 'service' => $service],
|
||||||
|
//// [
|
||||||
|
//// 'usage' => 3,
|
||||||
|
//// 'selector' => 1,
|
||||||
|
//// 'matching' => 1,
|
||||||
|
//// 'hash' => $hash,
|
||||||
|
//// 'cert_path' => $certPath,
|
||||||
|
//// ]
|
||||||
|
//// );
|
||||||
|
////
|
||||||
|
//// @mkdir('/etc/mailwolt/dns', 0755, true);
|
||||||
|
//// $line = sprintf('%s.%s IN TLSA %d %d %d %s', $service, $host, 3, 1, 1, $hash);
|
||||||
|
//// @file_put_contents("/etc/mailwolt/dns/{$host}.tlsa.txt", $line."\n");
|
||||||
|
////
|
||||||
|
//// return $rec;
|
||||||
|
//// }
|
||||||
//
|
//
|
||||||
//class TlsaService
|
//// public function computeHashFromCert(string $host): ?string
|
||||||
//{
|
//// {
|
||||||
// public function resolveMtaHost(): string
|
//// $certPath = "/etc/letsencrypt/live/{$host}/fullchain.pem";
|
||||||
// {
|
//// if (!is_file($certPath)) {
|
||||||
// $base = env('BASE_DOMAIN', 'example.com');
|
//// // optional: Log für Debug
|
||||||
// $sub = env('MTA_SUB', 'mx') ?: 'mx';
|
//// logger()->warning("TLSA: Zertifikat nicht gefunden", ['path' => $certPath]);
|
||||||
// return "{$sub}.{$base}";
|
//// return null;
|
||||||
// }
|
//// }
|
||||||
|
////
|
||||||
|
//// $cmd = "openssl x509 -in ".escapeshellarg($certPath)." -noout -pubkey"
|
||||||
|
//// . " | openssl pkey -pubin -outform DER"
|
||||||
|
//// . " | openssl dgst -sha256";
|
||||||
|
//// $out = shell_exec($cmd.' 2>/dev/null') ?? '';
|
||||||
|
//// $hash = preg_replace('/^SHA256\(stdin\)=\s*/', '', trim($out));
|
||||||
|
//// return $hash !== '' ? $hash : null;
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// /**
|
||||||
|
//// * TLSA (3 1 1) für den MX-Host der übergebenen Domain erzeugen/aktualisieren.
|
||||||
|
//// * Host kommt DIREKT aus $serverDomain->domain, nicht aus ENV.
|
||||||
|
//// */
|
||||||
|
//// public function refreshForServerDomain(Domain $serverDomain, string $service = '_25._tcp'): ?TlsaRecord
|
||||||
|
//// {
|
||||||
|
//// $host = $serverDomain->domain; // <— wichtig: Domain-Objekt statt ENV
|
||||||
|
//// $hash = $this->computeHashFromCert($host);
|
||||||
|
//// if (!$hash) {
|
||||||
|
//// return null; // Zert (noch) nicht vorhanden
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// $certPath = "/etc/letsencrypt/live/{$host}/fullchain.pem";
|
||||||
|
////
|
||||||
|
//// $rec = TlsaRecord::updateOrCreate(
|
||||||
|
//// ['domain_id' => $serverDomain->id, 'host' => $host, 'service' => $service],
|
||||||
|
//// [
|
||||||
|
//// 'usage' => 3, // DANE-EE
|
||||||
|
//// 'selector' => 1, // SPKI
|
||||||
|
//// 'matching' => 1, // SHA-256
|
||||||
|
//// 'hash' => $hash,
|
||||||
|
//// 'cert_path' => $certPath,
|
||||||
|
//// ]
|
||||||
|
//// );
|
||||||
|
////
|
||||||
|
//// // optional: Datei für Export/Debug
|
||||||
|
//// @mkdir('/etc/mailwolt/dns', 0755, true);
|
||||||
|
//// @file_put_contents("/etc/mailwolt/dns/{$host}.tlsa.txt", sprintf('%s.%s IN TLSA 3 1 1 %s', $service, $host, $hash)."\n");
|
||||||
|
////
|
||||||
|
//// return $rec;
|
||||||
|
//// }
|
||||||
//
|
//
|
||||||
// public function computeHashFromCert(string $host): ?string
|
//// public function resolveMxHost(): string
|
||||||
// {
|
//// {
|
||||||
// $certPath = "/etc/letsencrypt/live/{$host}/fullchain.pem";
|
//// $base = env('BASE_DOMAIN', 'example.com');
|
||||||
// if (!is_file($certPath)) return null;
|
//// $sub = env('MTA_SUB', 'mx') ?: 'mx';
|
||||||
|
//// return "{$sub}.{$base}";
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// public function computeHashFromCert(string $host): ?string
|
||||||
|
//// {
|
||||||
|
//// $certPath = "/etc/letsencrypt/live/{$host}/fullchain.pem";
|
||||||
|
//// if (!is_file($certPath)) return null;
|
||||||
|
////
|
||||||
|
//// $cmd = "openssl x509 -in ".escapeshellarg($certPath)." -noout -pubkey"
|
||||||
|
//// . " | openssl pkey -pubin -outform DER"
|
||||||
|
//// . " | openssl dgst -sha256";
|
||||||
|
//// $out = shell_exec($cmd.' 2>/dev/null') ?? '';
|
||||||
|
//// $hash = preg_replace('/^SHA256\(stdin\)=\s*/', '', trim($out));
|
||||||
|
//// return $hash !== '' ? $hash : null;
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// /**
|
||||||
|
//// * Schreibt/aktualisiert TLSA (3 1 1) für den MX-Host in DB
|
||||||
|
//// * und legt zusätzlich /etc/mailwolt/dns/<host>.tlsa.txt ab.
|
||||||
|
//// */
|
||||||
|
//// public function refreshForServerDomain(Domain $serverDomain, string $service = '_25._tcp'): ?TlsaRecord
|
||||||
|
//// {
|
||||||
|
//// $host = $this->resolveMxHost();
|
||||||
|
//// $hash = $this->computeHashFromCert($host);
|
||||||
|
//// if (!$hash) {
|
||||||
|
//// return null; // Zert (noch) nicht vorhanden
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// $certPath = "/etc/letsencrypt/live/{$host}/fullchain.pem";
|
||||||
|
////
|
||||||
|
//// $rec = TlsaRecord::updateOrCreate(
|
||||||
|
//// ['domain_id' => $serverDomain->id, 'host' => $host, 'service' => $service],
|
||||||
|
//// [
|
||||||
|
//// 'usage' => 3, // DANE-EE
|
||||||
|
//// 'selector' => 1, // SPKI
|
||||||
|
//// 'matching' => 1, // SHA-256
|
||||||
|
//// 'hash' => $hash,
|
||||||
|
//// 'cert_path' => $certPath,
|
||||||
|
//// ]
|
||||||
|
//// );
|
||||||
|
////
|
||||||
|
//// // Optional: TXT-Datei für Export/Debug
|
||||||
|
//// @mkdir('/etc/mailwolt/dns', 0755, true);
|
||||||
|
//// $line = sprintf('%s.%s IN TLSA %d %d %d %s', $service, $host, 3, 1, 1, $hash);
|
||||||
|
//// @file_put_contents("/etc/mailwolt/dns/{$host}.tlsa.txt", $line."\n");
|
||||||
|
////
|
||||||
|
//// return $rec;
|
||||||
|
//// }
|
||||||
|
////}
|
||||||
//
|
//
|
||||||
// $cmd = "openssl x509 -in ".escapeshellarg($certPath)." -noout -pubkey"
|
|
||||||
// . " | openssl pkey -pubin -outform DER"
|
|
||||||
// . " | openssl dgst -sha256";
|
|
||||||
// $out = shell_exec($cmd.' 2>/dev/null') ?? '';
|
|
||||||
// $hash = preg_replace('/^SHA256\(stdin\)=\s*/', '', trim($out));
|
|
||||||
// return $hash !== '' ? $hash : null;
|
|
||||||
// }
|
|
||||||
//
|
//
|
||||||
// /**
|
////class TlsaService
|
||||||
// * Schreibt/aktualisiert TLSA in DB (global) + Datei unter /etc/mailwolt/dns/.
|
////{
|
||||||
// * Wir speichern ohne domain_id (global, nur pro Host/Service).
|
//// public function resolveMtaHost(): string
|
||||||
// */
|
//// {
|
||||||
// public function refreshForMx(string $service = '_25._tcp'): ?TlsaRecord
|
//// $base = env('BASE_DOMAIN', 'example.com');
|
||||||
// {
|
//// $sub = env('MTA_SUB', 'mx') ?: 'mx';
|
||||||
// $host = $this->resolveMtaHost();
|
//// return "{$sub}.{$base}";
|
||||||
// $certPath = "/etc/letsencrypt/live/{$host}/fullchain.pem";
|
//// }
|
||||||
// $hash = $this->computeHashFromCert($host);
|
////
|
||||||
// if (!$hash) return null;
|
//// public function computeHashFromCert(string $host): ?string
|
||||||
|
//// {
|
||||||
|
//// $certPath = "/etc/letsencrypt/live/{$host}/fullchain.pem";
|
||||||
|
//// if (!is_file($certPath)) return null;
|
||||||
|
////
|
||||||
|
//// $cmd = "openssl x509 -in ".escapeshellarg($certPath)." -noout -pubkey"
|
||||||
|
//// . " | openssl pkey -pubin -outform DER"
|
||||||
|
//// . " | openssl dgst -sha256";
|
||||||
|
//// $out = shell_exec($cmd.' 2>/dev/null') ?? '';
|
||||||
|
//// $hash = preg_replace('/^SHA256\(stdin\)=\s*/', '', trim($out));
|
||||||
|
//// return $hash !== '' ? $hash : null;
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// public function refreshForMx(string $service = '_25._tcp'): ?TlsaRecord
|
||||||
|
//// {
|
||||||
|
//// $host = $this->resolveMtaHost();
|
||||||
|
//// $certPath = "/etc/letsencrypt/live/{$host}/fullchain.pem";
|
||||||
|
//// $hash = $this->computeHashFromCert($host);
|
||||||
|
//// if (!$hash) return null;
|
||||||
|
////
|
||||||
|
//// // DB upsert (global, domain_id = null)
|
||||||
|
//// $rec = TlsaRecord::updateOrCreate(
|
||||||
|
//// ['domain_id' => null, 'host' => $host, 'service' => $service],
|
||||||
|
//// [
|
||||||
|
//// 'usage' => 3, // DANE-EE
|
||||||
|
//// 'selector' => 1, // SPKI
|
||||||
|
//// 'matching' => 1, // SHA-256
|
||||||
|
//// 'hash' => $hash,
|
||||||
|
//// 'cert_path' => $certPath,
|
||||||
|
//// ]
|
||||||
|
//// );
|
||||||
|
////
|
||||||
|
//// // Datei – nur aktualisieren, wenn sich der Hash ändert
|
||||||
|
//// @mkdir('/etc/mailwolt/dns', 0755, true);
|
||||||
|
//// $file = "/etc/mailwolt/dns/{$host}.tlsa.txt";
|
||||||
|
//// $newLine = sprintf('%s.%s IN TLSA %d %d %d %s', $service, $host, 3, 1, 1, $hash);
|
||||||
|
////
|
||||||
|
//// $needWrite = true;
|
||||||
|
//// if (is_file($file)) {
|
||||||
|
//// $current = trim((string)file_get_contents($file));
|
||||||
|
//// if ($current === $newLine) {
|
||||||
|
//// $needWrite = false;
|
||||||
|
//// }
|
||||||
|
//// }
|
||||||
|
//// if ($needWrite) {
|
||||||
|
//// file_put_contents($file, $newLine."\n");
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// return $rec;
|
||||||
|
//// }
|
||||||
|
////}
|
||||||
|
////
|
||||||
|
////----
|
||||||
//
|
//
|
||||||
// // DB upsert (domain_id = null → globaler Eintrag)
|
|
||||||
// $rec = TlsaRecord::updateOrCreate(
|
|
||||||
// ['domain_id' => null, 'host' => $host, 'service' => $service],
|
|
||||||
// [
|
|
||||||
// 'usage' => 3, // DANE-EE
|
|
||||||
// 'selector' => 1, // SPKI
|
|
||||||
// 'matching' => 1, // SHA-256
|
|
||||||
// 'hash' => $hash,
|
|
||||||
// 'cert_path' => $certPath,
|
|
||||||
// ]
|
|
||||||
// );
|
|
||||||
//
|
//
|
||||||
// // Datei schreiben (für externen DNS-Export etc.)
|
////
|
||||||
// @mkdir('/etc/mailwolt/dns', 0755, true);
|
////namespace App\Services;
|
||||||
// $line = sprintf('%s.%s IN TLSA %d %d %d %s',
|
////
|
||||||
// $service, $host, 3, 1, 1, $hash);
|
////use App\Models\TlsaRecord;
|
||||||
// file_put_contents("/etc/mailwolt/dns/{$host}.tlsa.txt", $line."\n");
|
////
|
||||||
//
|
////class TlsaService
|
||||||
// return $rec;
|
////{
|
||||||
// }
|
//// public function resolveMtaHost(): string
|
||||||
//}
|
//// {
|
||||||
|
//// $base = env('BASE_DOMAIN', 'example.com');
|
||||||
|
//// $sub = env('MTA_SUB', 'mx') ?: 'mx';
|
||||||
|
//// return "{$sub}.{$base}";
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// public function computeHashFromCert(string $host): ?string
|
||||||
|
//// {
|
||||||
|
//// $certPath = "/etc/letsencrypt/live/{$host}/fullchain.pem";
|
||||||
|
//// if (!is_file($certPath)) return null;
|
||||||
|
////
|
||||||
|
//// $cmd = "openssl x509 -in ".escapeshellarg($certPath)." -noout -pubkey"
|
||||||
|
//// . " | openssl pkey -pubin -outform DER"
|
||||||
|
//// . " | openssl dgst -sha256";
|
||||||
|
//// $out = shell_exec($cmd.' 2>/dev/null') ?? '';
|
||||||
|
//// $hash = preg_replace('/^SHA256\(stdin\)=\s*/', '', trim($out));
|
||||||
|
//// return $hash !== '' ? $hash : null;
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// /**
|
||||||
|
//// * Schreibt/aktualisiert TLSA in DB (global) + Datei unter /etc/mailwolt/dns/.
|
||||||
|
//// * Wir speichern ohne domain_id (global, nur pro Host/Service).
|
||||||
|
//// */
|
||||||
|
//// public function refreshForMx(string $service = '_25._tcp'): ?TlsaRecord
|
||||||
|
//// {
|
||||||
|
//// $host = $this->resolveMtaHost();
|
||||||
|
//// $certPath = "/etc/letsencrypt/live/{$host}/fullchain.pem";
|
||||||
|
//// $hash = $this->computeHashFromCert($host);
|
||||||
|
//// if (!$hash) return null;
|
||||||
|
////
|
||||||
|
//// // DB upsert (domain_id = null → globaler Eintrag)
|
||||||
|
//// $rec = TlsaRecord::updateOrCreate(
|
||||||
|
//// ['domain_id' => null, 'host' => $host, 'service' => $service],
|
||||||
|
//// [
|
||||||
|
//// 'usage' => 3, // DANE-EE
|
||||||
|
//// 'selector' => 1, // SPKI
|
||||||
|
//// 'matching' => 1, // SHA-256
|
||||||
|
//// 'hash' => $hash,
|
||||||
|
//// 'cert_path' => $certPath,
|
||||||
|
//// ]
|
||||||
|
//// );
|
||||||
|
////
|
||||||
|
//// // Datei schreiben (für externen DNS-Export etc.)
|
||||||
|
//// @mkdir('/etc/mailwolt/dns', 0755, true);
|
||||||
|
//// $line = sprintf('%s.%s IN TLSA %d %d %d %s',
|
||||||
|
//// $service, $host, 3, 1, 1, $hash);
|
||||||
|
//// file_put_contents("/etc/mailwolt/dns/{$host}.tlsa.txt", $line."\n");
|
||||||
|
////
|
||||||
|
//// return $rec;
|
||||||
|
//// }
|
||||||
|
////}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue