class Instance(Base):
    @sanitize(value=s.BooleanSanitizer(required=True))
    @simple_response
    @log
    def bool(self, value):
        """ bool is just an int with 1 bit, so:
			True: 1 == True, 0 == False, isinstance(True, int)
			False: 2 == True, isinstance(1, bool)
		"""
        assert repr(value) in ('True', 'False'), 'Value is not a bool'
        return '%r' % (value, )

    _choices = ('Ja', 2, True, (2, ), [], {})

    @sanitize(value=s.ChoicesSanitizer(choices=_choices, required=True))
    @simple_response
    @log
    def choices(self, value):
        assert value in self._choices, 'A value is not in choices'
        assert isinstance(value, type(self._choices[self._choices.index(
            value)])), 'A choice has the wrong type'  # makes sense !;)
        return '%r' % (value, )

    @sanitize(value=s.DictSanitizer({}, required=True))
    @simple_response
    @log
    def dict(self, value):
        assert isinstance(value, dict), 'Value is not a dict: %r' % (value)
        return '%r' % (value, )

    @sanitize(value=s.DictSanitizer(
        {
            'foo': s.Sanitizer(),
            'bar': s.Sanitizer()
        },
        required=True,
        allow_other_keys=False))
    @simple_response
    @log
    def dict_a(self, value):
        assert set(value) == set(
            ['foo', 'bar']), 'There are invalid keys: %r' % (list(value))
        return '%r' % (value, )

    @sanitize(value=s.EmailSanitizer(required=True))
    @simple_response
    @log
    def email(self, value):
        assert isinstance(value, basestring) and value.count(
            '@') == 1, 'Value is not a string or does not contain @: %r' % (
                value, )
        return '%r' % (value, )

    @sanitize(value=s.IntegerSanitizer(required=True))
    @simple_response
    @log
    def int(self, value):
        assert isinstance(value, int), 'Value is not an int'  # could be long
        return '%r' % (value, )

    @sanitize(value=s.LDAPSearchSanitizer(required=True))
    @simple_response
    @log
    def ldapsearch(self, value):
        # TODO
        return '%r' % (value, )

    @sanitize(value=s.ListSanitizer(s.Sanitizer(), required=True))
    @simple_response
    @log
    def list(self, value):
        assert isinstance(value, (list, tuple)), 'No List given'
        return '%r' % (value, )

    @sanitize(value=s.ListSanitizer(min_elements=3,
                                    max_elements=6,
                                    required=True))
    @simple_response
    @log
    def list_a(self, value):
        assert 3 <= len(value) <= 6, 'wrong list length: %d' % len(value)
        return '%r' % (value, )

    _mapping = {u'foo': 'bar', b'bar': 1, 'baz': []}

    @sanitize(value=s.MappingSanitizer(_mapping, required=True))
    @simple_response
    @log
    def mapping(self, value):
        assert value in self._mapping.values(), 'Mapping failed: %r' % (
            value, )  # TODO: more?
        return '%r' % (value, )

    @sanitize(value=s.PatternSanitizer(required=True))
    @simple_response
    @log
    def pattern(self, value):
        import re
        assert isinstance(value, re._pattern_type)
        assert value.pattern.count(
            '.*') < 6, 'pattern contains more than 5 stars'
        return '%r' % (value, )

    @sanitize(value=s.StringSanitizer(required=True))
    @simple_response
    @log
    def string(self, value):
        assert isinstance(value, basestring)
        if not isinstance(value, unicode):
            # Is it possible that we don't have unicode here?
            try:
                value.decode('utf-8')
            except:
                assert False, 'no unicode'
        return '%r' % (value, )

    @simple_response
    @log
    def simple(self, value, foo='default'):
        return '%r %r' % (value, foo)

    @multi_response
    @log
    def multi(self, iterator, *values):
        assert all(map(lambda v: isinstance(v, dict), iterator))
        yield '%r %s' % (list(iterator), values)

    @file_upload
    def upload(self, request):
        assert request.command == 'UPLOAD'
        self.finished(request.id, True)

    @multi_response(single_values=True)
    def single(self, iterator, *values):
        return '%r' % (values)
class Instance(umc.modules.Base):
    def _get_description(self, description):
        # Try to return the localised description or
        # use english as a fallback
        if self.locale.language in description:
            return description[self.locale.language]
        elif u'en' in description:
            return description[u'en']
        else:
            return None

    @decorators.sanitize(category=sanitizers.ChoicesSanitizer((
        u'protocol',
        u'port',
        u'address',
        u'packageName',
        u'description',
    ),
                                                              default=u'port'),
                         pattern=sanitizers.PatternSanitizer(default=u'.*'))
    @decorators.simple_response
    def rules_query(self, category, pattern):
        """Searches for firewall rules

		requests.options = [
			'category': 'protocol' | 'port' | 'address' | 'package' |
            'description',
			'pattern': <str>,
		]
		"""
        def match(rule):
            if category == u'port':
                # Check every port number
                for port in range(*rule.port):
                    match = pattern.match(str(port))
                    if match:
                        return match
                else:
                    return False
            elif category == u'packageName':
                if rule.package:
                    return pattern.match(rule.package)
                else:
                    return False
            elif category == u'description':
                for language in rule.description.values():
                    match = pattern.match(language)
                    if match:
                        return match
                else:
                    return False
            else:
                # Simple match for most cases:
                return pattern.match(getattr(rule, category))

        def get_address(address):
            if address == u'all':
                return _(u'All addresses')
            elif address == u'ipv4':
                return _(u'All IPv4 addresses')
            elif address == u'ipv6':
                return _(u'All IPv6 addresses')
            else:
                return address

        # Try to load firewall configuration
        try:
            firewall = backend.Firewall()
        except backend.Error as e:
            message = _(u"Could not load firewall configuration")
            MODULE.error(u"%s: %s" % (
                message,
                str(e),
            ))
            raise umc.modules.UMC_CommandError(message)

        result = []
        for rule in firewall.rules.values():
            if not rule or not match(rule):
                # rule isn't complete (e.g. missing action) or
                # rule doesn't match the pattern
                continue
            entry = {}
            entry = {
                u'identifier': rule.identifier,
                u'protocol': rule.protocol,
                u'portStart': rule.port[0],
                u'portEnd': (rule.port[1] - 1),
                u'address': get_address(rule.address),
                u'packageName': rule.package,
                u'action': rule.action.lower(),
                u'description': self._get_description(rule.description),
            }
            result.append(entry)
        return result

    def _add_or_edit(self, iterator, object, edit=False):
        def get_address(address_type, address_value):
            if address_type == u'specific':
                return address_value
            else:
                return address_type

        # Try to load firewall configuration
        try:
            firewall = backend.Firewall()
        except backend.Error as e:
            message = _(u"Could not load firewall configuration")
            MODULE.error(u"%s: %s" % (
                message,
                str(e),
            ))
            raise umc.modules.UMC_CommandError(message)

        for (object, ) in iterator:
            try:
                if edit:
                    firewall.remove_rule(object[u'identifier'])

                port = (
                    object[u'portStart'],
                    (object[u'portEnd'] + 1),
                )
                address = get_address(object[u'addressType'],
                                      object[u'addressValue'])

                rule = backend.Rule(object[u'protocol'], port, address, None,
                                    object[u'action'].lower())
                firewall.add_rule(rule)
            except backend.Error as e:
                if edit:
                    yield {
                        u'object': object[u'identifier'],
                        u'success': False,
                        u'details': str(e),
                    }
                else:
                    yield {
                        u'success': False,
                        u'details': str(e),
                    }
            else:
                yield {
                    u'object': rule.identifier,
                    u'success': True,
                }

        # Try to save firewall configuration
        try:
            firewall.save()
        except backend.Error as e:
            message = _(u"Could not save firewall configuration")
            MODULE.error(u"%s: %s" % (
                message,
                str(e),
            ))
            raise umc.modules.UMC_CommandError(message)

    @decorators.sanitize(
        sanitizers.DictSanitizer({
            u'object':
            sanitizers.DictSanitizer(
                {
                    u'protocol':
                    sanitizers.ChoicesSanitizer(
                        (
                            u'tcp',
                            u'udp',
                        ), required=True),
                    u'portStart':
                    sanitizers.IntegerSanitizer(minimum=1,
                                                maximum=2**16,
                                                maximum_strict=True,
                                                required=True),
                    u'portEnd':
                    sanitizers.IntegerSanitizer(minimum=1,
                                                maximum=2**16,
                                                maximum_strict=True,
                                                required=True),
                    u'addressType':
                    sanitizers.ChoicesSanitizer((
                        u'all',
                        u'ipv4',
                        u'ipv6',
                        u'specific',
                    ),
                                                required=True),
                    u'addressValue':
                    sanitizers.StringSanitizer(default=u''),
                    u'action':
                    sanitizers.ChoicesSanitizer(
                        (
                            u'accept',
                            u'reject',
                            u'drop',
                        ), required=True),
                },
                required=True),
        }))
    @decorators.multi_response
    @decorators.log
    def rules_add(self, iterator, object):
        """Add the specified new rules:

		requests.options = [{
			'object': {
				'protocol': 'tcp' | 'udp',
				'portStart': <int>,
				'portEnd': <int>,
				'addressType': 'all' | 'ipv4' | 'ipv6' | 'specific',
				'addressValue': <string>
				'action': 'accept' | 'reject' | 'drop,
			}
		}, ]
		"""
        return self._add_or_edit(iterator, object, edit=False)

    @decorators.sanitize(sanitizers.StringSanitizer(required=True))
    @decorators.multi_response(single_values=True)
    @decorators.log
    def rules_get(self, iterator):
        """Returns the specified rules

		requests.options = [
			<string>,
		]
		"""
        def get_address_type(address):
            if backend.REGEX_RULE_ADDRESS.match(address):
                return address
            else:
                return u'specific'

        def get_address_value(address):
            if backend.REGEX_RULE_ADDRESS.match(address):
                return None
            else:
                return address

        # Try to load firewall configuration
        try:
            firewall = backend.Firewall()
        except backend.Error as e:
            message = _(u"Could not load firewall configuration")
            MODULE.error(u"%s: %s" % (
                message,
                str(e),
            ))
            raise umc.modules.UMC_CommandError(message)

        for identifier in iterator:
            try:
                rule = firewall.rules[identifier]

                entry = {
                    u'identifier': rule.identifier,
                    u'protocol': rule.protocol,
                    u'portStart': rule.port[0],
                    u'portEnd': (rule.port[1] - 1),
                    u'addressType': get_address_type(rule.address),
                    u'addressValue': get_address_value(rule.address),
                    u'packageName': rule.package,
                    u'action': rule.action.lower(),
                    u'description': self._get_description(rule.description),
                }
            except (backend.Error, KeyError) as e:
                message = _(u"Could not get firewall rule")
                MODULE.error(u"%s: %s" % (
                    message,
                    str(e),
                ))
                raise umc.modules.UMC_CommandError(message)
            else:
                yield entry

    @decorators.sanitize(
        sanitizers.DictSanitizer(
            {
                u'object':
                sanitizers.DictSanitizer({
                    u'identifier':
                    sanitizers.StringSanitizer(required=True),
                    u'protocol':
                    sanitizers.ChoicesSanitizer(
                        (
                            u'tcp',
                            u'udp',
                        ), required=True),
                    u'portStart':
                    sanitizers.IntegerSanitizer(minimum=1,
                                                maximum=2**16,
                                                maximum_strict=True,
                                                required=True),
                    u'portEnd':
                    sanitizers.IntegerSanitizer(minimum=1,
                                                maximum=2**16,
                                                maximum_strict=True,
                                                required=True),
                    u'addressType':
                    sanitizers.ChoicesSanitizer((
                        u'all',
                        u'ipv4',
                        u'ipv6',
                        u'specific',
                    ),
                                                required=True),
                    u'addressValue':
                    sanitizers.StringSanitizer(default=u''),
                    u'action':
                    sanitizers.ChoicesSanitizer(
                        (
                            u'accept',
                            u'reject',
                            u'drop',
                        ), required=True),
                }),
            },
            required=True))
    @decorators.multi_response
    @decorators.log
    def rules_put(self, iterator, object):
        """Edit the specified rules:

		requests.options = [{
			'object': {
				'identifier': <str>,
				'protocol': 'tcp' | 'udp',
				'portStart': <int>,
				'portEnd': <int>,
				'addressType': 'all' | 'ipv4' | 'ipv6' | 'specific',
				'addressValue': <string>
				'action': 'accept' | 'reject' | 'drop,
			}
		}, ]
		"""
        return self._add_or_edit(iterator, object, edit=True)

    @decorators.sanitize(
        sanitizers.DictSanitizer(
            {
                u'object': sanitizers.StringSanitizer(required=True),
            },
            required=True))
    @decorators.multi_response
    @decorators.log
    def rules_remove(self, iterator, object):
        """Remove the specified rules

		requests.options = [{
			'object': <string>,
		}, ]
		"""
        # Try to load firewall configuration
        try:
            firewall = backend.Firewall()
        except backend.Error as e:
            message = _(u"Could not load firewall configuration")
            MODULE.error(u"%s: %s" % (
                message,
                str(e),
            ))
            raise umc.modules.UMC_CommandError(message)

        for (object, ) in iterator:
            try:
                firewall.remove_rule(object)
            except backend.Error as e:
                yield {
                    u'object': object,
                    u'success': False,
                    u'details': str(e),
                }
            else:
                yield {
                    u'object': object,
                    u'success': True,
                }
        # Try to save firewall configuration
        try:
            firewall.save()
        except backend.Error as e:
            message = _(u"Could not save firewall configuration")
            MODULE.error(u"%s: %s" % (
                message,
                str(e),
            ))
            raise umc.modules.UMC_CommandError(message)
Exemple #3
0
class Instance(umc.modules.Base):
    @decorators.sanitize(category=sanitizers.ChoicesSanitizer(
        (
            'address',
            'port',
            'protocol',
            'description',
            'package',
        ),
        default='address'),
                         pattern=sanitizers.PatternSanitizer(default='.*'))
    @decorators.simple_response
    def query(self, category, pattern):
        def match(rule):
            if category != 'port':  # Simple match for most cases:
                return pattern.match(getattr(rule, category))
            # Special case 'port': Check every port number
            for port in range(*rule.port):
                match = pattern.match(str(port))
                if match:
                    return match
            else:
                return None

        firewall = backend.Firewall()
        rules = []
        for rule in firewall.rules.values():
            if not rule or not match(rule):
                # rule isn't complete (e.g. missing action) or
                # rule doesn't match the pattern
                continue
            entry = {}
            entry = {
                'name': rule.name,
                'address': rule.address,
                'port': rule.port,
                'protocol': rule.protocol,
                'package': rule.package,
                'action': rule.action,
                'description': rule.description,
            }
            rules.append(entry)
        return rules

    @decorators.sanitize(
        address=sanitizers.StringSanitizer(required=True),
        port_start=sanitizers.IntegerSanitizer(required=True),
        port_end=sanitizers.IntegerSanitizer(),
        protocol=sanitizers.StringSanitizer(required=True),
        action=sanitizers.StringSanitizer(required=True),
        description=sanitizers.StringSanitizer(),
    )
    @decorators.simple_response
    @decorators.log
    def add(self, address, port_start, port_end, protocol, action,
            description):
        try:
            rule = backend.Rule(address, (
                port_start,
                port_end,
            ), protocol)
            rule.action = action
            # TODO: Add the description
        except backend.Error as e:
            return {'success': False, 'message': str(e.message)}
        # TODO: try-except
        firewall = backend.Firewall()
        firewall.add_rule(rule)
        firewall.save()
        return {'success': True}

    def remove(self):  # TODO
        pass

    def modify(self):  # TODO
        pass