Skip to content

Commit 409c374

Browse files
committed
ImposrtSourceHook: Select import targets using ipl/orm
1 parent c1f4666 commit 409c374

File tree

2 files changed

+95
-62
lines changed

2 files changed

+95
-62
lines changed

library/X509/ProvidedHook/HostsImportSource.php

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,37 +5,40 @@
55
namespace Icinga\Module\X509\ProvidedHook;
66

77
use Icinga\Module\X509\DbTool;
8+
use Icinga\Module\X509\Model\X509Target;
89
use ipl\Sql;
10+
use ipl\Stdlib\Filter;
911

1012
class HostsImportSource extends X509ImportSource
1113
{
1214
public function fetchData()
1315
{
14-
$targets = (new Sql\Select())
15-
->from('x509_target t')
16+
$targets = X509Target::on($this->getDb())
17+
->utilize('chain')
18+
->utilize('chain.certificate');
19+
20+
$targets
1621
->columns([
17-
'host_ip' => 't.ip',
18-
'host_name' => 't.hostname'
22+
'host_ip' => 'ip',
23+
'host_name' => 'hostname'
1924
])
20-
->join('x509_certificate_chain cc', 'cc.id = t.latest_certificate_chain_id')
21-
->join('x509_certificate_chain_link ccl', 'ccl.certificate_chain_id = cc.id')
22-
->join('x509_certificate c', 'c.id = ccl.certificate_id')
23-
->where(['ccl.order = ?' => 0])
24-
->groupBy(['t.ip', 't.hostname']);
25+
->getSelectBase()
26+
->where(new Sql\Expression('x509_target_chain_x509_certificate_chain_link.order = 0'))
27+
->groupBy(['ip', 'hostname']);
2528

26-
if ($this->getDb()->getConfig()->db === 'pgsql') {
27-
$targets->columns(['host_ports' => 'ARRAY_TO_STRING(ARRAY_AGG(DISTINCT t.port), \',\')']);
29+
if ($this->getDb() instanceof Sql\Adapter\Pgsql) {
30+
$targets->withColumns([
31+
'host_ports' => new Sql\Expression('ARRAY_TO_STRING(ARRAY_AGG(DISTINCT port), \',\')')
32+
]);
2833
} else {
29-
$targets->columns(['host_ports' => 'GROUP_CONCAT(DISTINCT t.port SEPARATOR ",")']);
34+
$targets->withColumns([
35+
'host_ports' => new Sql\Expression('GROUP_CONCAT(DISTINCT port SEPARATOR ",")')
36+
]);
3037
}
3138

3239
$results = [];
3340
$foundDupes = [];
34-
foreach ($this->getDb()->select($targets) as $target) {
35-
if ($this->getDb()->getConfig()->db === 'pgsql') {
36-
$target->host_ip = DbTool::unmarshalBinary($target->host_ip);
37-
}
38-
41+
foreach ($targets as $target) {
3942
list($ipv4, $ipv6) = $this->transformIpAddress($target->host_ip);
4043
$target->host_ip = $ipv4 ?: $ipv6;
4144
$target->host_address = $ipv4;
@@ -56,7 +59,10 @@ public function fetchData()
5659
$target->host_name_or_ip = $target->host_ip;
5760
}
5861

59-
$results[$target->host_name_or_ip] = $target;
62+
$properties = iterator_to_array($target->getIterator());
63+
unset($properties['certificate_chain']); // We don't need any relation properties anymore
64+
65+
$results[$target->host_name_or_ip] = (object) $properties;
6066
}
6167

6268
return $results;

library/X509/ProvidedHook/ServicesImportSource.php

Lines changed: 71 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4,64 +4,88 @@
44

55
namespace Icinga\Module\X509\ProvidedHook;
66

7-
use Icinga\Module\X509\DbTool;
7+
use Icinga\Module\X509\Model\X509CrtSubjAltName;
8+
use Icinga\Module\X509\Model\X509Target;
89
use ipl\Sql;
10+
use ipl\Stdlib\Filter;
911

1012
class ServicesImportSource extends X509ImportSource
1113
{
1214
public function fetchData()
1315
{
14-
$targets = (new Sql\Select())
15-
->from('x509_target t')
16+
$targets = X509Target::on($this->getDb())->with([
17+
'chain',
18+
'chain.certificate',
19+
'chain.certificate.dn',
20+
'chain.certificate.issuer',
21+
]);
22+
23+
$targets->getWith()['x509_target.chain.certificate.issuer']->setJoinTypE('LEFT');
24+
$targets
1625
->columns([
17-
'host_ip' => 't.ip',
18-
'host_name' => 't.hostname',
19-
'host_port' => 't.port',
20-
'cert_subject' => 'c.subject',
21-
'cert_issuer' => 'c.issuer',
22-
'cert_self_signed' => 'COALESCE(ci.self_signed, c.self_signed)',
23-
'cert_trusted' => 'c.trusted',
24-
'cert_valid_from' => 'c.valid_from',
25-
'cert_valid_to' => 'c.valid_to'
26+
'host_ip' => 'ip',
27+
'host_name' => 'hostname',
28+
'host_port' => 'port',
29+
'cert_subject' => 'chain.certificate.subject',
30+
'cert_issuer' => 'chain.certificate.issuer',
31+
'cert_trusted' => 'chain.certificate.trusted',
32+
'cert_valid_from' => 'chain.certificate.valid_from',
33+
'cert_valid_to' => 'chain.certificate.valid_to',
34+
'cert_self_signed' => new Sql\Expression('COALESCE(%s, %s)', [
35+
'chain.certificate.issuer.self_signed',
36+
'chain.certificate.self_signed'
37+
])
2638
])
27-
->join('x509_certificate_chain cc', 'cc.id = t.latest_certificate_chain_id')
28-
->join('x509_certificate_chain_link ccl', 'ccl.certificate_chain_id = cc.id')
29-
->join('x509_certificate c', 'c.id = ccl.certificate_id')
30-
->joinLeft('x509_certificate ci', 'ci.subject_hash = c.issuer_hash')
31-
->joinLeft('x509_dn dn', 'dn.hash = c.subject_hash')
32-
->where(['ccl.order = ?' => 0])
33-
->groupBy(['t.ip', 't.hostname', 't.port']);
34-
35-
$certAltName = (new Sql\Select())
36-
->from('x509_certificate_subject_alt_name can')
37-
->where(['can.certificate_id = c.id'])
38-
->groupBy(['can.certificate_id']);
39-
40-
if ($this->getDb()->getConfig()->db === 'pgsql') {
41-
$targets->columns([
42-
'cert_fingerprint' => 'ENCODE(c.fingerprint, \'hex\')',
43-
'cert_dn' => 'ARRAY_TO_STRING(ARRAY_AGG(CONCAT(dn.key, \'=\', dn.value)), \',\')'
44-
])
45-
->groupBy(['c.id', 'ci.id']);
46-
47-
$certAltName->columns('ARRAY_TO_STRING(ARRAY_AGG(CONCAT(can.type, \':\', can.value)), \',\')');
39+
->getSelectBase()
40+
->where(new Sql\Expression('x509_target_chain_x509_certificate_chain_link.order = 0'))
41+
->groupBy(['ip, hostname, port']);
42+
43+
$certAltName = X509CrtSubjAltName::on($this->getDb());
44+
$certAltName
45+
->getSelectBase()
46+
->where(new Sql\Expression('certificate_id = x509_target_chain_certificate.id'))
47+
->groupBy(['x509_certificate_subject_alt_name.certificate_id']);
48+
49+
if ($this->getDb() instanceof Sql\Adapter\Pgsql) {
50+
$targets
51+
->withColumns([
52+
'cert_fingerprint' => new Sql\Expression('ENCODE(%s, \'hex\')', [
53+
'chain.link.certificate.fingerprint'
54+
]),
55+
'cert_dn' => new Sql\Expression(
56+
'ARRAY_TO_STRING(ARRAY_AGG(CONCAT(%s, \'=\', %s)), \',\')',
57+
[
58+
'chain.link.certificate.dn.key',
59+
'chain.link.certificate.dn.value'
60+
]
61+
)
62+
])
63+
->getSelectBase()
64+
->groupBy(['x509_target_chain_link_certificate.id', 'x509_target_chain_link_certificate_issuer.id']);
65+
66+
$certAltName->columns([
67+
'subj_alt_name' => new Sql\Expression('ARRAY_TO_STRING(ARRAY_AGG(CONCAT(type, \':\', value)), \',\')')
68+
]);
4869
} else {
49-
$targets->columns([
50-
'cert_fingerprint' => 'HEX(c.fingerprint)',
51-
'cert_dn' => 'GROUP_CONCAT(CONCAT(dn.key, \'=\', dn.value) SEPARATOR \',\')'
70+
$targets->withColumns([
71+
'cert_fingerprint' => new Sql\Expression('HEX(%s)', ['chain.certificate.fingerprint']),
72+
'cert_dn' => new Sql\Expression(
73+
'GROUP_CONCAT(CONCAT(%s, \'=\', %s) SEPARATOR \',\')',
74+
[
75+
'chain.certificate.dn.key',
76+
'chain.certificate.dn.value'
77+
]
78+
)
5279
]);
5380

54-
$certAltName->columns('GROUP_CONCAT(CONCAT(can.type, \':\', can.value) SEPARATOR \',\')');
81+
$certAltName->columns([new Sql\Expression('GROUP_CONCAT(CONCAT(type, \':\', value) SEPARATOR \',\')')]);
5582
}
5683

57-
$targets->columns(['cert_subject_alt_name' => $certAltName]);
84+
list($select, $values) = $certAltName->dump();
85+
$targets->withColumns(['cert_subject_alt_name' => new Sql\Expression("$select", null, ...$values)]);
5886

5987
$results = [];
60-
foreach ($this->getDb()->select($targets) as $target) {
61-
if ($this->getDb()->getConfig()->db === 'pgsql') {
62-
$target->host_ip = DbTool::unmarshalBinary($target->host_ip);
63-
}
64-
88+
foreach ($targets as $target) {
6589
list($ipv4, $ipv6) = $this->transformIpAddress($target->host_ip);
6690
$target->host_ip = $ipv4 ?: $ipv6;
6791
$target->host_address = $ipv4;
@@ -74,7 +98,10 @@ public function fetchData()
7498
$target->host_port
7599
);
76100

77-
$results[$target->host_name_ip_and_port] = $target;
101+
$properties = iterator_to_array($target->getIterator());
102+
unset($properties['chain']); // We don't need any relation properties anymore
103+
104+
$results[$target->host_name_ip_and_port] = (object) $properties;
78105
}
79106

80107
return $results;

0 commit comments

Comments
 (0)