diff --git a/pymisp/__init__.py b/pymisp/__init__.py index 55d2a19..3edf8b1 100644 --- a/pymisp/__init__.py +++ b/pymisp/__init__.py @@ -1,4 +1,9 @@ __version__ = '2.4.81.2' +import sys +import logging +logger = logging.getLogger(__name__) +FORMAT = "[%(filename)s:%(lineno)s - %(funcName)s() ] %(message)s" +logging.basicConfig(stream=sys.stderr, level=logging.WARNING, format=FORMAT) try: from .exceptions import PyMISPError, NewEventError, NewAttributeError, MissingDependency, NoURL, NoKey, InvalidMISPObject, UnknownMISPObjectTemplate # noqa @@ -9,5 +14,6 @@ try: from .tools import Neo4j # noqa from .tools import stix # noqa from .tools import openioc # noqa -except ImportError: - pass + logger.debug('pymisp loaded properly') +except ImportError as e: + logger.warning('Unable to load pymisp properly: {}'.format(e)) diff --git a/pymisp/abstract.py b/pymisp/abstract.py index a57795d..2a5d697 100644 --- a/pymisp/abstract.py +++ b/pymisp/abstract.py @@ -6,10 +6,12 @@ import json from json import JSONEncoder import collections import six # Remove that import when discarding python2 support. +import logging + +logger = logging.getLogger('pymisp') if six.PY2: - import warnings - warnings.warn("You're using python 2, it is strongly recommended to use python >=3.5") + logger.warning("You're using python 2, it is strongly recommended to use python >=3.5") class MISPEncode(JSONEncoder): diff --git a/pymisp/api.py b/pymisp/api.py index bbbfe84..3ec4ed3 100644 --- a/pymisp/api.py +++ b/pymisp/api.py @@ -9,16 +9,19 @@ import datetime import os import base64 import re -import warnings import functools import logging +logger = logging.getLogger('pymisp') try: from urllib.parse import urljoin + # Least dirty way to support python 2 and 3 + basestring = str + unicode = str except ImportError: from urlparse import urljoin - warnings.warn("You're using python 2, it is strongly recommended to use python >=3.5") + loger.warning("You're using python 2, it is strongly recommended to use python >=3.5") from io import BytesIO, open import zipfile @@ -40,19 +43,6 @@ from .exceptions import PyMISPError, SearchError, MissingDependency, NoURL, NoKe from .mispevent import MISPEvent, MISPAttribute from .abstract import MISPEncode -logger = logging.getLogger(__name__) - - -# Least dirty way to support python 2 and 3 -try: - basestring - unicode - warnings.warn("You're using python 2, it is strongly recommended to use python >=3.4") -except NameError: - basestring = str - unicode = str - - def deprecated(func): '''This is a decorator which can be used to mark functions as deprecated. It will result in a warning being emitted @@ -99,14 +89,14 @@ class PyMISP(object): self.cert = cert self.asynch = asynch if asynch and not ASYNC_OK: - warnings.warn("You turned on Async, but don't have requests_futures installed") + logger.warning("You turned on Async, but don't have requests_futures installed") self.asynch = False self.resources_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'data') if out_type != 'json': raise PyMISPError('The only output type supported by PyMISP is JSON. If you still rely on XML, use PyMISP v2.4.49') if debug is not None: - warnings.warn('debug is deprecated, configure logging in api client') + logger.warning('debug is deprecated, configure logging in your script: import logging; logging.getLogger(\'pymisp\').setLevel(logging.DEBUG)') try: # Make sure the MISP instance is working and the URL is valid @@ -163,6 +153,8 @@ class PyMISP(object): 'Accept': 'application/{}'.format(output), 'content-type': 'application/{}'.format(output), 'User-Agent': 'PyMISP {} - Python {}.{}.{}'.format(__version__, *sys.version_info)}) + if logger.isEnabledFor(logging.DEBUG): + logger.debug(session.headers) return session # ##################### @@ -209,15 +201,16 @@ class PyMISP(object): def _check_response(self, response): """Check if the response from the server is not an unexpected error""" + errors = [] if response.status_code >= 500: - response.raise_for_status() + errors.append(response.json()) + logger.critical('Something bad happened on the server-side: {}'.format(response.json())) try: to_return = response.json() except ValueError: - logger.debug(response.text) - raise PyMISPError('Unknown error: {}'.format(response.text)) + # It the server didn't return a JSON blob, we've a problem. + raise PyMISPError('Unknown error (something is very broken server-side: {}'.format(response.text)) - errors = [] if isinstance(to_return, (list, str)): to_return = {'response': to_return} if to_return.get('error'): @@ -905,8 +898,9 @@ class PyMISP(object): if controller not in ['events', 'attributes']: raise Exception('Invalid controller. Can only be {}'.format(', '.join(['events', 'attributes']))) url = urljoin(self.root_url, '{}/{}'.format(controller, path.lstrip('/'))) - logger.debug('URL: %s', url) - logger.debug('Query: %s', query) + if logger.isEnabledFor(logging.DEBUG): + logger.debug('URL: %s', url) + logger.debug('Query: %s', query) if ASYNC_OK and isinstance(session, FuturesSession) and async_callback: response = session.post(url, data=json.dumps(query), background_callback=async_callback) @@ -1699,6 +1693,8 @@ class PyMISP(object): """Add an object""" session = self.__prepare_session() url = urljoin(self.root_url, 'objects/add/{}/{}'.format(event_id, template_id)) + if logger.isEnabledFor(logging.DEBUG): + logger.debug(url) response = session.post(url, data=misp_object.to_json()) return self._check_response(response) diff --git a/pymisp/data/misp-objects b/pymisp/data/misp-objects index bbf3e45..6b43b68 160000 --- a/pymisp/data/misp-objects +++ b/pymisp/data/misp-objects @@ -1 +1 @@ -Subproject commit bbf3e45649af5af50c98ad90a86916cf75e8c74d +Subproject commit 6b43b68651a350a26891080ef0feda364b74727a diff --git a/pymisp/mispevent.py b/pymisp/mispevent.py index 20eeb49..fc435fa 100644 --- a/pymisp/mispevent.py +++ b/pymisp/mispevent.py @@ -16,12 +16,13 @@ from collections import Counter from .abstract import AbstractMISP from .exceptions import UnknownMISPObjectTemplate, InvalidMISPObject, PyMISPError, NewEventError, NewAttributeError +import logging +logger = logging.getLogger('pymisp') import six # Remove that import when discarding python2 support. if six.PY2: - import warnings - warnings.warn("You're using python 2, it is strongly recommended to use python >=3.5") + logger.warning("You're using python 2, it is strongly recommended to use python >=3.5") try: from dateutil.parser import parse diff --git a/pymisp/tools/create_misp_object.py b/pymisp/tools/create_misp_object.py index be16ae3..faa1258 100644 --- a/pymisp/tools/create_misp_object.py +++ b/pymisp/tools/create_misp_object.py @@ -3,7 +3,9 @@ from . import FileObject, PEObject, ELFObject, MachOObject from ..exceptions import MISPObjectException -import warnings +import logging + +logger = logging.getLogger('pymisp') try: import lief @@ -57,15 +59,15 @@ def make_binary_objects(filepath=None, pseudofile=None, filename=None): elif isinstance(lief_parsed, lief.MachO.Binary): return make_macho_objects(lief_parsed, misp_file) except lief.bad_format as e: - warnings.warn('\tBad format: {}'.format(e)) + logger.warning('Bad format: {}'.format(e)) except lief.bad_file as e: - warnings.warn('\tBad file: {}'.format(e)) + logger.warning('Bad file: {}'.format(e)) except lief.parser_error as e: - warnings.warn('\tParser error: {}'.format(e)) + logger.warning('Parser error: {}'.format(e)) except FileTypeNotImplemented as e: # noqa - warnings.warn(e) + logger.warning(e) if not HAS_LIEF: - warnings.warn('Please install lief, documentation here: https://github.com/lief-project/LIEF') + logger.warning('Please install lief, documentation here: https://github.com/lief-project/LIEF') if not filepath: - warnings.warn('LIEF currently requires a filepath and not a pseudo file') + logger.warning('LIEF currently requires a filepath and not a pseudo file') return misp_file, None, None diff --git a/pymisp/tools/elfobject.py b/pymisp/tools/elfobject.py index ee3bd29..d9c9561 100644 --- a/pymisp/tools/elfobject.py +++ b/pymisp/tools/elfobject.py @@ -5,8 +5,9 @@ from .abstractgenerator import AbstractMISPObjectGenerator from ..exceptions import InvalidMISPObject from io import BytesIO from hashlib import md5, sha1, sha256, sha512 -import warnings +import logging +logger = logging.getLogger('pymisp') try: import lief @@ -25,7 +26,7 @@ class ELFObject(AbstractMISPObjectGenerator): def __init__(self, parsed=None, filepath=None, pseudofile=None): if not HAS_PYDEEP: - warnings.warn("Please install pydeep: pip install git+https://github.com/kbandla/pydeep.git") + logger.warning("Please install pydeep: pip install git+https://github.com/kbandla/pydeep.git") if not HAS_LIEF: raise ImportError('Please install lief, documentation here: https://github.com/lief-project/LIEF') if pseudofile: diff --git a/pymisp/tools/fileobject.py b/pymisp/tools/fileobject.py index e75884c..a12d38f 100644 --- a/pymisp/tools/fileobject.py +++ b/pymisp/tools/fileobject.py @@ -8,7 +8,10 @@ from io import BytesIO from hashlib import md5, sha1, sha256, sha512 import math from collections import Counter -import warnings +import logging + +logger = logging.getLogger('pymisp') + try: import pydeep @@ -27,9 +30,9 @@ class FileObject(AbstractMISPObjectGenerator): def __init__(self, filepath=None, pseudofile=None, filename=None): if not HAS_PYDEEP: - warnings.warn("Please install pydeep: pip install git+https://github.com/kbandla/pydeep.git") + logger.warning("Please install pydeep: pip install git+https://github.com/kbandla/pydeep.git") if not HAS_MAGIC: - warnings.warn("Please install python-magic: pip install python-magic.") + logger.warning("Please install python-magic: pip install python-magic.") if filename: # Useful in case the file is copied with a pre-defined name by a script but we want to keep the original name self.__filename = filename diff --git a/pymisp/tools/machoobject.py b/pymisp/tools/machoobject.py index 15663c9..6cf3fa2 100644 --- a/pymisp/tools/machoobject.py +++ b/pymisp/tools/machoobject.py @@ -5,7 +5,9 @@ from ..exceptions import InvalidMISPObject from .abstractgenerator import AbstractMISPObjectGenerator from io import BytesIO from hashlib import md5, sha1, sha256, sha512 -import warnings +import logging + +logger = logging.getLogger('pymisp') try: @@ -25,7 +27,7 @@ class MachOObject(AbstractMISPObjectGenerator): def __init__(self, parsed=None, filepath=None, pseudofile=None): if not HAS_PYDEEP: - warnings.warn("Please install pydeep: pip install git+https://github.com/kbandla/pydeep.git") + logger.warning("Please install pydeep: pip install git+https://github.com/kbandla/pydeep.git") if not HAS_LIEF: raise ImportError('Please install lief, documentation here: https://github.com/lief-project/LIEF') if pseudofile: diff --git a/pymisp/tools/peobject.py b/pymisp/tools/peobject.py index 3467243..2e8bf4a 100644 --- a/pymisp/tools/peobject.py +++ b/pymisp/tools/peobject.py @@ -6,8 +6,9 @@ from .abstractgenerator import AbstractMISPObjectGenerator from io import BytesIO from hashlib import md5, sha1, sha256, sha512 from datetime import datetime -import warnings +import logging +logger = logging.getLogger('pymisp') try: import lief @@ -26,7 +27,7 @@ class PEObject(AbstractMISPObjectGenerator): def __init__(self, parsed=None, filepath=None, pseudofile=None): if not HAS_PYDEEP: - warnings.warn("Please install pydeep: pip install git+https://github.com/kbandla/pydeep.git") + logger.warning("Please install pydeep: pip install git+https://github.com/kbandla/pydeep.git") if not HAS_LIEF: raise ImportError('Please install lief, documentation here: https://github.com/lief-project/LIEF') if pseudofile: