From 22ac68bd71707ac7dd61b4edbec84dbe7ef8d691 Mon Sep 17 00:00:00 2001 From: Lukas Oyen Date: Wed, 28 Jun 2017 15:53:14 +0200 Subject: [PATCH 1/2] Bug #xxx: umc-diagnostic: new check `inconsistent_policies.py` Inspired by `inconsistent_pw_policies_posix.py` and `inconsistent_pw_policies_samba.py` by Julian Hupertz. --- .../diagnostic/plugins/inconsistent_policies.py | 184 +++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100755 management/univention-management-console-module-diagnostic/umc/python/diagnostic/plugins/inconsistent_policies.py diff --git a/management/univention-management-console-module-diagnostic/umc/python/diagnostic/plugins/inconsistent_policies.py b/management/univention-management-console-module-diagnostic/umc/python/diagnostic/plugins/inconsistent_policies.py new file mode 100755 index 0000000..9a3e615 --- /dev/null +++ b/management/univention-management-console-module-diagnostic/umc/python/diagnostic/plugins/inconsistent_policies.py @@ -0,0 +1,184 @@ +#!/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 ldap + +import univention.uldap +import univention.admin.uldap +import univention.admin.modules as udm_modules +from univention.management.console.modules.diagnostic import Warning + +from univention.lib.i18n import Translation +_ = Translation('univention-management-console-module-diagnostic').translate + +title = _('Check password policy inconsistencies') +description = _('No problems found.') + + +def fix_policies(umc_instance): + for mismatch in check_policies(): + mismatch.fix() + return run(umc_instance) + + +actions = { + 'fix_policies': fix_policies, +} + + +class PolicyMismatch(Exception): + def __init__(self, policy, mismatches): + super(PolicyMismatch, self).__init__(policy.dn) + self.policy = policy + self.mismatches = mismatches + + def __str__(self): + msg = _('In policy {name!r} (see {{udm:policies/policy}}):') + messages = [msg.format(name=self.policy.get('name'))] + empty_tmpl = _('Attribute {attr} should be empty.') + mismatch_tmpl = _('Attribute {attr} should have value {value}.') + properties = udm_modules.get(self.policy.module).property_descriptions + + for (attr, value) in self.mismatches: + template = empty_tmpl if value is None else mismatch_tmpl + attr_desc = properties.get(attr).short_description + messages.append(template.format(attr=attr_desc, value=value)) + return '\n'.join(messages) + + def module(self): + return { + 'module': 'udm', + 'flavor': 'policies/policy', + 'props': { + 'openObject': { + 'objectDN': self.policy.dn, + 'objectType': 'policies/pwhistory' + } + } + } + + def fix(self): + for (attr, value) in self.mismatches: + self.policy[attr] = value + self.policy.modify() + + +def get_samba_domain(ldap_connection, position): + module = udm_modules.get('settings/sambadomain') + udm_modules.init(ldap_connection, position, module) + for sambadomain in module.lookup(None, ldap_connection, ''): + sambadomain.open() + return sambadomain + + +def policy_used(ldap_connection, dn): + filter_expr = ldap.filter.filter_format('(univentionPolicyReference=%s)', (dn,)) + search = ldap_connection.search(filter=filter_expr, sizelimit=3, attr=['dn']) + return any(dn is not None for (dn, attr) in search) + + +def get_pw_policies(ldap_connection, position): + module = udm_modules.get('policies/pwhistory') + udm_modules.init(ldap_connection, position, module) + for policy in module.lookup(None, ldap_connection, ''): + if policy_used(ldap_connection, policy.dn): + policy.open() + yield policy + + +def to_days(unix_time_interval, default_unit='seconds'): + if unix_time_interval is None: + return None + + try: + (value, unit) = unix_time_interval + except ValueError: + (value, unit) = (unix_time_interval, default_unit) + + try: + as_int = int(value) + except ValueError: + as_int = 0 + + if unit == 'days': + return str(as_int) + elif unit == 'hours': + return str(as_int / 24) + elif unit == 'minutes': + return str(as_int / (24 * 60)) + return str(as_int / (24 * 60 * 60)) + + +def policy_mismatch(samba_domain, pw_policy): + def compare(policy_attr, domain_attr, convert=lambda x: x): + (policy_value, domain_value) = (pw_policy.get(policy_attr), samba_domain.get(domain_attr)) + converted_domain_value = convert(domain_value) + if policy_value != converted_domain_value: + yield (policy_attr, converted_domain_value) + + for result in compare('length', 'passwordHistory'): + yield result + for result in compare('pwLength', 'passwordLength'): + yield result + for result in compare('expiryInterval', 'maxPasswordAge', to_days): + yield result + + +def check_policies(): + (ldap_connection, position) = univention.admin.uldap.getAdminConnection() + samba_domain = get_samba_domain(ldap_connection, position) + for policy in get_pw_policies(ldap_connection, position): + mismatch = list(policy_mismatch(samba_domain, policy)) + if mismatch: + yield PolicyMismatch(policy, mismatch) + + +def run(_umc_instance): + univention.admin.modules.update() + problems = list(check_policies()) + error = _('There are inconsistencies between the Univention policies and the Samba settings.') + buttons = [{ + 'action': 'fix_policies', + 'label': _('Fix password policies'), + }] + + if problems: + ed = [error, ''] + ed.extend(str(error) for error in problems) + umc_modules = [e.module() for e in problems] + raise Warning(description='\n'.join(ed), umc_modules=umc_modules, buttons=buttons) + + +if __name__ == '__main__': + from univention.management.console.modules.diagnostic import main + main() -- 2.7.4 From 6747526fa5fda21c6304b12bc67be76663eafda8 Mon Sep 17 00:00:00 2001 From: Lukas Oyen Date: Thu, 29 Jun 2017 14:48:10 +0200 Subject: [PATCH 2/2] Bug #xxx: umc-diagnostic: new check `inconsistent_policies.py` (po) --- .../umc/python/diagnostic/de.po | 36 +++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/management/univention-management-console-module-diagnostic/umc/python/diagnostic/de.po b/management/univention-management-console-module-diagnostic/umc/python/diagnostic/de.po index c9e171e..c348a11 100644 --- a/management/univention-management-console-module-diagnostic/umc/python/diagnostic/de.po +++ b/management/univention-management-console-module-diagnostic/umc/python/diagnostic/de.po @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: univention-management-console-module-diagnostic\n" "Report-Msgid-Bugs-To: packages@univention.de\n" -"POT-Creation-Date: 2017-08-01 15:41+0200\n" +"POT-Creation-Date: 2017-08-01 16:46+0200\n" "PO-Revision-Date: \n" "Last-Translator: Univention GmbH \n" "Language-Team: Univention GmbH \n" @@ -76,6 +76,16 @@ msgstr "Alle Nameserver Einträge sind in Ordnung." msgid "All shared folder ACLs are in sync with UDM." msgstr "Alle ACL Einträge der globalen IMAP Ordner stimmen mit UDM überein." +#: umc/python/diagnostic/plugins/inconsistent_policies.py:68 +#, python-brace-format +msgid "Attribute {attr} should be empty." +msgstr "Attribut {attr} sollte nicht gesetzt sein." + +#: umc/python/diagnostic/plugins/inconsistent_policies.py:69 +#, python-brace-format +msgid "Attribute {attr} should have value {value}." +msgstr "Attribut {attr} sollte den Wert {value} haben." + #: umc/python/diagnostic/plugins/check_server_password.py:150 msgid "Authentication against the local LDAP failed with the machine password." msgstr "" @@ -163,6 +173,10 @@ msgstr "Password für das Rechnerkonto testen" msgid "Check nameserver entries on DNS zones" msgstr "Überprüfe die Nameserver Einträge der DNS Zonen" +#: umc/python/diagnostic/plugins/inconsistent_policies.py:44 +msgid "Check password policy inconsistencies" +msgstr "Überprüfe Password Richtlinien" + #: umc/python/diagnostic/plugins/check_update_sites.py:43 msgid "Check resolving repository servers" msgstr "Überprüfe DNS Auflösung der Repository Server" @@ -209,6 +223,10 @@ msgstr "" msgid "Fix machine password" msgstr "Korrigiere Password für das Rechnerkonto" +#: umc/python/diagnostic/plugins/inconsistent_policies.py:172 +msgid "Fix password policies" +msgstr "Berichtige Password Richtlinien" + #: umc/python/diagnostic/plugins/mail_acl_sync.py:316 msgid "" "Found differences in the ACLs for IMAP shared folders between UDM and IMAP." @@ -298,6 +316,10 @@ msgstr "In der Forward-Zone {name} (siehe {{{link}}}):" msgid "In mail folder {name} (see {{udm:mail/mail}}):" msgstr "Im globalen Mail Ordner {name} (siehe {{udm:mail/mail}}):" +#: umc/python/diagnostic/plugins/inconsistent_policies.py:66 +msgid "In policy {name!r} (see {{udm:policies/policy}}):" +msgstr "In der Richtlinie {name!r} (siehe {{udm:policies/policy}}):" + #: umc/python/diagnostic/plugins/check_nameservers.py:221 #, python-brace-format msgid "In reverse zone {name} (see {{{link}}}):" @@ -397,6 +419,10 @@ msgstr "Keine Prolbleme mit der UDN Replikation gefunden." msgid "No problems found with modified UCR templates" msgstr "Keine Probleme mit modifizierten UCR Vorlagen gefunden." +#: umc/python/diagnostic/plugins/inconsistent_policies.py:45 +msgid "No problems found." +msgstr "Keine Probleme gefunden." + #: umc/python/diagnostic/plugins/check_update_sites.py:44 msgid "No problems were found while resolving update respositories." msgstr "Es wurden keine Probleme beim Auflösen der Repository-Server gefunden." @@ -679,6 +705,14 @@ msgstr "" "Der SSH Host-Key des entfernten Rechners hat sich geändert (vielleicht wurde " "der Rechner neu installiert). " +#: umc/python/diagnostic/plugins/inconsistent_policies.py:169 +msgid "" +"There are inconsistencies between the Univention policies and the Samba " +"settings." +msgstr "" +"Es gibt Widersprüche in den Univention Password Richtlinien und den Samba " +"Einstellungen." + #: umc/python/diagnostic/plugins/gateway.py:28 msgid "There is no gateway configured." msgstr "Es ist kein Gateway eingerichtet." -- 2.7.4