mirror of https://github.com/MISP/PyMISP
				
				
				
			
		
			
				
	
	
		
			115 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
			
		
		
	
	
			115 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
| #!/usr/bin/env python3
 | |
| # -*- coding: utf-8 -*-
 | |
| 
 | |
| import argparse
 | |
| from datetime import date
 | |
| import importlib
 | |
| 
 | |
| from pymisp import MISPEvent
 | |
| from defang import defang
 | |
| from pytaxonomies import Taxonomies
 | |
| 
 | |
| 
 | |
| class ReportGenerator():
 | |
|     def __init__(self, profile="daily_report"):
 | |
|         self.taxonomies = Taxonomies()
 | |
|         self.report = ''
 | |
|         profile_name = "profiles.{}".format(profile)
 | |
|         self.template = importlib.import_module(name=profile_name)
 | |
| 
 | |
|     def from_remote(self, event_id):
 | |
|         from pymisp import PyMISP
 | |
|         from keys import misp_url, misp_key, misp_verifycert
 | |
|         misp = PyMISP(misp_url, misp_key, misp_verifycert)
 | |
|         result = misp.get(event_id)
 | |
|         self.misp_event = MISPEvent()
 | |
|         self.misp_event.load(result)
 | |
| 
 | |
|     def from_file(self, path):
 | |
|         self.misp_event = MISPEvent()
 | |
|         self.misp_event.load_file(path)
 | |
| 
 | |
|     def attributes(self):
 | |
|         if not self.misp_event.attributes:
 | |
|             return ''
 | |
|         list_attributes = []
 | |
|         for attribute in self.misp_event.attributes:
 | |
|             if attribute.type in self.template.types_to_attach:
 | |
|                 list_attributes.append("* {}".format(defang(attribute.value)))
 | |
|         for obj in self.misp_event.Object:
 | |
|             if obj.name in self.template.objects_to_attach:
 | |
|                 for attribute in obj.Attribute:
 | |
|                     if attribute.type in self.template.types_to_attach:
 | |
|                         list_attributes.append("* {}".format(defang(attribute.value)))
 | |
|         return self.template.attributes.format(list_attributes="\n".join(list_attributes))
 | |
| 
 | |
|     def _get_tag_info(self, machinetag):
 | |
|         return self.taxonomies.revert_machinetag(machinetag)
 | |
| 
 | |
|     def report_headers(self):
 | |
|         content = {'org_name': 'name',
 | |
|                    'date': date.today().isoformat()}
 | |
|         self.report += self.template.headers.format(**content)
 | |
| 
 | |
|     def event_level_tags(self):
 | |
|         if not self.misp_event.Tag:
 | |
|             return ''
 | |
|         for tag in self.misp_event.Tag:
 | |
|             # Only look for TLP for now
 | |
|             if tag['name'].startswith('tlp'):
 | |
|                 tax, predicate = self._get_tag_info(tag['name'])
 | |
|                 return self.template.event_level_tags.format(value=predicate.predicate.upper(), expanded=predicate.expanded)
 | |
| 
 | |
|     def title(self):
 | |
|         internal_id = ''
 | |
|         summary = ''
 | |
|         # Get internal refs for report
 | |
|         for obj in self.misp_event.Object:
 | |
|             if obj.name != 'report':
 | |
|                 continue
 | |
|             for a in obj.Attribute:
 | |
|                 if a.object_relation == 'case-number':
 | |
|                     internal_id = a.value
 | |
|                 if a.object_relation == 'summary':
 | |
|                     summary = a.value
 | |
| 
 | |
|         return self.template.title.format(internal_id=internal_id, title=self.misp_event.info,
 | |
|                                           summary=summary)
 | |
| 
 | |
|     def asciidoc(self, lang='en'):
 | |
|         self.report += self.title()
 | |
|         self.report += self.event_level_tags()
 | |
|         self.report += self.attributes()
 | |
| 
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     try:
 | |
|         parser = argparse.ArgumentParser(description='Create a human-readable report out of a MISP event')
 | |
|         parser.add_argument("--profile", default="daily_report", help="Profile template to use")
 | |
|         parser.add_argument("-o", "--output", help="Output file to write to (generally ends in .adoc)")
 | |
|         group = parser.add_mutually_exclusive_group(required=True)
 | |
|         group.add_argument("-e", "--event", default=[], nargs='+', help="Event ID to get.")
 | |
|         group.add_argument("-p", "--path", default=[], nargs='+', help="Path to the JSON dump.")
 | |
| 
 | |
|         args = parser.parse_args()
 | |
| 
 | |
|         report = ReportGenerator(args.profile)
 | |
|         report.report_headers()
 | |
| 
 | |
|         if args.event:
 | |
|             for eid in args.event:
 | |
|                 report.from_remote(eid)
 | |
|                 report.asciidoc()
 | |
|         else:
 | |
|             for f in args.path:
 | |
|                 report.from_file(f)
 | |
|                 report.asciidoc()
 | |
| 
 | |
|         if args.output:
 | |
|             with open(args.output, "w") as ofile:
 | |
|                 ofile.write(report.report)
 | |
|         else:
 | |
|             print(report.report)
 | |
|     except ModuleNotFoundError as err:
 | |
|         print(err)
 |