polyswarm-api 3.8.0__tar.gz → 3.9.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.
- {polyswarm-api-3.8.0/src/polyswarm_api.egg-info → polyswarm-api-3.9.0}/PKG-INFO +1 -1
- {polyswarm-api-3.8.0 → polyswarm-api-3.9.0}/setup.py +1 -1
- {polyswarm-api-3.8.0 → polyswarm-api-3.9.0}/src/polyswarm_api/__init__.py +1 -1
- {polyswarm-api-3.8.0 → polyswarm-api-3.9.0}/src/polyswarm_api/api.py +110 -26
- {polyswarm-api-3.8.0 → polyswarm-api-3.9.0}/src/polyswarm_api/resources.py +47 -0
- {polyswarm-api-3.8.0 → polyswarm-api-3.9.0/src/polyswarm_api.egg-info}/PKG-INFO +1 -1
- {polyswarm-api-3.8.0 → polyswarm-api-3.9.0}/LICENSE +0 -0
- {polyswarm-api-3.8.0 → polyswarm-api-3.9.0}/MANIFEST.in +0 -0
- {polyswarm-api-3.8.0 → polyswarm-api-3.9.0}/README.md +0 -0
- {polyswarm-api-3.8.0 → polyswarm-api-3.9.0}/requirements.txt +0 -0
- {polyswarm-api-3.8.0 → polyswarm-api-3.9.0}/setup.cfg +0 -0
- {polyswarm-api-3.8.0 → polyswarm-api-3.9.0}/src/polyswarm_api/core.py +0 -0
- {polyswarm-api-3.8.0 → polyswarm-api-3.9.0}/src/polyswarm_api/exceptions.py +0 -0
- {polyswarm-api-3.8.0 → polyswarm-api-3.9.0}/src/polyswarm_api/settings.py +0 -0
- {polyswarm-api-3.8.0 → polyswarm-api-3.9.0}/src/polyswarm_api.egg-info/SOURCES.txt +0 -0
- {polyswarm-api-3.8.0 → polyswarm-api-3.9.0}/src/polyswarm_api.egg-info/dependency_links.txt +0 -0
- {polyswarm-api-3.8.0 → polyswarm-api-3.9.0}/src/polyswarm_api.egg-info/requires.txt +0 -0
- {polyswarm-api-3.8.0 → polyswarm-api-3.9.0}/src/polyswarm_api.egg-info/top_level.txt +0 -0
|
@@ -9,7 +9,7 @@ with open('README.md', 'r') as readme:
|
|
|
9
9
|
|
|
10
10
|
setup(
|
|
11
11
|
name='polyswarm-api',
|
|
12
|
-
version='3.
|
|
12
|
+
version='3.9.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,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
|
-
|
|
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
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
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
|
-
|
|
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
|
-
|
|
250
|
-
|
|
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
|
-
|
|
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
|
-
|
|
718
|
-
zip_password=None,
|
|
724
|
+
preprocessing=None,
|
|
719
725
|
):
|
|
720
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
|
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=
|
|
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()
|
|
@@ -1019,6 +1019,8 @@ class SandboxTask(core.BaseJsonResource):
|
|
|
1019
1019
|
self.sha256 = content['sha256']
|
|
1020
1020
|
self.report = content['report']
|
|
1021
1021
|
self.upload_url = content['upload_url']
|
|
1022
|
+
self.config = content['config']
|
|
1023
|
+
self.artifact = content['artifact']
|
|
1022
1024
|
self.sandbox_artifacts = [SandboxArtifact(a, api=api) for a in content.get('sandbox_artifacts', [])]
|
|
1023
1025
|
|
|
1024
1026
|
def upload_file(self, artifact, attempts=3, **kwargs):
|
|
@@ -1203,3 +1205,48 @@ class ReportTemplate(core.BaseJsonResource):
|
|
|
1203
1205
|
},
|
|
1204
1206
|
result_parser=self.__class__
|
|
1205
1207
|
).execute()
|
|
1208
|
+
|
|
1209
|
+
|
|
1210
|
+
class AccountFeatures(core.BaseJsonResource):
|
|
1211
|
+
RESOURCE_ENDPOINT = "/public/accounts"
|
|
1212
|
+
|
|
1213
|
+
def __init__(self, content, api=None):
|
|
1214
|
+
super().__init__(content, api=api)
|
|
1215
|
+
self.account_number = content['account_number']
|
|
1216
|
+
self.user_account_number = content.get('user_account_number')
|
|
1217
|
+
self.account_plan_name = content['account_plan_name']
|
|
1218
|
+
self.plan_period_start = content['plan_period_start']
|
|
1219
|
+
self.plan_period_end = content['plan_period_end']
|
|
1220
|
+
self.window_start = content['window_start']
|
|
1221
|
+
self.window_end = content['window_end']
|
|
1222
|
+
self.tenant = content.get('tenant')
|
|
1223
|
+
self.daily_api_limit = content['daily_api_limit']
|
|
1224
|
+
self.daily_api_remaining = content['daily_api_remaining']
|
|
1225
|
+
self.has_stream_access = content['has_stream_access']
|
|
1226
|
+
self.is_trial = content['is_trial']
|
|
1227
|
+
self.is_trial_expired = content['is_trial_expired']
|
|
1228
|
+
self.trial_started_at = content['trial_started_at']
|
|
1229
|
+
self.trial_ended_at = content['trial_ended_at']
|
|
1230
|
+
self.features = []
|
|
1231
|
+
for feature in content['features']:
|
|
1232
|
+
self.features.append({
|
|
1233
|
+
'base_uses': feature['base_uses'],
|
|
1234
|
+
'name': feature['name'],
|
|
1235
|
+
'overage': feature['overage'],
|
|
1236
|
+
'remaining_uses': feature['remaining_uses'],
|
|
1237
|
+
'tag': feature['tag'],
|
|
1238
|
+
'value': feature['value'],
|
|
1239
|
+
})
|
|
1240
|
+
|
|
1241
|
+
|
|
1242
|
+
class WhoIs(core.BaseJsonResource):
|
|
1243
|
+
RESOURCE_ENDPOINT = "/public/accounts/whois"
|
|
1244
|
+
|
|
1245
|
+
def __init__(self, content, api=None):
|
|
1246
|
+
super().__init__(content, api=api)
|
|
1247
|
+
self.account_number = content['account_number']
|
|
1248
|
+
self.user_account_number = content.get('user_account_number')
|
|
1249
|
+
self.account_name = content['account_name']
|
|
1250
|
+
self.account_type = content['account_type']
|
|
1251
|
+
self.communities = content['communities']
|
|
1252
|
+
self.tenant = content.get('tenant')
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|