Beispiel #1
0
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
Beispiel #2
0
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)
Beispiel #3
0
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
Beispiel #4
0
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