Example #1
0
 def upload_file(self, artifact, attempts=3, **kwargs):
     if not self.upload_url:
         raise exceptions.InvalidValueException(
             'upload_url must be set to upload a file')
     if not artifact:
         raise exceptions.InvalidValueException(
             'A LocalArtifact must be provided in order to upload')
     r = None
     while attempts > 0 and not r:
         attempts -= 1
         artifact.seek(0)
         r = requests.put(self.upload_url, data=artifact, **kwargs)
     return r
Example #2
0
    def from_path(cls,
                  api,
                  path,
                  artifact_type=None,
                  analyze=False,
                  create=False,
                  **kwargs):
        if not isinstance(path, string_types):
            raise exceptions.InvalidValueException('Path should be a string')
        folder, file_name = os.path.split(path)
        if create:
            # TODO: this should be replaced with os.makedirs(path, exist_ok=True)
            #  once we drop support to python 2.7
            if not os.path.exists(folder):
                try:
                    os.makedirs(folder)
                except FileExistsError:
                    pass
        elif not os.path.isfile(path):
            raise exceptions.ArtifactDeletedException(
                "The file does not exist")

        mode = kwargs.pop('mode', 'wb+' if create else 'rb')
        handler = open(path, mode=mode, **kwargs)
        return cls(handler,
                   artifact_name=file_name,
                   artifact_type=artifact_type,
                   analyze=analyze,
                   polyswarm=api)
Example #3
0
 def _endpoint(cls, api, **kwargs):
     if cls.RESOURCE_ENDPOINT is None:
         raise exceptions.InvalidValueException(
             'RESOURCE_ENDPOINT is not configured for this resource.')
     return '{api.uri}{endpoint}'.format(api=api,
                                         endpoint=cls.RESOURCE_ENDPOINT,
                                         **kwargs)
Example #4
0
 def refresh_engine_cache(self):
     """
     Rrefresh the cached engine listing
     """
     engines = list(resources.Engine.list(self).result())
     if not engines:
         raise exceptions.InvalidValueException(
             "Recieved empty engines listing")
     self._engines = engines
Example #5
0
 def parse(value):
     if isinstance(value, ArtifactType):
         return value
     try:
         return ArtifactType[value.upper()]
     except Exception as e:
         raise raise_from(
             exceptions.InvalidValueException(
                 'Unable to get the artifact type from the provided value {}'
                 .format(value)), e)
Example #6
0
    def submit(self,
               artifact,
               artifact_type=resources.ArtifactType.FILE,
               artifact_name=None,
               scan_config=None):
        """
        Submit artifacts to polyswarm and return UUIDs

        :param artifact: A file-like, path to file, url or LocalArtifact instance
        :param artifact_type: The ArtifactType or strings containing "file" or "url"
        :param artifact_name: An appropriate filename for the Artifact
        :param scan_config: The scan configuration to be used, e.g.: "default", "more-time", "most-time"
        :return: An ArtifactInstance resource
        """
        logger.info('Submitting artifact of type %s', artifact_type)
        artifact_type = resources.ArtifactType.parse(artifact_type)
        # TODO This is a python 2.7 check if artifact is a file-like instance, consider changing
        #  to isinstance(artifact, io.IOBase) when deprecating 2.7 and implementing making LocalHandle
        #  inherit io.IOBase, although this will change the method delegation logic in the resource
        if hasattr(artifact, 'read') and hasattr(artifact.read, '__call__'):
            artifact = resources.LocalArtifact.from_handle(
                self,
                artifact,
                artifact_name=artifact_name or '',
                artifact_type=artifact_type)
        elif isinstance(artifact, string_types):
            if artifact_type == resources.ArtifactType.FILE:
                artifact = resources.LocalArtifact.from_path(
                    self,
                    artifact,
                    artifact_type=artifact_type,
                    artifact_name=artifact_name)
            elif artifact_type == resources.ArtifactType.URL:
                artifact = resources.LocalArtifact.from_content(
                    self,
                    artifact,
                    artifact_name=artifact_name or artifact,
                    artifact_type=artifact_type)
        if artifact_type == resources.ArtifactType.URL:
            scan_config = scan_config or 'more-time'
        if isinstance(artifact, resources.LocalArtifact):
            instance = resources.ArtifactInstance.create(
                self,
                artifact_name=artifact.artifact_name,
                artifact_type=artifact.artifact_type.name,
                scan_config=scan_config,
                community=self.community).result()
            instance.upload_file(artifact)
            return resources.ArtifactInstance.update(self,
                                                     id=instance.id).result()
        else:
            raise exceptions.InvalidValueException(
                'Artifacts should be a path to a file or a LocalArtifact instance'
            )
Example #7
0
    def __init__(self, hash_, hash_type=None, polyswarm=None):
        super(Hash, self).__init__(polyswarm=polyswarm)
        hash_ = hash_.strip()

        if hash_type and hash_type not in Hash.SUPPORTED_HASH_TYPES:
            raise exceptions.InvalidValueException(
                'Hash type provided is not supported.')

        self._hash_type = Hash.get_hash_type(hash_)

        if self._hash_type is None:
            raise exceptions.InvalidValueException(
                'Invalid hash provided: {}'.format(hash_))

        if hash_type and self.hash_type != hash_type:
            raise exceptions.InvalidValueException(
                'Detected hash type {}, got {} for hash {}'.format(
                    hash_type, self.hash_type, hash_))

        self._hash = hash_
Example #8
0
    def __init__(self, content, api=None):
        super(YaraRuleset, self).__init__(content, api=api)
        self.yara = content['yara']
        self.name = content.get('name')
        self.id = content.get('id')
        self.description = content.get('description')
        self.created = core.parse_isoformat(content.get('created'))
        self.modified = core.parse_isoformat(content.get('modified'))
        self.deleted = content.get('deleted')

        if not self.yara:
            raise exceptions.InvalidValueException(
                "Must provide yara ruleset content")
Example #9
0
    def __init__(self, json, polyswarm=None):
        super(YaraRuleset, self).__init__(json, polyswarm)
        self.yara = json['yara']
        self.name = json.get('name')
        self.id = json.get('id')
        self.description = json.get('description')
        self.created = date.parse_isoformat(json.get('created'))
        self.modified = date.parse_isoformat(json.get('modified'))
        self.deleted = json.get('deleted')

        if not self.yara:
            raise exceptions.InvalidValueException(
                "Must provide yara ruleset content")
Example #10
0
 def _parse_rule(self, rule):
     if isinstance(rule, string_types):
         rule, rule_id = resources.YaraRuleset(dict(yara=rule),
                                               api=self), None
         try:
             rule.validate()
         except exceptions.NotImportedException as e:
             logger.debug('%s\nSkipping validation.', str(e))
     elif isinstance(rule, (resources.YaraRuleset, int)):
         rule, rule_id = None, rule
     else:
         raise exceptions.InvalidValueException(
             'Either yara or rule_id must be provided.')
     return rule, rule_id
Example #11
0
    def __init__(self, *args, **kwargs):
        # hack to behave as in python 3, signature should be
        # __init__(self, content, *args, hash_value=None, hash_type=None, validate_hash=False, **kwargs)
        hash_value = kwargs.pop('hash_value', None)
        hash_type = kwargs.pop('hash_type', None)
        validate_hash = kwargs.pop('validate_hash', False)
        super(Hashable, self).__init__(*args, **kwargs)

        self._hash = hash_value.strip() if hash_value is not None else None

        if hash_type:
            if hash_type not in self.SUPPORTED_HASH_TYPES:
                raise exceptions.InvalidValueException(
                    'Hash type provided is not supported.')
            self._hash_type = hash_type
        else:
            self._hash_type = self.resolve_hash_type()

        if self._hash_type is None:
            raise exceptions.InvalidValueException(
                'Invalid hash provided: {}'.format(self._hash))

        if validate_hash:
            self.validate()
Example #12
0
    def from_hashable(cls, hash_, hash_type=None):
        """
        Coerce to Hashable object

        :param hash_: Hashable object
        :param hash_type: Hash type
        :param polyswarm: PolyswarmAPI instance
        :return: Hash
        """
        if issubclass(type(hash_), core.Hashable):
            if hash_type and hash_.hash_type != hash_type:
                raise exceptions.InvalidValueException(
                    'Detected hash type {}, got {} for hashable {}'.format(
                        hash_.hash_type, hash_type, hash_.hash))
            return Hash(hash_.hash, hash_type=hash_type)
        return Hash(hash_, hash_type=hash_type)
Example #13
0
 def from_path(cls,
               api,
               path,
               artifact_type=None,
               analyze=False,
               artifact_name=None,
               **kwargs):
     if not isinstance(path, string_types):
         raise exceptions.InvalidValueException('Path should be a string')
     artifact_name = artifact_name or os.path.basename(path)
     handle = open(path, mode='rb', **kwargs)
     # create the LocalHandle with the given handle and don't write anything to it
     return cls(b'',
                handle=handle,
                artifact_name=artifact_name,
                artifact_type=artifact_type,
                analyze=analyze,
                api=api)
Example #14
0
    def __init__(self,
                 response,
                 api=None,
                 handle=None,
                 folder=None,
                 artifact_name=None,
                 artifact_type=None,
                 analyze=False,
                 **kwargs):
        """
        A representation of an artifact we have locally

        :param artifact_name: Name of the artifact
        :param artifact_type: Type of artifact
        :param api: PolyswarmAPI instance
        :param analyze: Boolean, if True will run analyses on artifact on startup (Note: this may still run later if False)
        """
        # check if we have a destination to store the file
        # raise an error if we don't have exacltly one
        if folder and handle:
            raise exceptions.InvalidValueException(
                'Only one of path or handle should be defined.')
        if not (folder or handle):
            raise exceptions.InvalidValueException(
                'At least one of path or handle must be defined.')

        # initialize super classes and default values
        super(LocalArtifact, self).__init__(response,
                                            api=api,
                                            hash_type='sha256')
        self.sha256 = None
        self.sha1 = None
        self.md5 = None
        self.analyzed = False
        self.artifact_type = artifact_type or ArtifactType.FILE

        # resolve the file name
        if artifact_name:
            # prioritize explicitly provided name
            self.artifact_name = artifact_name
        else:
            if response:
                # respect content-disposition if there is a response
                filename = response.headers.get('content-disposition',
                                                '').partition('filename=')[2]
                if filename:
                    self.artifact_name = filename
                elif os.path.basename(getattr(handle, 'name', '')):
                    self.artifact_name = os.path.basename(
                        getattr(handle, 'name', ''))
                else:
                    self.artifact_name = os.path.basename(
                        urlparse(response.url).path)
            elif os.path.basename(getattr(handle, 'name', '')):
                # if there is no response and no artifact_name, try to get from the handle
                self.artifact_name = os.path.basename(
                    getattr(handle, 'name', ''))

        # resolve the handle to be used
        # only one of handle or folder can be provided (we checked for this above)
        # if one was explicitly provided, use it
        # if we have a folder, use a file named after file_name in that folder
        # otherwise use an in-memory handle
        remove_on_error = False
        try:
            if folder:
                # TODO: this should be replaced with os.makedirs(path, exist_ok=True)
                #  once we drop support to python 2.7
                if not os.path.exists(folder):
                    try:
                        os.makedirs(folder)
                    except FileExistsError:
                        pass
                remove_on_error = True
                self.handle = open(os.path.join(folder, self.artifact_name),
                                   mode='wb+',
                                   **kwargs)
            else:
                self.handle = handle or io.BytesIO()

            if response:
                # process the content in the response if available, write to handle
                for chunk in response.iter_content(
                        settings.DOWNLOAD_CHUNK_SIZE):
                    self.handle.write(chunk)
                    if hasattr(self.handle, 'flush'):
                        self.handle.flush()
            if analyze:
                # analyze the artifact in case it is needed
                self.analyze_artifact()
        except Exception:
            try:
                if remove_on_error and self.handle:
                    # make sure we cleanup the handle
                    # if an exception happened and this is a file we created
                    self.handle.close()
                    os.remove(self.handle.name)
            except Exception:
                logger.exception('Failed to cleanup the target file.')
            raise
Example #15
0
 def validate(self):
     hash_type = self.resolve_hash_type()
     if self.hash_type != hash_type:
         raise exceptions.InvalidValueException(
             'Detected hash type {}, got type {} for hash {}'.format(
                 hash_type, self.hash_type, self.hash))