From 630d6b7936d689271f837d73e0e11617a8ad26d4 Mon Sep 17 00:00:00 2001
From: Robbert Rijkse <42551307+sestary@users.noreply.github.com>
Date: Mon, 19 Dec 2022 07:01:04 -0500
Subject: [PATCH] dns/bind: revamp logging (#3223)
---
dns/bind/pkg-descr | 1 +
.../OPNsense/Bind/LogsController.php | 46 +++++
.../app/models/OPNsense/Bind/Menu/Menu.xml | 8 +-
.../mvc/app/views/OPNsense/Bind/logs.volt | 173 ++++++++++++++++++
.../scripts/syslog/logformats/bind.py | 112 ++++++++++++
5 files changed, 337 insertions(+), 3 deletions(-)
create mode 100644 dns/bind/src/opnsense/mvc/app/controllers/OPNsense/Bind/LogsController.php
create mode 100644 dns/bind/src/opnsense/mvc/app/views/OPNsense/Bind/logs.volt
create mode 100644 dns/bind/src/opnsense/scripts/syslog/logformats/bind.py
diff --git a/dns/bind/pkg-descr b/dns/bind/pkg-descr
index 4091c536b..65e8d0fe2 100644
--- a/dns/bind/pkg-descr
+++ b/dns/bind/pkg-descr
@@ -11,6 +11,7 @@ Plugin Changelog
1.25
+* Revamp the logging page with proper columns (contributed by Robbert Rijkse)
* Update base to BIND 9.18
1.24
diff --git a/dns/bind/src/opnsense/mvc/app/controllers/OPNsense/Bind/LogsController.php b/dns/bind/src/opnsense/mvc/app/controllers/OPNsense/Bind/LogsController.php
new file mode 100644
index 000000000..23fde619e
--- /dev/null
+++ b/dns/bind/src/opnsense/mvc/app/controllers/OPNsense/Bind/LogsController.php
@@ -0,0 +1,46 @@
+view->pick('OPNsense/Bind/logs');
+ }
+}
diff --git a/dns/bind/src/opnsense/mvc/app/models/OPNsense/Bind/Menu/Menu.xml b/dns/bind/src/opnsense/mvc/app/models/OPNsense/Bind/Menu/Menu.xml
index 13b24d1e0..5ff8fe460 100644
--- a/dns/bind/src/opnsense/mvc/app/models/OPNsense/Bind/Menu/Menu.xml
+++ b/dns/bind/src/opnsense/mvc/app/models/OPNsense/Bind/Menu/Menu.xml
@@ -2,9 +2,11 @@
-
-
-
+
+
+
+
+
diff --git a/dns/bind/src/opnsense/mvc/app/views/OPNsense/Bind/logs.volt b/dns/bind/src/opnsense/mvc/app/views/OPNsense/Bind/logs.volt
new file mode 100644
index 000000000..33f044215
--- /dev/null
+++ b/dns/bind/src/opnsense/mvc/app/views/OPNsense/Bind/logs.volt
@@ -0,0 +1,173 @@
+{#
+ # Copyright (c) 2022 Robbert Rijkse
+ # Copyright (c) 2019 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.
+ #}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ | {{ lang._('Date') }} |
+ {{ lang._('Type') }} |
+ {{ lang._('Level')}} |
+ {{ lang._('Line') }} |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ | {{ lang._('Date') }} |
+ {{ lang._('Client') }} |
+ {{ lang._('IP Address') }} |
+ {{ lang._('Record') }} |
+ {{ lang._('Query') }} |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ | {{ lang._('Date') }} |
+ {{ lang._('Client') }} |
+ {{ lang._('IP Address') }} |
+ {{ lang._('Record') }} |
+ {{ lang._('Query') }} |
+
+
+
+
+
+
+
+
+
+
diff --git a/dns/bind/src/opnsense/scripts/syslog/logformats/bind.py b/dns/bind/src/opnsense/scripts/syslog/logformats/bind.py
new file mode 100644
index 000000000..c4ef34892
--- /dev/null
+++ b/dns/bind/src/opnsense/scripts/syslog/logformats/bind.py
@@ -0,0 +1,112 @@
+"""
+ Copyright (c) 2022 Robbert Rijkse
+ 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.
+"""
+import datetime
+import re
+from . import NewBaseLogFormat
+
+class BindGeneralLogFormat(NewBaseLogFormat):
+ def __init__(self, filename):
+ super().__init__(filename)
+ self._priority = 1
+ self._parts = list()
+
+ def match(self, line):
+ return self._filename.find('named/named.log') > -1
+
+ def set_line(self, line):
+ super().set_line(line)
+ self._parts = self._line.split(maxsplit=4)
+
+ @property
+ def timestamp(self):
+ # bind format return actual log data
+ ts = datetime.datetime.strptime(f"{self._parts[0]} {self._parts[1]}", "%d-%b-%Y %H:%M:%S.%f")
+ return ts.isoformat()
+
+ @property
+ def severity(self):
+ # Grab the log level
+ severity = self._parts[3].strip(":")
+ options = {
+ "critical": 2,
+ "error": 3,
+ "warning": 4,
+ "notice": 5,
+ "info": 6,
+ "debug": 7,
+ "dynamic": 7
+ }
+ if severity in options:
+ return options[severity]
+ return None
+
+ @property
+ def process_name(self):
+ # Grab the type of log message
+ return self._parts[2].strip(":")
+
+ @property
+ def line(self):
+ # Only grab the left over message
+ return self._parts[4].strip()
+
+class BindQueryLogFormat(NewBaseLogFormat):
+ def __init__(self, filename):
+ super().__init__(filename)
+ self._priority = 1
+ self._parts = list()
+
+ def match(self, line):
+ return self._filename.find('named/query.log') > -1 or self._filename.find('named/rpz.log') > -1
+
+ def set_line(self, line):
+ super().set_line(line)
+ self._parts = self._line.split(maxsplit=7)
+
+ @property
+ def timestamp(self):
+ # bind format return actual log data
+ ts = datetime.datetime.strptime(f"{self._parts[0]} {self._parts[1]}", "%d-%b-%Y %H:%M:%S.%f")
+ return ts.isoformat()
+
+ @property
+ def pid(self):
+ # Grab the IP and Port number of the client
+ # pid is used for this because you can't define custom names
+ return self._parts[4].strip()
+
+ @property
+ def facility(self):
+ # Grab the record the query was for
+ # facility is used for this because you can't define custom names
+ return self._parts[5].strip()[1:-2]
+
+ @property
+ def process_name(self):
+ # Grab the client memory ID
+ # process_name is used for this because you can't define custom names
+ return self._parts[3].strip()
+
+ @property
+ def line(self):
+ # Only grab the left over message
+ return self._parts[7].strip()