def report(link): report = Report.query.filter_by(public_link=link).first() if not report: return redirect(url_for("main.reports")) # The report is now seen report.seen = True db.session.commit() alerts = Alert.query.options( joinedload("cve")).filter_by(report_id=report.id).all() # List of vendors/products per alert alerts_sorted = {} for alert in alerts: for vendor in alert.details["vendors"]: if vendor not in alerts_sorted: alerts_sorted[vendor] = { "name": _humanize_filter(vendor), "alerts": [], "max": 0, } alerts_sorted[vendor]["alerts"].append(alert) for product in alert.details["products"]: if product not in alerts_sorted: alerts_sorted[product] = { "name": _humanize_filter(product), "alerts": [], "max": 0, } alerts_sorted[product]["alerts"].append(alert) # For each vendor, we take the max score for k, als in alerts_sorted.items(): # Get the max score cvss = [al.cve.cvss3 for al in als["alerts"] if al.cve.cvss3] if cvss: alerts_sorted[k]["max"] = max(cvss) alerts_sorted = OrderedDict( sorted(alerts_sorted.items(), key=lambda i: i[1]["max"], reverse=True)) # Some stats total_alerts = len(alerts) maximum_score = max([v["max"] for k, v in alerts_sorted.items()]) return render_template( "report.html", alerts_sorted=alerts_sorted, total_alerts=total_alerts, total_vendors_products=len(alerts_sorted.keys()), maximum_score=maximum_score, report=report, )
def report(link): report = ReportController.get({"public_link": link}) alerts = AlertController.list_items({"report_id": report.id}) # List of vendors/products per alert alerts_sorted = {} for alert in alerts: for vendor in alert.details["vendors"]: if vendor not in alerts_sorted: alerts_sorted[vendor] = { "name": _humanize_filter(vendor), "alerts": [], "max": 0, } alerts_sorted[vendor]["alerts"].append(alert) for product in alert.details["products"]: if product not in alerts_sorted: alerts_sorted[product] = { "name": _humanize_filter(product), "alerts": [], "max": 0, } alerts_sorted[product]["alerts"].append(alert) # For each vendor, we take the max score for k, als in alerts_sorted.items(): # Get the max score cvss = [al.cve.cvss3 for al in als["alerts"] if al.cve.cvss3] if cvss: alerts_sorted[k]["max"] = max(cvss) alerts_sorted = OrderedDict( sorted(alerts_sorted.items(), key=lambda i: i[1]["max"], reverse=True) ) # Some stats total_alerts = len(alerts) maximum_score = max([v["max"] for k, v in alerts_sorted.items()]) return render_template( "report.html", alerts_sorted=alerts_sorted, total_alerts=total_alerts, total_vendors_products=len(alerts_sorted.keys()), maximum_score=maximum_score, report=report, )
def get_sorted_alerts(alerts): """ Sort the alerts by vendors and products then extract their max score. """ alerts_sorted = {} for alert in alerts: for vendor in alert.details["vendors"]: if vendor not in alerts_sorted: alerts_sorted[vendor] = { "name": _humanize_filter(vendor), "alerts": [], "max": 0, } alerts_sorted[vendor]["alerts"].append(alert) for product in alert.details["products"]: if product not in alerts_sorted: alerts_sorted[product] = { "name": _humanize_filter(product), "alerts": [], "max": 0, } alerts_sorted[product]["alerts"].append(alert) # For each vendor, we take the max score for k, als in alerts_sorted.items(): # Get the max score cvss = [al.cve.cvss3 for al in als["alerts"] if al.cve.cvss3] if cvss: alerts_sorted[k]["max"] = max(cvss) alerts_sorted = OrderedDict( sorted(alerts_sorted.items(), key=lambda i: i[1]["max"], reverse=True)) return alerts_sorted
def human_name(self): return _humanize_filter(self.name)
def humanize_filter(s): return _humanize_filter(s)
def handle_reports(): cel.app.app_context().push() # The server name is mandatory to generate the mails if not cel.app.config.get("SERVER_NAME"): raise ValueError( "The `server_name` variable is not set in your `opencve.cf` file. " "Please configure it to allow OpenCVE to create reports and send the mails." ) query = User.query.filter(User.alerts.any(Alert.notify == False)) # If we are between 11:00 AM and 11:15 AM, we get all the users (including `once` # and `always`). Otherwise we just take the `always` ones. # /!\ TODO : change this ! It can happen that a previous job takes too much time, # so this period can be sometimes no reached. now = datetime.now() if time(11, 0) <= now.time() <= time(11, 15): logger.info( "We are between 11:00 AM and 11:15 AM, get all the users...") users = query.all() else: logger.info("Get the users who want to always receive email...") users = query.filter(User.frequency_notifications == "always").all() if not users: logger.info("No alert to send.") return # Get alerts for all users, create a report containing it # and send a mail with the top alerts. logger.info("Checking {} users with alerts to send...".format(len(users))) for user in users: alerts = Alert.query.filter_by(user=user, notify=False).all() count_alerts = len(alerts) logger.info("{} alerts to notify for {}".format( count_alerts, user.username)) # Order the Top 10 alerts top_alerts = (db.session.query(Alert.id).filter_by( user=user, notify=False).join(Alert.cve).order_by( Cve.cvss3.desc()).limit(10).all()) # Then we convert this list of ID in a list of objects top_alerts = [alert[0] for alert in top_alerts] top_alerts = db.session.query(Alert).filter( Alert.id.in_(top_alerts)).all() # List of vendors/products per alert alerts_sorted = {} for alert in top_alerts: for vendor in alert.details["vendors"]: if vendor not in alerts_sorted: alerts_sorted[vendor] = { "name": _humanize_filter(vendor), "alerts": [], "max": 0, } alerts_sorted[vendor]["alerts"].append(alert) for product in alert.details["products"]: if product not in alerts_sorted: alerts_sorted[product] = { "name": _humanize_filter(product), "alerts": [], "max": 0, } alerts_sorted[product]["alerts"].append(alert) # For each vendor, we take the max score for k, als in alerts_sorted.items(): # Get the max score cvss = [al.cve.cvss3 for al in als["alerts"] if al.cve.cvss3] if cvss: alerts_sorted[k]["max"] = max(cvss) alerts_sorted = OrderedDict( sorted(alerts_sorted.items(), key=lambda i: i[1]["max"], reverse=True)) # Get the vendors and products of all alerts all_vendors_products = [] for alert in alerts: all_vendors_products.extend( sorted( list(set(alert.details["vendors"])) + list(set(alert.details["products"])))) # Remove duplicates all_vendors_products = sorted(list(set(all_vendors_products))) # Humanize it for the mail title all_vendors_products_humanized = list( map(_humanize_filter, all_vendors_products)) # Create the report report = Report(user=user, alerts=alerts, details=all_vendors_products) db.session.add(report) db.session.commit() logger.info("Report {0} created.".format(report.id)) if not user.enable_notifications: logger.info( "User {} do not want to receive email notifications, skip it.". format(user.username)) else: alert_str = "alerts" if len(alerts) > 1 else "alert" subject = "{count} {alerts} on {vendors}".format( count=count_alerts, alerts=alert_str, vendors=", ".join(all_vendors_products_humanized), ) user_manager.email_manager.send_user_report( user, **{ "subject": subject, "total_alerts": count_alerts, "alerts_sorted": alerts_sorted, "report_public_link": report.public_link, }) logger.info("Mail sent for {}".format(user.email)) # The alerts have been notified for alert in alerts: alert.notify = True db.session.commit()
def format(self, value): return _humanize_filter(value)