From 9f06ea81a067ce25cfe0e7d74566e7643bb762ba Mon Sep 17 00:00:00 2001 From: amel Date: Tue, 22 Feb 2022 16:13:11 +0000 Subject: [PATCH] Email report with group filter --- examples/email_report_filters.md | 219 +++++++++++++++++++++++++++++++ 1 file changed, 219 insertions(+) create mode 100644 examples/email_report_filters.md diff --git a/examples/email_report_filters.md b/examples/email_report_filters.md new file mode 100644 index 0000000..15c183c --- /dev/null +++ b/examples/email_report_filters.md @@ -0,0 +1,219 @@ +"""Generate a HTML email with the summary""" + +import os +import smtplib +import ssl +from configparser import ConfigParser +from datetime import datetime +from email.mime.text import MIMEText +from cbw_api_toolbox.cbw_api import CBWApi + +CONF = ConfigParser() +CONF.read(os.path.join(os.path.abspath( + os.path.dirname(__file__)), '..', 'api.conf')) + +############################################################ +# CONFIGURATION - USE THIS SECTION TO CUSTOMIZE YOUR REPORTS +############################################################ + +# Filters to use, please comment unused parameters +# ( ["group"] or ["groupA", "groupB", "groupC"]...) +GROUPS = ["GROUPE_1","GROUP_2"] + +# Add the following block to api.conf and set variables in SMTP_SETTINGS: +# [SMTP] +# server = +# login = +# password = + +SMTP_SETTINGS = { + "server": CONF.get('SMTP', 'server'), + "port": 587, + "username": CONF.get('SMTP', 'login'), + "password": CONF.get('SMTP', 'password'), + "sender": "", + "recipient": "" +} + +############################################################ + +print("! Testing communication with Cyberwatch API") +CLIENT = CBWApi(CONF.get('cyberwatch', 'url'), CONF.get( + 'cyberwatch', 'api_key'), CONF.get('cyberwatch', 'secret_key')) +API_URL = CONF.get('cyberwatch', 'url') + +CLIENT.ping() + + +def find_groups_details(GROUPS): + '''d''' + groups_id = [] + all_groups = CLIENT.groups() + for group in GROUPS: + for group_detail in all_groups: + if group_detail.name == group: + groups_id.append(group_detail.id) + return groups_id + + +def get_servers_details(): + '''Find servers with group filters''' + server_details = [] + for group_id in find_groups_details(GROUPS): + filters = {"group_id": group_id} + servers_with_groups = CLIENT.servers(filters) + for server in servers_with_groups: + server_details.append(CLIENT.server(str(server.id))) + return server_details + + +def build_data(): + '''dd''' + + data_for_mail = [] + + critical_cve_details_list = {} + + for server in get_servers_details(): + data = { + 'server_id':server.id, + 'hostname':server.hostname, + 'cve_count': 0, + 'critical_count': 0, + 'critical_with_exploit': 0, + 'critical_issues': 0, + 'major_issues': 0, + } + for cve in server.cve_announcements: + data['cve_count'] += 1 + + if cve.score is not None and cve.score >= 9: + data['critical_count'] += 1 + if cve.cve_code not in critical_cve_details_list: + # faire un appel a l'api pour les details CVEs et stocker dans "critical_cve_details_list" pour eviter de dupliquer les appels + # ensuite calculer "critical_with_exploit" + critical_cve_details_list[cve.cve_code] = CLIENT.cve_announcement(str(cve.cve_code)) + if critical_cve_details_list[cve.cve_code].exploitable : + data['critical_with_exploit'] += 1 + else: + # Si deja dans la liste, juste faire le calcul de "critical_with_exploit" + if critical_cve_details_list[cve.cve_code].exploitable : + data['critical_with_exploit'] += 1 + print("") + + # Ensuite faire le calcul pour "critical_issues" et "major_issues" avant de build_email avec les donnees et envoyer le mail + for security_issue in server.security_issues: + if security_issue.level == "level_critical": + data['critical_issues'] += 1 + if security_issue.level == "level_major": + data['major_issues'] += 1 + + data_for_mail.append(data) + return data_for_mail + + +def build_email(cve_counts): + '''Build HTML for email''' + html_start = """ + + + + + + + + + + + + + + + + + + + +""" + if cve_counts == {}: + html = "

Aucun serveur avec une CVE critique, une CVE critique avec exploit ou un défaut de sécurité critique/majeur correspondant aux critères définis n'a été remonté

" + data = html_start + html + html_end + return data + + html_start += """ + + +Serveur +CVE +CVE critiques +CVE critiques avec exploit disponible +Défauts de sécurité critiques +Défauts de sécurité majeurs + + + +""" + for line in cve_counts: + html_for_each = """ + +{} +{} +{} +{} +{} +{} +""".format(API_URL,line['server_id'],line['hostname'], line['cve_count'], line['critical_count'], line['critical_with_exploit'], line['critical_issues'], line['major_issues']) + + html_start += html_for_each + + html_start += html_end + + return html_start + +cve_counts = build_data() +HTML = build_email(cve_counts) +print("! Testing communication with SMTP server") +context = ssl.create_default_context() +smtpserver = smtplib.SMTP(SMTP_SETTINGS["server"], SMTP_SETTINGS["port"]) +smtpserver.ehlo() # Can be omitted +smtpserver.starttls(context=context) # Secure the connection +smtpserver.ehlo() # Can be omitted +smtpserver.login(SMTP_SETTINGS["username"], SMTP_SETTINGS["password"]) +print("INFO:OK") + +today = datetime.now().strftime("%Y-%m-%d %H:%M") +msg = MIMEText(HTML, 'html', 'utf-8') +msg['Subject'] = 'Cyberwatch - Bilan du '+ today +msg['From'] = SMTP_SETTINGS["sender"] +msg['To'] = SMTP_SETTINGS["recipient"] +smtpserver.send_message(msg) + +smtpserver.quit()