def _update_notice_object(notice, data): """ Set fields on a Notice model object """ notice.title = data["title"] notice.summary = data["summary"] notice.details = data["description"] notice.release_packages = data["release_packages"] notice.published = data["published"] notice.references = data["references"] notice.instructions = data["instructions"] notice.releases = [ db_session.query(Release).get(codename) for codename in data["release_packages"].keys() ] notice.cves.clear() for cve_id in data["cves"]: notice.cves.append(db_session.query(CVE).get(cve_id) or CVE(id=cve_id)) return notice
def bulk_upsert_cve(): """ Receives a PUT request from load_cve.py Parses the object and bulk inserts or updates @returns 3 lists of CVEs, created CVEs, updated CVEs and failed CVEs """ cves_schema = CVESchema(many=True) cves_schema.context["release_codenames"] = [ rel.codename for rel in db_session.query(Release).all() ] try: cves_data = cves_schema.load(flask.request.json) except ValidationError as error: return ( flask.jsonify({ "message": "Invalid payload", "errors": error.messages }), 400, ) if len(cves_data) > 50: return ( flask.jsonify({ "message": ("Please only submit up to 50 CVEs at a time. " f"({len(cves_data)} submitted)") }), 413, ) packages = {} for package in db_session.query(Package).all(): packages[package.name] = package for data in cves_data: cve = db_session.query(CVE).get(data["id"]) or CVE(id=data["id"]) cve.status = data.get("status") cve.published = data.get("published") cve.priority = data.get("priority") cve.cvss3 = data.get("cvss3") cve.description = data.get("description") cve.ubuntu_description = data.get("ubuntu_description") cve.notes = data.get("notes") cve.references = data.get("references") cve.bugs = data.get("bugs") statuses = update_statuses(cve, data, packages, releases=db_session.query(Release)) db_session.add(cve) db_session.add_all(statuses) created = defaultdict(lambda: 0) updated = defaultdict(lambda: 0) for item in db_session.new: created[type(item).__name__] += 1 for item in db_session.dirty: updated[type(item).__name__] += 1 try: db_session.commit() except DataError as error: return ( flask.jsonify({ "message": "Failed bulk upserting session", "error": error.orig.args[0], }), 400, ) return (flask.jsonify({"created": created, "updated": updated}), 200)
def update_notice(): if not flask.request.json: return (flask.jsonify({"message": "No payload received"}), 400) notice_schema = NoticeSchema() try: data = notice_schema.load(flask.request.json, unknown=EXCLUDE) except ValidationError as error: return ( flask.jsonify( {"message": "Invalid payload", "errors": error.messages} ), 400, ) notice = db_session.query(Notice).get(data["notice_id"]) if not notice: return ( flask.jsonify( {"message": f"Notice {data['notice_id']} doesn't exist"} ), 404, ) notice.title = data["title"] notice.summary = data["summary"] notice.details = data["description"] notice.packages = data["releases"] notice.published = datetime.fromtimestamp(data["timestamp"]) if "action" in data: notice.instructions = data["action"] if "isummary" in data: notice.isummary = data["isummary"] # Clear m2m relations to re-add notice.cves.clear() notice.releases.clear() notice.references.clear() # Link releases for release_codename in data["releases"].keys(): try: notice.releases.append( db_session.query(Release) .filter(Release.codename == release_codename) .one() ) except NoResultFound: message = f"No release with codename: {release_codename}." return (flask.jsonify({"message": message}), 400) # Link CVEs, creating them if they don't exist refs = set(data.get("references", [])) for ref in refs: if ref.startswith("CVE-"): cve_id = ref[4:] cve = db_session.query(CVE).get(cve_id) if not cve: cve = CVE(id=cve_id) notice.cves.append(cve) else: reference = ( db_session.query(Reference) .filter(Reference.uri == ref) .first() ) if not reference: reference = Reference(uri=ref) notice.references.append(reference) db_session.add(notice) db_session.commit() return flask.jsonify({"message": "Notice updated"}), 200
def api_create_notice(): if not flask.request.json: return (flask.jsonify({"message": f"No payload received"}), 400) # Because we get a dict with ID as a key and the payload as a value notice_id, payload = flask.request.json.popitem() notice = db_session.query(Notice).filter(Notice.id == notice_id).first() if notice: return ( flask.jsonify({"message": f"Notice '{notice.id}' already exists"}), 400, ) notice_schema = NoticeSchema() try: data = notice_schema.load(payload, unknown=EXCLUDE) except ValidationError as error: return ( flask.jsonify({ "message": "Invalid payload", "errors": error.messages }), 400, ) notice = Notice( id=data["notice_id"], title=data["title"], summary=data["summary"], details=data["description"], packages=data["releases"], published=datetime.fromtimestamp(data["timestamp"]), ) if "action" in data: notice.instructions = data["action"] if "isummary" in data: notice.isummary = data["isummary"] # Link releases for release_codename in data["releases"].keys(): try: notice.releases.append( db_session.query(Release).filter( Release.codename == release_codename).one()) except NoResultFound: message = f"No release with codename: {release_codename}." return (flask.jsonify({"message": message}), 400) # Link CVEs, creating them if they don't exist refs = set(data.get("references", [])) for ref in refs: if ref.startswith("CVE-"): cve_id = ref[4:] cve = db_session.query(CVE).filter(CVE.id == cve_id).first() if not cve: cve = CVE(id=cve_id) notice.cves.append(cve) else: reference = (db_session.query(Reference).filter( Reference.uri == ref).first()) if not reference: reference = Reference(uri=ref) notice.references.append(reference) db_session.add(notice) db_session.commit() return flask.jsonify({"message": "Notice created"}), 201