Skip to content

Commit 4f9f7c3

Browse files
authored
Cleanup SslCertificate Model (librenms#19970)
* Cleanup SslCertificate Model the use of attributes as arrays caused some phpstan errors on new versions refactor to just use Model properties directly * Use firstOrNew and remove unnecessary check * Update SslCertificatePolicy to check device access * style fixes * restore property definition... something is probably messed
1 parent 6c97dca commit 4f9f7c3

5 files changed

Lines changed: 103 additions & 151 deletions

File tree

app/Console/Commands/MaintenanceDiscoverSslCertificates.php

Lines changed: 17 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,11 @@
22

33
namespace App\Console\Commands;
44

5-
use AcmePhp\Ssl\Exception\CertificateParsingException;
65
use App\Console\LnmsCommand;
76
use App\Facades\LibrenmsConfig;
87
use App\Models\Device;
98
use App\Models\Eventlog;
109
use App\Models\SslCertificate;
11-
use Jalle19\CertificateParser\Parser;
12-
use Jalle19\CertificateParser\Provider\Exception\ProviderException;
13-
use Jalle19\CertificateParser\Provider\StreamContext;
14-
use Jalle19\CertificateParser\Provider\StreamSocketProvider;
1510
use LibreNMS\Enum\Severity;
1611
use Symfony\Component\Console\Input\InputOption;
1712

@@ -44,10 +39,6 @@ public function handle(): int
4439
return 0;
4540
}
4641

47-
$parser = new Parser();
48-
$context = new StreamContext();
49-
$context->setVerifyPeerName(false);
50-
5142
$port = 443;
5243
$timeout = 10;
5344
$created = 0;
@@ -65,42 +56,35 @@ public function handle(): int
6556
continue;
6657
}
6758

68-
try {
69-
$provider = new StreamSocketProvider($host, $port, $timeout, $context);
70-
$results = $parser->parse($provider);
71-
} catch (ProviderException|CertificateParsingException $e) {
72-
if ($this->getOutput()->isVerbose()) {
73-
$this->line(" {$host}:{$port}" . $e->getMessage());
74-
}
75-
$failed++;
76-
continue;
77-
}
78-
79-
$data = array_merge(SslCertificate::attributesFromParserResults($results), [
59+
$cert = SslCertificate::firstOrNew([
8060
'device_id' => $device->device_id,
8161
'host' => $host,
8262
'port' => $port,
83-
'last_checked_at' => now(),
63+
], [
8464
'disabled' => false,
8565
]);
8666

87-
$existing = SslCertificate::where('device_id', $device->device_id)
88-
->where('host', $host)
89-
->where('port', $port)
90-
->first();
67+
try {
68+
$cert->updateFromHost($timeout);
69+
} catch (\Throwable $e) {
70+
if ($this->getOutput()->isVerbose()) {
71+
$this->line(" $host:$port" . $e->getMessage());
72+
}
73+
$failed++;
74+
continue;
75+
}
9176

92-
if ($existing) {
93-
$changes = SslCertificate::formatAttributeChanges($existing->only(['subject', 'issuer', 'valid_to', 'valid_from', 'fingerprint', 'days_until_expiry']), $data);
94-
// Always persist bookkeeping fields like last_checked_at, even if there are no meaningful changes.
95-
$existing->update($data);
77+
if ($cert->exists) {
78+
$changes = $cert->getTrackedChanges();
79+
$cert->save();
9680
if ($changes !== '') {
9781
$updated++;
98-
Eventlog::log("SSL certificate updated: {$host}:{$port}{$changes}", $device->device_id, 'ssl-certificate', Severity::Info, $existing->id);
82+
Eventlog::log("SSL certificate updated: {$host}:{$port}{$changes}", $device->device_id, 'ssl-certificate', Severity::Info, $cert->id);
9983
}
10084
} else {
101-
$cert = SslCertificate::create($data);
85+
$cert->save();
10286
$created++;
103-
$msg = "SSL certificate discovered: {$host}:{$port} – Subject: {$data['subject']}, Issuer: {$data['issuer']}, Valid until: " . ($data['valid_to'] ?? 'N/A') . ', Days until expiry: ' . ($data['days_until_expiry'] ?? 'N/A');
87+
$msg = "SSL certificate discovered: {$host}:{$port} – Subject: {$cert->subject}, Issuer: {$cert->issuer}, Valid until: " . ($cert->valid_to?->format('Y-m-d H:i:s') ?? 'N/A') . ', Days until expiry: ' . ($cert->days_until_expiry ?? 'N/A');
10488
Eventlog::log($msg, $device->device_id, 'ssl-certificate', Severity::Info, $cert->id);
10589
}
10690
}

app/Console/Commands/MaintenanceRefreshSslCertificates.php

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,10 @@
22

33
namespace App\Console\Commands;
44

5-
use AcmePhp\Ssl\Exception\CertificateParsingException;
65
use App\Console\LnmsCommand;
76
use App\Facades\LibrenmsConfig;
87
use App\Models\Eventlog;
98
use App\Models\SslCertificate;
10-
use Jalle19\CertificateParser\Parser;
11-
use Jalle19\CertificateParser\Provider\Exception\ProviderException;
12-
use Jalle19\CertificateParser\Provider\StreamContext;
13-
use Jalle19\CertificateParser\Provider\StreamSocketProvider;
149
use LibreNMS\Enum\Severity;
1510
use Symfony\Component\Console\Input\InputOption;
1611

@@ -32,7 +27,7 @@ public function handle(): int
3227
$id = $this->option('id');
3328

3429
$query = SslCertificate::query()->where('disabled', 0);
35-
if ($id !== null && is_numeric($id)) {
30+
if (is_numeric($id)) {
3631
$query->where('id', $id);
3732
}
3833
$certificates = $query->get();
@@ -48,34 +43,23 @@ public function handle(): int
4843
return 0;
4944
}
5045

51-
$parser = new Parser();
52-
$context = new StreamContext();
53-
$context->setVerifyPeerName(false);
54-
5546
$timeout = 10;
5647
$refreshed = 0;
5748
$failed = 0;
5849

59-
/** @var \App\Models\SslCertificate $cert */
6050
foreach ($certificates as $cert) {
6151
try {
62-
$provider = new StreamSocketProvider($cert->host, $cert->port, $timeout, $context);
63-
$results = $parser->parse($provider);
64-
} catch (ProviderException|CertificateParsingException $e) {
52+
$cert->updateFromHost($timeout);
53+
} catch (\Throwable $e) {
6554
if ($this->getOutput()->isVerbose()) {
66-
$this->line(" {$cert->host}:{$cert->port}" . $e->getMessage());
55+
$this->line(" $cert->host:$cert->port" . $e->getMessage());
6756
}
6857
$failed++;
6958
continue;
7059
}
7160

72-
$attrData = SslCertificate::attributesFromParserResults($results);
73-
$newData = array_merge($attrData, [
74-
'last_checked_at' => now(),
75-
]);
76-
$oldAttrs = $cert->only(['subject', 'issuer', 'valid_to', 'valid_from', 'fingerprint', 'days_until_expiry']);
77-
$changes = SslCertificate::formatAttributeChanges($oldAttrs, $attrData);
78-
$cert->update($newData);
61+
$changes = $cert->getTrackedChanges();
62+
$cert->save();
7963
if ($changes !== '') {
8064
$refreshed++;
8165
Eventlog::log("SSL certificate refreshed: {$cert->host}:{$cert->port}{$changes}", $cert->device_id, 'ssl-certificate', Severity::Info, $cert->id);

app/Http/Controllers/SslCertificateController.php

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -52,28 +52,25 @@ public function store(Request $request)
5252
->withErrors(['device_id' => __('You may only assign certificates to devices you can access.')]);
5353
}
5454

55-
$host = $validated['host'];
56-
$port = (int) ($validated['port'] ?? 443);
57-
$deviceId = (int) $validated['device_id'];
55+
$cert = new SslCertificate([
56+
'device_id' => $request->integer('device_id'),
57+
'host' => $request->string('host'),
58+
'port' => $request->integer('port', 443),
59+
'disabled' => false,
60+
]);
5861

5962
try {
60-
$cert = SslCertificate::fetchAndParse($host, $port);
63+
$cert->updateFromHost();
6164
} catch (\Throwable $e) {
6265
return redirect()->route('ssl-certificates.create')
6366
->withInput()
6467
->withErrors(['host' => __('Failed to fetch certificate: :error', ['error' => $e->getMessage()])]);
6568
}
6669

67-
$cert['device_id'] = $deviceId;
68-
$cert['host'] = $host;
69-
$cert['port'] = $port;
70-
$cert['last_checked_at'] = now();
71-
$cert['disabled'] = false;
72-
73-
SslCertificate::create($cert);
70+
$cert->save();
7471

7572
return redirect()->route('ssl-certificates.index')
76-
->with('success', __('SSL certificate added for :host.', ['host' => $host . ':' . $port]));
73+
->with('success', __('SSL certificate added for :host.', ['host' => $validated['host'] . ':' . ((int) ($validated['port'] ?? 443))]));
7774
}
7875

7976
/**
@@ -104,7 +101,7 @@ public function update(Request $request, SslCertificate $ssl_certificate)
104101
]);
105102

106103
if ($request->has('disabled')) {
107-
$ssl_certificate->disabled = (bool) $request->input('disabled');
104+
$ssl_certificate->disabled = $request->boolean('disabled');
108105
$ssl_certificate->save();
109106
}
110107

0 commit comments

Comments
 (0)