Files
ismysiteup.online/app/Jobs/CheckSslCertificate.php
T

129 lines
4.1 KiB
PHP
Raw Normal View History

2026-01-17 13:46:20 +02:00
<?php
namespace App\Jobs;
use App\Models\Notification;
use App\Models\Site;
use App\Models\SslCertificate;
use App\Notifications\SslExpiryAlert;
use Carbon\Carbon;
use Illuminate\Bus\Batchable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Facades\Log;
class CheckSslCertificate implements ShouldQueue
{
use Queueable, Batchable;
/**
* Create a new job instance.
*/
public function __construct(
public Site $site
) {
}
/**
* Execute the job.
*/
public function handle(): void
{
try {
// Parse URL to get host
$parsedUrl = parse_url($this->site->url);
if (!isset($parsedUrl['host'])) {
Log::warning("Invalid URL for SSL check on site {$this->site->id}: {$this->site->url}");
return;
}
$host = $parsedUrl['host'];
$port = $parsedUrl['scheme'] === 'https' ? 443 : 443;
// Create SSL context
$context = stream_context_create([
'ssl' => [
'capture_peer_cert' => true,
'verify_peer' => false,
'verify_peer_name' => false,
],
]);
// Connect to the server and get SSL certificate
$client = @stream_socket_client(
"ssl://{$host}:{$port}",
$errno,
$errstr,
10,
STREAM_CLIENT_CONNECT,
$context
);
if ($client === false) {
Log::warning("Failed to connect to {$host}:{$port} for SSL check: {$errstr}");
return;
}
$params = stream_context_get_params($client);
fclose($client);
if (!isset($params['options']['ssl']['peer_certificate'])) {
Log::warning("No SSL certificate found for site {$this->site->id}");
return;
}
$cert = openssl_x509_parse($params['options']['ssl']['peer_certificate']);
if ($cert === false) {
Log::warning("Failed to parse SSL certificate for site {$this->site->id}");
return;
}
// Extract certificate information
$issuer = $cert['issuer']['O'] ?? $cert['issuer']['CN'] ?? 'Unknown';
$expiresAt = Carbon::createFromTimestamp($cert['validTo_time_t']);
$checkedAt = now();
// Store the SSL certificate check result
SslCertificate::create([
'site_id' => $this->site->id,
'issuer' => $issuer,
'expires_at' => $expiresAt,
'checked_at' => $checkedAt,
]);
// Check if certificate expires within 30 days
$daysUntilExpiry = $checkedAt->diffInDays($expiresAt, false);
if ($daysUntilExpiry < 30 && $daysUntilExpiry >= 0) {
// Send notification to user
$this->site->user->notify(new SslExpiryAlert(
$this->site,
$issuer,
$expiresAt,
(int) $daysUntilExpiry,
false
));
Log::warning("SSL certificate expiring soon for site {$this->site->id}: {$daysUntilExpiry} days remaining");
} elseif ($daysUntilExpiry < 0) {
// Certificate already expired
$this->site->user->notify(new SslExpiryAlert(
$this->site,
$issuer,
$expiresAt,
(int) $daysUntilExpiry,
true
));
Log::error("SSL certificate expired for site {$this->site->id}");
}
Log::info("SSL check completed for site {$this->site->id} ({$this->site->url}): Issuer={$issuer}, Expires={$expiresAt->format('Y-m-d')}");
} catch (\Exception $e) {
Log::error("SSL check failed for site {$this->site->id}: {$e->getMessage()}");
}
}
}