assemblyline-core 4.5.1.dev460__tar.gz → 4.5.1.dev462__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.
Files changed (89) hide show
  1. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/PKG-INFO +1 -1
  2. assemblyline_core-4.5.1.dev462/assemblyline_core/VERSION +1 -0
  3. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/tasking_client.py +49 -43
  4. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core.egg-info/PKG-INFO +1 -1
  5. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core.egg-info/SOURCES.txt +1 -0
  6. assemblyline_core-4.5.1.dev462/test/test_tasking_client.py +39 -0
  7. assemblyline_core-4.5.1.dev460/assemblyline_core/VERSION +0 -1
  8. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/LICENCE.md +0 -0
  9. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/README.md +0 -0
  10. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/__init__.py +0 -0
  11. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/alerter/__init__.py +0 -0
  12. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/alerter/processing.py +0 -0
  13. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/alerter/run_alerter.py +0 -0
  14. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/archiver/__init__.py +0 -0
  15. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/archiver/run_archiver.py +0 -0
  16. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/badlist_client.py +0 -0
  17. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/dispatching/__init__.py +0 -0
  18. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/dispatching/__main__.py +0 -0
  19. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/dispatching/client.py +0 -0
  20. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/dispatching/dispatcher.py +0 -0
  21. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/dispatching/schedules.py +0 -0
  22. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/dispatching/timeout.py +0 -0
  23. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/expiry/__init__.py +0 -0
  24. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/expiry/run_expiry.py +0 -0
  25. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/ingester/__init__.py +0 -0
  26. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/ingester/__main__.py +0 -0
  27. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/ingester/constants.py +0 -0
  28. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/ingester/ingester.py +0 -0
  29. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/metrics/__init__.py +0 -0
  30. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/metrics/es_metrics.py +0 -0
  31. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/metrics/heartbeat_formatter.py +0 -0
  32. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/metrics/helper.py +0 -0
  33. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/metrics/metrics_server.py +0 -0
  34. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/metrics/run_heartbeat_manager.py +0 -0
  35. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/metrics/run_metrics_aggregator.py +0 -0
  36. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/metrics/run_statistics_aggregator.py +0 -0
  37. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/plumber/__init__.py +0 -0
  38. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/plumber/run_plumber.py +0 -0
  39. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/replay/__init__.py +0 -0
  40. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/replay/client.py +0 -0
  41. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/replay/creator/__init__.py +0 -0
  42. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/replay/creator/run.py +0 -0
  43. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/replay/creator/run_worker.py +0 -0
  44. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/replay/loader/__init__.py +0 -0
  45. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/replay/loader/run.py +0 -0
  46. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/replay/loader/run_worker.py +0 -0
  47. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/replay/replay.py +0 -0
  48. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/safelist_client.py +0 -0
  49. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/scaler/__init__.py +0 -0
  50. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/scaler/collection.py +0 -0
  51. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/scaler/controllers/__init__.py +0 -0
  52. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/scaler/controllers/docker_ctl.py +0 -0
  53. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/scaler/controllers/interface.py +0 -0
  54. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/scaler/controllers/kubernetes_ctl.py +0 -0
  55. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/scaler/run_scaler.py +0 -0
  56. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/scaler/scaler_server.py +0 -0
  57. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/server_base.py +0 -0
  58. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/signature_client.py +0 -0
  59. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/submission_client.py +0 -0
  60. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/updater/__init__.py +0 -0
  61. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/updater/helper.py +0 -0
  62. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/updater/run_updater.py +0 -0
  63. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/vacuum/__init__.py +0 -0
  64. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/vacuum/crawler.py +0 -0
  65. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/vacuum/department_map.py +0 -0
  66. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/vacuum/safelist.py +0 -0
  67. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/vacuum/stream_map.py +0 -0
  68. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/vacuum/worker.py +0 -0
  69. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/workflow/__init__.py +0 -0
  70. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core/workflow/run_workflow.py +0 -0
  71. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core.egg-info/dependency_links.txt +0 -0
  72. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core.egg-info/requires.txt +0 -0
  73. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/assemblyline_core.egg-info/top_level.txt +0 -0
  74. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/setup.cfg +0 -0
  75. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/setup.py +0 -0
  76. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/test/test_alerter.py +0 -0
  77. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/test/test_badlist_client.py +0 -0
  78. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/test/test_dispatcher.py +0 -0
  79. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/test/test_expiry.py +0 -0
  80. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/test/test_plumber.py +0 -0
  81. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/test/test_replay.py +0 -0
  82. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/test/test_safelist_client.py +0 -0
  83. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/test/test_scaler.py +0 -0
  84. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/test/test_scheduler.py +0 -0
  85. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/test/test_signature_client.py +0 -0
  86. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/test/test_simulation.py +0 -0
  87. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/test/test_vacuum.py +0 -0
  88. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/test/test_worker_ingest.py +0 -0
  89. {assemblyline_core-4.5.1.dev460 → assemblyline_core-4.5.1.dev462}/test/test_worker_submit.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: assemblyline-core
3
- Version: 4.5.1.dev460
3
+ Version: 4.5.1.dev462
4
4
  Summary: Assemblyline 4 - Core components
5
5
  Home-page: https://github.com/CybercentreCanada/assemblyline-core/
6
6
  Author: CCCS Assemblyline development team
@@ -0,0 +1 @@
1
+ 4.5.1.dev462
@@ -49,6 +49,8 @@ class TaskingClient:
49
49
  self.event_sender = EventSender('changes', redis)
50
50
  self.cleanup = False
51
51
  self.event_listener = None
52
+ self.heuristics: dict[str, Heuristic] = {}
53
+ self.register_only = register_only
52
54
 
53
55
  # If we're performing service registration, we only need a connection to the datastore
54
56
  if not register_only:
@@ -56,7 +58,6 @@ class TaskingClient:
56
58
  self.event_listener = EventWatcher(redis)
57
59
  self.filestore = filestore or forge.get_filestore(self.config)
58
60
  self.heuristic_handler = HeuristicHandler(self.datastore)
59
- self.heuristics: dict[str, Heuristic] = {}
60
61
  self.reload_heuristics({})
61
62
  self.status_table = ExpiringHash(SERVICE_STATE_HASH, ttl=60*30, host=redis)
62
63
  self.tag_safelister = forge.CachedObject(forge.get_tag_safelister, kwargs=dict(
@@ -126,7 +127,7 @@ class TaskingClient:
126
127
 
127
128
  try:
128
129
  # Get heuristics list
129
- heuristics = service_data.pop('heuristics', None)
130
+ heuristics = service_data.pop('heuristics', [])
130
131
 
131
132
  # Patch update_channel, registry_type before Service registration object creation
132
133
  service_data['update_channel'] = service_data.get(
@@ -162,57 +163,62 @@ class TaskingClient:
162
163
  self.log.info(f"{log_prefix}{service.name} version ({service.version}) registered")
163
164
 
164
165
  new_heuristics = []
165
- if heuristics:
166
- plan = self.datastore.heuristic.get_bulk_plan()
167
- for index, heuristic in enumerate(heuristics):
168
- heuristic_id = f'#{index}' # Set heuristic id to it's position in the list for logging purposes
169
- try:
170
- # Append service name to heuristic ID
171
- heuristic['heur_id'] = f"{service.name.upper()}.{str(heuristic['heur_id'])}"
172
-
173
- # Attack_id field is now a list, make it a list if we receive otherwise
174
- attack_id = heuristic.get('attack_id', None)
175
- if isinstance(attack_id, str):
176
- heuristic['attack_id'] = [attack_id]
177
-
178
- heuristic = Heuristic(heuristic)
179
- heuristic_id = heuristic.heur_id
180
- existing_heuristic_obj = self.datastore.heuristic.get_if_exists(heuristic_id)
181
- if existing_heuristic_obj:
182
- # Ensure statistics of heuristic are preserved
183
- heuristic.stats = existing_heuristic_obj.stats
184
- plan.add_upsert_operation(heuristic_id, heuristic)
185
- except Exception as e:
186
- msg = f"{service.name} has an invalid heuristic ({heuristic_id}): {str(e)}"
187
- self.log.exception(f"{log_prefix}{msg}")
188
- raise ValueError(msg)
189
-
166
+
167
+ plan = self.datastore.heuristic.get_bulk_plan()
168
+ for index, heuristic in enumerate(heuristics):
169
+ heuristic_id = f'#{index}' # Set heuristic id to it's position in the list for logging purposes
170
+ try:
171
+ # Append service name to heuristic ID
172
+ heuristic['heur_id'] = f"{service.name.upper()}.{str(heuristic['heur_id'])}"
173
+
174
+ # Attack_id field is now a list, make it a list if we receive otherwise
175
+ attack_id = heuristic.get('attack_id', None)
176
+ if isinstance(attack_id, str):
177
+ heuristic['attack_id'] = [attack_id]
178
+
179
+ heuristic = Heuristic(heuristic)
180
+ heuristic_id = heuristic.heur_id
181
+ existing_heuristic_obj = self.datastore.heuristic.get_if_exists(heuristic_id)
182
+ if existing_heuristic_obj:
183
+ # Ensure statistics of heuristic are preserved
184
+ heuristic.stats = existing_heuristic_obj.stats
185
+ plan.add_upsert_operation(heuristic_id, heuristic)
186
+ except Exception as e:
187
+ msg = f"{service.name} has an invalid heuristic ({heuristic_id}): {str(e)}"
188
+ self.log.exception(f"{log_prefix}{msg}")
189
+ raise ValueError(msg)
190
+
191
+ if plan.operations:
190
192
  for item in self.datastore.heuristic.bulk(plan)['items']:
191
193
  if item['update']['result'] != "noop":
192
194
  new_heuristics.append(item['update']['_id'])
193
195
  self.log.info(f"{log_prefix}{service.name} "
194
- f"heuristic {item['update']['_id']}: {item['update']['result'].upper()}")
196
+ f"heuristic {item['update']['_id']}: {item['update']['result'].upper()}")
195
197
 
196
- # Look for heuristics that are no longer managed by the service and clean them up
197
- all_heuristics = set(h_id for h_id in self.heuristics.keys()
198
- if h_id.startswith(f"{service.name.upper()}."))
199
- removed_heuristics = all_heuristics - set(h['heur_id'] for h in heuristics)
198
+ # Look for heuristics that are no longer managed by the service and clean them up
199
+ if self.register_only:
200
+ # Fetch current heuristics for the service during registration
201
+ self.reload_heuristics({'service_name': service.name})
200
202
 
201
- for heuristic in removed_heuristics:
202
- # Only remove heuristics that aren't actively referenced in a result
203
- if not self.datastore.result.search(f"result.sections.heuristic.heur_id:{heuristic}",
204
- rows=0, track_total_hits=True)['total']:
205
- self.datastore.heuristic.delete(heuristic)
203
+ all_heuristics = set(h_id for h_id in self.heuristics.keys()
204
+ if h_id.startswith(f"{service.name.upper()}."))
205
+ removed_heuristics = all_heuristics - set(h['heur_id'] for h in heuristics)
206
206
 
207
+ for heuristic in removed_heuristics:
208
+ # Only remove heuristics that aren't actively referenced in a result
209
+ if not self.datastore.result.search(f"result.sections.heuristic.heur_id:{heuristic}",
210
+ rows=0, track_total_hits=True)['total']:
211
+ self.datastore.heuristic.delete(heuristic)
207
212
 
208
213
 
209
- self.datastore.heuristic.commit()
210
214
 
211
- # Notify components watching for heuristic config changes
212
- self.event_sender.send('heuristics', {
213
- 'operation': Operation.Modified,
214
- 'service_name': service.name
215
- })
215
+ self.datastore.heuristic.commit()
216
+
217
+ # Notify components watching for heuristic config changes
218
+ self.event_sender.send('heuristics', {
219
+ 'operation': Operation.Modified,
220
+ 'service_name': service.name
221
+ })
216
222
 
217
223
  service_config = self.datastore.get_service_with_delta(service.name, as_obj=False)
218
224
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: assemblyline-core
3
- Version: 4.5.1.dev460
3
+ Version: 4.5.1.dev462
4
4
  Summary: Assemblyline 4 - Core components
5
5
  Home-page: https://github.com/CybercentreCanada/assemblyline-core/
6
6
  Author: CCCS Assemblyline development team
@@ -81,6 +81,7 @@ test/test_scaler.py
81
81
  test/test_scheduler.py
82
82
  test/test_signature_client.py
83
83
  test/test_simulation.py
84
+ test/test_tasking_client.py
84
85
  test/test_vacuum.py
85
86
  test/test_worker_ingest.py
86
87
  test/test_worker_submit.py
@@ -0,0 +1,39 @@
1
+
2
+ import pytest
3
+ from assemblyline_core.tasking_client import TaskingClient
4
+
5
+ from assemblyline.odm.models.service import Service
6
+ from assemblyline.odm.models.heuristic import Heuristic
7
+ from assemblyline.odm.models.result import Result, Section, Heuristic as SectionHeuristic
8
+
9
+ from assemblyline.odm.randomizer import random_minimal_obj
10
+
11
+ def test_register_service(datastore_connection):
12
+ client = TaskingClient(datastore_connection, register_only=True)
13
+
14
+ # Test service registration
15
+ service = random_minimal_obj(Service).as_primitives()
16
+ heuristics = [random_minimal_obj(Heuristic).as_primitives() for _ in range(2)]
17
+ service['heuristics'] = heuristics
18
+ assert client.register_service(service)
19
+ assert all([datastore_connection.heuristic.exists(h['heur_id']) for h in heuristics])
20
+
21
+ # Test registration with heuristics that were removed but still have related results
22
+ heuristic = heuristics.pop(0)
23
+ result = random_minimal_obj(Result)
24
+ section = random_minimal_obj(Section)
25
+ section.heuristic = SectionHeuristic(heuristic)
26
+ result.result.sections = [section]
27
+ datastore_connection.result.save('test_result', result)
28
+ datastore_connection.result.commit()
29
+
30
+ # Heuristics that were removed should still reside in the system if there are still associated data to it
31
+ service['heuristics'] = heuristics
32
+ assert client.register_service(service)
33
+ assert datastore_connection.heuristic.exists(heuristic['heur_id'])
34
+
35
+ # Test registration with removed heuristics that have no related results
36
+ datastore_connection.result.delete('test_result')
37
+ datastore_connection.result.commit()
38
+ assert client.register_service(service)
39
+ assert not datastore_connection.heuristic.exists(heuristic['heur_id'])
@@ -1 +0,0 @@
1
- 4.5.1.dev460