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 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 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 add_lo_to_samba_interfaces(umc_instance): configRegistry = univention.config_registry.ConfigRegistry() configRegistry.load() interfaces = configRegistry.get('samba/interfaces', '').split() interfaces.append('lo') MODULE.process('Setting samba/interfaces') ucr_set(['samba/interfaces={}'.format(' '.join(interfaces))]) return run(umc_instance, retest=True)
def test_resolve(url): parsed = urlparse.urlsplit(url if '//' in url else '//' + url) MODULE.process("Trying to resolve address of repository server %s" % (parsed.hostname)) MODULE.process("Similar to running: host %s" % (parsed.hostname)) try: socket.getaddrinfo(parsed.hostname, parsed.scheme) except socket.gaierror: return False return True
def kinit(principal, keytab=None, password_file=None): auth = '--keytab={tab}' if keytab else '--password-file={file}' cmd = ('kinit', auth.format(tab=keytab, file=password_file), principal) MODULE.process('Running: %s' % (' '.join(cmd))) try: subprocess.check_call(cmd) except subprocess.CalledProcessError: raise KinitError(principal, keytab, password_file) else: yield subprocess.call(('kdestroy', ))
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_samba_tool_dbcheck_fix(umc_instance): if not util.is_service_active('Samba 4'): return cmd = ['samba-tool', 'dbcheck', '--fix', '--cross-ncs', '--yes'] (success, output) = util.run_with_output(cmd) cmd_string = ' '.join(cmd) MODULE.process('Output of %s:\n%s' % (cmd_string, output)) fix_log = [_('Output of `{cmd}`:').format(cmd=cmd_string)] fix_log.append(output.decode('utf-8', 'replace')) run(umc_instance, rerun=True, fix_log='\n'.join(fix_log))
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_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 restore_machine_password(role, ldap_connection): with open('/etc/machine.secret') as fob: password = fob.read().rstrip('\n') if not password: password = univention.lib.misc.createMachinePassword() with open('/etc/machine.secret', 'w') as fob: fob.write(password) computers = udm_modules.get('computers/{}'.format(role)) position = univention.admin.uldap.position(ldap_connection.base) udm_modules.init(ldap_connection, position, computers) filter_expr = ldap.filter.filter_format('(cn=%s)', (socket.gethostname(),)) for computer in computers.lookup(None, ldap_connection, filter_expr): MODULE.process('Restoring password of UDM computer object') computer.open() computer['password'] = password computer.modify()
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))
def run(_umc_instance): MODULE.info('Checking samba logfiles for "Too many open files" messages') counter = 0 try: with open('/var/log/samba/log.smbd', 'rb') as fd: for line in fd: counter += len(re.findall('Too many open files', line)) except (OSError, IOError): return # logfile does not exists ucr.load() try: max_open_files = int(ucr.get('samba/max_open_files', 32808)) except ValueError: max_open_files = 0 MODULE.process("open files: %s , max open files: %s" % (counter, max_open_files)) if counter and max_open_files < suggested_max_open_files: raise Critical(umc_modules=[{'module': 'ucr'}])
def probe_kdc(kdc, port, protocol, target_realm, user_name): request = build_kerberos_request(target_realm, user_name) if protocol == 'udp': MODULE.process( "Trying to contact KDC %s on udp port %d Similar to running: nmap %s -sU -p %d" % (kdc, port, kdc, port)) else: MODULE.process( "Trying to contact KDC %s on tcp port %d Similar to running: nmap %s -sT -p %d" % (kdc, port, kdc, port)) try: received = send_and_receive(kdc, port, protocol, request) except KerberosException: return False if target_realm in received: return True return False # this no longer works with >= 4.3, ?? # I think the new pyasn1 version might need the full asn1Spec to work?: # http://snmplabs.com/pyasn1/changelog.html # Keyword: require strict two-zeros sentinel encoding try: (error, _sub) = pyasn1.codec.der.decoder.decode(received, asn1Spec=KrbError()) except pyasn1.error.PyAsn1Error: pass else: return True try: (rep, _sub) = pyasn1.codec.der.decoder.decode(received, asn1Spec=AsRep()) except pyasn1.error.PyAsn1Error: return False return True
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 reset_kerberos_kdc(umc_instance): MODULE.process('Resetting kerberos/kdc=127.0.0.1') ucr_set(['kerberos/kdc=127.0.0.1']) return run(umc_instance, retest=True)
def reset_password_change(umc_instance): MODULE.process('Unsetting server/password/change') ucr_unset(['server/password/change']) return run(umc_instance, retest=True)
def run(_umc_instance, url='http://www.univention.de/', connecttimeout=30, timeout=30): ucr.load() proxy = ucr.get('proxy/http') if not proxy: return proxy = urlparse(proxy) MODULE.info('The proxy is configured, using host=%r, port=%r' % (proxy.hostname, proxy.port)) curl = pycurl.Curl() curl.setopt(pycurl.PROXYTYPE, pycurl.PROXYTYPE_HTTP) if proxy.hostname: curl.setopt(pycurl.PROXY, proxy.hostname) if proxy.port: curl.setopt(pycurl.PROXYPORT, proxy.port) curl.setopt(pycurl.FOLLOWLOCATION, True) curl.setopt(pycurl.MAXREDIRS, 5) curl.setopt(pycurl.CONNECTTIMEOUT, connecttimeout) curl.setopt(pycurl.TIMEOUT, 30) if proxy.username: curl.setopt(pycurl.PROXYAUTH, pycurl.HTTPAUTH_ANY) credentials = '%s' % (proxy.username, ) if proxy.password: credentials = '%s:%s' % (proxy.username, proxy.password) curl.setopt(pycurl.PROXYUSERPWD, credentials) curl.setopt(pycurl.URL, url) # curl.setopt(pycurl.VERBOSE, bVerbose) buf = io.StringIO() curl.setopt(pycurl.WRITEFUNCTION, buf.write) MODULE.process(''.join("Trying to connect to %s via HTTP proxy %s" % (url, proxy))) try: curl.perform() except pycurl.error as exc: try: code, msg = exc.args msg = '%s (code=%s)' % (msg, code) MODULE.info(msg) except ValueError: MODULE.error(traceback.format_exc()) code = 0 msg = str(exc) if code == pycurl.E_COULDNT_CONNECT: msg = _( 'The proxy host could not be reached. Make sure that hostname (%(hostname)r) and port (%(port)r) are correctly set up.' ) % { 'hostname': proxy.hostname, 'port': proxy.port } elif code == pycurl.E_COULDNT_RESOLVE_PROXY: msg = _( 'The hostname of the proxy could not be resolved. May check your DNS configuration.' ) elif code == pycurl.E_OPERATION_TIMEOUTED: msg = _( 'The server did not respond within %d seconds. Please check your network configuration.' ) % (timeout, ) elif code == 0: MODULE.error(traceback.format_exc()) MODULE.error('\n'.join([description, msg])) raise Critical('\n'.join([description, msg])) else: # page = buf.getvalue() # MODULE.info(page[:100]) buf.close() http_status = curl.getinfo(pycurl.HTTP_CODE) if http_status >= 400: warning = '\n'.join([ description, _('The proxy server is reachable but the HTTP response status code (%d) does not indicate success.' ) % (http_status, ), _('This warning might be harmless. Nevertheless make sure the authentication credentials (if any) are correct and the proxy server ACLs do not forbid requests to %s.' ) % (url, ) ]) MODULE.warn(warning) raise Warning(warning) finally: curl.close()
def reset_password_interval(umc_instance): MODULE.process('Resetting server/password/interval=21') ucr_set(['server/password/interval=21']) return run(umc_instance, retest=True)
def adjust(_umc_instance): MODULE.process('Setting samba/max_open_files') handler_set(['samba/max_open_files=%d' % (suggested_max_open_files, )]) raise ProblemFixed( _('The limits have been adjusted to the suggested value.'), buttons=[])