コード例 #1
0
ファイル: sysctl.py プロジェクト: teselkin/xccdf-yaml
    def parse(self, id, metadata):
        res = ParsedObjects(self.xccdf)
        res.new_rule(id)

        affected = metadata.get('affected', 'Ubuntu 1604')

        # Object
        obj = OvalObject('oval:{}:obj:1'.format(id),
                         'sysctl_object',
                         ns=self.__ns__)
        obj.sub_element('name').set_text(metadata['key'])
        res.objects.append(obj)

        # State
        state = OvalState('oval:{}:ste:1'.format(id),
                          'sysctl_state',
                          ns=self.__ns__)
        sysctl_value = state.sub_element('value').set_text(metadata['value'])
        sysctl_value.set_attrs({
            'datatype': 'int',
            'operation': 'equals',
        })
        res.states.append(state)

        # Test
        test = OvalTest('oval:{}:tst:1'.format(id),
                        'sysctl_test',
                        ns=self.__ns__)
        test.add_object(obj)
        test.add_state(state)
        res.tests.append(test)

        # Definition
        definition = Definition('oval:{}:def:1'.format(id))

        metadata = definition.add_metadata()
        metadata.set_title(str(id))
        metadata.set_description('Check for {}'.format(id))
        if isinstance(affected, list):
            for affect in affected:
                metadata.set_affected('unix', get_affected_from_cpe(affect))
        else:
            metadata.set_affected('unix', get_affected_from_cpe(affected))

        criteria = definition.add_criteria()
        for test in res.tests:
            criterion = Criterion(test.get_attr('id'))
            criteria.add_criterion(criterion)
        res.definition = definition

        return res
コード例 #2
0
    def parse(self, id, metadata):
        res = ParsedObjects(self.xccdf)
        res.new_rule(id)

        if 'name' not in metadata:
            raise KeyError('name of service must be set')

        affected = metadata.get('affected', 'Ubuntu 1604')
        name = metadata['name']
        target = metadata.get('target', 'multi-user.target')

        service_disabled = metadata.get('disabled', False)

        service_state = 'active'
        dep_check = 'at least one'
        test_running_attrs = {
            'check': 'at least one',
            'check_existence': 'at_least_one_exists'
        }

        if metadata.get('disabled', False):
            service_state = 'inactive'
            dep_check = 'none satisfy'
            # operator = 'OR'
            test_running_attrs = {
                'check': 'all',
                'check_existence': 'any_exist'
            }

        # Check target
        # object
        obj = OvalObject('oval:target_for_{}:obj:1'.format(name),
                         'systemdunitdependency_object',
                         ns=self.__ns__)

        obj.sub_element('unit').set_text(target)

        res.objects.append(obj)
        # state
        state = OvalState('oval:systemd_service_{}:ste:1'.format(name),
                          'systemdunitdependency_state',
                          ns=self.__ns__)

        state.sub_element('dependency')\
            .set_text('{}.service'.format(name))\
            .set_attr('entity_check', dep_check)

        res.states.append(state)
        # test
        test = OvalTest('oval:target_wants_{}:tst:1'.format(name),
                        'systemdunitdependency_test',
                        ns=self.__ns__)
        test.__elements_order__ = (
            'object',
            'state',
        )
        test.add_object(obj)
        test.add_state(state)

        res.tests.append(test)

        # Check socket
        # object
        obj = OvalObject('oval:target_for_{}_socket:obj:1'.format(name),
                         'systemdunitdependency_object',
                         ns=self.__ns__)

        obj.sub_element('unit').set_text(target)

        res.objects.append(obj)

        # state
        state = OvalState('oval:systemd_{}_socket:ste:1'.format(name),
                          'systemdunitdependency_state',
                          ns=self.__ns__)

        state.sub_element('dependency')\
            .set_text('{}.socket'.format(name))\
            .set_attr('entity_check', dep_check)

        res.states.append(state)

        # test
        test = OvalTest('oval:target_wants_{}_socket:tst:1'.format(name),
                        'systemdunitdependency_test',
                        ns=self.__ns__)

        test.__elements_order__ = (
            'object',
            'state',
        )

        test.add_object(obj)
        test.add_state(state)

        res.tests.append(test)

        # Check service [not]running
        # object
        obj = OvalObject('oval:service_{}_state:obj:1'.format(name),
                         'systemdunitproperty_object',
                         ns=self.__ns__)

        obj.__elements_order__ = (
            'unit',
            'property',
        )

        obj.sub_element('unit')\
            .set_text(r'{}\.(socket|service)'.format(name))\
            .set_attr('operation', 'pattern match')

        obj.sub_element('property').set_text('ActiveState')

        res.objects.append(obj)

        # state
        state = OvalState('oval:service_{}_state:ste:1'.format(name),
                          'systemdunitproperty_state',
                          ns=self.__ns__)

        state.sub_element('value').set_text(service_state)

        res.states.append(state)

        # test
        test = OvalTest('oval:service_{}_state:tst:1'.format(name),
                        'systemdunitproperty_test',
                        ns=self.__ns__)

        test.__elements_order__ = (
            'object',
            'state',
        )

        test.set_attrs(test_running_attrs)
        test.add_object(obj)
        test.add_state(state)

        res.tests.append(test)

        # definition
        definition = Definition('oval:{}:def:1'.format(id))

        metadata = definition.add_metadata()
        metadata.set_title(str(id))
        metadata.set_description('Check for {}'.format(id))
        if isinstance(affected, list):
            for affect in affected:
                metadata.set_affected('unix', get_affected_from_cpe(affect))
        else:
            metadata.set_affected('unix', get_affected_from_cpe(affected))

        criteria = definition.add_criteria(operator='AND')

        statecriterion = Criterion('oval:service_{}_state:tst:1'.format(name))
        criteria.add_criterion(statecriterion)

        if service_disabled:
            srvcriterion = Criterion('oval:target_wants_{}:tst:1'.format(name))
            sockcriretion = Criterion(
                'oval:target_wants_{}_socket:tst:1'.format(name))
            criteria.add_criterion(srvcriterion)
            criteria.add_criterion(sockcriretion)
        else:
            srvcrit = Criteria()
            srvcriterion = Criterion('oval:target_wants_{}:tst:1'.format(name))
            sockcriterion = Criterion(
                'oval:target_wants_{}_socket:tst:1'.format(name))
            srvcrit.add_criterion(srvcriterion)
            srvcrit.add_criterion(sockcriterion)
            criteria.add_criteria(srvcrit)

        res.definition = definition

        return res
コード例 #3
0
    def parse(self, id, metadata):
        res = ParsedObjects(self.xccdf)
        rule = res.new_rule(id)

        if 'title' in metadata:
            rule.set_title(metadata['title'])

        if 'description' in metadata:
            rule.set_description(metadata['title'])

        if 'filename' not in metadata:
            raise KeyError('filename must be set')

        if 'pattern' not in metadata and 'variable' not in metadata:
            raise KeyError('pattern or variable must be set')

        filenames = []
        if isinstance(metadata['filename'], str):
            filenames.append(metadata['filename'])
        elif isinstance(metadata['filename'], list):
            filenames = metadata['filename']
        else:
            raise ValueError('Unsupported filename format')

        pattern = metadata.get('pattern')
        variable = metadata.get('variable')
        subexpression = metadata.get('subexpression')

        oval_var_id = 'oval:{}:var:1'.format(variable)

        affected = metadata.get('affected', 'Ubuntu 1604')

        for idx, f in enumerate(filenames):
            state = None
            # Object
            path, filename = os.path.split(f)

            # If filename not a regular expression
            if not filename.startswith('^'):
                filename = '^{}'.format(filename)
            if not filename.endswith('$'):
                filename = '{}$'.format(filename)

            obj = OvalObject('oval:{}_{}:obj:1'.format(id, idx),
                             'textfilecontent54_object',
                             ns=self.__ns__)

            obj.__elements_order__ = (
                'path',
                'filename',
                'pattern',
                'instance',
            )

            obj.sub_element('path')\
                .set_text(path)

            obj.sub_element('filename')\
                .set_text(filename)\
                .set_attr('operation', 'pattern match')

            if pattern:
                obj.sub_element('pattern')\
                    .set_text(pattern)\
                    .set_attr('operation', 'pattern match')
            else:
                if not subexpression:
                    obj.sub_element('pattern')\
                        .set_attr('var_ref', oval_var_id)\
                        .set_attr('operation', 'pattern match')

            obj.sub_element('instance')\
                .set_text('1')\
                .set_attr('datatype', 'int')

            res.objects.append(obj)

            # State
            if subexpression and pattern:
                state = OvalState('oval:{}_{}:ste:1'.format(id, idx),
                                  'textfilecontent54_state',
                                  ns=self.__ns__)
                if variable:
                    state.sub_element('subexpression')\
                        .set_attr('var_check', 'all')\
                        .set_attr('var_ref', oval_var_id)
                res.states.append(state)

            # Test
            test = OvalTest('oval:{}_{}:tst:1'.format(id, idx),
                            'textfilecontent54_test',
                            ns=self.__ns__)

            if metadata.get('match', True):
                exists = 'all_exist'
            else:
                exists = 'none_exist'

            test.set_attr('check_existence', exists)
            test.add_object(obj)
            if state:
                test.add_state(state)
            res.tests.append(test)

        # variable
        if variable:
            var_type = metadata['external-variables'][variable]
            res.variable = ExternalVariable(oval_var_id, var_type)

        # definition
        definition = Definition('oval:{}:def:1'.format(id))

        metadata = definition.add_metadata()
        metadata.set_title(str(id))
        metadata.set_description('Check for {}'.format(id))
        if isinstance(affected, list):
            for affect in affected:
                metadata.set_affected('unix', get_affected_from_cpe(affect))
        else:
            metadata.set_affected('unix', get_affected_from_cpe(affected))

        criteria = definition.add_criteria()
        for test in res.tests:
            criterion = Criterion(test.get_attr('id'))
            criteria.add_criterion(criterion)
        res.definition = definition
        return res
コード例 #4
0
    def parse(self, id, metadata):
        res = ParsedObjects()
        rule = res.new_rule(id)

        if 'title' in metadata:
            rule.set_title(metadata['title'])

        if 'description' in metadata:
            rule.set_description(metadata['title'])

        if 'port' not in metadata:
            if 'local_full_address' not in metadata:
                raise KeyError('port or local_full_address must be set')

        protocol = metadata.get('protocol', 'tcp')

        if 'local_full_address' in metadata:
            address, port = metadata['local_full_address'].split(':')
        else:
            address = metadata.get('address', '127.0.0.1')
            port = str(metadata['port'])

        listen = metadata.get('listen', True)
        program = metadata.get('program')
        # uid = metadata.get('uid')

        variable = metadata.get('variable')
        oval_var_id = 'oval:{}:var:1'.format(variable)

        address = variable if variable else address

        affected = metadata.get('affected', 'Ubuntu 1604')

        any_addr_re = r'^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'

        elements_order = (
            'protocol',
            'local_address',
            'local_port',
            'program_name',
            'pid',
            'user_id',
        )

        # Objects
        if listen and address not in ['all', 'any', '0.0.0.0', '*'] \
                and not variable:
            any_listen_obj = OvalObject('oval:{}_listen_any:obj:1'.format(id),
                                        'inetlisteningservers_object',
                                        ns=self.__ns__)
            any_listen_obj.__elements_order__ = elements_order

            any_listen_obj.sub_element('protocol')\
                .set_text(protocol)
            any_listen_obj.sub_element('local_address')\
                .set_text(any_addr_re)\
                .set_attr('operation', 'pattern match')
            any_listen_obj.sub_element('local_port')\
                .set_text(port)\
                .set_attr('datatype', 'int')
            res.objects.append(any_listen_obj)

        obj = OvalObject('oval:{}:obj:1'.format(id),
                         'inetlisteningservers_object',
                         ns=self.__ns__)
        obj.__elements_order__ = elements_order

        obj.sub_element('protocol')\
            .set_text(protocol)

        if address in ['any', '*']:
            obj.sub_element('local_address')\
                .set_text(any_addr_re)\
                .set_attr('operation', 'pattern match')
        elif address in ['all', '0.0.0.0']:
            obj.sub_element('local_address')\
                .set_text('0.0.0.0')
        elif variable:
            obj.sub_element('local_address')\
                .set_attr('var_ref', oval_var_id)
        else:
            obj.sub_element('local_address')\
                .set_text(address)

        obj.sub_element('local_port')\
            .set_text(port)\
            .set_attr('datatype', 'int')

        res.objects.append(obj)

        # State
        state = OvalState('oval:{}:ste:1'.format(id),
                          'inetlisteningservers_state',
                          ns=self.__ns__)
        state.__elements_order__ = elements_order

        if program:
            state.sub_element('program_name')\
                .set_text(program)

        state.sub_element('pid')\
            .set_text('0')\
            .set_attr('operation', 'greater than')\
            .set_attr('datatype', 'int')

        if 'uid' in metadata:
            state.sub_element('user_id')\
                .set_text(str(metadata['uid']))\
                .set_attr('operation', 'equals')\
                .set_attr('datatype', 'int')

        res.states.append(state)

        # Tests
        if listen and address not in ['all', 'any', '0.0.0.0', '*'] \
                and not variable:
            listen_any_test = OvalTest('oval:{}_listen_any:tst:1'.format(id),
                                       'inetlisteningservers_test',
                                       ns=self.__ns__)
            listen_any_test.set_attr('check', 'none exist')
            listen_any_test.add_object(any_listen_obj)
            res.tests.append(listen_any_test)

        test = OvalTest('oval:{}:tst:1'.format(id),
                        'inetlisteningservers_test',
                        ns=self.__ns__)

        test.__elements_order__ = (
            'object',
            'state',
        )
        test.set_attr('check', 'at least one')
        test.add_object(obj)
        test.add_state(state)
        res.tests.append(test)

        # Variable
        if variable:
            var_type = metadata['external-variables'][variable]
            res.variable = ExternalVariable(oval_var_id, var_type)

        # Definition
        definition = Definition('oval:{}:def:1'.format(id))

        metadata = definition.add_metadata()
        metadata.set_title(str(id))
        metadata.set_description('Check for {}'.format(id))
        if isinstance(affected, list):
            for affect in affected:
                metadata.set_affected('unix', get_affected_from_cpe(affect))
        else:
            metadata.set_affected('unix', get_affected_from_cpe(affected))

        if listen and address not in ['all', 'any', '0.0.0.0', '*'] \
                and not variable:
            operator = 'OR'
        else:
            operator = 'AND'
        criteria = definition.add_criteria(operator=operator)

        for test in res.tests:
            criterion = Criterion(test.get_attr('id'))
            criteria.add_criterion(criterion)
        res.definition = definition
        return res
コード例 #5
0
    def parse(self, id, metadata):
        res = ParsedObjects(self.xccdf)
        res.new_rule(id)

        if 'filename' not in metadata:
            raise KeyError('filename must be set')

        filenames = []
        if isinstance(metadata['filename'], str):
            filenames.append(metadata['filename'])
        elif isinstance(metadata['filename'], list):
            filenames = metadata['filename']
        else:
            raise ValueError('filename must be string or list')

        affected = metadata.get('affected', 'Ubuntu 1604')

        for idx, filename in enumerate(filenames):
            # Object
            obj = OvalObject('oval:{}_{}:obj:1'.format(id, idx),
                             'file_object',
                             ns=self.__ns__)

            obj.sub_element('filepath')\
                .set_text(filename)\
                .set_attr('operation', 'pattern match')

            res.objects.append(obj)

            # states and tests
            if 'mode' in metadata:
                mode = str(metadata['mode'])
                if 4 < len(mode) < 1:
                    raise ValueError("mode must be 1 to 4 digits")
                if not str(mode).isdecimal():
                    raise ValueError("mode must be decimal")
                modes = self.__parse_mode__(mode)

                # State
                state = OvalState('oval:{}_mode_{}:ste:1'.format(id, idx),
                                  'file_state',
                                  ns=self.__ns__)
                state.__elements_order__ = (
                    'suid',
                    'sgid',
                    'sticky',
                    'uread',
                    'uwrite',
                    'uexec',
                    'gread',
                    'gwrite',
                    'gexec',
                    'oread',
                    'owrite',
                    'oexec',
                )
                for k, v in modes.items():
                    state.sub_element(k)\
                        .set_text(v)\
                        .set_attr('datatype', 'boolean')

                res.states.append(state)

                # Test
                test = OvalTest('oval:{}_mode_{}:tst:1'.format(id, idx),
                                'file_test',
                                ns=self.__ns__)
                test.__elements_order__ = (
                    'object',
                    'state',
                )
                test.add_object(obj)
                test.add_state(state)
                res.tests.append(test)

            if 'uid' in metadata:
                uid = str(metadata['uid'])
                if int(uid) < 0 or not uid.isdecimal():
                    raise ValueError('UID must be positive decimal')
                # tid = 'oval:{}_uid:tst:1'.format(uid)

                # State
                state = OvalState('oval:{}_uid_{}:ste:1'.format(id, idx),
                                  'file_state',
                                  ns=self.__ns__)

                state.sub_element('user_id')\
                    .set_text(uid)\
                    .set_attr('datatype', 'int')\
                    .set_attr('operation', 'equals')

                res.states.append(state)

                # Test
                test = OvalTest('oval:{}_uid_{}:tst:1'.format(id, idx),
                                'file_test',
                                ns=self.__ns__)
                test.__elements_order__ = (
                    'object',
                    'state',
                )
                test.add_object(obj)
                test.add_state(state)
                res.tests.append(test)

            if 'gid' in metadata:
                gid = str(metadata['gid'])
                if int(gid) < 0 or not gid.isdecimal():
                    raise ValueError('GID must be positive decimal')
                # State
                state = OvalState('oval:{}_gid_{}:ste:1'.format(id, idx),
                                  'file_state',
                                  ns=self.__ns__)

                state.sub_element('group_id')\
                    .set_text(gid)\
                    .set_attr('datatype', 'int')\
                    .set_attr('operation', 'equals')

                res.states.append(state)

                # Test
                test = OvalTest('oval:{}_gid_{}:tst:1'.format(id, idx),
                                'file_test',
                                ns=self.__ns__)
                test.__elements_order__ = (
                    'object',
                    'state',
                )
                test.add_object(obj)
                test.add_state(state)
                res.tests.append(test)

        # definition
        definition = Definition('oval:{}:def:1'.format(id))

        metadata = definition.add_metadata()
        metadata.set_title(str(id))
        metadata.set_description('Check for {}'.format(id))
        if isinstance(affected, list):
            for affect in affected:
                metadata.set_affected('unix', get_affected_from_cpe(affect))
        else:
            metadata.set_affected('unix', get_affected_from_cpe(affected))

        criteria = definition.add_criteria()
        for test in res.tests:
            criterion = Criterion(test.get_attr('id'))
            criteria.add_criterion(criterion)
        res.definition = definition

        return res
コード例 #6
0
    def parse(self, id, metadata):
        res = ParsedObjects(self.xccdf)
        res.new_rule(id)

        affected = metadata.get('affected', 'Ubuntu 1604')

        packages = []
        if isinstance(metadata['name'], str):
            packages.append(metadata['name'])
        elif isinstance(metadata['name'], list):
            packages = metadata['name']
        else:
            raise ValueError('name must be string or array')

        for idx, package in enumerate(packages):
            # Object
            obj = OvalObject('oval:{}_{}:obj:1'.format(id, idx),
                             'dpkginfo_object',
                             ns=self.__ns__)
            obj.sub_element('name').set_text(package)
            res.objects.append(obj)

            # State
            state = OvalState('oval:{}_{}:ste:1'.format(id, idx),
                              'dpkginfo_state',
                              ns=self.__ns__)
            if 'version' in metadata:
                version = metadata['version']
                operation = metadata.get('match')
                if ':' not in version:
                    version = '0:{}'.format(version)  # we need to have evr
                if operation == 'eq':
                    operation = 'equal'
                elif operation == 'ge':
                    operation = 'greater than or equal'
                elif operation == 'gt':
                    operation = 'greater than'
                else:
                    raise ValueError('Unsupported pkg version matching')
                evr = state.sub_element('evr').set_text(version)
                evr.set_attrs({
                    'datatype': 'evr_string',
                    'operation': operation,
                })
            res.states.append(state)

            # Test
            test = OvalTest('oval:{}_{}:tst:1'.format(id, idx),
                            'dpkginfo_test',
                            ns=self.__ns__)
            if metadata.get('removed', False):
                check_existence = 'none_exist'
            else:
                check_existence = 'all_exist'
            test.set_attr('check_existence', check_existence)
            test.add_object(obj)
            res.tests.append(test)

        # definition
        definition = Definition('oval:{}:def:1'.format(id))

        metadata = definition.add_metadata()
        metadata.set_title(str(id))
        metadata.set_description('Check for {}'.format(id))
        if isinstance(affected, list):
            for affect in affected:
                metadata.set_affected('unix', get_affected_from_cpe(affect))
        else:
            metadata.set_affected('unix', get_affected_from_cpe(affected))

        criteria = definition.add_criteria()
        for test in res.tests:
            criterion = Criterion(test.get_attr('id'))
            criteria.add_criterion(criterion)
        res.definition = definition

        return res