def create(item: dict): if '** REJECT **' not in CveFactory.summary(item): old = CveDocument.search().filter( 'term', id=CveFactory.get_id(item)).sort( '-last_modified_date')[0].execute() if old.hits: last_modified_date = old.hits[0].last_modified_date else: last_modified_date = None if not last_modified_date or last_modified_date < CveFactory.last_modified_date( item): cve = CveDocument(id=CveFactory.get_id(item)) for field in CveDocument.get_fields_name(): parser = getattr(CveFactory, field, None) if parser: try: setattr(cve, field, parser(item)) except Exception as err: logging.debug( F'cve id {cve.id}, field {field}, err {err}') for cpe in CveFactory.get_cpe(item): cve.cpe.append(cpe) if old.hits and cve.has_changed(old.hits[0]): return old.hits[0].update(cve, weak=True) else: return cve.save(weak=True) return None logging.info(F'cve id {CveFactory.get_id(item)} is rejected') return None
class CveFactory: FIELDS = [i for i in CveDocument.get_fields_name()] @staticmethod def process(handle): data = json.load(handle) docs = [] for obj in data['CVE_Items']: cve = CveFactory.create(obj) if cve: docs.append(cve.to_dict(include_meta=True)) if len(docs) > 500: async_bulk(docs, CveDocument.Index.name) docs = [] async_bulk(docs, CveDocument.Index.name) @staticmethod def create(item: dict): if '** REJECT **' not in CveFactory.summary(item): old = CveDocument.search().filter( 'term', id=CveFactory.get_id(item)).sort( '-last_modified_date')[0].execute() if old.hits: last_modified_date = old.hits[0].last_modified_date else: last_modified_date = None if not last_modified_date or last_modified_date < CveFactory.last_modified_date( item): cve = CveDocument(id=CveFactory.get_id(item)) for field in CveDocument.get_fields_name(): parser = getattr(CveFactory, field, None) if parser: try: setattr(cve, field, parser(item)) except Exception as err: logging.debug( F'cve id {cve.id}, field {field}, err {err}') for cpe in CveFactory.get_cpe(item): cve.cpe.append(cpe) if old.hits and cve.has_changed(old.hits[0]): return old.hits[0].update(cve, weak=True) else: return cve.save(weak=True) return None logging.info(F'cve id {CveFactory.get_id(item)} is rejected') return None @staticmethod def get_id(item: dict) -> str: return item['cve']['CVE_data_meta']['ID'] @staticmethod def base_score_v2(item: dict) -> [float, None]: return CveFactory.base_score('cvssV2', item) @staticmethod def base_score_v3(item: dict) -> [float, None]: return CveFactory.base_score('cvssV3', item) @staticmethod def base_score(version: str, item: dict) -> [float, None]: score = CveFactory.value_from_base_metrics(version, 'baseScore', item) return float(score) if score else None @staticmethod def summary(item: dict) -> str: for desc in item['cve']['description']['description_data']: if desc['lang'] == 'en': return desc['value'] return str() @staticmethod def references(item: RestrictedElement) -> str: objs = [] for ref in item['cve']['references']['reference_data']: objs.append({'source': ref['refsource'], 'url': ref['url']}) return json.dumps(objs) @staticmethod def cwe(item: dict) -> CweDocument: for problemtype_data in item['cve']['problemtype']['problemtype_data']: for desc in problemtype_data['description']: if desc['lang'] == 'en': return CWEFactory.get(desc['value']) @staticmethod def get_cpe(item: dict) -> list: cpes = [] try: for conf in item['configurations']['nodes']: for cpe_match in conf['cpe_match']: cpes.append(CpeFactory.get(cpe_match['cpe23Uri'])) except (KeyError, IndexError): pass return cpes @staticmethod def published_date(item: dict) -> datetime: return parse_datetime(item['publishedDate']) @staticmethod def last_modified_date(item: dict) -> datetime: return parse_datetime(item['lastModifiedDate']) @staticmethod def access_vector_v2(item: dict) -> metrics.AccessVectorV2: av = CveFactory.value_from_base_metrics('cvssV2', 'accessVector', item) return metrics.AccessVectorV2(av).value @staticmethod def access_complexity_v2(item: dict) -> metrics.AccessComplexityV2: ac = CveFactory.value_from_base_metrics('cvssV2', 'accessComplexity', item) return metrics.AccessComplexityV2(ac).value @staticmethod def authentication_v2(item: dict) -> metrics.AuthenticationV2: auth = CveFactory.value_from_base_metrics('cvssV2', 'authentication', item) return metrics.AuthenticationV2(auth).value @staticmethod def confidentiality_impact_v2(item: dict) -> metrics.ImpactV2: imp = CveFactory.value_from_base_metrics('cvssV2', 'confidentialityImpact', item) return metrics.ImpactV2(imp).value @staticmethod def integrity_impact_v2(item: dict) -> metrics.ImpactV2: imp = CveFactory.value_from_base_metrics('cvssV2', 'integrityImpact', item) return metrics.ImpactV2(imp).value @staticmethod def availability_impact_v2(item: dict) -> metrics.ImpactV2: imp = CveFactory.value_from_base_metrics('cvssV2', 'availabilityImpact', item) return metrics.ImpactV2(imp).value @staticmethod def attack_vector_v3(item: dict) -> metrics.AttackVectorV3: av = CveFactory.value_from_base_metrics('cvssV3', 'attackVector', item) return metrics.AttackVectorV3(av).value @staticmethod def attack_complexity_v3(item: dict) -> metrics.AttackComplexityV3: ac = CveFactory.value_from_base_metrics('cvssV3', 'attackComplexity', item) return metrics.AttackComplexityV3(ac).value @staticmethod def privileges_required_v3(item: dict) -> metrics.PrivilegesRequiredV3: pr = CveFactory.value_from_base_metrics('cvssV3', 'privilegesRequired', item) return metrics.PrivilegesRequiredV3(pr).value @staticmethod def user_interaction_v3(item: dict) -> metrics.UserInteractionV3: us = CveFactory.value_from_base_metrics('cvssV3', 'userInteraction', item) return metrics.UserInteractionV3(us).value @staticmethod def scope_v3(item: dict) -> metrics.ScopeV3: sc = CveFactory.value_from_base_metrics('cvssV3', 'scope', item) return metrics.ScopeV3(sc).value @staticmethod def confidentiality_impact_v3(item: dict) -> metrics.ImpactV3: ci = CveFactory.value_from_base_metrics('cvssV3', 'confidentialityImpact', item) return metrics.ImpactV3(ci).value @staticmethod def integrity_impact_v3(item: dict) -> metrics.ImpactV3: ii = CveFactory.value_from_base_metrics('cvssV3', 'integrityImpact', item) return metrics.ImpactV3(ii).value @staticmethod def availability_impact_v3(item: dict) -> metrics.ImpactV3: ai = CveFactory.value_from_base_metrics('cvssV3', 'availabilityImpact', item) return metrics.ImpactV3(ai).value @staticmethod def value_from_base_metrics(version: str, value: str, item: dict) -> [str, None]: return item['impact']['baseMetricV2' if version == 'cvssV2' else 'baseMetricV3'][version][value]