From 64c2e02b0b5f2af83b767db500a43762375bf5ea Mon Sep 17 00:00:00 2001 From: Ad Schellevis Date: Fri, 30 Apr 2021 17:54:29 +0200 Subject: [PATCH] System / Settings / Logging - targets: add TLS transport option closes https://github.com/opnsense/core/issues/4937 --- src/etc/inc/system.inc | 2 + .../Syslog/forms/dialogDestination.xml | 10 +++ .../mvc/app/models/OPNsense/Syslog/Syslog.php | 26 +++++--- .../mvc/app/models/OPNsense/Syslog/Syslog.xml | 6 ++ .../mvc/app/views/OPNsense/Syslog/index.volt | 11 ++++ src/opnsense/scripts/syslog/generate_certs | 63 +++++++++++++++++++ .../Syslog/syslog-ng-destinations.conf | 15 ++++- 7 files changed, 125 insertions(+), 8 deletions(-) create mode 100755 src/opnsense/scripts/syslog/generate_certs diff --git a/src/etc/inc/system.inc b/src/etc/inc/system.inc index 50ce99cea..35fcbe87f 100644 --- a/src/etc/inc/system.inc +++ b/src/etc/inc/system.inc @@ -673,6 +673,8 @@ EOD; } } + // deploy certificates (separate caller in case we ever remove clog, in which case we can move all to configd) + mwexecf("/usr/local/opnsense/scripts/syslog/generate_certs"); if (!empty($config['syslog']['disable_clog'])) { // non legacy mode if (isvalidpid('/var/run/syslog.pid')) { diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Syslog/forms/dialogDestination.xml b/src/opnsense/mvc/app/controllers/OPNsense/Syslog/forms/dialogDestination.xml index 484c9040e..36ad7bd96 100644 --- a/src/opnsense/mvc/app/controllers/OPNsense/Syslog/forms/dialogDestination.xml +++ b/src/opnsense/mvc/app/controllers/OPNsense/Syslog/forms/dialogDestination.xml @@ -39,6 +39,16 @@ text + + destination.certificate + + + dropdown + this is a good + resource for tracking common issues.]]> + + destination.description diff --git a/src/opnsense/mvc/app/models/OPNsense/Syslog/Syslog.php b/src/opnsense/mvc/app/models/OPNsense/Syslog/Syslog.php index c5f11c409..2fb911dd5 100644 --- a/src/opnsense/mvc/app/models/OPNsense/Syslog/Syslog.php +++ b/src/opnsense/mvc/app/models/OPNsense/Syslog/Syslog.php @@ -51,14 +51,26 @@ class Syslog extends BaseModel $parentNode = $node->getParentNode(); $ptagname = $parentNode->getInternalXMLTagName(); $tagname = $node->getInternalXMLTagName(); - if ($ptagname == 'destination' && in_array($tagname, array('hostname', 'transport'))) { - // protocol family check - if (in_array((string)$parentNode->transport, array('udp4', 'udp6', 'tcp4', 'tcp6'))) { - $ipproto = ((string)$parentNode->transport)[3]; - $hostproto = strpos((string)$parentNode->hostname, ":") === false ? "4" : "6"; - if (Util::isIpAddress((string)$parentNode->hostname) && $ipproto != $hostproto) { + $transport = (string)$parentNode->transport; + if ($ptagname == 'destination') { + if (in_array($tagname, array('hostname', 'transport'))) { + // protocol family check + if (in_array($transport, ['udp4', 'udp6', 'tcp4', 'tcp6', 'tls4', 'tls6'])) { + $ipproto = ((string)$parentNode->transport)[3]; + $hostproto = strpos((string)$parentNode->hostname, ":") === false ? "4" : "6"; + if (Util::isIpAddress((string)$parentNode->hostname) && $ipproto != $hostproto) { + $messages->appendMessage(new Message( + gettext("Transport protocol does not match address in hostname"), + $key + )); + } + } + } + if (in_array($tagname, ['certificate', 'transport']) && in_array($transport, ['tls4', 'tls6'])) { + // certificate availability + if (empty((string)$parentNode->certificate)) { $messages->appendMessage(new Message( - gettext("Transport protocol does not match address in hostname"), + gettext("A certificate is required for tls types"), $key )); } diff --git a/src/opnsense/mvc/app/models/OPNsense/Syslog/Syslog.xml b/src/opnsense/mvc/app/models/OPNsense/Syslog/Syslog.xml index d2362c0cf..6ed227d99 100644 --- a/src/opnsense/mvc/app/models/OPNsense/Syslog/Syslog.xml +++ b/src/opnsense/mvc/app/models/OPNsense/Syslog/Syslog.xml @@ -22,6 +22,8 @@ TCP(4) UDP(6) TCP(6) + TLS(4) + TLS(6) @@ -80,6 +82,10 @@ Y + + N + Please select a valid certificate from the list + Y 514 diff --git a/src/opnsense/mvc/app/views/OPNsense/Syslog/index.volt b/src/opnsense/mvc/app/views/OPNsense/Syslog/index.volt index ee5fa2ac4..5f80efa2e 100644 --- a/src/opnsense/mvc/app/views/OPNsense/Syslog/index.volt +++ b/src/opnsense/mvc/app/views/OPNsense/Syslog/index.volt @@ -48,6 +48,17 @@ */ $("#reconfigureAct").SimpleActionButton(); updateServiceControlUI('syslog'); + + $("#destination\\.transport").change(function(){ + let transport_type = $(this).val(); + $(".transport_type").each(function(){ + if ($(this).hasClass("transport_type_" + transport_type)) { + $(this).closest("tr").show(); + } else { + $(this).closest("tr").hide(); + } + }); + }); }); diff --git a/src/opnsense/scripts/syslog/generate_certs b/src/opnsense/scripts/syslog/generate_certs new file mode 100755 index 000000000..ac8730ce2 --- /dev/null +++ b/src/opnsense/scripts/syslog/generate_certs @@ -0,0 +1,63 @@ +#!/usr/local/bin/php +object(); +@mkdir("/usr/local/etc/syslog-ng/cert.d", 0700, true); +foreach ((new OPNsense\Syslog\Syslog())->destinations->destination->iterateItems() as $id => $item) { + if (in_array($item->transport, ['tls4', 'tls6']) && !empty($configObj->cert) && (string)$item->enabled == "1"){ + $dest_key = str_replace("-", "", $id); + $instances[] = $dest_key; + $cert_refid = (string)$item->certificate; + foreach ($configObj->cert as $cert) { + if ($cert_refid == (string)$cert->refid) { + file_put_contents("/usr/local/etc/syslog-ng/cert.d/{$dest_key}.key", base64_decode((string)$cert->prv)); + file_put_contents("/usr/local/etc/syslog-ng/cert.d/{$dest_key}.crt", base64_decode((string)$cert->crt)); + $cert = (array)$cert; + $ca = ca_chain($cert); + file_put_contents("/usr/local/etc/syslog-ng/cert.d/{$dest_key}.ca", (string)$ca); + } + } + } +} + +// cleanup old/unused certs +foreach (glob("/usr/local/etc/syslog-ng/cert.d/*") as $filename) { + $instance = explode(".", basename($filename))[0]; + $ext = pathinfo($filename)['extension']; + if (!in_array($instance, $instances) && in_array($ext, ['crt', 'key', 'ca'])) { + unlink($filename); + } +} diff --git a/src/opnsense/service/templates/OPNsense/Syslog/syslog-ng-destinations.conf b/src/opnsense/service/templates/OPNsense/Syslog/syslog-ng-destinations.conf index 047d176db..5c0c8569f 100644 --- a/src/opnsense/service/templates/OPNsense/Syslog/syslog-ng-destinations.conf +++ b/src/opnsense/service/templates/OPNsense/Syslog/syslog-ng-destinations.conf @@ -30,7 +30,20 @@ destination d_{{dest_key}} { ip-protocol({{destination.transport[3]}}) persist-name("{{dest_key}}") ); -{% endif %} +{% elif destination.transport in ['tls4', 'tls6'] %} + network( + "{{destination.hostname}}" + transport("tls") + port({{destination.port}}) + ip-protocol({{destination.transport[3]}}) + persist-name("{{dest_key}}") + tls( + ca-file("/usr/local/etc/syslog-ng/cert.d/{{dest_key}}.ca") + key-file("/usr/local/etc/syslog-ng/cert.d/{{dest_key}}.key") + cert-file("/usr/local/etc/syslog-ng/cert.d/{{dest_key}}.crt") + ) + ); +{% endif %} }; log {