Skip to content

Commit 9c9d26a

Browse files
committed
WIP
1 parent cfc5f78 commit 9c9d26a

File tree

4 files changed

+99
-21
lines changed

4 files changed

+99
-21
lines changed

application/clicommands/CheckCommand.php

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -113,15 +113,15 @@ public function hostAction()
113113

114114
$state = 3;
115115
foreach ($this->getDb()->select($targets) as $target) {
116-
if ($target['valid'] === 'no' && ($target['self_signed'] === 'no' || ! $allowSelfSigned)) {
117-
$invalidMessage = $target['subject'] . ': ' . $target['invalid_reason'];
116+
if ($target->valid === 'no' && ($target->self_signed === 'no' || ! $allowSelfSigned)) {
117+
$invalidMessage = $target->subject . ': ' . $target->invalid_reason;
118118
$output[$invalidMessage] = $invalidMessage;
119119
$state = 2;
120120
}
121121

122122
$now = new \DateTime();
123-
$validFrom = (new \DateTime())->setTimestamp($target['valid_from']);
124-
$validTo = (new \DateTime())->setTimestamp($target['valid_to']);
123+
$validFrom = (new \DateTime())->setTimestamp($target->valid_from);
124+
$validTo = (new \DateTime())->setTimestamp($target->valid_to);
125125
$criticalAfter = $this->thresholdToDateTime($validFrom, $validTo, $criticalThreshold, $criticalUnit);
126126
$warningAfter = $this->thresholdToDateTime($validFrom, $validTo, $warningThreshold, $warningUnit);
127127

@@ -136,28 +136,28 @@ public function hostAction()
136136
$remainingTime = $now->diff($validTo);
137137
if (! $remainingTime->invert) {
138138
// The certificate has not expired yet
139-
$output[$target['subject']] = sprintf(
139+
$output[$target->subject] = sprintf(
140140
'%s expires in %d days',
141-
$target['subject'],
141+
$target->subject,
142142
$remainingTime->days
143143
);
144144
} else {
145-
$output[$target['subject']] = sprintf(
145+
$output[$target->subject] = sprintf(
146146
'%s has expired since %d days',
147-
$target['subject'],
147+
$target->subject,
148148
$remainingTime->days
149149
);
150150
}
151151

152-
$perfData[$target['subject']] = sprintf(
152+
$perfData[$target->subject] = sprintf(
153153
"'%s'=%ds;%d:;%d:;0;%d",
154-
$target['subject'],
154+
$target->subject,
155155
$remainingTime->invert
156156
? 0
157-
: $target['valid_to'] - time(),
158-
$target['valid_to'] - $warningAfter->getTimestamp(),
159-
$target['valid_to'] - $criticalAfter->getTimestamp(),
160-
$target['valid_to'] - $target['valid_from']
157+
: $target->valid_to - time(),
158+
$target->valid_to - $warningAfter->getTimestamp(),
159+
$target->valid_to - $criticalAfter->getTimestamp(),
160+
$target->valid_to - $target->valid_from
161161
);
162162
}
163163

application/clicommands/ScanCommand.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
use Icinga\Module\X509\Command;
1010
use Icinga\Module\X509\Hook\SniHook;
1111
use Icinga\Module\X509\Job;
12+
use ipl\Sql\Connection;
13+
use ipl\Sql\Expression;
1214

1315
class ScanCommand extends Command
1416
{
@@ -58,9 +60,19 @@ public function indexAction()
5860
$name
5961
);
6062

63+
// $this->cleanupTargets($this->getDb());
64+
6165
$verified = CertificateUtils::verifyCertificates($this->getDb());
6266

6367
Logger::info("Checked %d certificate chain%s.", $verified, $verified !== 1 ? 's' : '');
6468
}
6569
}
70+
71+
protected function cleanupTargets(Connection $db)
72+
{
73+
$db->delete(
74+
'x509_target',
75+
['last_seen = ?' => new Expression('NOW() - INTERVAL 1 DAY')]
76+
);
77+
}
6678
}

library/X509/CertificateUtils.php

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Icinga\Application\Logger;
99
use Icinga\File\Storage\TemporaryLocalFileStorage;
1010
use ipl\Sql\Connection;
11+
use ipl\Sql\Expression;
1112
use ipl\Sql\Select;
1213

1314
class CertificateUtils
@@ -244,7 +245,8 @@ public static function findOrInsertCert(Connection $db, $cert)
244245
'valid_to' => $certInfo['validTo_time_t'],
245246
'fingerprint' => $dbTool->marshalBinary($fingerprint),
246247
'serial' => $dbTool->marshalBinary(gmp_export($certInfo['serialNumber'])),
247-
'certificate' => $dbTool->marshalBinary($der)
248+
'certificate' => $dbTool->marshalBinary($der),
249+
'last_seen' => new Expression('NOW()')
248250
]
249251
);
250252

@@ -353,6 +355,26 @@ private static function findOrInsertDn($db, $certInfo, $type)
353355
return $hash;
354356
}
355357

358+
public static function cleanupCertificates(Connection $db)
359+
{
360+
$db->delete(
361+
'x509_certificate',
362+
['last_seen = ?' => new Expression('NOW() - INTERVAL 7 DAY')]
363+
);
364+
365+
$db->delete(
366+
'x509_dn',
367+
['last_seen' => new Expression('NOW() - INTERVAL 7 DAY')]
368+
);
369+
370+
// DELETE
371+
//FROM x509_dn
372+
//WHERE type='subject' AND HASH <> ALL (
373+
// SELECT DISTINCT subject_hash
374+
//FROM x509_certificate
375+
//);
376+
}
377+
356378
/**
357379
* Verify certificates
358380
*
@@ -405,7 +427,7 @@ public static function verifyCertificates(Connection $db)
405427
$certs = $db->select(
406428
(new Select())
407429
->from('x509_certificate c')
408-
->columns('c.certificate')
430+
->columns(['c.certificate', 'c.id'])
409431
->join('x509_certificate_chain_link ccl', 'ccl.certificate_id = c.id')
410432
->where(['ccl.certificate_chain_id = ?' => $chain->id])
411433
->orderBy(['ccl.order' => 'DESC'])
@@ -414,6 +436,11 @@ public static function verifyCertificates(Connection $db)
414436
$collection = [];
415437

416438
foreach ($certs as $cert) {
439+
$db->update(
440+
'x509_certificate',
441+
['last_seen' => new Expression('NOW()')],
442+
['id = ?' => $chain->id]
443+
);
417444
$collection[] = CertificateUtils::der2pem(DbTool::unmarshalBinary($cert->certificate));
418445
}
419446

library/X509/Job.php

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ private static function numberToAddr($num, $ipv6 = true)
8585
}
8686
}
8787

88-
private static function generateTargets(ConfigObject $jobDescription, array $hostnamesConfig)
88+
private function generateTargets(ConfigObject $jobDescription, array $hostnamesConfig)
8989
{
9090
foreach (StringHelper::trimSplit($jobDescription->get('cidrs')) as $cidr) {
9191
$pieces = explode('/', $cidr);
@@ -124,6 +124,17 @@ private static function generateTargets(ConfigObject $jobDescription, array $hos
124124
foreach (range($start_port, $end_port) as $port) {
125125
$hostnames = isset($hostnamesConfig[$ip]) ? $hostnamesConfig[$ip] : [];
126126

127+
if (! empty($hostnames)) {
128+
$this->db->delete(
129+
'x509_target',
130+
[
131+
'ip = ?' => $this->dbTool->marshalBinary(static::binary($ip)),
132+
'port = ?' => $port,
133+
'hostname NOT IN (?)' => array_values($hostnames)
134+
]
135+
);
136+
}
137+
127138
if (empty($hostnames)) {
128139
$hostnames[] = null;
129140
}
@@ -133,6 +144,8 @@ private static function generateTargets(ConfigObject $jobDescription, array $hos
133144
$target->ip = $ip;
134145
$target->port = $port;
135146
$target->hostname = $hostname;
147+
148+
$this->updateLastScan($target);
136149
yield $target;
137150
}
138151
}
@@ -243,6 +256,22 @@ function (\Exception $exception) use ($target, $streamCapture) {
243256
});
244257
}
245258

259+
protected function updateLastScan($target)
260+
{
261+
if (isset($target->id)) {
262+
$filter = ['id = ?' => $target->id];
263+
} else {
264+
$filter = [
265+
'ip = ?' => $this->dbTool->marshalBinary(static::binary($target->ip)),
266+
'port = ?' => $target->port,
267+
'hostname = ?' => $target->hostname
268+
];
269+
}
270+
271+
$now = new Expression('NOW()');
272+
$this->db->update('x509_target', ['last_scan' => $now], $filter);
273+
}
274+
246275
public function getJobId()
247276
{
248277
return $this->jobId;
@@ -252,13 +281,13 @@ public function run()
252281
{
253282
$this->loop = Factory::create();
254283

255-
$this->totalTargets = iterator_count(static::generateTargets($this->jobDescription, $this->snimap));
284+
$this->totalTargets = iterator_count($this->generateTargets($this->jobDescription, $this->snimap));
256285

257286
if ($this->totalTargets == 0) {
258287
return null;
259288
}
260289

261-
$this->targets = static::generateTargets($this->jobDescription, $this->snimap);
290+
$this->targets = $this->generateTargets($this->jobDescription, $this->snimap);
262291

263292
$this->db->insert(
264293
'x509_job_run',
@@ -309,7 +338,8 @@ protected function processChain($target, $chain)
309338
[
310339
'ip' => $this->dbTool->marshalBinary(static::binary($target->ip)),
311340
'port' => $target->port,
312-
'hostname' => $target->hostname
341+
'hostname' => $target->hostname,
342+
'last_scan' => new Expression('NOW()')
313343
]
314344
);
315345
$targetId = $this->db->lastInsertId();
@@ -369,6 +399,12 @@ protected function processChain($target, $chain)
369399

370400
$certId = CertificateUtils::findOrInsertCert($this->db, $cert, $certInfo);
371401

402+
$this->db->update(
403+
'x509_certificate',
404+
['last_seen' => new Expression('NOW()')],
405+
['id = ?' => $certId]
406+
);
407+
372408
$this->db->insert(
373409
'x509_certificate_chain_link',
374410
[
@@ -382,7 +418,10 @@ protected function processChain($target, $chain)
382418

383419
$this->db->update(
384420
'x509_target',
385-
['latest_certificate_chain_id' => $chainId],
421+
[
422+
'latest_certificate_chain_id' => $chainId,
423+
'last_seen' => new Expression('NOW()')
424+
],
386425
['id = ?' => $targetId]
387426
);
388427
});

0 commit comments

Comments
 (0)