assemblyline-v4-service 4.5.1.dev380__py3-none-any.whl → 4.5.1.dev382__py3-none-any.whl
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.
Potentially problematic release.
This version of assemblyline-v4-service might be problematic. Click here for more details.
- assemblyline_v4_service/VERSION +1 -1
- assemblyline_v4_service/updater/client.py +24 -0
- assemblyline_v4_service/updater/helper.py +5 -1
- assemblyline_v4_service/updater/updater.py +50 -22
- {assemblyline_v4_service-4.5.1.dev380.dist-info → assemblyline_v4_service-4.5.1.dev382.dist-info}/METADATA +1 -1
- {assemblyline_v4_service-4.5.1.dev380.dist-info → assemblyline_v4_service-4.5.1.dev382.dist-info}/RECORD +9 -9
- {assemblyline_v4_service-4.5.1.dev380.dist-info → assemblyline_v4_service-4.5.1.dev382.dist-info}/LICENCE.md +0 -0
- {assemblyline_v4_service-4.5.1.dev380.dist-info → assemblyline_v4_service-4.5.1.dev382.dist-info}/WHEEL +0 -0
- {assemblyline_v4_service-4.5.1.dev380.dist-info → assemblyline_v4_service-4.5.1.dev382.dist-info}/top_level.txt +0 -0
assemblyline_v4_service/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
4.5.1.
|
|
1
|
+
4.5.1.dev382
|
|
@@ -17,6 +17,7 @@ class SyncableBadlistClient(BadlistClient):
|
|
|
17
17
|
def __init__(self, datastore, config=None):
|
|
18
18
|
super().__init__(datastore, config)
|
|
19
19
|
self.sync = False
|
|
20
|
+
self.classification_override = None
|
|
20
21
|
|
|
21
22
|
def add_update_many(self, data: List[Union[dict, BadlistModel]]) -> Dict[str, Any]:
|
|
22
23
|
return hashlist_add_update_many(self, self.datastore.badlist, data)
|
|
@@ -26,6 +27,7 @@ class SyncableSafelistClient(SafelistClient):
|
|
|
26
27
|
def __init__(self, datastore, config=None):
|
|
27
28
|
super().__init__(datastore, config)
|
|
28
29
|
self.sync = False
|
|
30
|
+
self.classification_override = None
|
|
29
31
|
|
|
30
32
|
def add_update_many(self, data: List[Union[dict, SafelistModel]]) -> Dict[str, Any]:
|
|
31
33
|
return hashlist_add_update_many(self, self.datastore.safelist, data)
|
|
@@ -55,9 +57,14 @@ def hashlist_add_update_many(client: Union[SyncableBadlistClient, SyncableSafeli
|
|
|
55
57
|
# Set the source name
|
|
56
58
|
source = d["sources"][0]["name"]
|
|
57
59
|
|
|
60
|
+
if client.classification_override:
|
|
61
|
+
# Override the classification of the signature based on what's assigned to the client
|
|
62
|
+
d["sources"][0]["classification"] = client.classification_override
|
|
63
|
+
|
|
58
64
|
if client.sync:
|
|
59
65
|
# Compute the expected ID and add it to the list
|
|
60
66
|
current_ids.add(client._preprocess_object(d))
|
|
67
|
+
|
|
61
68
|
# Update with JSON-friendly version of data to be sent to API
|
|
62
69
|
data[i] = d
|
|
63
70
|
|
|
@@ -122,6 +129,7 @@ class SyncableSignatureClient(SignatureClient):
|
|
|
122
129
|
def __init__(self, datastore, config=None):
|
|
123
130
|
super().__init__(datastore, config)
|
|
124
131
|
self.sync = False
|
|
132
|
+
self.classification_override = None
|
|
125
133
|
|
|
126
134
|
def add_update_many(self, source: str, sig_type: str, data: List[Union[dict, SignatureModel]],
|
|
127
135
|
dedup_name: bool = True) -> Dict[str, Any]:
|
|
@@ -144,6 +152,10 @@ class SyncableSignatureClient(SignatureClient):
|
|
|
144
152
|
d['status'] = sig_exists['status']
|
|
145
153
|
d['state_change_user'] = sig_exists['state_change_user']
|
|
146
154
|
|
|
155
|
+
if self.classification_override:
|
|
156
|
+
# Override the classification of the signature based on what's assigned to the client
|
|
157
|
+
d['classification'] = self.classification_override
|
|
158
|
+
|
|
147
159
|
if self.sync:
|
|
148
160
|
# Add signature ID to the list
|
|
149
161
|
current_signature_ids.add(sig_id)
|
|
@@ -208,6 +220,7 @@ class UpdaterClient(object):
|
|
|
208
220
|
def __init__(self, datastore) -> None:
|
|
209
221
|
self.datastore = datastore
|
|
210
222
|
self._sync = False
|
|
223
|
+
self._classification_override = None
|
|
211
224
|
self.badlist = SyncableBadlistClient(datastore)
|
|
212
225
|
self.safelist = SyncableSafelistClient(datastore)
|
|
213
226
|
self.signature = SyncableSignatureClient(datastore)
|
|
@@ -223,3 +236,14 @@ class UpdaterClient(object):
|
|
|
223
236
|
self.safelist.sync = value
|
|
224
237
|
self.signature.sync = value
|
|
225
238
|
self._sync = value
|
|
239
|
+
|
|
240
|
+
@property
|
|
241
|
+
def classification_override(self):
|
|
242
|
+
return self._classification_override
|
|
243
|
+
@classification_override.setter
|
|
244
|
+
def classification_override(self, value: str):
|
|
245
|
+
# Set the classification override
|
|
246
|
+
self.badlist.classification_override = value
|
|
247
|
+
self.safelist.classification_override = value
|
|
248
|
+
self.signature.classification_override = value
|
|
249
|
+
self._classification_override = value
|
|
@@ -88,6 +88,7 @@ def url_download(source: Dict[str, Any], previous_update: int, logger: Logger, o
|
|
|
88
88
|
ca_cert = source.get('ca_cert', None)
|
|
89
89
|
ignore_ssl_errors = source.get('ssl_ignore_errors', False)
|
|
90
90
|
auth = (username, password) if username and password else None
|
|
91
|
+
fetch_method = source.get('fetch_method', 'GET').lower()
|
|
91
92
|
|
|
92
93
|
proxy = source.get('proxy', None)
|
|
93
94
|
headers_list = source.get('headers', [])
|
|
@@ -134,7 +135,10 @@ def url_download(source: Dict[str, Any], previous_update: int, logger: Logger, o
|
|
|
134
135
|
else:
|
|
135
136
|
headers = {'If-Modified-Since': previous_update}
|
|
136
137
|
|
|
137
|
-
|
|
138
|
+
if fetch_method in ['get', 'post']:
|
|
139
|
+
response = getattr(session, fetch_method)(uri, auth=auth, headers=headers, proxies=proxies, stream=True)
|
|
140
|
+
else:
|
|
141
|
+
raise ValueError(f"Unknown fetch method: {fetch_method}")
|
|
138
142
|
|
|
139
143
|
# Check the response code
|
|
140
144
|
if response.status_code == requests.codes['not_modified']:
|
|
@@ -378,14 +378,38 @@ class ServiceUpdater(ThreadedCoreBase):
|
|
|
378
378
|
source_obj = sources[source_name]
|
|
379
379
|
old_update_time = self.get_source_update_time()
|
|
380
380
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
default_classification = source.get('default_classification', classification.UNRESTRICTED)
|
|
385
|
-
# Enable syncing if the source specifies it
|
|
386
|
-
self.client.sync = source.get('sync', False)
|
|
387
|
-
|
|
381
|
+
# Are we ignoring the cache for this source?
|
|
382
|
+
if source_obj.ignore_cache:
|
|
383
|
+
old_update_time = 0
|
|
388
384
|
try:
|
|
385
|
+
|
|
386
|
+
source = source_obj.as_primitives()
|
|
387
|
+
uri: str = source_obj.uri
|
|
388
|
+
|
|
389
|
+
# If source is not currently enabled/active, skip..
|
|
390
|
+
if not source_obj.enabled:
|
|
391
|
+
raise SkipSource
|
|
392
|
+
|
|
393
|
+
# Is it time for this source to run?
|
|
394
|
+
elapsed_time = time.time() - old_update_time
|
|
395
|
+
update_interval = source.get('update_interval') or service.update_config.update_interval_seconds
|
|
396
|
+
if elapsed_time < update_interval:
|
|
397
|
+
# Too early to run the update for this particular source, skip for now
|
|
398
|
+
raise SkipSource
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
self.push_status("UPDATING", "Starting..")
|
|
402
|
+
fetch_method = source.get('fetch_method', 'GET')
|
|
403
|
+
default_classification = source.get('default_classification', classification.UNRESTRICTED)
|
|
404
|
+
|
|
405
|
+
# Configure the client as necessary
|
|
406
|
+
|
|
407
|
+
# Enable syncing if the source specifies it
|
|
408
|
+
self.client.sync = source.get('sync', False)
|
|
409
|
+
# Override classfication of signatures if specified
|
|
410
|
+
self.client.classification_override = default_classification \
|
|
411
|
+
if source.get('override_classification', False) else None
|
|
412
|
+
|
|
389
413
|
self.push_status("UPDATING", "Pulling..")
|
|
390
414
|
output = None
|
|
391
415
|
seen_fetch = seen_fetches.get(uri)
|
|
@@ -397,21 +421,20 @@ class ServiceUpdater(ThreadedCoreBase):
|
|
|
397
421
|
self.log.info(f'Already visited {uri} in this run. Using cached download path..')
|
|
398
422
|
output = seen_fetches[uri]
|
|
399
423
|
else:
|
|
400
|
-
|
|
401
|
-
|
|
424
|
+
self.log.info(f"Fetching {source_name} using {fetch_method}")
|
|
425
|
+
# Pull sources from external locations
|
|
426
|
+
if uri.startswith("file://"):
|
|
427
|
+
# Perform an update using a local mount
|
|
428
|
+
output = uri.split("file://", 1)[1]
|
|
429
|
+
if not os.path.exists(output):
|
|
430
|
+
raise FileNotFoundError(f"{output} doesn't exist within container.")
|
|
431
|
+
elif fetch_method == "GIT" or uri.endswith('.git'):
|
|
402
432
|
# First we'll attempt by performing a Git clone
|
|
403
433
|
# (since not all services hint at being a repository in their URL),
|
|
404
434
|
output = git_clone_repo(source, old_update_time, self.log, update_dir)
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
# Should that fail, we'll attempt a direct-download using Python Requests
|
|
409
|
-
if not uri.endswith('.git'):
|
|
410
|
-
# Proceed with direct download, raise exception as required if necessary
|
|
411
|
-
output = url_download(source, old_update_time, self.log, update_dir)
|
|
412
|
-
else:
|
|
413
|
-
# Raise Git Exception
|
|
414
|
-
raise git_ex
|
|
435
|
+
else:
|
|
436
|
+
# Other fetch methods are meant for URL downloads using Requests
|
|
437
|
+
output = url_download(source, old_update_time, self.log, update_dir)
|
|
415
438
|
# Add output path to the list of seen fetches in this run
|
|
416
439
|
seen_fetches[uri] = output
|
|
417
440
|
|
|
@@ -430,7 +453,8 @@ class ServiceUpdater(ThreadedCoreBase):
|
|
|
430
453
|
|
|
431
454
|
self.push_status("UPDATING", "Importing..")
|
|
432
455
|
# Import into Assemblyline
|
|
433
|
-
self.import_update(validated_files, source_name, default_classification
|
|
456
|
+
self.import_update(validated_files, source_name, default_classification,
|
|
457
|
+
source.get('configuration') or {})
|
|
434
458
|
self.push_status("DONE", "Signature(s) Imported.")
|
|
435
459
|
except SkipSource:
|
|
436
460
|
# This source hasn't changed, no need to re-import into Assemblyline
|
|
@@ -457,7 +481,8 @@ class ServiceUpdater(ThreadedCoreBase):
|
|
|
457
481
|
return True
|
|
458
482
|
|
|
459
483
|
# Define how your source update gets imported into Assemblyline
|
|
460
|
-
def import_update(self, files_sha256: List[Tuple[str, str]], source_name: str, default_classification=None
|
|
484
|
+
def import_update(self, files_sha256: List[Tuple[str, str]], source_name: str, default_classification=None,
|
|
485
|
+
configuration: dict = {}, *args, **kwargs):
|
|
461
486
|
raise NotImplementedError()
|
|
462
487
|
|
|
463
488
|
# Define how to prepare the output directory before being served, must return the path of the directory to serve.
|
|
@@ -486,7 +511,10 @@ class ServiceUpdater(ThreadedCoreBase):
|
|
|
486
511
|
while self.running:
|
|
487
512
|
# Stringify and hash the the current update configuration
|
|
488
513
|
service = self._service
|
|
489
|
-
|
|
514
|
+
|
|
515
|
+
# The update interval (or sleep interval) will be based on the smallest interval across sources
|
|
516
|
+
update_interval = min([service.update_config.update_interval_seconds] +
|
|
517
|
+
[s.update_interval for s in service.update_config.sources if s.update_interval])
|
|
490
518
|
|
|
491
519
|
# Is it time to update yet?
|
|
492
520
|
if time.time() - self.get_scheduled_update_time() < update_interval \
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
assemblyline_v4_service/VERSION,sha256=
|
|
1
|
+
assemblyline_v4_service/VERSION,sha256=j3Q1A-qJKdruXTUxjMOGy8WVYeCkHuWM1sHlUgs74VU,13
|
|
2
2
|
assemblyline_v4_service/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
3
|
assemblyline_v4_service/healthz.py,sha256=sS1cFkDLw8hUPMpj7tbHXFv8ZmHcazrwZ0l6oQDwwkQ,1575
|
|
4
4
|
assemblyline_v4_service/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -19,10 +19,10 @@ assemblyline_v4_service/dev/run_service_once.py,sha256=iEWkLnF4cWN0V3Mc6GhMKjDAP
|
|
|
19
19
|
assemblyline_v4_service/updater/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
20
|
assemblyline_v4_service/updater/__main__.py,sha256=9Os-u8Tf7MD73JSrUSPmOaErTgfvesNLiEeszU4ujXA,133
|
|
21
21
|
assemblyline_v4_service/updater/app.py,sha256=Mtmx4bkXfP4nFqqa5q15jW8QIXr4JK84lCovxAVyvPs,3317
|
|
22
|
-
assemblyline_v4_service/updater/client.py,sha256=
|
|
22
|
+
assemblyline_v4_service/updater/client.py,sha256=mmCwNuGSDymbvrMuEXLgTR13vqaUEjs0Jjew-9QkQtM,10848
|
|
23
23
|
assemblyline_v4_service/updater/gunicorn_config.py,sha256=p3j2KPBeD5jvMw9O5i7vAtlRgPSVVxIG9AO0DfN82J8,1247
|
|
24
|
-
assemblyline_v4_service/updater/helper.py,sha256
|
|
25
|
-
assemblyline_v4_service/updater/updater.py,sha256=
|
|
24
|
+
assemblyline_v4_service/updater/helper.py,sha256=f0yB6iKExQAqCMkMs0aWPkzcaSy_z9sycgunoCOJlU4,9756
|
|
25
|
+
assemblyline_v4_service/updater/updater.py,sha256=b_vCg9u75Dmp09NWAZXfG-_CriqnS7KeJ7SKjmXmrxI,31299
|
|
26
26
|
test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
27
27
|
test/conftest.py,sha256=W3SieQpZsZpGEmtLqY4aIlxREDSsHceyCrFcFsWUM0U,1851
|
|
28
28
|
test/test_healthz.py,sha256=DkeLUlrb7rGx3nZ04aADU9HXXu5mZTf_DBwT0xhzIv4,7
|
|
@@ -38,8 +38,8 @@ test/test_common/test_request.py,sha256=Ceyds8BNO1O0f1kH1VEb84faJcaupvSjVKIrGdHe
|
|
|
38
38
|
test/test_common/test_result.py,sha256=6BiOKxEPrKBjOY44jv3TY-yiXm0qI1ok_CZBnjP9TM4,45447
|
|
39
39
|
test/test_common/test_task.py,sha256=P44mNcSe-3tJgDk9ppN3KbM7oN4LBVIuhONG-Gveh74,19007
|
|
40
40
|
test/test_common/test_utils.py,sha256=TbnBxqpS_ZC5ptXR9XJX3xtbItD0mTbtiBxxdyP8J5k,5904
|
|
41
|
-
assemblyline_v4_service-4.5.1.
|
|
42
|
-
assemblyline_v4_service-4.5.1.
|
|
43
|
-
assemblyline_v4_service-4.5.1.
|
|
44
|
-
assemblyline_v4_service-4.5.1.
|
|
45
|
-
assemblyline_v4_service-4.5.1.
|
|
41
|
+
assemblyline_v4_service-4.5.1.dev382.dist-info/LICENCE.md,sha256=NSkYo9EH8h5oOkzg4VhjAHF4339MqPP2cQ8msTPgl-c,1396
|
|
42
|
+
assemblyline_v4_service-4.5.1.dev382.dist-info/METADATA,sha256=f1LMGxK8nW3ZZFuhlYX2FQa-lTGGTFsI8n8uAWsYtSA,9493
|
|
43
|
+
assemblyline_v4_service-4.5.1.dev382.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
|
44
|
+
assemblyline_v4_service-4.5.1.dev382.dist-info/top_level.txt,sha256=LpTOEaVCatkrvbVq3EZseMSIa2PQZU-2rhuO_FTpZgY,29
|
|
45
|
+
assemblyline_v4_service-4.5.1.dev382.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|