def run(_umc_instance): if not util.is_service_active('IMAP'): return configRegistry = univention.config_registry.ConfigRegistry() configRegistry.load() if configRegistry.is_true('mail/dovecot'): acl_class = DovecotACL else: return differences = list(all_differences(acl_class)) ed = [ _('Found differences in the ACLs for IMAP shared folders between UDM and IMAP.' ) + ' ' + _('This is not necessarily a problem, if the the ACL got changed via IMAP.' ) ] modules = list() for (folder, group) in it.groupby(differences, lambda x: x[0]): name = folder.common_name ed.append('') ed.append( _('In mail folder {name} (see {{udm:mail/mail}}):').format( name=name)) ed.extend(str(error) for (_, error) in group) modules.append(udm_mail_link(folder)) if modules: MODULE.error('\n'.join(ed)) raise Warning(description='\n'.join(ed), umc_modules=modules)
def run(_umc_instance): high = high_disk_usage() tmpl = _('- Disk for mountpoint %(mp)s is %(pc)s%% full.') disk_errors = [tmpl % {'mp': mp, 'pc': pc} for (mp, pc) in high.items()] problem_on_root = '/' in high problem_on_varlog = '/var/log' in high or '/var' in high or \ (problem_on_root and not is_varlog_own_partition()) if disk_errors: umc_modules = [{'module': 'appcenter', 'flavor': 'appcenter'}] error_descriptions = [_('Some disks are nearly full:')] error_descriptions.extend(disk_errors) if problem_on_root: error_descriptions.append('\n'.join(solutions())) if problem_on_varlog and high_log_levels(): lvl_errors = (_('You have configured some high log levels.'), _('You may want to reset them via {ucr}.')) umc_modules.append({'module': 'ucr'}) error_descriptions.append(' '.join(lvl_errors)) if problem_on_root: MODULE.error('\n'.join(error_descriptions)) raise Critical('\n'.join(error_descriptions), umc_modules=umc_modules) raise Warning('\n'.join(error_descriptions), umc_modules=umc_modules)
def run(_umc_instance): ucr.load() failed = [] fqdn = ".".join((ucr['hostname'], ucr['domainname'])) hostnames = { 'www.univention.de': ('dns/forwarder1', 'dns/forwarder2', 'dns/forwarder3'), fqdn: ('nameserver1', 'nameserver2', 'nameserver3') } for hostname, nameservers in hostnames.items(): for nameserver in nameservers: if not ucr.get(nameserver): continue MODULE.process("Trying %s to resolve %s" % (ucr[nameserver], hostname)) MODULE.process("Similar to running: dig +short %s @%s" % (hostname, ucr[nameserver])) try: query_dns_server(ucr[nameserver], hostname) except DNSException as exc: msgs = ['\n', _('The nameserver %(nameserver)s (UCR variable %(var)r) is not responsive:') % {'nameserver': ucr[nameserver], 'var': nameserver}] if isinstance(exc, Timeout): msgs.append(_('A timeout occurred while reaching the nameserver (is it online?).')) else: msgs.append('%s' % (exc,)) failed.append('\n'.join(msgs)) if failed: MODULE.error('%s%s' % (description % (len(failed),), '\n'.join(failed))) raise Warning('%s%s' % (description % (len(failed),), '\n'.join(failed)))
def get_s4_connector(configbasename='connector'): configRegistry = univention.config_registry.ConfigRegistry() configRegistry.load() if '%s/s4/ldap/certificate' % configbasename not in configRegistry or True: if configRegistry.is_true('%s/s4/ldap/ssl' % configbasename): MODULE.error('Missing Configuration Key %s/s4/ldap/certificate' % configbasename) raise MissingConfigurationKey('%s/s4/ldap/certificate' % configbasename) if configRegistry.get('%s/s4/ldap/bindpw' % configbasename): with open(configRegistry['%s/s4/ldap/bindpw' % configbasename]) as fob: s4_ldap_bindpw = fob.read().rstrip('\n') else: s4_ldap_bindpw = None try: s4 = univention.s4connector.s4.s4( configbasename, load_mapping(configbasename), configRegistry, configRegistry['%s/s4/ldap/host' % configbasename], configRegistry['%s/s4/ldap/port' % configbasename], configRegistry['%s/s4/ldap/base' % configbasename], configRegistry.get('%s/s4/ldap/binddn' % configbasename), s4_ldap_bindpw, configRegistry['%s/s4/ldap/certificate' % configbasename], configRegistry['%s/s4/listener/dir' % configbasename], False) except KeyError as error: MODULE.error('Missing Configuration key %s' % error.message) raise MissingConfigurationKey(error.message) else: return s4
def run(_umc_instance): if util.is_service_active('LDAP'): ucr.load() if not ucr.is_true('ldap/overlay/memberof'): MODULE.error(warning_message) raise Warning(description=warning_message) return
def run(_umc_instance, rerun=False, fix_log=''): if not util.is_service_active('Samba 4'): return error_descriptions = list() if rerun and fix_log: error_descriptions.append(fix_log) buttons = [{ 'action': 'run_samba_tool_dbcheck_fix', 'label': _('Run `samba-tool dbcheck --fix --cross-ncs --yes`'), }] cmd = ['samba-tool', 'dbcheck'] (success, output) = util.run_with_output(cmd) if [x for x in output.split('\n') if x.startswith("ERROR:")]: error = _( '`samba-tool dbcheck` found an error in the local AD database.') error_descriptions.append(error) error_descriptions.append(output) if not rerun: fix = _('You can run `samba-tool dbcheck --fix` to fix the issue.') error_descriptions.append(fix) raise Critical(description='\n'.join(error_descriptions), buttons=buttons) if rerun: fixed = _( '`samba-tool dbcheck` found no errors in the local AD database.') error_descriptions.append(fixed) MODULE.error('\n'.join(error_descriptions)) raise ProblemFixed(description='\n'.join(error_descriptions))
def test_service_provider_certificate(): # compare /etc/univention/ssl/$(hostname -f)/cert.pem with # univention-ldapsearch -LLL "(&(serviceProviderMetadata=*)(univentionObjectType=saml/serviceprovider)(SAMLServiceProviderIdentifier=https://$(hostname -f)/univention/saml/metadata))" serviceProviderMetadata | ldapsearch-wrapper | ldapsearch-decode64 # If it fails: /usr/share/univention-management-console/saml/update_metadata # # fails because https://help.univention.com/t/renewing-the-ssl-certificates/37 was not used. https://help.univention.com/t/renewing-the-complete-ssl-certificate-chain/36 lo = univention.uldap.getMachineConnection() certs = lo.search(filter_format( '(&(serviceProviderMetadata=*)(univentionObjectType=saml/serviceprovider)(SAMLServiceProviderIdentifier=https://%s/univention/saml/metadata))', ['%s.%s' % (ucr.get('hostname'), ucr.get('domainname'))]), attr=['serviceProviderMetadata']) MODULE.process( "Checking certificates of /etc/univention/ssl/%s.%s/cert.pem" % (ucr.get('hostname'), ucr.get('domainname'))) with open('/etc/univention/ssl/%s.%s/cert.pem' % (ucr.get('hostname'), ucr.get('domainname'))) as fd: for cert in certs: cert = find_node( fromstring( cert[1]['serviceProviderMetadata'][0].decode('UTF-8')), '{http://www.w3.org/2000/09/xmldsig#}X509Certificate') if cert.text.strip() not in fd.read(): MODULE.error( 'The certificate of the SAML service provider does not match.' ) raise Critical( _('The certificate of the SAML service provider does not match.' ))
def run(_umc_instance): configRegistry = univention.config_registry.ConfigRegistry() configRegistry.load() all_certificates = certificates(configRegistry) is_local_check = configRegistry.get('server/role') in \ ('domaincontroller_master', 'domaincontroller_backup') if is_local_check: cert_verify = list(verify_local(all_certificates)) else: cert_verify = list( verify_from_master(configRegistry.get('ldap/master'), all_certificates)) error_descriptions = [ str(error) for error in cert_verify if isinstance(error, CertificateWarning) ] if error_descriptions: error_descriptions.append( _('Please see {sdb} on how to renew certificates.')) if any(isinstance(error, CertificateError) for error in cert_verify): raise Critical(description='\n'.join(error_descriptions)) MODULE.error('\n'.join(error_descriptions)) raise Warning(description='\n'.join(error_descriptions))
def run(_umc_instance): error_descriptions = [_('The following FQDNs were not resolvable:')] unresolvable = list(unresolvable_repositories()) if unresolvable: error_descriptions.extend(unresolvable) error_descriptions.append(_('Please see {sdb} for troubleshooting DNS problems.')) MODULE.error('\n'.join(error_descriptions)) raise Warning(description='\n'.join(error_descriptions))
def run(_umc_instance): if not util.is_service_active('S4 Connector'): return check_errors = list(check_existence_and_consistency()) if check_errors: MODULE.error('\n'.join(str(x) for x in check_errors)) raise Warning(description='\n'.join(str(x) for x in check_errors))
def run(_umc_instance, retest=False): configRegistry = univention.config_registry.ConfigRegistry() configRegistry.load() error_descriptions = list() buttons = [{ 'action': 'fix_machine_password', 'label': _('Fix machine password'), }] is_master = configRegistry.get('server/role') == 'domaincontroller_master' if not is_master and not check_machine_password(master=False): error = _( 'Authentication against the local LDAP failed with the machine password.' ) error_descriptions.append(error) if not check_machine_password(master=True): error = _( 'Authentication against the master LDAP failed with the machine password.' ) error_descriptions.append(error) password_change = configRegistry.is_true('server/password/change', True) try: change_interval = int( configRegistry.get('server/password/interval', '21')) except TypeError: change_interval = 21 error_change = _( 'Note that password rotation is disabled via the UCR variable server/password/change.' ) error_interval = _('Note that server/password/interval is set to {}.') if error_descriptions: note_sdb = _( 'See {sdb} for information on manual server password change.') error_descriptions.append(note_sdb) if not password_change: error_descriptions.append(error_change) buttons.append({ 'action': 'reset_password_change', 'label': _('Set server/password/change=True'), }) if change_interval < 1: error_descriptions.append(error_interval.format(change_interval)) buttons.append({ 'action': 'reset_password_interval', 'label': _('Set server/password/interval=21'), }) MODULE.error('\n'.join(error_descriptions)) raise Critical(description=' '.join(error_descriptions), buttons=buttons) if retest: raise ProblemFixed(buttons=[])
def run(_umc_instance): hostnames = list(non_compliant_hostnames()) if hostnames: invalid = _('The following non-compliant hostnames have been found: {hostnames}.') problem = _('This may lead to DNS problems.') specification = _('Please refer to {rfc1123} for the syntax of host names.') description = [invalid.format(hostnames=', '.join(hostnames)), problem, specification] MODULE.error('\n'.join(description)) raise Warning(description='\n'.join(description))
def migrate_users(_umc_instance): process = Popen(['/usr/share/univention-directory-manager-tools/univention-migrate-users-to-ucs4.3'], stderr=STDOUT, stdout=PIPE) stdout, stderr = process.communicate() if process.returncode: MODULE.error('Error running univention-migrate-users-to-ucs4.3:\n%s' % (stdout,)) raise Critical(_('The migration failed: %s') % (stdout,)) else: MODULE.process('Output of univention-migrate-users-to-ucs4.3:\n%s' % (stdout,)) raise ProblemFixed(buttons=[])
def run(_umc_instance): ucr.load() gateway = ucr.get('gateway') if not gateway: MODULE.error('There is no gateway configured.') raise Critical(_('There is no gateway configured.')) process = Popen(['/bin/ping', '-c3', '-w4', '-W4', gateway], stdout=PIPE, stderr=STDOUT) stdout, stderr = process.communicate() if process.returncode: MODULE.error('\n'.join(description)) raise Critical('\n'.join([description % (gateway,), '', stdout]))
def get_s4_connector(configbasename='connector'): configRegistry = univention.config_registry.ConfigRegistry() configRegistry.load() try: s4 = univention.s4connector.s4.s4.main(configRegistry, configbasename) except SystemExit as error: MODULE.error('Missing Configuration key %s' % (error, )) raise MissingConfigurationKey(error.code) else: s4.init_ldap_connections() return s4
def migrate_users(_umc_instance): process = Popen([SCRIPT], stderr=STDOUT, stdout=PIPE) stdout, stderr = process.communicate() stdout = stdout.decode('UTF-8', 'replace') if process.returncode: MODULE.error('Error running univention-migrate-users-to-ucs4.3:\n%s' % (stdout, )) raise Critical(_('The migration failed: %s') % (stdout, )) else: MODULE.process('Output of univention-migrate-users-to-ucs4.3:\n%s' % (stdout, )) raise ProblemFixed(buttons=[])
def run(_umc_instance): process = Popen(['univention-check-join-status'], stdout=PIPE, stderr=STDOUT) (stdout, stderr) = process.communicate() if process.returncode != 0: errors = [_('"univention-check-join-status" returned a problem with the domain join.')] if stdout: errors.append("\nSTDOUT:\n{}".format(stdout.decode('UTF-8', 'replace'))) if stderr: errors.append("\nSTDERR:\n{}".format(stderr.decode('UTF-8', 'replace'))) errors.append(_('See {erroranalysis} or run the join-scripts via {join}.')) MODULE.error('\n'.join(errors)) raise Critical(description='\n'.join(errors))
def nsupdate(server, domainname): process = subprocess.Popen(('nsupdate', '-g', '-t', '15'), stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) cmd_template = 'server {server}\nprereq yxdomain {domain}\nsend\nquit\n' cmd = cmd_template.format(server=server, domain=domainname) MODULE.process("Running: 'echo %s | nsupdate -g -t 15'" % (cmd, )) process.communicate(cmd) if process.poll() != 0: MODULE.error('NS Update Error at %s %s' % (server, domainname)) raise NSUpdateError(server, domainname)
def run(_umc_instance): if ucr.get('server/role') != 'domaincontroller_master': return process = Popen([SCRIPT, '--check'], stderr=STDOUT, stdout=PIPE) stdout, stderr = process.communicate() stdout = stdout.decode('UTF-8', 'replace') if process.returncode: MODULE.error(description + stdout) raise Critical(description + stdout, buttons=[{ 'action': 'migrate_users', 'label': _('Migrate user objects'), }])
def run(_umc_instance): cmd = ['univention-check-templates'] try: subprocess.check_output(cmd) except subprocess.CalledProcessError as error: error_description = [ _('Errors found by `univention-check-templates`.'), _('The following UCR files are modified locally.'), _('Updated versions will be named FILENAME.dpkg-*.'), _('The files should be checked for differences.'), ] if error.output: MODULE.error('\n'.join(error_description)) error_description.extend(('\n\n', error.output)) raise Warning(' '.join(error_description))
def run(_umc_instance): if not util.is_service_active('S4 Connector'): return try: import univention.s4connector import univention.s4connector.s4 except ImportError: error_description = _('Univention S4 Connector is not installed.') raise Critical(description=error_description) try: s4 = get_s4_connector() except MissingConfigurationKey as error: error_description = _( 'The UCR variable {variable!r} is unset, but necessary for the S4 Connector.' ) MODULE.error(error_description.format(variable=error.message)) raise Critical(description=error_description.format( variable=error.message)) ucs_rejects = list(get_ucs_rejected(s4)) s4_rejects = list(get_s4_rejected(s4)) if ucs_rejects or s4_rejects: error_description = _( 'Found {ucs} UCS rejects and {s4} S4 rejects. See {{sdb}} for more information.' ) error_description = error_description.format(ucs=len(ucs_rejects), s4=len(s4_rejects)) error_descriptions = [error_description] if ucs_rejects: error_descriptions.append(_('UCS rejected:')) for (filename, ucs_dn, s4_dn) in ucs_rejects: s4_dn = s4_dn if s4_dn else _('not found') line = _('UCS DN: {ucs}, S4 DN: {s4}, Filename: {fn}') line = line.format(ucs=ucs_dn, s4=s4_dn, fn=filename) error_descriptions.append(line) if s4_rejects: error_descriptions.append(_('S4 rejected:')) for (_s4_id, s4_dn, ucs_dn) in s4_rejects: ucs_dn = ucs_dn if ucs_dn else _('not found') line = _('S4 DN: {s4}, UCS DN: {ucs}') line = line.format(s4=s4_dn, ucs=ucs_dn) error_descriptions.append(line) MODULE.error('\n'.join(error_descriptions)) raise Warning(description='\n'.join(error_descriptions))
def run_samba_tool_ntacl_sysvolreset(umc_instance): if not util.is_service_active('Samba 4'): return cmd = ['samba-tool', 'ntacl', 'sysvolreset'] (success, output) = util.run_with_output(cmd) cmd_string = ' '.join(cmd) if success: fix_log = [_('`{cmd}` succeeded.').format(cmd=cmd_string)] MODULE.process('Output of %s:\n%s' % (cmd_string, output)) else: fix_log = [_('`{cmd}` failed.').format(cmd=cmd_string)] MODULE.error('Error running %s:\n%s' % (cmd_string, output)) fix_log.append(output.decode('utf-8', 'replace')) run(umc_instance, rerun=True, fix_log='\n'.join(fix_log))
def run(_umc_instance): if ucr.get('server/role') != 'domaincontroller_master': return unregistered = [] for fname in sorted(SCHEMA_FILES): if not os.path.exists(fname): continue if not udm_schema_obj_exists(fname): unregistered.append(fname) if unregistered: MODULE.error(description + repr(unregistered)) raise Warning(description + '\n' + _('The following files seem to be registered in the old way:') + '\n * ' + '\n * '.join(unregistered), buttons=[{ 'action': 'register_schema', 'label': _('Register Schema files'), }])
def run(_umc_instance): if ucr.get('server/role') != 'domaincontroller_master': return process = Popen([ '/usr/share/univention-directory-manager-tools/univention-migrate-users-to-ucs4.3', '--check' ], stderr=STDOUT, stdout=PIPE) stdout, stderr = process.communicate() if process.returncode: MODULE.error(description + stdout) raise Critical(description + stdout, buttons=[{ 'action': 'migrate_users', 'label': _('Migrate user objects'), }])
def run(_umc_instance): error = _( 'This is a Samba 4 DC, but `samba-tool processes` reports no `kdc_server`.' ) heimdal_error = _('This may be, because Heimdal KDC seems to be running.') autostart_error = _( 'This may be, because `kerberos/autostart` is not disabled.') solution = _( 'You may want to stop Heimdal KDC and restart Samba via {services}') if util.is_service_active('Samba 4') and not samba_kdc_running(): error_descriptions = [error] if is_heimdal_kdc_running(): error_descriptions.append(heimdal_error) if not is_kerberos_autostart_disabled(): error_descriptions.append(autostart_error) error_descriptions.append(solution) MODULE.error('n'.join(error_descriptions)) raise Critical('\n'.join(error_descriptions))
def run(_umc_instance, rerun=False): error_descriptions = [str(exc) for exc in check_for_tracebacks()] buttons = [{ 'action': 'run_ucr_commit', 'label': _('Regenerate sources.list'), }] if error_descriptions: error_descriptions.append( _('Please check the files for more details.')) if not rerun: error_descriptions.append( _('The error might be fixable by regenerating the sources.list.' )) MODULE.error('\n'.join(error_descriptions)) raise Warning(description='\n'.join(error_descriptions), buttons=buttons) raise Warning(description='\n'.join(error_descriptions))
def run(_umc_instance): configRegistry = univention.config_registry.ConfigRegistry() configRegistry.load() try: notifier_id = get_id(configRegistry.get('ldap/master')) except socket.error: MODULE.error('Error retrieving notifier ID from the UDN.') raise Warning(_('Error retrieving notifier ID from the UDN.')) else: with open('/var/lib/univention-directory-listener/notifier_id') as fob: id_from_file = fob.read().strip() if notifier_id != id_from_file: ed = [ _('Univention Directory Notifier ID and the locally stored version differ.'), _('This might indicate an error or still processing transactions.') ] MODULE.error('\n'.join(ed)) raise Warning('\n'.join(ed))
def run(_umc_instance): config_registry = univention.config_registry.ConfigRegistry() config_registry.load() active_services = util.active_services() if not set(active_services) & {'Samba 4', 'Samba 3'}: return # ddns updates are not possible try: server = get_dns_server(config_registry, active_services) if not server: return except NSUpdateError: return # ddns updates are not possible problems = list(check_nsupdate(config_registry, server)) if problems: ed = [_('Errors occurred while running `kinit` or `nsupdate`.')] ed.extend(str(error) for error in problems) MODULE.error('\n'.join(ed)) raise Critical(description='\n'.join(ed))
def test_identity_provider_certificate(): # download from all ip addresses of ucs-sso. the IDP certificate (/etc/simplesamlphp/*-idp-certificate.crt) # compare this with /usr/share/univention-management-console/saml/idp/*.xml # If it fails: univention-run-joinscripts --force --run-scripts 92univention-management-console-web-server sso_fqdn = ucr.get('ucs/server/sso/fqdn') MODULE.process( "Checks ucs-sso by comparing 'ucr get ucs/server/sso/fqdn' with the Location field in /usr/share/univention-management-console/saml/idp/*.xml" ) if not sso_fqdn: return for host in socket.gethostbyname_ex(sso_fqdn)[2]: try: with download_tempfile( 'https://%s/simplesamlphp/saml2/idp/certificate' % (host, ), {'host': sso_fqdn}) as certificate: certificate = certificate.read() for idp in glob.glob( '/usr/share/univention-management-console/saml/idp/*.xml' ): with open(idp) as fd: cert = find_node( fromstring(fd.read()), '{http://www.w3.org/2000/09/xmldsig#}X509Certificate' ) if cert.text.strip() not in certificate: MODULE.error( 'The certificate of the SAML identity provider does not match.' ) raise Critical( _('The certificate of the SAML identity provider does not match.' )) except requests.exceptions.ConnectionError: print('error, connecting') pass
def change_server_password(configRegistry): interval = configRegistry.get('server/password/interval', '21') ucr_set('server/password/interval=-1') try: cmd = ['/usr/lib/univention-server/server_password_change'] output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) MODULE.process('Output of server_password_change:\n%s' % (output,)) except subprocess.CalledProcessError: MODULE.error('Error running server_password_change') MODULE.error('Output:\n%s' % (output,)) error_descriptions = [ _('Calling /usr/lib/univention-server/server_password_change failed.'), _('Please see {sdb} for more information.'), ] MODULE.error(' '.join(error_descriptions)) raise Critical(description=' '.join(error_descriptions)) finally: ucr_set('server/password/interval={}'.format(interval))