@@ -, +, @@
---
.../python/diagnostic/plugins/check_nameservers.py | 238 +++++++++++++++++++++
1 file changed, 238 insertions(+)
create mode 100755 management/univention-management-console-module-diagnostic/umc/python/diagnostic/plugins/check_nameservers.py
--- a/management/univention-management-console-module-diagnostic/umc/python/diagnostic/plugins/check_nameservers.py
+++ a/management/univention-management-console-module-diagnostic/umc/python/diagnostic/plugins/check_nameservers.py
@@ -0,0 +1,238 @@
+#!/usr/bin/python2.7
+# coding: utf-8
+#
+# Univention Management Console module:
+# System Diagnosis UMC module
+#
+# Copyright 2017 Univention GmbH
+#
+# http://www.univention.de/
+#
+# All rights reserved.
+#
+# The source code of this program is made available
+# under the terms of the GNU Affero General Public License version 3
+# (GNU AGPL V3) as published by the Free Software Foundation.
+#
+# Binary versions of this program provided by Univention to you as
+# well as other copyrighted, protected or trademarked materials like
+# Logos, graphics, fonts, specific documentations and configurations,
+# cryptographic keys etc. are subject to a license agreement between
+# you and Univention and not subject to the GNU AGPL V3.
+#
+# In the case you use this program under the terms of the GNU AGPL V3,
+# the program is provided in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public
+# License with the Debian GNU/Linux or Univention distribution in file
+# /usr/share/common-licenses/AGPL-3; if not, see
+# .
+
+import socket
+import ldap.filter
+import itertools as it
+
+import univention.admin.uldap
+import univention.admin.modules as udm_modules
+import univention.admin.objects as udm_objects
+
+import univention.config_registry
+from univention.management.console.modules.diagnostic import Warning
+
+from univention.lib.i18n import Translation
+_ = Translation('univention-management-console-module-diagnostic').translate
+
+title = _('Check nameserver entries on DNS zones')
+description = _('All nameserver entries are ok.')
+links = [{
+ 'name': 'sdb',
+ 'href': _('http://sdb.univention.de/1273'),
+ 'label': _('Univention Support Database - Bind: zone transfer failed')
+}]
+
+
+class RecordNotFound(Exception):
+ pass
+
+
+class ZoneError(Exception):
+ def __init__(self, nameserver):
+ self.nameserver = nameserver
+
+ @property
+ def zone(self):
+ return self.nameserver.zone
+
+
+class NoHostRecord(ZoneError):
+ def __str__(self):
+ msg = _('Found no host record (A/AAAA record) for nameserver {ns}.')
+ return msg.format(ns=self.nameserver.nameserver())
+
+
+class CnameAsNameServer(ZoneError):
+ def __str__(self):
+ msg = _('Found illegal alias record (CNAME record) for nameserver {ns}.')
+ return msg.format(ns=self.nameserver.nameserver())
+
+
+class Zone(object):
+ def __init__(self, udm_zone, domainname):
+ self.udm_zone = udm_zone
+ self.domainname = domainname
+
+ @property
+ def kind(self):
+ return self.udm_zone.module
+
+ @property
+ def zone(self):
+ if self.kind == 'dns/forward_zone':
+ return self.udm_zone.get('zone')
+ return self.udm_zone.get('subnet')
+
+ def base(self):
+ if self.kind == 'dns/forward_zone':
+ return self.zone
+ return '{}.in-addr.arpa'.format(self.zone)
+
+ def nameserver(self):
+ for nameserver in self.udm_zone.get('nameserver'):
+ yield NameServer(self, nameserver)
+
+ def umc_link(self):
+ text = 'udm:dns/dns'
+ link = {
+ 'module': 'udm',
+ 'flavor': 'dns/dns',
+ 'props': {
+ 'openObject': {
+ 'objectDN': self.udm_zone.dn,
+ 'objectType': self.kind,
+ }
+ }
+ }
+ return (text, link)
+
+
+class NameServer(object):
+ def __init__(self, zone, nameserver):
+ self.zone = zone
+ self._nameserver = nameserver
+
+ def is_qualified(self):
+ return self._nameserver.endswith('.')
+
+ def nameserver(self):
+ return self._nameserver.rstrip('.')
+
+ def fqdn(self):
+ if self.is_qualified():
+ return self.nameserver()
+ return '{}.{}'.format(self.nameserver(), self.zone.base())
+
+ def is_in_zone(self):
+ return not self.is_qualified() or \
+ self.nameserver().endswith(self.zone.domainname)
+
+ def _generate_splits(self, fqdn):
+ zn = fqdn
+ while True:
+ (rdn, zn) = zn.split('.', 1)
+ if rdn and zn:
+ yield (rdn, zn)
+ if '.' not in zn or zn == self.zone.domainname:
+ break
+
+ def build_filter(self):
+ template = '(&(relativeDomainName=%s)(zoneName=%s))'
+ expressions = (ldap.filter.filter_format(template, (rdn, zn))
+ for (rdn, zn) in self._generate_splits(self.fqdn()))
+ return '(|{})'.format(''.join(expressions))
+
+
+class UDM(object):
+ def __init__(self):
+ univention.admin.modules.update()
+ (self.ldap_connection, self.position) = univention.admin.uldap.getMachineConnection()
+ self.configRegistry = univention.config_registry.ConfigRegistry()
+ self.configRegistry.load()
+
+ def lookup(self, module_name, filter_expression=''):
+ module = udm_modules.get(module_name)
+ for instance in module.lookup(None, self.ldap_connection, filter_expression):
+ instance.open()
+ yield instance
+
+ def find(self, nameserver):
+ filter_expression = nameserver.build_filter()
+ for (dn, attr) in self.ldap_connection.search(filter_expression):
+ if dn:
+ for module in udm_modules.identify(dn, attr):
+ record = udm_objects.get(module, None,
+ self.ldap_connection, self.position, dn, attr=attr,
+ attributes=attr)
+ record.open()
+ return record
+ raise RecordNotFound()
+
+ def all_zones(self):
+ domainname = self.configRegistry.get('domainname')
+ for zone in self.lookup('dns/forward_zone'):
+ yield Zone(zone, domainname)
+ for zone in self.lookup('dns/reverse_zone'):
+ yield Zone(zone, domainname)
+
+ def check_zone(self, zone):
+ for nameserver in zone.nameserver():
+ try:
+ record = self.find(nameserver)
+ except RecordNotFound:
+ if not nameserver.is_in_zone():
+ try:
+ socket.getaddrinfo(nameserver.fqdn(), None)
+ except socket.gaierror:
+ yield NoHostRecord(nameserver)
+ else:
+ yield NoHostRecord(nameserver)
+
+ else:
+ if record.module == 'dns/alias':
+ yield CnameAsNameServer(nameserver)
+ elif record.module != 'dns/host_record':
+ yield NoHostRecord(nameserver)
+
+
+def find_all_zone_problems():
+ udm = UDM()
+ for zone in udm.all_zones():
+ for error in udm.check_zone(zone):
+ yield error
+
+
+def run():
+ ed = [_('Found errors in the nameserver entries of the following zones.') + ' ' +
+ _('Please refer to {sdb} for further information.')]
+ modules = list()
+ tmpl_forward = _('In forward zone {name} (see {{{link}}}):')
+ tmpl_reverse = _('In reverse zone {name} (see {{{link}}}):')
+ for (zone, group) in it.groupby(find_all_zone_problems(), lambda error: error.zone):
+ (text, link) = zone.umc_link()
+ ed.append('')
+ if zone.kind == 'dns/forward_zone':
+ ed.append(tmpl_forward.format(kind=zone.kind, name=zone.zone, link=text))
+ elif zone.kind == 'dns/reverse_zone':
+ ed.append(tmpl_reverse.format(kind=zone.kind, name=zone.zone, link=text))
+ ed.extend(str(error) for error in group)
+ modules.append(link)
+
+ if modules:
+ raise Warning(description='\n'.join(ed), umc_modules=modules)
+
+
+if __name__ == '__main__':
+ from univention.management.console.modules.diagnostic import main
+ main()
--
(po)
---
.../umc/python/diagnostic/de.po | 50 +++++++++++++++++++++-
1 file changed, 48 insertions(+), 2 deletions(-)
--- a/management/univention-management-console-module-diagnostic/umc/python/diagnostic/de.po
+++ a/management/univention-management-console-module-diagnostic/umc/python/diagnostic/de.po
@@ -2,8 +2,8 @@
msgid ""
msgstr ""
"Project-Id-Version: univention-management-console-module-diagnostic\n"
-"Report-Msgid-Bugs-To: packages@univention.de\n"
-"POT-Creation-Date: 2016-01-14 12:19+0100\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-06-22 16:36+0200\n"
"PO-Revision-Date: \n"
"Last-Translator: Univention GmbH \n"
"Language-Team: Univention GmbH \n"
@@ -27,6 +27,29 @@ msgstr ""
msgid "Adjust to suggested limits"
msgstr "An vorgeschlagene Limits anpassen"
+#: umc/python/diagnostic/plugins/check_nameservers.py:49
+msgid "All nameserver entries are ok."
+msgstr "Alle Nameserver Einträge sind in Ordnung."
+
+#: umc/python/diagnostic/plugins/check_nameservers.py:48
+msgid "Check nameserver entries on DNS zones"
+msgstr "Überprüfe die Nameserver Einträge der DNS Zonen"
+
+#: umc/python/diagnostic/plugins/check_nameservers.py:217
+msgid "Found errors in the nameserver entries of the following zones."
+msgstr ""
+"Es wurden Fehler in den Nameserver Einträgen der folgenden Zonen gefunden."
+
+#: umc/python/diagnostic/plugins/check_nameservers.py:78
+#, python-brace-format
+msgid "Found illegal alias record (CNAME record) for nameserver {ns}."
+msgstr "Ungültiger Alias-Record (CNAME record) für Namenserver {ns} gefunden."
+
+#: umc/python/diagnostic/plugins/check_nameservers.py:72
+#, python-brace-format
+msgid "Found no host record (A/AAAA record) for nameserver {ns}."
+msgstr "Kein Host-Record (A/AAAA record) für Namenserver {ns} gefunden."
+
#: umc/python/diagnostic/plugins/gateway.py:11
msgid "Gateway is not reachable"
msgstr "Gateway ist nicht erreichbar"
@@ -49,6 +72,16 @@ msgid "If these settings are correct the problem relies in the gateway itself:"
msgstr ""
"Wenn diese Einstellungen richtig sind liegt das Problem im Gateway selbst:"
+#: umc/python/diagnostic/plugins/check_nameservers.py:220
+#, python-brace-format
+msgid "In forward zone {name} (see {{{link}}}):"
+msgstr "In der Forward-Zone {name} (siehe {{{link}}}):"
+
+#: umc/python/diagnostic/plugins/check_nameservers.py:221
+#, python-brace-format
+msgid "In reverse zone {name} (see {{{link}}}):"
+msgstr "In der Reverse-Zone {name} (siehe {{{link}}}):"
+
#: umc/python/diagnostic/plugins/security_limits.py:19
#, python-brace-format
msgid ""
@@ -116,6 +149,11 @@ msgstr ""
"Bitte sicherstellen, dass die DNS-Einstellungen in {setup:network} korrekt "
"konfiguriert sind."
+#: umc/python/diagnostic/plugins/check_nameservers.py:218
+#, python-brace-format
+msgid "Please refer to {sdb} for further information."
+msgstr "Siehe {sdb} für weitere Informationen."
+
#: umc/python/diagnostic/plugins/ssh_connection.py:52
#, python-format
msgid ""
@@ -260,6 +298,14 @@ msgstr ""
"dass Authentifikations-Zugangsdaten (falls existierend) korrekt sind und die "
"ACL's des Proxy-Servers nicht verbieten, Anfragen an %s zu stellen."
+#: umc/python/diagnostic/plugins/check_nameservers.py:53
+msgid "Univention Support Database - Bind: zone transfer failed"
+msgstr ""
+
+#: umc/python/diagnostic/plugins/check_nameservers.py:52
+msgid "http://sdb.univention.de/1273"
+msgstr ""
+
#: umc/python/diagnostic/plugins/package_status.py:28
msgid "some"
msgstr "einigen"
--