System / Settings / Logging - targets: add TLS transport option

closes https://github.com/opnsense/core/issues/4937
This commit is contained in:
Ad Schellevis 2021-04-30 17:54:29 +02:00
parent d485b40096
commit 64c2e02b0b
7 changed files with 125 additions and 8 deletions

View File

@ -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')) {

View File

@ -39,6 +39,16 @@
<label>Port</label>
<type>text</type>
</field>
<field>
<id>destination.certificate</id>
<style>transport_type_tls4 transport_type_tls6 transport_type</style>
<label>Certificate</label>
<type>dropdown</type>
<help><![CDATA[Transport certificate to use, please make sure to check the general system log when experiencing issues.
Error messages can be a bit cryptic from time to time, in which case <a href="https://support.oneidentity.com/kb/263658/common-issues-of-tls-encrypted-message-transfer">this</a> is a good
resource for tracking common issues.]]>
</help>
</field>
<field>
<id>destination.description</id>
<label>Description</label>

View File

@ -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
));
}

View File

@ -22,6 +22,8 @@
<tcp4>TCP(4)</tcp4>
<udp6>UDP(6)</udp6>
<tcp6>TCP(6)</tcp6>
<tls4>TLS(4)</tls4>
<tls6>TLS(6)</tls6>
</OptionValues>
</transport>
<program type="JsonKeyValueStoreField">
@ -80,6 +82,10 @@
<hostname type="HostnameField">
<Required>Y</Required>
</hostname>
<certificate type="CertificateField">
<Required>N</Required>
<ValidationMessage>Please select a valid certificate from the list</ValidationMessage>
</certificate>
<port type="PortField">
<Required>Y</Required>
<default>514</default>

View File

@ -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();
}
});
});
});
</script>

View File

@ -0,0 +1,63 @@
#!/usr/local/bin/php
<?php
/*
* Copyright (C) 2021 Deciso B.V.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
require_once("config.inc");
require_once("certs.inc");
require_once("legacy_bindings.inc");
use OPNsense\Core\Config;
$instances = [];
$configObj = Config::getInstance()->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);
}
}

View File

@ -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 {