Пример #1
0
	def __update_status(self):
		ucr.load()
		fn = ucr.get('connector/ad/ldap/certificate')
		self.status_ssl = ucr.is_true('connector/ad/ldap/ssl')
		self.status_password_sync = ucr.is_true('connector/ad/mapping/user/password/kinit')
		self.status_certificate = bool(fn and os.path.exists(fn))
		self.status_running = self.__is_process_running('*python*univention/connector/ad/main.py*')
		self.status_mode_admember = admember.is_localhost_in_admember_mode(ucr)
		self.status_mode_adconnector = admember.is_localhost_in_adconnector_mode(ucr)
 def __init__(self):
     ucr.load()
     self._is_master = ucr.get('server/role') == 'domaincontroller_master'
     self._updates_available = ucr.is_true('update/available')
     self._fqdn = '%s.%s' % (ucr.get('hostname'), ucr.get('domainname'))
     message = '\n'.join(self._error_msg())
     super(LDAP_ServerDown, self).__init__(message, status=503)
    def query_maintenance_information(self):
        ucr.load()
        if ucr.is_true('license/extended_maintenance/disable_warning'):
            return {'show_warning': False}
        version = self.uu.get_ucs_version()
        try:
            url = 'http://updates.software-univention.de/download/ucs-maintenance/{}.yaml'.format(
                version)
            response = requests.get(url, timeout=10)
            if not response.ok:
                response.raise_for_status()
            status = yaml.load(response.content)
            if not isinstance(status, dict):
                raise yaml.YAMLError(repr(status))
            # the yaml file contains for maintained either false, true or extended as value.
            # yaml.load converts true and false into booleans but extended into string.
            _maintained_status = status.get('maintained')
            maintenance_extended = _maintained_status == 'extended'
            show_warning = maintenance_extended or not _maintained_status
        except yaml.YAMLError as exc:
            MODULE.error('The YAML format is malformed: %s' % (exc, ))
            return {'show_warning': False}
        except requests.exceptions.RequestException as exc:
            MODULE.error("Querying maintenance information failed: %s" %
                         (exc, ))
            return {'show_warning': False}

        return {
            'ucs_version': version,
            'show_warning': show_warning,
            'maintenance_extended': maintenance_extended,
            'base_dn': ucr.get('license/base')
        }
    def query_releases(self):
        """
		Returns a list of system releases suitable for the
		corresponding ComboBox
		"""

        # be as current as possible.
        self.uu.ucr_reinit()
        ucr.load()

        appliance_mode = ucr.is_true('server/appliance')

        available_versions, blocking_components = self.uu.get_all_available_release_updates(
        )
        result = [{
            'id': rel,
            'label': 'UCS %s' % (rel, )
        } for rel in available_versions]
        #
        # appliance_mode=no ; blocking_comp=no  → add "latest version"
        # appliance_mode=no ; blocking_comp=yes →  no "latest version"
        # appliance_mode=yes; blocking_comp=no  → add "latest version"
        # appliance_mode=yes; blocking_comp=yes → add "latest version"
        #
        if result and (appliance_mode or not blocking_components):
            # UniventionUpdater returns available version in ascending order, so
            # the last returned entry is the one to be flagged as 'latest' if there's
            # no blocking component.
            result[-1]['label'] = '%s (%s)' % (result[-1]['label'],
                                               _('latest version'))

        return result
Пример #5
0
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
Пример #6
0
    def admember_set_password(self, username, password):
        ldb_url = ucr.get('connector/ad/ldap/host')
        ldb_url = 'ldaps://%s' % (ldb_url, ) if ucr.is_true(
            'connector/ad/ldap/ldaps') else 'ldap://%s' % (ldb_url, )
        try:
            reset_username = dict(ucr)['ad/reset/username']
            with open(dict(ucr)['ad/reset/password']) as fd:
                reset_password = fd.readline().strip()
        except (EnvironmentError, KeyError):
            raise UMC_Error(_(
                'The configuration of the password reset service is not complete. The UCR variables "ad/reset/username" and "ad/reset/password" need to be set properly. Please inform an administration.'
            ),
                            status=500)
        process = Popen([
            'samba-tool', 'user', 'setpassword', '--username', reset_username,
            '--password', reset_password, '--filter',
            filter_format('samaccountname=%s', (username, )), '--newpassword',
            password, '-H', ldb_url
        ],
                        stdout=PIPE,
                        stderr=STDOUT)
        stdouterr = process.communicate()[0]

        if stdouterr:
            MODULE.process('samba-tool user setpassword: %s' % (stdouterr, ))

        if process.returncode:
            MODULE.error(
                "admember_set_password(): failed to set password. Return code: %s"
                % (process.returncode, ))
            return False
        return True
def run(_umc_instance):

	ucr.load()

	if ucr.is_true('diagnostic/check/disable/59_ldap_server_name') or ucr.get('server/role') != 'memberserver':
		return

	ldap_server_name = ucr.get('ldap/server/name')
	domainname = ucr.get('domainname')
	lo = univention.uldap.getMachineConnection()
	master = lo.search(base=ucr.get('ldap/base'), filter='(univentionServerRole=master)', attr=['cn'])
	try:
		master_cn = master[0][1].get('cn')[0].decode('UTF-8')
	except IndexError:
		raise Critical('Could not find a Primary Directory Node %s' % (master,))

	master_fqdn = '.'.join([master_cn, domainname])

	if master_fqdn == ldap_server_name:
		res = lo.searchDn(base=ucr.get('ldap/base'), filter='univentionServerRole=backup')

		# Case: ldap/server/name is the Primary Directory Node and there are Backup Directory Nodes available.
		if res:
			button = [{
				'action': 'deactivate_test',
				'label': _('Deactivate test'),
			}]
			warn = (_('The primary LDAP Server of this System (UCR ldap/server/name) is set to the Primary Directory Node of this UCS domain (%s).\nSince this environment provides further LDAP Servers, we recommend a different configuration to reduce the load on the Primary Directory Node.\nPlease see {sdb} for further information.') % (master_fqdn,))
			raise Warning(warn, buttons=button)
 def main(cls):
     parser = argparse.ArgumentParser(
         prog='python -m univention.admin.rest.server')
     parser.add_argument('-d', '--debug', type=int, default=2)
     args = parser.parse_args()
     ud.init('stdout', ud.FLUSH, ud.NO_FUNCTION)
     ud.set_level(ud.MAIN, args.debug)
     tornado.httpclient.AsyncHTTPClient.configure(
         'tornado.curl_httpclient.CurlAsyncHTTPClient')
     tornado.locale.load_gettext_translations(
         '/usr/share/locale', 'univention-management-console-module-udm')
     cls.start_processes()
     cls.register_signal_handlers()
     app = tornado.web.Application(
         [
             (r'.*', cls),
         ],
         serve_traceback=ucr.is_true(
             'directory/manager/rest/show-tracebacks', True),
     )
     app.listen(
         int(ucr.get('directory/manager/rest/server/port', 9979)),
         ucr.get('directory/manager/rest/server/address', '127.0.0.1'))
     ioloop = tornado.ioloop.IOLoop.instance()
     ioloop.start()
Пример #9
0
    def guess_username(self, lo, date_format):
        # already provided. use this one
        if self.name:
            return self.name

        # search database
        hints = []
        if self.lastname:
            hints.append(
                expression('lastname', escape_filter_chars(self.lastname)))
            if self.firstname:
                hints.append(
                    expression('firstname',
                               escape_filter_chars(self.firstname)))
            if self.birthday:
                hints.append(
                    expression(
                        'birthday',
                        escape_filter_chars(
                            unformat_date(self.birthday, date_format))))
        if hints:
            ldap_filter = conjunction('&', hints)
            udm_obj = self.get_first_udm_obj(lo, str(ldap_filter))
            if udm_obj:
                return udm_obj['username']

        # generate a reasonable one
        firstname = u''
        if self.firstname:
            firstname = u'%s' % (self.firstname.split()[0].lower(), )
        lastname = u''
        if self.lastname:
            lastname = u'%s' % (self.lastname.split()[-1].lower())

        firstname = self.RE_UID_INVALID.sub('', firstname)
        lastname = self.RE_UID_INVALID.sub('', lastname)

        def replace_invalid_chars(u):
            return re.sub(r'^(?:[^\w]+)?(.*?)(?:[^\w]+)?$', r'\1', u,
                          re.UNICODE)

        if ucr.is_true(
                'ucsschool/csvimport/username/generation/firstname_lastname',
                False):
            username = firstname + (u'.' if firstname else u'') + lastname
            return replace_invalid_chars(username)

        if firstname:
            firstname = firstname[:5] + '.'

        username = firstname + lastname[:5]
        maxlength = 20 - len(
            ucr.get('ucsschool/ldap/default/userprefix/exam', 'exam-'))
        return replace_invalid_chars(username[:maxlength])
Пример #10
0
    def _read_user(self, userstr, ldap_user_read=None):
        match = self.USER_REGEX.match(userstr)
        if not match or not userstr:
            raise AttributeError('invalid key "%s"' % userstr)
        username = match.groupdict()['username']
        if not username:
            raise AttributeError('username missing: %s' % userstr)

        lo = ldap_user_read
        try:
            userobj = User.get_only_udm_obj(
                lo, filter_format('uid=%s', (username, )))
            if userobj is None:
                raise noObject(username)
            user = User.from_udm_obj(userobj, None, lo)
        except (noObject, MultipleObjectsError):
            MODULE.info('Unknown user "%s"' % username)
            dict.__setitem__(self, userstr, UserInfo('', ''))
            return

        blacklisted_groups = set([
            x.strip().lower() for x in ucr.get(
                'ucsschool/umc/computerroom/hide_screenshots/groups',
                'Domain Admins').split(',')
        ])
        users_groupmemberships = set(
            [explode_dn(x, True)[0].lower() for x in userobj['groups']])
        MODULE.info('UserMap: %s: hide screenshots for following groups: %s' %
                    (
                        username,
                        blacklisted_groups,
                    ))
        MODULE.info('UserMap: %s: user is member of following groups: %s' % (
            username,
            users_groupmemberships,
        ))
        hide_screenshot = bool(blacklisted_groups & users_groupmemberships)

        if ucr.is_true('ucsschool/umc/computerroom/hide_screenshots/teachers',
                       True) and user.is_teacher(lo):
            MODULE.info('UserMap: %s: is teacher hiding screenshot' %
                        (username, ))
            hide_screenshot = True

        MODULE.info('UserMap: %s: hide_screenshot=%r' %
                    (username, hide_screenshot))

        dict.__setitem__(
            self, userstr,
            UserInfo(user.dn,
                     username,
                     isTeacher=user.is_teacher(lo),
                     hide_screenshot=hide_screenshot))
Пример #11
0
    def run(self, args):
        # locale must be set before importing UDM!
        log_init('/dev/stdout', args.debug)
        language = str(Locale(args.language))
        locale.setlocale(locale.LC_MESSAGES, language)
        os.umask(
            0o077)  # FIXME: should probably be changed, this is what UMC sets

        # The UMC-Server and module processes are clearing environment variables
        os.environ.clear()
        os.environ['PATH'] = '/bin:/sbin:/usr/bin:/usr/sbin'
        os.environ['LANG'] = language

        import univention.admin.modules as udm_modules
        udm_modules.update()

        from univention.admin.rest.module import Application
        application = Application(serve_traceback=ucr.is_true(
            'directory/manager/rest/show-tracebacks', True))

        server = HTTPServer(application)
        if args.port:
            server.bind(args.port)
        server.start(args.cpus)

        if args.unix_socket:
            socket = bind_unix_socket(args.unix_socket)
            server.add_socket(socket)
        signal.signal(signal.SIGTERM, partial(self.signal_handler_stop,
                                              server))
        signal.signal(signal.SIGINT, partial(self.signal_handler_stop, server))
        signal.signal(signal.SIGHUP, self.signal_handler_reload)

        channel = logging.StreamHandler()
        channel.setFormatter(
            tornado.log.LogFormatter(
                fmt=
                '%(color)s%(asctime)s  %(levelname)10s      (%(process)9d) :%(end_color)s %(message)s',
                datefmt='%d.%m.%y %H:%M:%S'))
        logger = logging.getLogger()
        logger.setLevel(logging.INFO)
        logger.addHandler(channel)

        try:
            tornado.ioloop.IOLoop.current().start()
        except (SystemExit, KeyboardInterrupt):
            raise
        except:
            CORE.error(traceback.format_exc())
            raise
Пример #12
0
	def _delete_obj(self, request, ldap_user_read=None, ldap_user_write=None, ldap_admin_write=None):
		# Bug #44641: workaround with security implications!
		if ucr.is_true('ucsschool/wizards/schoolwizards/workaround/admin-connection'):
			ldap_user_write = ldap_admin_write

		ret = []
		for obj in iter_objects_in_request(request, ldap_user_write, True):
			obj.name = obj.get_name_from_dn(obj.old_dn)
			MODULE.process('Deleting %r' % (obj))
			if obj.remove(ldap_user_write):
				ret.append(True)
			else:
				ret.append({'result': {'message': _('"%s" does not exist!') % obj.name}})
		return ret
Пример #13
0
    def init(self):
        if not ucr.is_true("umc/self-service/passwordreset/enabled"):
            raise UMC_Error(_(
                'The password reset service is disabled via configuration registry.'
            ),
                            status=503)

        if not IS_SELFSERVICE_MASTER:
            return

        self._usersmod = None
        self.groupmod = None

        self.db = TokenDB(MODULE)
        self.conn = self.db.conn
        atexit.register(self.db.close_db)
        if not self.db.table_exists():
            self.db.create_table()

        def ucr_try_int(variable, default):
            try:
                return int(ucr.get(variable, default))
            except ValueError:
                MODULE.error(
                    'UCR variables %s is not a number, using default: %s' %
                    (variable, default))
                return default

        self.token_validity_period = ucr_try_int(
            "umc/self-service/passwordreset/token_validity_period", 3600)
        self.send_plugins = get_sending_plugins(MODULE.process)
        self.memcache = pylibmc.Client([MEMCACHED_SOCKET], binary=True)

        limit_total_minute = ucr_try_int(
            "umc/self-service/passwordreset/limit/total/minute", 0)
        limit_total_hour = ucr_try_int(
            "umc/self-service/passwordreset/limit/total/hour", 0)
        limit_total_day = ucr_try_int(
            "umc/self-service/passwordreset/limit/total/day", 0)
        self.limit_user_minute = ucr_try_int(
            "umc/self-service/passwordreset/limit/per_user/minute", 0)
        self.limit_user_hour = ucr_try_int(
            "umc/self-service/passwordreset/limit/per_user/hour", 0)
        self.limit_user_day = ucr_try_int(
            "umc/self-service/passwordreset/limit/per_user/day", 0)

        self.total_limits = [("t:c_minute", 60, limit_total_minute),
                             ("t:c_hour", 3600, limit_total_hour),
                             ("t:c_day", 86400, limit_total_day)]
Пример #14
0
 def udm_set_password(self, username, password):
     user = self.get_udm_user(username=username, admin=True)
     if ucr.is_true('ad/member') and 'synced' in user.get('objectFlag', []):
         return self.admember_set_password(username, password)
     try:
         user["password"] = password
         user["pwdChangeNextLogin"] = 0
         user.modify()
         return True
     except (udm_errors.pwToShort, udm_errors.pwQuality) as exc:
         raise UMC_Error(str(exc))
     except udm_errors.pwalreadyused as exc:
         raise UMC_Error(exc.message)
     except Exception:
         MODULE.error(
             "udm_set_password(): failed to set password: {}".format(
                 traceback.format_exc()))
         raise
Пример #15
0
	def _modify_obj(self, request, ldap_user_read=None, ldap_user_write=None, ldap_admin_write=None):
		# Bug #44641: workaround with security implications!
		if ucr.is_true('ucsschool/wizards/schoolwizards/workaround/admin-connection'):
			ldap_user_write = ldap_admin_write

		ret = []
		for obj in iter_objects_in_request(request, ldap_user_write, True):
			MODULE.process('Modifying %r' % (obj))
			obj.validate(ldap_user_read)
			if obj.errors:
				ret.append({'result': {'message': obj.get_error_msg()}})
				continue
			try:
				obj.modify(ldap_user_write, validate=False)
			except uldapBaseException as exc:
				ret.append({'result': {'message': get_exception_msg(exc)}})
			else:
				ret.append(True)  # no changes? who cares?
		return ret
Пример #16
0
    def run(self, args):
        # locale must be set before importing UDM!
        log_init('/dev/stdout', args.debug)
        language = str(Locale(args.language))
        locale.setlocale(locale.LC_MESSAGES, language)
        os.umask(
            0o077)  # FIXME: should probably be changed, this is what UMC sets

        # The UMC-Server and module processes are clearing environment variables
        os.environ.clear()
        os.environ['PATH'] = '/bin:/sbin:/usr/bin:/usr/sbin'
        os.environ['LANG'] = language

        import univention.admin.modules as udm_modules
        udm_modules.update()

        from univention.admin.rest.module import Application
        application = Application(serve_traceback=ucr.is_true(
            'directory/manager/rest/show-tracebacks', True))

        server = HTTPServer(application)
        server.start(args.cpus)

        if args.port:
            server.listen(args.port)
        if args.unix_socket:
            socket = bind_unix_socket(args.unix_socket)
            server.add_socket(socket)
        signal.signal(signal.SIGTERM, partial(self.signal_handler_stop,
                                              server))
        signal.signal(signal.SIGINT, partial(self.signal_handler_stop, server))
        signal.signal(signal.SIGHUP, self.signal_handler_reload)
        tornado.log.enable_pretty_logging()

        try:
            tornado.ioloop.IOLoop.current().start()
        except (SystemExit, KeyboardInterrupt):
            raise
        except:
            CORE.error(traceback.format_exc())
            raise
Пример #17
0
	def delete_user(self, request, ldap_user_read=None, ldap_user_write=None, ldap_admin_write=None):
		# Bug #44641: workaround with security implications!
		if ucr.is_true('ucsschool/wizards/schoolwizards/workaround/admin-connection'):
			ldap_user_write = ldap_admin_write

		ret = []
		for obj_props in request.options:
			obj_props = obj_props['object']
			try:
				obj = User.from_dn(obj_props['$dn$'], None, ldap_user_write)
			except noObject:
				raise UMC_Error(_('The %s %r does not exists or might have been removed in the meanwhile.') % (getattr(User, 'type_name', None) or User.__name__, User.get_name_from_dn(obj_props['$dn$'])))
			school = obj_props['remove_from_school']
			success = obj.remove_from_school(school, ldap_user_write)
			# obj.old_dn is None when the ucsschool lib has deleted the user after the last school was removed from it
			if success and obj.old_dn is not None:
				success = obj.modify(ldap_user_write)
			if not success:
				success = {'result': {'message': _('Failed to remove user from school.')}}
			ret.append(success)
		return ret
Пример #18
0
	def _create_obj(self, request, ldap_user_read=None, ldap_user_write=None, ldap_admin_write=None):
		# Bug #44641: workaround with security implications!
		if ucr.is_true('ucsschool/wizards/schoolwizards/workaround/admin-connection'):
			ldap_user_write = ldap_admin_write

		ret = []
		for obj in iter_objects_in_request(request, ldap_user_write):
			MODULE.process('Creating %r' % (obj,))
			obj.validate(ldap_user_read)
			if obj.errors:
				ret.append({'result': {'message': obj.get_error_msg()}})
				MODULE.process('Validation failed %r' % (ret[-1],))
				continue
			try:
				if obj.create(ldap_user_write, validate=False):
					ret.append(True)
				else:
					ret.append({'result': {'message': _('"%s" already exists!') % obj.name}})
			except uldapBaseException as exc:
				ret.append({'result': {'message': get_exception_msg(exc)}})
				MODULE.process('Creation failed %r' % (ret[-1],))
		return ret
    def _maintenance_information(self) -> Dict[str, Any]:
        default = {'show_warning': False}
        if not self.uu:
            return default

        ucr.load()
        if ucr.is_true('license/extended_maintenance/disable_warning'):
            return default

        version = self.uu.current_version
        for _ver, data in self.uu.get_releases(version, version):
            status = data.get('status', 'unmaintained')

            maintenance_extended = status == 'extended'
            show_warning = maintenance_extended or status != 'maintained'

            return {
                'ucs_version': str(version),
                'show_warning': show_warning,
                'maintenance_extended': maintenance_extended,
                'base_dn': ucr.get('license/base'),
            }

        return default
Пример #20
0
	def change(self, role, ip, netmask, oldip=None):
		'''Return a dict with all necessary values for ipchange read from the current
		status of the system.'''

		# ignore link local addresses (no DHCP address received)
		network = ipaddress.IPv4Network(u'%s/%s' % (ip, netmask), False)
		if network.is_link_local:
			MODULE.error('Ignore link local address change.')
			return

		lo, position = univention.admin.uldap.getAdminConnection()
		hmodule = univention.admin.modules.get('dns/host_record')
		cmodule = univention.admin.modules.get('computers/%s' % (role,))

		# check if already used
		res = univention.admin.modules.lookup(hmodule, None, lo, scope='sub', filter=filter_format('aRecord=%s', (ip,)))
		if res:
			used_by = []
			for i in res:
				if 'name' in i:
					used_by.append(i['name'])
			raise BadRequest('The IP address is already in used by host record(s) for: %s' % ', '.join(used_by))

		# do we have a forward zone for this IP address?
		if oldip and oldip != ip:
			fmodule = univention.admin.modules.get('dns/forward_zone')
			for forwardobject in univention.admin.modules.lookup(fmodule, None, lo, scope='sub', superordinate=None, filter=filter_format('(aRecord=%s)', (oldip,))):
				forwardobject.open()
				forwardobject['a'].remove(oldip)
				forwardobject['a'].append(ip)
				forwardobject.modify()

		# remove old DNS reverse entries with old IP
		server = cmodule.object(None, lo, position, self.user_dn)
		server.open()
		current_ips = server['ip']
		for e in server['dnsEntryZoneReverse']:
			if e[1] in current_ips:
				server['dnsEntryZoneReverse'].remove(e)

		# change IP
		server['ip'] = ip
		MODULE.info('Change IP to %s' % (ip,))
		server.modify()

		# do we have a new reverse zone for this IP address?
		rmodule = univention.admin.modules.get('dns/reverse_zone')
		parts = network.network_address.exploded.split('.')
		while parts[-1] == '0':
			parts.pop()

		while parts:
			subnet = '.'.join(parts)
			parts.pop()
			filter = filter_format('(subnet=%s)', (subnet,))
			reverseobject = univention.admin.modules.lookup(rmodule, None, lo, scope='sub', superordinate=None, filter=filter)
			if reverseobject:
				server = cmodule.object(None, lo, position, self.user_dn)
				server.open()
				server['dnsEntryZoneReverse'].append([reverseobject[0].dn, ip])
				server.modify()
				break

		# Change ucs-sso entry
		# FIXME: this should be done for UCS-in-AD domains as well!
		ucr.load()
		sso_fqdn = ucr.get('ucs/server/sso/fqdn')
		if ucr.is_true('ucs/server/sso/autoregistraton', True):
			fmodule = univention.admin.modules.get('dns/forward_zone')
			forwardobjects = univention.admin.modules.lookup(fmodule, None, lo, scope='sub', superordinate=None, filter=None)
			for forwardobject in forwardobjects:
				zone = forwardobject.get('zone')
				if not sso_fqdn.endswith(zone):
					continue
				sso_name = sso_fqdn[:-(len(zone) + 1)]
				for current_ip in current_ips:
					records = univention.admin.modules.lookup(hmodule, None, lo, scope='sub', superordinate=forwardobject, filter=filter_format('(&(relativeDomainName=%s)(aRecord=%s))', (sso_name, current_ip)))
					for record in records:
						record.open()
						if oldip in record['a']:
							record['a'].remove(oldip)
						record['a'].append(ip)
						record.modify()
Пример #21
0
def list(filterName=None, userRule=False):
    '''Returns a list of all existing rules. If name is given, returns only the
	rule matching the specified name or None. userRule specifies whether all
	common rules (=False) or only user-specific rules (=True) are listed.
	If filterName is specified, only rule matching this name is returned as
	single object (not as list!).'''

    # iterate over all UCR variables
    rules = {}
    for k, v in findUCRVariables(filterName, userRule).iteritems():
        imatch = _regFilterNames.match(k)
        if not imatch:
            # should not happen
            continue

        # get filter name
        iname = imatch.group('name')

        # get the rule from our cache
        irule = rules.get(iname, Rule(iname))

        # update the rule with the given property
        # NOTE: URL black-/whitelists are not supported anymore, only domain lists
        iproperty = imatch.group('property')
        if iproperty == 'filtertype':
            if v not in _filterTypes:
                irule.type = WHITELIST
                MODULE.error(
                    'Unknown filtertype "%s" for rule "%s", using whitelist as default.'
                    % (v, irule))
            else:
                irule.type = _filterTypes[v]
        elif iproperty == 'priority':
            try:
                irule.priority = int(v)
            except ValueError:
                irule.priority = 5
                MODULE.error(
                    'Could not parse priority "%s" for rule "%s", using default value "5".'
                    % (v, irule))
        elif iproperty == 'wlan':
            irule.wlan = ucr.is_true(k)
        elif iproperty == 'domain':
            # get the index
            idx = -1
            try:
                idx = int(imatch.group('index'))
            except ValueError:
                pass

            # get list type (blacklisted or whitelisted)
            listType = _listTypes.get(imatch.group('listType'))

            # add domain to list of domains
            irule.addDomain(v, idx, listType)

        # save the rule back to our cache
        rules[iname] = irule

    if filterName:
        # handle case for filtered search
        if not len(rules):
            # no match
            return None
        # return single element
        return rules.items()[0][1]

    return rules.values()
	def __init__(self, **kwargs):
		ucr.load()
		self._is_master = ucr.get('server/role') == 'domaincontroller_master'
		self._updates_available = ucr.is_true('update/available')
		self._fqdn = '%s.%s' % (ucr.get('hostname'), ucr.get('domainname'))
		super(UMCError, self).__init__('\n'.join(self._error_msg()), **kwargs)
Пример #23
0
        def _thread():
            # make sure that a project with the same name does not exist
            directory = request.options['directory']
            # get absolute path of project file and test for existance
            fn_test_project = util.distribution.Project.sanitize_project_filename(
                directory)
            if os.path.exists(fn_test_project):
                raise UMC_Error(
                    _('An exam with the name "%s" already exists. Please choose a different name for the exam.'
                      ) % (directory, ))

            # validate the project data and save project
            my.project = util.distribution.Project(
                dict(
                    name=directory,
                    description=request.options['name'],
                    files=request.options.get('files'),
                    sender=sender,
                ))
            my.project.validate()
            my.project.save()

            # copy files into project directory
            if self._tmpDir:
                for ifile in my.project.files:
                    isrc = os.path.join(self._tmpDir, ifile)
                    itarget = os.path.join(my.project.cachedir, ifile)
                    if os.path.exists(isrc):
                        # copy file to cachedir
                        shutil.move(isrc, itarget)
                        os.chown(itarget, 0, 0)

            # open a new connection to the master UMC
            try:
                master = ucr['ldap/master']
                client = Client(master)
                client.authenticate_with_machine_account()
            except (ConnectionError, HTTPError) as exc:
                MODULE.error('Could not connect to UMC on %s: %s' %
                             (master, exc))
                raise UMC_Error(
                    _('Could not connect to master server %s.') %
                    ucr.get('ldap/master'))

            # mark the computer room for exam mode
            progress.component(
                _('Preparing the computer room for exam mode...'))
            client.umc_command(
                'schoolexam-master/set-computerroom-exammode',
                dict(
                    school=request.options['school'],
                    roomdn=request.options['room'],
                )).result  # FIXME: no error handling
            progress.add_steps(5)

            # read all recipients and fetch all user objects
            users = []
            for idn in request.options['recipients']:
                ientry = util.distribution.openRecipients(idn, ldap_user_read)
                if not ientry:
                    continue
                # recipients can in theory be users or groups
                members = []
                if isinstance(ientry, util.distribution.User):
                    members = [ientry]
                elif isinstance(ientry, util.distribution.Group):
                    members = ientry.members
                for entry in members:
                    # ignore exam users
                    user = User.from_dn(entry.dn, None, ldap_user_read)
                    if not user.is_exam_student(ldap_user_read):
                        users.append(entry)

            # start to create exam user accounts
            progress.component(_('Preparing exam accounts'))
            percentPerUser = 25.0 / (1 + len(users))
            examUsers = set()
            student_dns = set()
            usersReplicated = set()
            for iuser in users:
                progress.info(
                    '%s, %s (%s)' %
                    (iuser.lastname, iuser.firstname, iuser.username))
                try:
                    ires = client.umc_command(
                        'schoolexam-master/create-exam-user',
                        dict(
                            school=request.options['school'],
                            userdn=iuser.dn,
                        )).result
                    examuser_dn = ires.get('examuserdn')
                    examUsers.add(examuser_dn)
                    student_dns.add(iuser.dn)
                    MODULE.info('Exam user has been created: %r' % examuser_dn)
                except (ConnectionError, HTTPError) as exc:
                    MODULE.warn(
                        'Could not create exam user account for %r: %s' %
                        (iuser.dn, exc))

                # indicate the the user has been processed
                progress.add_steps(percentPerUser)

            client.umc_command(
                'schoolexam-master/add-exam-users-to-groups',
                dict(
                    users=list(student_dns),
                    school=request.options['school'],
                ))

            progress.add_steps(percentPerUser)

            # wait for the replication of all users to be finished
            progress.component(_('Preparing user home directories'))
            recipients = []  # list of User objects for all exam users
            openAttempts = 30 * 60  # wait max. 30 minutes for replication
            while (len(examUsers) > len(usersReplicated)) and (openAttempts >
                                                               0):
                openAttempts -= 1
                MODULE.info(
                    'waiting for replication to be finished, %s user objects missing'
                    % (len(examUsers) - len(usersReplicated)))
                for idn in examUsers - usersReplicated:
                    try:
                        ldap_user_read.get(idn, required=True)
                    except ldap.NO_SUCH_OBJECT:
                        continue  # not replicated yet
                    iuser = util.distribution.openRecipients(
                        idn, ldap_user_read)
                    if not iuser:
                        continue  # not a users/user object
                    MODULE.info('user has been replicated: %s' % idn)

                    # call hook scripts
                    if 0 != subprocess.call([
                            '/bin/run-parts', CREATE_USER_POST_HOOK_DIR,
                            '--arg', iuser.username, '--arg', iuser.dn,
                            '--arg', iuser.homedir
                    ]):
                        raise ValueError(
                            'failed to run hook scripts for user %r' %
                            (iuser.username))

                    # store User object in list of final recipients
                    recipients.append(iuser)

                    # mark the user as replicated
                    usersReplicated.add(idn)
                    progress.info(
                        '%s, %s (%s)' %
                        (iuser.lastname, iuser.firstname, iuser.username))
                    progress.add_steps(percentPerUser)

                # wait a second
                time.sleep(1)

            progress.add_steps(percentPerUser)

            if openAttempts <= 0:
                MODULE.error(
                    'replication timeout - %s user objects missing: %r ' %
                    ((len(examUsers) - len(usersReplicated)),
                     (examUsers - usersReplicated)))
                raise UMC_Error(
                    _('Replication timeout: could not create all exam users'))

            # update the final list of recipients
            my.project.recipients = recipients
            my.project.save()

            # update local NSS group cache
            if ucr.is_true('nss/group/cachefile', True):
                cmd = ['/usr/lib/univention-pam/ldap-group-to-file.py']
                if ucr.is_true('nss/group/cachefile/check_member', False):
                    cmd.append('--check_member')
                MODULE.info('Updating local nss group cache...')
                if subprocess.call(cmd):
                    MODULE.error('Updating local nss group cache failed: %s' %
                                 ' '.join(cmd))
                else:
                    MODULE.info(
                        'Update of local nss group cache finished successfully.'
                    )

            # distribute exam files
            progress.component(_('Distributing exam files'))
            progress.info('')
            my.project.distribute()
            progress.add_steps(20)

            # prepare room settings via UMCP...
            #   first step: acquire room
            #   second step: adjust room settings
            progress.component(_('Prepare room settings'))
            try:
                user_client = Client(None, self.username, self.password)
            except (ConnectionError, HTTPError) as exc:
                MODULE.warn('Authentication failed: %s' % (exc, ))
                raise UMC_Error(_('Could not connect to local UMC server.'))

            room = request.options['room']
            MODULE.info('Acquire room: %s' % (room, ))
            user_client.umc_command('computerroom/room/acquire',
                                    dict(
                                        room=request.options['room'], )).result
            progress.add_steps(1)
            MODULE.info('Adjust room settings:\n%s' % '\n'.join(
                ['  %s=%s' % (k, v) for k, v in request.options.iteritems()]))
            user_client.umc_command(
                'computerroom/exam/start',
                dict(
                    room=room,
                    examDescription=request.options['name'],
                    exam=directory,
                    examEndTime=request.options.get('examEndTime'),
                )).result
            progress.add_steps(4)
            user_client.umc_command(
                'computerroom/settings/set',
                dict(
                    room=room,
                    internetRule=request.options['internetRule'],
                    customRule=request.options.get('customRule'),
                    shareMode=request.options['shareMode'],
                    printMode='default',
                )).result
            progress.add_steps(5)
    def status(self, request):  # TODO: remove unneeded things
        """One call for all single-value variables."""

        result = {}
        ucr.load()

        try:
            result['erratalevel'] = int(ucr.get('version/erratalevel', 0))
        except ValueError:
            result['erratalevel'] = 0

        result['appliance_mode'] = ucr.is_true('server/appliance')
        result['easy_mode'] = ucr.is_true('update/umc/updateprocess/easy',
                                          False)
        result['timestamp'] = int(time())
        result['reboot_required'] = ucr.is_true('update/reboot/required',
                                                False)

        try:
            # be as current as possible.
            what = 'reinitializing UniventionUpdater'
            self.uu.ucr_reinit()

            what = 'getting UCS version'
            result['ucs_version'] = self.uu.get_ucs_version()

            # if nothing is returned -> convert to empty string.
            what = 'querying available release updates'
            try:
                result[
                    'release_update_available'] = self.uu.release_update_available(
                        errorsto='exception')
            except RequiredComponentError as exc:
                result['release_update_available'] = exc.version
            if result['release_update_available'] is None:
                result['release_update_available'] = ''

            what = 'querying update-blocking components'
            blocking_components = self.uu.get_all_available_release_updates(
            )[1]
            result['release_update_blocking_components'] = ' '.join(
                blocking_components or [])

            what = "querying availability for easy mode"

            if result['easy_mode']:
                # updates/available should reflect the need for an update
                easy_update_available = ucr.is_true('update/available', False)
                # but dont rely on ucr! update/available is set during univention-upgrade --check
                # but when was the last time this was run?

                # release update
                easy_update_available = easy_update_available or result[
                    'release_update_available']
                # if no update seems necessary perform a real (expensive) check nonetheless
                easy_update_available = easy_update_available or self.uu.component_update_available(
                )
                result['easy_update_available'] = bool(easy_update_available)
            else:
                result['easy_update_available'] = False

            # Component counts are now part of the general 'status' data.
            what = "counting components"
            c_count = 0
            e_count = 0
            for comp in self.uu.get_all_components():
                c_count = c_count + 1
                if ucr.is_true('repository/online/component/%s' % (comp, ),
                               False):
                    e_count = e_count + 1
            result['components'] = c_count
            result['enabled'] = e_count

            # HACK: the 'Updates' form polls on the serial file
            #       to refresh itself. Including the serial value
            #       into the form helps us to have a dependent field
            #       that can trigger the refresh of the "Releases"
            #       combobox and the 'package updates available' field.
            result['serial'] = self._serial_file.timestamp()

        except Exception as exc:  # FIXME: don't catch everything
            typ = str(type(exc)).strip('<>')
            msg = '[while %s] [%s] %s' % (what, typ, exc)
            result['message'] = msg
            result['status'] = 1
            MODULE.error(msg)

        self.finished(request.id, [result])
Пример #25
0
	def is_singlemaster(self):
		return ucr.is_true('ucsschool/singlemaster', False)
Пример #26
0
from univention.config_registry import handler_set

import univention.directory.reports as udr

from .udm_ldap import (
	UDM_Error, UDM_Module,
	ldap_dn2path, get_module, read_syntax_choices, list_objects, _get_syntax,
	LDAP_Connection, set_bind_function, container_modules,
	info_syntax_choices, search_syntax_choices_by_key,
	UserWithoutDN, ObjectDoesNotExist, SuperordinateDoesNotExist, NoIpLeft,
	LDAP_AuthenticationFailed
)
from .tools import LicenseError, LicenseImport, install_opener, urlopen, dump_license, check_license

USE_ASTERISKS = ucr.is_true('directory/manager/web/allow_wildcard_search', True)
ADD_ASTERISKS = USE_ASTERISKS and ucr.is_true('directory/manager/web/auto_substring_search', True)

_ = Translation('univention-management-console-module-udm').translate


def sanitize_func(sanitizer_func):
	from univention.management.console.modules.decorators import copy_function_meta_data, sanitize

	def _decorated(function):
		def _response(self, request):
			sanitizer_parameters = sanitizer_func(self, request)
			if isinstance(sanitizer_parameters, dict):
				sanitizer = sanitize(**sanitizer_parameters)
			else:  # if isinstance(sanitizer_parameters, (list, tuple)):
				sanitizer = sanitize(*sanitizer_parameters)
    def status(self, request: Request) -> None:  # TODO: remove unneeded things
        """One call for all single-value variables."""

        result = {}  # type: Dict[str, Any]
        ucr.load()

        try:
            result['erratalevel'] = int(ucr.get('version/erratalevel', 0))
        except ValueError:
            result['erratalevel'] = 0

        result['appliance_mode'] = ucr.is_true('server/appliance')
        result['timestamp'] = int(time())
        result['reboot_required'] = ucr.is_true('update/reboot/required',
                                                False)

        try:
            # be as current as possible.
            what = 'reinitializing UniventionUpdater'
            self.uu.ucr_reinit()

            what = 'getting UCS version'
            result['ucs_version'] = str(self.uu.current_version)

            # if nothing is returned -> convert to empty string.
            what = 'querying available release updates'
            try:
                ver = self.uu.release_update_available(errorsto='exception')
                result[
                    'release_update_available'] = '' if ver is None else str(
                        ver)
            except RequiredComponentError as exc:
                result['release_update_available'] = exc.version

            what = 'querying update-blocking components'
            blocking_components = self.uu.get_all_available_release_updates(
            )[1] or set()
            # check apps
            if result['release_update_available']:
                try:
                    from univention.appcenter.actions import get_action
                    update_check = get_action('update-check')
                    if update_check:
                        blocking_apps = update_check.get_blocking_apps(
                            ucs_version=result['release_update_available'])
                        if blocking_apps:
                            blocking_components.update(set(blocking_apps))
                except (ImportError, ValueError):
                    # the new univention.appcenter package is not installed.
                    # Cannot be a dependency as the app center depends on updater...
                    raise UMC_Error(
                        _('Error checking if installed apps are available for next UCS version.'
                          ))

            result['release_update_blocking_components'] = ' '.join(
                blocking_components)

            # Component counts are now part of the general 'status' data.
            what = "counting components"
            components = [
                bool(comp) for comp in self.uu.get_components(all=True)
            ]
            result['components'] = len(components)
            result['enabled'] = sum(components)

            # HACK: the 'Updates' form polls on the serial file
            #       to refresh itself. Including the serial value
            #       into the form helps us to have a dependent field
            #       that can trigger the refresh of the "Releases"
            #       combobox and the 'package updates available' field.
            result['serial'] = self._serial_file.timestamp()

        except Exception as exc:  # FIXME: don't catch everything
            raise UMC_Error("%s %s %s" % (
                _('Error contacting the update server. Please check your proxy or firewall settings, if any. Or it may be a problem with your configured DNS server.'
                  ),
                _('This is the error message:'),
                exc,
            ),
                            traceback=format_exc())

        self.finished(request.id, [result])
Пример #28
0
	def _create_disks( self, node_uri, disks, domain_info, profile = None ):
		drives = []

		uri = urlparse.urlsplit( node_uri )
		for disk in disks:
			drive = Disk()
			# do we create a new disk or just copy data from an already defined drive
			create_new = disk.get( 'source', None ) is None

			drive.device = disk[ 'device' ]
			drive.driver_type = disk[ 'driver_type' ]
			drive.driver_cache = disk.get('driver_cache', 'default')

			# set old values of existing drive
			if not create_new:
				drive.source = disk[ 'source' ]
				drive.driver = disk[ 'driver' ]
				drive.target_bus = disk[ 'target_bus' ]
				drive.target_dev = disk[ 'target_dev' ]
				if disk[ 'size' ] is not None:
					drive.size = MemorySize.str2num( disk[ 'size' ], unit = 'MB' )
			else: # when changing the medium of a CDROM we must keep the target
				drive.target_bus = disk.get( 'target_bus', None )
				drive.target_dev = disk.get( 'target_dev', None )

			# creating new drive
			pool_path = self.get_pool_path( node_uri, disk.get( 'pool' ) )
			file_pool = self.is_file_pool( node_uri, disk.get( 'pool' ) )

			if pool_path:
				drive.source = os.path.join( pool_path, disk[ 'volumeFilename' ] )
			elif not file_pool and disk.get( 'volumeType', Disk.TYPE_BLOCK ) and disk[ 'volumeFilename' ]:
				drive.source = disk[ 'volumeFilename' ]
			elif drive.source is None:
				raise ValueError( _( 'No valid source for disk "%s" found' ) % drive.device )

			if file_pool:
				drive.type = Disk.TYPE_FILE
			else:
				drive.type = Disk.TYPE_BLOCK
				drive.target_bus = 'ide'
				drive.source = disk[ 'volumeFilename' ]

			# get default for paravirtual
			if create_new:
				if profile is not None:
					if drive.device == Disk.DEVICE_DISK:
						driver_pv = getattr( profile, 'pvdisk', False )
					elif drive.device == Disk.DEVICE_CDROM:
						driver_pv = getattr( profile, 'pvcdrom', False )
				else:
					driver_pv = disk.get( 'paravirtual', False ) # by default no paravirtual devices
			else:
				driver_pv = disk.get( 'paravirtual', False ) # by default no paravirtual devices

			MODULE.info( 'Creating a %s drive' % ( driver_pv and 'paravirtual' or 'non-paravirtual' ) )

			if drive.device in ( Disk.DEVICE_DISK, Disk.DEVICE_CDROM ):
				if drive.device == Disk.DEVICE_CDROM:
					drive.driver_type = 'raw' # ISOs need driver/@type='raw'
			elif drive.device == Disk.DEVICE_FLOPPY:
				drive.target_bus = 'fdc'
			else:
				raise ValueError('Invalid drive-type "%s"' % drive.device)

			if uri.scheme.startswith( 'qemu' ):
				drive.driver = 'qemu'
				if driver_pv and drive.device != Disk.DEVICE_FLOPPY and drive.type != Disk.TYPE_BLOCK:
					drive.target_bus = 'virtio'
				elif disk.get( 'paravirtual', None ) == False and not drive.target_bus:
					drive.target_bus = 'ide'
			elif uri.scheme.startswith( 'xen' ):
				pv_domain = domain_info.os_type == 'xen'
				if driver_pv and drive.device != Disk.DEVICE_FLOPPY and drive.type != Disk.TYPE_BLOCK:
					drive.target_bus = 'xen'
				elif pv_domain and not driver_pv:
					# explicitly set ide bus
					drive.target_bus = 'ide'
				# block devices of para-virtual xen instances must use bus xen
				if pv_domain and drive.type == Disk.TYPE_BLOCK:
					drive.target_bus = 'xen'
				# Since UCS 2.4-2 Xen 3.4.3 contains the blktab2 driver
				# from Xen 4.0.1
				if file_pool:
					# Use tapdisk2 by default, but not for empty CDROM drives
					if drive.source is not None and ucr.is_true( 'uvmm/xen/images/tap2', True ):
						drive.driver = 'tap2'
						drive.driver_type = 'aio'
						# if drive.type == 'raw':
						# 	drive.driver_type = 'aio'
					else:
						drive.driver = 'file'
						drive.driver_type = None # only raw support
				else:
					drive.driver = 'phy'
			else:
				raise ValueError( 'Unknown virt-tech "%s"' % node_uri )
			if disk[ 'size' ]:
				drive.size = MemorySize.str2num( disk[ 'size' ], unit = 'MB' )

			drives.append( drive )

		return drives