polyswarm-api 3.8.0__tar.gz → 3.10.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: polyswarm-api
3
- Version: 3.8.0
3
+ Version: 3.10.0
4
4
  Summary: Client library to simplify interacting with the PolySwarm consumer API
5
5
  Home-page: https://github.com/polyswarm/polyswarm-api
6
6
  Author: PolySwarm Developers
@@ -9,7 +9,7 @@ with open('README.md', 'r') as readme:
9
9
 
10
10
  setup(
11
11
  name='polyswarm-api',
12
- version='3.8.0',
12
+ version='3.10.0',
13
13
  description='Client library to simplify interacting with the PolySwarm consumer API',
14
14
  long_description=long_description,
15
15
  long_description_content_type='text/markdown',
@@ -1,5 +1,5 @@
1
1
  # https://www.python.org/dev/peps/pep-0008/#module-level-dunder-names
2
- __version__ = '3.8.0'
2
+ __version__ = '3.10.0'
3
3
  __release_url__ = 'https://api.github.com/repos/polyswarm/polyswarm-api/releases/latest'
4
4
 
5
5
  from . import api
@@ -1,3 +1,4 @@
1
+ import io
1
2
  import logging
2
3
  import time
3
4
 
@@ -217,8 +218,7 @@ class PolyswarmAPI:
217
218
  artifact_type=resources.ArtifactType.FILE,
218
219
  artifact_name=None,
219
220
  scan_config=None,
220
- is_zip=False,
221
- zip_password=None,
221
+ preprocessing=None,
222
222
  ):
223
223
  """
224
224
  Submit artifacts to polyswarm
@@ -227,18 +227,18 @@ class PolyswarmAPI:
227
227
  :param artifact_type: The ArtifactType or strings containing "file" or "url"
228
228
  :param artifact_name: An appropriate filename for the Artifact
229
229
  :param scan_config: The scan configuration to be used, e.g.: "default", "more-time", "most-time"
230
- :param is_zip: If this flag is set, will handle the file as a zip
231
- in the server and decompress before processing.
232
- :param zip_password: Will use this password to decompress the zip file.
233
- If provided, will handle the file as a zip.
230
+ :param preprocessing: Preprocessing settings to be applied to the artifact, None means no preprocessing,
231
+ otherwise a dict with the following attributes can be passed:
232
+ - type (string): either "zip" or "qrcode", the first mean the file is a zip that
233
+ the server has to decompress to then scan the content (only one file inside allowed).
234
+ "qrcode" means the file is a QR Code image with a URL as payload, and you want
235
+ to scan the URL, not the actual file (artifact_type has to be "URL").
236
+ - password (string, optional): will use this password to decompress the zip file.
234
237
  :return: An ArtifactInstance resource
235
238
  """
236
239
  logger.info('Submitting artifact of type %s', artifact_type)
237
240
  artifact_type = resources.ArtifactType.parse(artifact_type)
238
- # TODO This is a python 2.7 check if artifact is a file-like instance, consider changing
239
- # to isinstance(artifact, io.IOBase) when deprecating 2.7 and implementing making LocalHandle
240
- # inherit io.IOBase, although this will change the method delegation logic in the resource
241
- if hasattr(artifact, 'read') and hasattr(artifact.read, '__call__'):
241
+ if isinstance(artifact, io.IOBase):
242
242
  artifact = resources.LocalArtifact.from_handle(self, artifact, artifact_name=artifact_name or '',
243
243
  artifact_type=artifact_type)
244
244
  elif isinstance(artifact, str):
@@ -246,8 +246,16 @@ class PolyswarmAPI:
246
246
  artifact = resources.LocalArtifact.from_path(self, artifact, artifact_type=artifact_type,
247
247
  artifact_name=artifact_name)
248
248
  elif artifact_type == resources.ArtifactType.URL:
249
- artifact = resources.LocalArtifact.from_content(self, artifact, artifact_name=artifact_name or artifact,
250
- artifact_type=artifact_type)
249
+ if preprocessing and preprocessing['type'] == 'qrcode':
250
+ artifact = resources.LocalArtifact.from_path(self,
251
+ artifact,
252
+ artifact_type=artifact_type,
253
+ artifact_name=artifact_name)
254
+ else:
255
+ artifact = resources.LocalArtifact.from_content(self,
256
+ artifact,
257
+ artifact_name=artifact_name or artifact,
258
+ artifact_type=artifact_type)
251
259
  if artifact_type == resources.ArtifactType.URL:
252
260
  scan_config = scan_config or 'more-time'
253
261
  if isinstance(artifact, resources.LocalArtifact):
@@ -257,8 +265,7 @@ class PolyswarmAPI:
257
265
  artifact_type=artifact.artifact_type.name,
258
266
  scan_config=scan_config,
259
267
  community=self.community,
260
- is_zip=is_zip,
261
- zip_password=zip_password,
268
+ preprocessing=preprocessing,
262
269
  ).result()
263
270
  instance.upload_file(artifact)
264
271
  return resources.ArtifactInstance.update(self, id=instance.id, community=self.community).result()
@@ -714,15 +721,35 @@ class PolyswarmAPI:
714
721
  artifact_type=resources.ArtifactType.FILE,
715
722
  artifact_name=None,
716
723
  network_enabled=True,
717
- is_zip=False,
718
- zip_password=None,
724
+ preprocessing=None,
719
725
  ):
720
- logger.info('Sandboxing file in provider %s vm %s', provider_slug, vm_slug)
726
+ """
727
+ Submit artifacts to Polyswarm Sandboxing system.
728
+
729
+ :param artifact: A file-like, path to file, url or LocalArtifact instance
730
+ :param artifact_name: An appropriate filename for the Artifact
731
+ :artifact_type: the type of artifact to be submitted, default FILE. Use URL type
732
+ with the preprocessing field to scan URLs inside QR Code images
733
+ :param network_enabled: Whether the VM has to have Internet connection enabled or not.
734
+ :param provider_slug: the slug of the provider that is going to execute the sandboxing, e.g.
735
+ 'cape' or 'triage'.
736
+ Use `sandbox_providers()` to get the list of providers.
737
+ :param vm_slug: The slug of the virtual machine used for the sandboxing, depending on the
738
+ VM chosen is the OS and software that is going to host the sandboxing. Each
739
+ provider (provider_slug) support different VMs, so check with `sandbox_providers()`
740
+ the list of VMs available.
741
+ :param preprocessing: Preprocessing settings to be applied to the artifact, None means no preprocessing,
742
+ otherwise a dict with the following attributes can be passed:
743
+ - type (string): either "zip" or "qrcode", the first mean the file is a zip that
744
+ the server has to decompress to then scan the content (only one file inside allowed).
745
+ "qrcode" means the file is a QR Code image with a URL as payload, and you want
746
+ to scan the URL, not the actual file (artifact_type has to be "URL").
747
+ - password (string, optional): will use this password to decompress the zip file.
748
+ :return: An ArtifactInstance resource
749
+ """
750
+ logger.info('Sandboxing %s in provider %s vm %s', artifact_type.name.lower(), provider_slug, vm_slug)
721
751
  artifact_type = resources.ArtifactType.parse(artifact_type)
722
- # TODO This is a python 2.7 check if artifact is a file-like instance, consider changing
723
- # to isinstance(artifact, io.IOBase) when deprecating 2.7 and implementing making LocalHandle
724
- # inherit io.IOBase, although this will change the method delegation logic in the resource
725
- if hasattr(artifact, 'read') and hasattr(artifact.read, '__call__'):
752
+ if isinstance(artifact, io.IOBase):
726
753
  artifact = resources.LocalArtifact.from_handle(self, artifact, artifact_name=artifact_name or '',
727
754
  artifact_type=artifact_type)
728
755
  elif isinstance(artifact, str):
@@ -742,8 +769,7 @@ class PolyswarmAPI:
742
769
  provider_slug=provider_slug,
743
770
  vm_slug=vm_slug,
744
771
  network_enabled=network_enabled,
745
- is_zip=is_zip,
746
- zip_password=zip_password,
772
+ preprocessing=preprocessing,
747
773
  ).result()
748
774
  task.upload_file(artifact)
749
775
  return resources.SandboxTask.update_file(self, id=task.id, community=self.community).result()
@@ -751,16 +777,68 @@ class PolyswarmAPI:
751
777
  raise exceptions.InvalidValueException(
752
778
  'Artifacts should be a path to a file or a LocalArtifact instance')
753
779
 
754
- def sandbox_url(self, url, provider_slug, vm_slug, browser=None):
780
+ def sandbox_url(self,
781
+ url,
782
+ provider_slug,
783
+ vm_slug,
784
+ browser=None,
785
+ artifact=None,
786
+ artifact_name=None,
787
+ preprocessing=None):
788
+ """
789
+ Submit URL to Polyswarm Sandboxing system.
790
+ :param url: A string with the URL to be submitted. Set to `None` if the URL is provided
791
+ through a QR Code image in the artifact param (see artifact and preprocessing params).
792
+ :param provider_slug: the slug of the provider that is going to execute the sandboxing, e.g.
793
+ 'cape' or 'triage'.
794
+ Use `sandbox_providers()` to get the list of providers.
795
+ :param vm_slug: The slug of the virtual machine used for the sandboxing, depending on the
796
+ VM chosen is the OS and software that is going to host the sandboxing. Each
797
+ provider (provider_slug) support different VMs, so check with `sandbox_providers()`
798
+ the list of VMs available.
799
+ :param browser: browser name, e.g. 'edge' or 'firefox'.
800
+ :param artifact: A file-like, path to file, or LocalArtifact instance (default None). The url
801
+ param has to be None to use this param. For now QR Code image files
802
+ are supported
803
+ :param artifact_name: name of the artifact, if None (default) the URL string is used as a name,
804
+ or the file name if artifact is provided (QR Code image file).
805
+ :param preprocessing: Preprocessing settings to be applied to the artifact, None means no preprocessing,
806
+ otherwise a dict with the following attributes can be passed:
807
+ - type (string): only "qrcode" is supported for URL sandboxing:
808
+ the file is a QR Code image with a URL as payload, and you want
809
+ to scan the URL, not the actual file. This argument has to be used with the
810
+ `artifact` param, and `url` set to `None`.
811
+ """
755
812
  logger.info('Sandboxing url in provider %s vm %s', provider_slug, vm_slug)
756
- artifact = resources.LocalArtifact.from_content(self, url, artifact_name=url, artifact_type='URL')
813
+ if artifact and url:
814
+ raise exceptions.InvalidValueException("Cannot use artifact with url param")
815
+ if artifact:
816
+ if not preprocessing or preprocessing.get('type') != 'qrcode':
817
+ raise exceptions.InvalidValueException("Only artifact of type qrcode is supported")
818
+ if isinstance(artifact, str):
819
+ artifact = resources.LocalArtifact.from_path(self,
820
+ artifact,
821
+ artifact_type='URL',
822
+ artifact_name=artifact_name)
823
+ else:
824
+ artifact = resources.LocalArtifact.from_handle(self,
825
+ artifact,
826
+ artifact_name=artifact_name or '',
827
+ artifact_type='URL')
828
+ else:
829
+ artifact_name = url
830
+ artifact = resources.LocalArtifact.from_content(self,
831
+ url,
832
+ artifact_name=artifact_name,
833
+ artifact_type='URL')
757
834
  task = resources.SandboxTask.create_file(self,
758
- artifact_name=url,
835
+ artifact_name=artifact_name,
759
836
  artifact_type="URL",
760
837
  community=self.community,
761
838
  provider_slug=provider_slug,
762
839
  vm_slug=vm_slug,
763
840
  browser=browser,
841
+ preprocessing=preprocessing,
764
842
  network_enabled=True).result()
765
843
  task.upload_file(artifact)
766
844
  return resources.SandboxTask.update_file(self, id=task.id, community=self.community).result()
@@ -978,3 +1056,9 @@ class PolyswarmAPI:
978
1056
 
979
1057
  def report_template_list(self, is_default=None, **kwargs):
980
1058
  return resources.ReportTemplate.list(self, is_default=is_default, **kwargs).result()
1059
+
1060
+ def account_whois(self, **kwargs):
1061
+ return resources.WhoIs.get(self, **kwargs).result()
1062
+
1063
+ def account_features(self, **kwargs):
1064
+ return resources.AccountFeatures.get(self, **kwargs).result()
@@ -295,6 +295,7 @@ class ArtifactInstance(core.BaseJsonResource, core.Hashable):
295
295
  self.community = content.get('community')
296
296
  self.created = core.parse_isoformat(content.get('created'))
297
297
  self.failed = content.get('failed')
298
+ self.failed_reason = content.get('failed_reason')
298
299
  self.filename = content.get('filename')
299
300
  self.result = content.get('result')
300
301
  self.type = content.get('type')
@@ -1019,6 +1020,8 @@ class SandboxTask(core.BaseJsonResource):
1019
1020
  self.sha256 = content['sha256']
1020
1021
  self.report = content['report']
1021
1022
  self.upload_url = content['upload_url']
1023
+ self.config = content['config']
1024
+ self.artifact = content['artifact']
1022
1025
  self.sandbox_artifacts = [SandboxArtifact(a, api=api) for a in content.get('sandbox_artifacts', [])]
1023
1026
 
1024
1027
  def upload_file(self, artifact, attempts=3, **kwargs):
@@ -1129,6 +1132,10 @@ class ReportTask(core.BaseJsonResource):
1129
1132
 
1130
1133
  def download_report(self, folder=None):
1131
1134
  """ This method is special, in that it is simply for downloading from S3 """
1135
+ if self.state == 'PENDING':
1136
+ raise exceptions.InvalidValueException('Report is in PENDING state, wait for completion first')
1137
+ if self.state == 'FAILED':
1138
+ raise exceptions.InvalidValueException("Report is in FAILED state, won't be generated")
1132
1139
  return core.PolyswarmRequest(
1133
1140
  self.api,
1134
1141
  {
@@ -1203,3 +1210,48 @@ class ReportTemplate(core.BaseJsonResource):
1203
1210
  },
1204
1211
  result_parser=self.__class__
1205
1212
  ).execute()
1213
+
1214
+
1215
+ class AccountFeatures(core.BaseJsonResource):
1216
+ RESOURCE_ENDPOINT = "/public/accounts"
1217
+
1218
+ def __init__(self, content, api=None):
1219
+ super().__init__(content, api=api)
1220
+ self.account_number = content['account_number']
1221
+ self.user_account_number = content.get('user_account_number')
1222
+ self.account_plan_name = content['account_plan_name']
1223
+ self.plan_period_start = content['plan_period_start']
1224
+ self.plan_period_end = content['plan_period_end']
1225
+ self.window_start = content['window_start']
1226
+ self.window_end = content['window_end']
1227
+ self.tenant = content.get('tenant')
1228
+ self.daily_api_limit = content['daily_api_limit']
1229
+ self.daily_api_remaining = content['daily_api_remaining']
1230
+ self.has_stream_access = content['has_stream_access']
1231
+ self.is_trial = content['is_trial']
1232
+ self.is_trial_expired = content['is_trial_expired']
1233
+ self.trial_started_at = content['trial_started_at']
1234
+ self.trial_ended_at = content['trial_ended_at']
1235
+ self.features = []
1236
+ for feature in content['features']:
1237
+ self.features.append({
1238
+ 'base_uses': feature['base_uses'],
1239
+ 'name': feature['name'],
1240
+ 'overage': feature['overage'],
1241
+ 'remaining_uses': feature['remaining_uses'],
1242
+ 'tag': feature['tag'],
1243
+ 'value': feature['value'],
1244
+ })
1245
+
1246
+
1247
+ class WhoIs(core.BaseJsonResource):
1248
+ RESOURCE_ENDPOINT = "/public/accounts/whois"
1249
+
1250
+ def __init__(self, content, api=None):
1251
+ super().__init__(content, api=api)
1252
+ self.account_number = content['account_number']
1253
+ self.user_account_number = content.get('user_account_number')
1254
+ self.account_name = content['account_name']
1255
+ self.account_type = content['account_type']
1256
+ self.communities = content['communities']
1257
+ self.tenant = content.get('tenant')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: polyswarm-api
3
- Version: 3.8.0
3
+ Version: 3.10.0
4
4
  Summary: Client library to simplify interacting with the PolySwarm consumer API
5
5
  Home-page: https://github.com/polyswarm/polyswarm-api
6
6
  Author: PolySwarm Developers
File without changes
File without changes
File without changes