def create_notice(): """ POST method to create a new notice """ notice_schema = NoticeSchema() notice_schema.context["release_codenames"] = [ rel.codename for rel in db_session.query(Release).all() ] try: notice_data = notice_schema.load(flask.request.json) except ValidationError as error: return ( flask.jsonify({ "message": "Invalid payload", "errors": error.messages }), 400, ) db_session.add( _update_notice_object(Notice(id=notice_data["id"]), notice_data)) try: db_session.commit() except IntegrityError: return ( flask.jsonify( {"message": f"Notice {notice_data['id']} already exists"}), 400, ) return flask.jsonify({"message": "Notice created"}), 201
def update_notice(notice_id): """ PUT method to update a single notice """ notice = db_session.query(Notice).get(notice_id) if not notice: return ( flask.jsonify({"message": f"Notice {notice_id} doesn't exist"}), 404, ) notice_schema = NoticeSchema() notice_schema.context["release_codenames"] = [ rel.codename for rel in db_session.query(Release).all() ] try: notice_data = notice_schema.load(flask.request.json, unknown=EXCLUDE) except ValidationError as error: return ( flask.jsonify({ "message": "Invalid payload", "errors": error.messages }), 400, ) notice = _update_notice_object(notice, notice_data) db_session.add(notice) db_session.commit() return flask.jsonify({"message": "Notice updated"}), 200
def update_statuses(cve, data, packages): statuses = cve.packages statuses_query = db_session.query(Status).filter(Status.cve_id == cve.id) statuses_to_delete = { f"{v.package_name}||{v.release_codename}": v for v in statuses_query.all() } for package_data in data.get("packages", []): name = package_data["name"] if packages.get(name) is None: package = Package(name=name) package.source = package_data["source"] package.ubuntu = package_data["ubuntu"] package.debian = package_data["debian"] packages[name] = package db_session.add(package) for status_data in package_data["statuses"]: update_status = False codename = status_data["release_codename"] status = statuses[name].get(codename) if status is None: update_status = True status = Status( cve_id=cve.id, package_name=name, release_codename=codename ) elif f"{name}||{codename}" in statuses_to_delete: del statuses_to_delete[f"{name}||{codename}"] if status.status != status_data["status"]: update_status = True status.status = status_data["status"] if status.description != status_data["description"]: update_status = True status.description = status_data["description"] if status.component != status_data.get("component"): update_status = True status.component = status_data.get("component") if status.pocket != status_data.get("pocket"): update_status = True status.pocket = status_data.get("pocket") if update_status: statuses[name][codename] = status db_session.add(status) for key in statuses_to_delete: db_session.delete(statuses_to_delete[key])
def create_release(): """ POST method to create a new release """ release_schema = ReleaseSchema() try: release_data = release_schema.load(flask.request.json) except ValidationError as error: return ( flask.jsonify( {"message": "Invalid payload", "errors": error.messages} ), 400, ) release = Release( codename=release_data["codename"], version=release_data["version"], name=release_data["name"], development=release_data["development"], lts=release_data["lts"], release_date=release_data["release_date"], esm_expires=release_data["esm_expires"], support_expires=release_data["support_expires"], ) db_session.add(release) try: db_session.commit() except IntegrityError: return ( flask.jsonify( { "message": ( f"Release with [codename:'{release_data['codename']}']" f" or [version:'{release_data['version']}'] or " f"[name:'{release_data['name']}'] already exists" ) } ), 400, ) return flask.jsonify({"message": "Release created"}), 200
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 load_releases(): releases = [ Release( codename="warty", version="4.10", name="Warty Warthog", development=False, lts=False, release_date=datetime.strptime("2004-10-20", "%Y-%m-%d"), esm_expires=datetime.strptime("2004-10-20", "%Y-%m-%d"), support_expires=datetime.strptime("2004-10-20", "%Y-%m-%d"), ), Release( codename="hoary", version="5.04", name="Hoary Hedgehog", development=False, lts=False, release_date=datetime.strptime("2005-04-08", "%Y-%m-%d"), esm_expires=datetime.strptime("2005-04-08", "%Y-%m-%d"), support_expires=datetime.strptime("2005-04-08", "%Y-%m-%d"), ), Release( codename="breezy", version="5.10", name="Breezy Badger", development=False, lts=False, release_date=datetime.strptime("2005-10-13", "%Y-%m-%d"), esm_expires=datetime.strptime("2005-10-13", "%Y-%m-%d"), support_expires=datetime.strptime("2005-10-13", "%Y-%m-%d"), ), Release( codename="dapper", version="6.06", name="Dapper Drake", development=False, lts=True, release_date=datetime.strptime("2006-06-01", "%Y-%m-%d"), esm_expires=datetime.strptime("2006-06-01", "%Y-%m-%d"), support_expires=datetime.strptime("2006-06-01", "%Y-%m-%d"), ), Release( codename="edgy", version="6.10", name="Edgy Eft", development=False, lts=False, release_date=datetime.strptime("2006-10-26", "%Y-%m-%d"), esm_expires=datetime.strptime("2006-10-26", "%Y-%m-%d"), support_expires=datetime.strptime("2006-10-26", "%Y-%m-%d"), ), Release( codename="feisty", version="7.04", name="Feisty Fawn", development=False, lts=False, release_date=datetime.strptime("2007-04-19", "%Y-%m-%d"), esm_expires=datetime.strptime("2007-04-19", "%Y-%m-%d"), support_expires=datetime.strptime("2007-04-19", "%Y-%m-%d"), ), Release( codename="gutsy", version="7.10", name="Gutsy Gibbon", development=False, lts=False, release_date=datetime.strptime("2007-10-18", "%Y-%m-%d"), esm_expires=datetime.strptime("2007-10-18", "%Y-%m-%d"), support_expires=datetime.strptime("2007-10-18", "%Y-%m-%d"), ), Release( codename="hardy", version="8.04", name="Hardy Heron", development=False, lts=True, release_date=datetime.strptime("2008-04-24", "%Y-%m-%d"), esm_expires=datetime.strptime("2008-04-24", "%Y-%m-%d"), support_expires=datetime.strptime("2008-04-24", "%Y-%m-%d"), ), Release( codename="intrepid", version="8.10", name="Intrepid Ibex", development=False, lts=False, release_date=datetime.strptime("2008-10-30", "%Y-%m-%d"), esm_expires=datetime.strptime("2008-10-30", "%Y-%m-%d"), support_expires=datetime.strptime("2008-10-30", "%Y-%m-%d"), ), Release( codename="jaunty", version="9.04", name="Jaunty Jackalope", development=False, lts=False, release_date=datetime.strptime("2009-04-23", "%Y-%m-%d"), esm_expires=datetime.strptime("2008-10-30", "%Y-%m-%d"), support_expires=datetime.strptime("2008-10-30", "%Y-%m-%d"), ), Release( codename="karmic", version="9.10", name="Karmic Koala", development=False, lts=False, release_date=datetime.strptime("2009-10-29", "%Y-%m-%d"), esm_expires=datetime.strptime("2009-10-29", "%Y-%m-%d"), support_expires=datetime.strptime("2009-10-29", "%Y-%m-%d"), ), Release( codename="lucid", version="10.04", name="Lucid Lynx", development=False, lts=True, release_date=datetime.strptime("2010-04-29", "%Y-%m-%d"), esm_expires=datetime.strptime("2010-04-29", "%Y-%m-%d"), support_expires=datetime.strptime("2010-04-29", "%Y-%m-%d"), ), Release( codename="maverick", version="10.10", name="Maverick Meerkat", development=False, lts=False, release_date=datetime.strptime("2010-10-10", "%Y-%m-%d"), esm_expires=datetime.strptime("2010-10-10", "%Y-%m-%d"), support_expires=datetime.strptime("2010-10-10", "%Y-%m-%d"), ), Release( codename="natty", version="11.04", name="Natty Narwhal", development=False, lts=False, release_date=datetime.strptime("2011-04-28", "%Y-%m-%d"), esm_expires=datetime.strptime("2011-04-28", "%Y-%m-%d"), support_expires=datetime.strptime("2011-04-28", "%Y-%m-%d"), ), Release( codename="oneiric", version="11.10", name="Oneiric Ocelot", development=False, lts=False, release_date=datetime.strptime("2011-10-13", "%Y-%m-%d"), esm_expires=datetime.strptime("2011-10-13", "%Y-%m-%d"), support_expires=datetime.strptime("2011-10-13", "%Y-%m-%d"), ), Release( codename="precise", version="12.04", name="Precise Pangolin", development=False, lts=True, release_date=datetime.strptime("2012-04-26", "%Y-%m-%d"), esm_expires=datetime.strptime("2021-04-30", "%Y-%m-%d"), support_expires=datetime.strptime("2012-04-26", "%Y-%m-%d"), ), Release( codename="quantal", version="12.10", name="Quantal Quetzal", development=False, lts=False, release_date=datetime.strptime("2012-10-18", "%Y-%m-%d"), esm_expires=datetime.strptime("2012-10-18", "%Y-%m-%d"), support_expires=datetime.strptime("2012-10-18", "%Y-%m-%d"), ), Release( codename="raring", version="13.04", name="Raring Ringtail", development=False, lts=False, release_date=datetime.strptime("2013-04-25", "%Y-%m-%d"), esm_expires=datetime.strptime("2013-04-25", "%Y-%m-%d"), support_expires=datetime.strptime("2013-04-25", "%Y-%m-%d"), ), Release( codename="saucy", version="13.10", name="Saucy Salamander", development=False, lts=False, release_date=datetime.strptime("2013-10-17", "%Y-%m-%d"), esm_expires=datetime.strptime("2013-10-17", "%Y-%m-%d"), support_expires=datetime.strptime("2013-10-17", "%Y-%m-%d"), ), Release( codename="trusty", version="14.04", name="Trusty Tahr", development=False, lts=True, release_date=datetime.strptime("2014-04-17", "%Y-%m-%d"), esm_expires=datetime.strptime("2022-04-30", "%Y-%m-%d"), support_expires=datetime.strptime("2019-04-30", "%Y-%m-%d"), ), Release( codename="utopic", version="14.10", name="Utopic Unicorn", development=False, lts=False, release_date=datetime.strptime("2014-10-23", "%Y-%m-%d"), esm_expires=datetime.strptime("2014-10-23", "%Y-%m-%d"), support_expires=datetime.strptime("2014-10-23", "%Y-%m-%d"), ), Release( codename="vivid", version="15.04", name="Vivid Vervet", development=False, lts=False, release_date=datetime.strptime("2015-04-23", "%Y-%m-%d"), esm_expires=datetime.strptime("2015-04-23", "%Y-%m-%d"), support_expires=datetime.strptime("2015-04-23", "%Y-%m-%d"), ), Release( codename="wily", version="15.10", name="Wily Werewolf", development=False, lts=False, release_date=datetime.strptime("2015-10-22", "%Y-%m-%d"), esm_expires=datetime.strptime("2015-10-22", "%Y-%m-%d"), support_expires=datetime.strptime("2015-10-22", "%Y-%m-%d"), ), Release( codename="xenial", version="16.04", name="Xenial Xerus", development=False, lts=True, release_date=datetime.strptime("2016-04-21", "%Y-%m-%d"), esm_expires=datetime.strptime("2024-04-30", "%Y-%m-%d"), support_expires=datetime.strptime("2021-04-30", "%Y-%m-%d"), ), Release( codename="yakkety", version="16.10", name="Yakkety Yak", development=False, lts=False, release_date=datetime.strptime("2016-10-13", "%Y-%m-%d"), esm_expires=datetime.strptime("2016-10-13", "%Y-%m-%d"), support_expires=datetime.strptime("2016-10-13", "%Y-%m-%d"), ), Release( codename="zesty", version="17.04", name="Zesty Zapus", development=False, lts=False, release_date=datetime.strptime("2017-04-13", "%Y-%m-%d"), esm_expires=datetime.strptime("2017-04-13", "%Y-%m-%d"), support_expires=datetime.strptime("2017-04-13", "%Y-%m-%d"), ), Release( codename="artful", version="17.10", name="Artful Aardvark", development=False, lts=False, release_date=datetime.strptime("2017-10-19", "%Y-%m-%d"), esm_expires=datetime.strptime("2017-10-19", "%Y-%m-%d"), support_expires=datetime.strptime("2017-10-19", "%Y-%m-%d"), ), Release( codename="bionic", version="18.04", name="Bionic Beaver", development=False, lts=True, release_date=datetime.strptime("2018-04-26", "%Y-%m-%d"), esm_expires=datetime.strptime("2028-04-30", "%Y-%m-%d"), support_expires=datetime.strptime("2023-04-30", "%Y-%m-%d"), ), Release( codename="cosmic", version="18.10", name="Cosmic Cuttlefish", development=False, lts=False, release_date=datetime.strptime("2018-10-18", "%Y-%m-%d"), esm_expires=datetime.strptime("2018-10-18", "%Y-%m-%d"), support_expires=datetime.strptime("2018-10-18", "%Y-%m-%d"), ), Release( codename="disco", version="19.04", name="Disco Dingo", development=False, lts=False, release_date=datetime.strptime("2019-04-18", "%Y-%m-%d"), esm_expires=datetime.strptime("2019-04-18", "%Y-%m-%d"), support_expires=datetime.strptime("2019-04-18", "%Y-%m-%d"), ), Release( codename="eoan", version="19.10", name="Eoan Ermine", development=False, lts=False, release_date=datetime.strptime("2019-10-17", "%Y-%m-%d"), esm_expires=datetime.strptime("2020-07-31", "%Y-%m-%d"), support_expires=datetime.strptime("2019-10-17", "%Y-%m-%d"), ), Release( codename="focal", version="20.04", name="Focal Fossa", development=False, lts=True, release_date=datetime.strptime("2020-04-23", "%Y-%m-%d"), esm_expires=datetime.strptime("2030-04-30", "%Y-%m-%d"), support_expires=datetime.strptime("2025-04-30", "%Y-%m-%d"), ), Release( codename="groovy", version="20.10", name="Groovy Gorilla", development=True, lts=False, release_date=datetime.strptime("2020-10-20", "%Y-%m-%d"), esm_expires=datetime.strptime("2021-07-31", "%Y-%m-%d"), support_expires=datetime.strptime("2021-07-31", "%Y-%m-%d"), ), Release(codename="upstream", name="Upstream"), ] for release in releases: exists = db_session.query(Release).get(release.codename) if not exists: db_session.add(release) db_session.commit()
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