Multiple updates, cleanup

* Remove attribute (Fix #4)
* Deprecate pure XML API
* Cleanups and fixes in the upload file functionality
pull/2/merge
Raphaël Vinot 2015-08-28 17:03:35 +02:00
parent e4d96bd198
commit c7b03640fb
2 changed files with 80 additions and 25 deletions

30
examples/suricata.py Executable file
View File

@ -0,0 +1,30 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pymisp import PyMISP
from keys import url_priv, key_priv
# from keys import url_cert, key_cert
import argparse
def init(url, key):
return PyMISP(url, key, True, 'json')
def fetch(m, all_events, event):
if all_events:
print(misp.download_all_suricata().text)
else:
print(misp.download_suricata_rule_event(event).text)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Download Suricata events.')
parser.add_argument("-a", "--all", action='store_true', help="Download all suricata rules available.")
parser.add_argument("-e", "--event", help="Download suricata rules from one event.")
args = parser.parse_args()
misp = init(url_priv, key_priv)
# misp = init(url_cert, key_cert)
fetch(misp, args.all, args.event)

View File

@ -11,6 +11,8 @@ import base64
from urlparse import urljoin from urlparse import urljoin
import StringIO import StringIO
import zipfile import zipfile
import warnings
import functools
class PyMISPError(Exception): class PyMISPError(Exception):
@ -27,6 +29,23 @@ class NewAttributeError(PyMISPError):
pass pass
def deprecated(func):
'''This is a decorator which can be used to mark functions
as deprecated. It will result in a warning being emitted
when the function is used.'''
@functools.wraps(func)
def new_func(*args, **kwargs):
warnings.warn_explicit(
"Call to deprecated function {}.".format(func.__name__),
category=DeprecationWarning,
filename=func.func_code.co_filename,
lineno=func.func_code.co_firstlineno + 1
)
return func(*args, **kwargs)
return new_func
class PyMISP(object): class PyMISP(object):
""" """
Python API for MISP Python API for MISP
@ -139,6 +158,11 @@ class PyMISP(object):
url = urljoin(self.root_url, 'events/{}'.format(event_id)) url = urljoin(self.root_url, 'events/{}'.format(event_id))
return session.delete(url) return session.delete(url)
def delete_attribute(self, attribute_id):
session = self.__prepare_session()
url = urljoin(self.root_url, 'attributes/{}'.format(attribute_id))
return session.delete(url)
# ######### Create/update events through the API ######### # ######### Create/update events through the API #########
def _create_event(self, distribution, threat_level_id, analysis, info): def _create_event(self, distribution, threat_level_id, analysis, info):
@ -173,32 +197,29 @@ class PyMISP(object):
return to_post return to_post
def prepare_sample(self, filename, filepath): # ############ Samples ############
with open(filepath, 'rb') as f:
return {'files': [{'filename': filename, 'data': base64.b64encode(f.read())}]}
def prepare_samplelist(self, filepaths): def _encode_file_to_upload(self, path):
files = [] with open(path, 'rb') as f:
for path in filepaths: return base64.b64encode(f.read())
if not os.path.isfile(path):
continue
files.append({'filename': os.path.basename(path), 'data': path})
return {'files': files}
def upload_sample(self, filename, filepath, event_id, distribution, to_ids, def upload_sample(self, filename, filepath, event_id, distribution, to_ids,
category, info, analysis, threat_level_id): category, info, analysis, threat_level_id):
to_post = self.prepare_attribute(event_id, distribution, to_ids, category, to_post = self.prepare_attribute(event_id, distribution, to_ids, category,
info, analysis, threat_level_id) info, analysis, threat_level_id)
to_post['request'].update(self.prepare_sample(filename, filepath)) to_post['request']['files'] = [{'filename': filename, 'data': self._encode_file_to_upload(filepath)}]
return self._upload_sample(to_post) return self._upload_sample(to_post)
def upload_samplelist(self, filepaths, event_id, distribution, to_ids, category, def upload_samplelist(self, filepaths, event_id, distribution, to_ids, category,
info, analysis, threat_level_id): info, analysis, threat_level_id):
to_post = self.prepare_attribute(event_id, distribution, to_ids, category, to_post = self.prepare_attribute(event_id, distribution, to_ids, category,
info, analysis, threat_level_id) info, analysis, threat_level_id)
to_post['request'].update(self.prepare_samplelist(filepaths)) files = []
for path in filepaths:
if not os.path.isfile(path):
continue
files.append({'filename': os.path.basename(path), 'data': self._encode_file_to_upload(path)})
to_post['request']['files'] = files
return self._upload_sample(to_post) return self._upload_sample(to_post)
def _upload_sample(self, to_post): def _upload_sample(self, to_post):
@ -322,10 +343,10 @@ class PyMISP(object):
archive = zipfile.ZipFile(zipped) archive = zipfile.ZipFile(zipped)
try: try:
# New format # New format
unzipped = StringIO.StringIO(archive.open(f['filename'], pwd='infected').read()) unzipped = StringIO.StringIO(archive.open(f['md5'], pwd='infected').read())
except KeyError: except KeyError:
# Old format # Old format
unzipped = StringIO.StringIO(archive.open(f['md5'], pwd='infected').read()) unzipped = StringIO.StringIO(archive.open(f['filename'], pwd='infected').read())
details.append([f['event_id'], f['filename'], unzipped]) details.append([f['event_id'], f['filename'], unzipped])
return True, details return True, details
@ -337,15 +358,7 @@ class PyMISP(object):
""" """
return self.search(last=last) return self.search(last=last)
# ############## Export ############### # ############## Suricata ###############
def download_all(self):
"""
Download all event from the instance
"""
xml = urljoin(self.root_url, 'events/xml/download')
session = self.__prepare_session('xml')
return session.get(xml)
def download_all_suricata(self): def download_all_suricata(self):
""" """
@ -365,6 +378,18 @@ class PyMISP(object):
session = self.__prepare_session('rules') session = self.__prepare_session('rules')
return session.get(template) return session.get(template)
# ############## Deprecated (Pure XML API should not be used) ##################
@deprecated
def download_all(self):
"""
Download all event from the instance
"""
xml = urljoin(self.root_url, 'events/xml/download')
session = self.__prepare_session('xml')
return session.get(xml)
@deprecated
def download(self, event_id, with_attachement=False): def download(self, event_id, with_attachement=False):
""" """
Download one event in XML Download one event in XML