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
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
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
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
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
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