assemblyline-ui 4.7.0.dev25__py3-none-any.whl → 4.7.0.dev27__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.
assemblyline_ui/VERSION CHANGED
@@ -1 +1 @@
1
- 4.7.0.dev25
1
+ 4.7.0.dev27
@@ -4,8 +4,6 @@ import re
4
4
  import subprocess
5
5
  import tempfile
6
6
 
7
- from flask import request
8
-
9
7
  from assemblyline.common.codec import encode_file
10
8
  from assemblyline.common.dict_utils import unflatten
11
9
  from assemblyline.common.hexdump import dump, hexdump
@@ -15,6 +13,8 @@ from assemblyline.datastore.collection import Index
15
13
  from assemblyline.filestore import FileStoreException
16
14
  from assemblyline.odm.models.user import ROLES
17
15
  from assemblyline.odm.models.user_settings import ENCODINGS as FILE_DOWNLOAD_ENCODINGS
16
+ from flask import request
17
+
18
18
  from assemblyline_ui.api.base import (
19
19
  api_login,
20
20
  make_api_response,
@@ -48,6 +48,27 @@ file_api._doc = "Perform operations on files"
48
48
  API_MAX_SIZE = 1 * 1024 * 1024
49
49
 
50
50
 
51
+ def retrieve_file_content(file_obj: dict) -> bytes:
52
+ """ Retrieve file content from filestore or archivestore based on availability and file metadata."""
53
+ data = None
54
+ try:
55
+ if file_obj.get('from_archive'):
56
+ # Try to download from archive first
57
+ if ARCHIVESTORE is not None and ARCHIVESTORE.exists(file_obj['sha256']):
58
+ data = ARCHIVESTORE.get(file_obj['sha256'])
59
+
60
+ # If for some reason the file is not in archive, try filestore
61
+ elif FILESTORE.exists(file_obj['sha256']):
62
+ data = FILESTORE.get(file_obj['sha256'])
63
+
64
+ elif FILESTORE.exists(file_obj['sha256']):
65
+ # Try to download from filestore
66
+ data = FILESTORE.get(file_obj['sha256'])
67
+ except FileStoreException:
68
+ pass
69
+
70
+ return data
71
+
51
72
  @file_api.route("/ascii/<sha256>/", methods=["GET"])
52
73
  @api_login(require_role=[ROLES.file_detail])
53
74
  def get_file_ascii(sha256, **kwargs):
@@ -71,30 +92,23 @@ def get_file_ascii(sha256, **kwargs):
71
92
  """
72
93
 
73
94
  user = kwargs['user']
74
- file_obj = STORAGE.file.get(sha256, as_obj=False)
95
+ index_type = None
96
+ if ROLES.archive_download in user['roles']:
97
+ # User is allowed to access archive, so we check both hot and archive
98
+ index_type = Index.HOT_AND_ARCHIVE
75
99
 
76
- if not file_obj or not FILESTORE.exists(sha256):
100
+ file_obj = STORAGE.file.get(sha256, as_obj=False, index_type=index_type)
101
+
102
+ if not file_obj:
77
103
  return make_api_response({}, "The file was not found in the system.", 404)
78
104
 
79
105
  if user and Classification.is_accessible(user['classification'], file_obj['classification']):
80
- try:
81
- data = FILESTORE.get(sha256)[:API_MAX_SIZE]
82
- except (FileStoreException, TypeError):
83
- data = None
84
-
85
- # Try to download from archive
86
- if not data and \
87
- ARCHIVESTORE is not None and \
88
- ARCHIVESTORE != FILESTORE and \
89
- ROLES.archive_download in user['roles'] and \
90
- ARCHIVESTORE.exists(sha256):
91
- try:
92
- data = ARCHIVESTORE.get(sha256)
93
- except FileStoreException:
94
- data = None
95
-
106
+ data = retrieve_file_content(file_obj)
96
107
  if not data:
97
108
  return make_api_response({}, "This file was not found in the system.", 404)
109
+ else:
110
+ # Trim data to API max size
111
+ data = data[:API_MAX_SIZE]
98
112
 
99
113
  return make_api_response({
100
114
  "content": data.translate(FILTER_ASCII).decode(),
@@ -129,7 +143,12 @@ def download_file(sha256, **kwargs):
129
143
  <THE FILE BINARY ENCODED IN SPECIFIED FORMAT>
130
144
  """
131
145
  user = kwargs['user']
132
- file_obj = STORAGE.file.get(sha256, as_obj=False)
146
+ index_type = None
147
+ if ROLES.archive_download in user['roles']:
148
+ # User is allowed to access archive, so we check both hot and archive
149
+ index_type = Index.HOT_AND_ARCHIVE
150
+
151
+ file_obj = STORAGE.file.get(sha256, as_obj=False, index_type=index_type)
133
152
 
134
153
  if not file_obj:
135
154
  return make_api_response({}, "The file was not found in the system.", 404)
@@ -145,7 +164,7 @@ def download_file(sha256, **kwargs):
145
164
  submission = {}
146
165
  file_metadata = {}
147
166
  if sid is not None:
148
- submission = STORAGE.submission.get(sid, as_obj=False)
167
+ submission = STORAGE.submission.get(sid, as_obj=False, index_type=index_type)
149
168
  if submission is None:
150
169
  submission = {}
151
170
 
@@ -185,20 +204,21 @@ def download_file(sha256, **kwargs):
185
204
  _, download_path = tempfile.mkstemp()
186
205
 
187
206
  try:
207
+ downloaded_from = None
188
208
  try:
189
- downloaded_from = FILESTORE.download(sha256, download_path)
209
+ if file_obj.get('from_archive'):
210
+ # Try to download from archive first
211
+ if ARCHIVESTORE is not None and ARCHIVESTORE.exists(sha256):
212
+ downloaded_from = ARCHIVESTORE.download(sha256, download_path)
213
+
214
+ # If for some reason the file is not in archive, try filestore
215
+ elif FILESTORE.exists(sha256):
216
+ downloaded_from = FILESTORE.download(sha256, download_path)
217
+ else:
218
+ # Try to download from filestore
219
+ downloaded_from = FILESTORE.download(sha256, download_path)
190
220
  except FileStoreException:
191
- downloaded_from = None
192
-
193
- # Try to download from archive
194
- if not downloaded_from and \
195
- ARCHIVESTORE is not None and \
196
- ARCHIVESTORE != FILESTORE and \
197
- ROLES.archive_download in user['roles']:
198
- try:
199
- downloaded_from = ARCHIVESTORE.download(sha256, download_path)
200
- except FileStoreException:
201
- downloaded_from = None
221
+ pass
202
222
 
203
223
  if not downloaded_from:
204
224
  return make_api_response({}, "The file was not found in the system.", 404)
@@ -379,7 +399,12 @@ def summarize_code_snippet(sha256, **kwargs):
379
399
  ai_summary = CACHE.get(cache_key)
380
400
 
381
401
  if not ai_summary:
382
- file_obj = STORAGE.file.get(sha256, as_obj=False)
402
+ index_type = None
403
+ if ROLES.archive_download in user['roles']:
404
+ # User is allowed to access archive, so we check both hot and archive
405
+ index_type = Index.HOT_AND_ARCHIVE
406
+
407
+ file_obj = STORAGE.file.get(sha256, as_obj=False, index_type=index_type)
383
408
 
384
409
  if not file_obj:
385
410
  return make_api_response({}, "The file was not found in the system.", 404)
@@ -392,22 +417,7 @@ def summarize_code_snippet(sha256, **kwargs):
392
417
  # return make_api_response({}, "This file is too big to be seen through this API.", 403)
393
418
 
394
419
  if user and Classification.is_accessible(user['classification'], file_obj['classification']):
395
- try:
396
- data = FILESTORE.get(sha256)
397
- except (FileStoreException, TypeError):
398
- data = None
399
-
400
- # Try to download from archive
401
- if not data and \
402
- ARCHIVESTORE is not None and \
403
- ARCHIVESTORE != FILESTORE and \
404
- ROLES.archive_download in user['roles'] and \
405
- ARCHIVESTORE.exists(sha256):
406
- try:
407
- data = ARCHIVESTORE.get(sha256)
408
- except FileStoreException:
409
- data = None
410
-
420
+ data = retrieve_file_content(file_obj)
411
421
  if not data:
412
422
  return make_api_response({}, "The file was not found in the system.", 404)
413
423
 
@@ -450,33 +460,26 @@ def get_file_hex(sha256, **kwargs):
450
460
  }
451
461
  """
452
462
  user = kwargs['user']
453
- file_obj = STORAGE.file.get(sha256, as_obj=False)
463
+ index_type = None
464
+ if ROLES.archive_download in user['roles']:
465
+ # User is allowed to access archive, so we check both hot and archive
466
+ index_type = Index.HOT_AND_ARCHIVE
467
+ file_obj = STORAGE.file.get(sha256, as_obj=False, index_type=index_type)
454
468
 
455
469
  bytes_only = request.args.get('bytes_only', 'false').lower() in ['true', '']
456
470
  length = int(request.args.get('length', '16'))
457
471
 
458
- if not file_obj or not FILESTORE.exists(sha256):
472
+ if not file_obj:
459
473
  return make_api_response({}, "The file was not found in the system.", 404)
460
474
 
461
475
  if user and Classification.is_accessible(user['classification'], file_obj['classification']):
462
- try:
463
- data = FILESTORE.get(sha256)[:API_MAX_SIZE]
464
- except FileStoreException:
465
- data = None
466
-
467
- # Try to download from archive
468
- if not data and \
469
- ARCHIVESTORE is not None and \
470
- ARCHIVESTORE != FILESTORE and \
471
- ROLES.archive_download in user['roles'] and \
472
- ARCHIVESTORE.exists(sha256):
473
- try:
474
- data = ARCHIVESTORE.get(sha256)
475
- except FileStoreException:
476
- data = None
476
+ data = retrieve_file_content(file_obj)
477
477
 
478
478
  if not data:
479
479
  return make_api_response({}, "This file was not found in the system.", 404)
480
+ else:
481
+ # Trim data to API max size
482
+ data = data[:API_MAX_SIZE]
480
483
 
481
484
  if bytes_only:
482
485
  return make_api_response({
@@ -514,7 +517,11 @@ def get_file_image_datastream(sha256, **kwargs):
514
517
  data:image/png;base64,...
515
518
  """
516
519
  user = kwargs['user']
517
- file_obj = STORAGE.file.get(sha256, as_obj=False)
520
+ index_type = None
521
+ if ROLES.archive_download in user['roles']:
522
+ # User is allowed to access archive, so we check both hot and archive
523
+ index_type = Index.HOT_AND_ARCHIVE
524
+ file_obj = STORAGE.file.get(sha256, as_obj=False, index_type=index_type)
518
525
 
519
526
  if not file_obj:
520
527
  return make_api_response({}, "The file was not found in the system.", 404)
@@ -523,22 +530,7 @@ def get_file_image_datastream(sha256, **kwargs):
523
530
  return make_api_response({}, "This file is not allowed to be downloaded as a datastream.", 403)
524
531
 
525
532
  if user and Classification.is_accessible(user['classification'], file_obj['classification']):
526
- try:
527
- data = FILESTORE.get(sha256)
528
- except (FileStoreException, TypeError):
529
- data = None
530
-
531
- # Try to download from archive
532
- if not data and \
533
- ARCHIVESTORE is not None and \
534
- ARCHIVESTORE != FILESTORE and \
535
- ROLES.archive_download in user['roles'] and \
536
- ARCHIVESTORE.exists(sha256):
537
- try:
538
- data = ARCHIVESTORE.get(sha256)
539
- except FileStoreException:
540
- data = None
541
-
533
+ data = retrieve_file_content(file_obj)
542
534
  if not data:
543
535
  return make_api_response({}, "This file was not found in the system.", 404)
544
536
 
@@ -570,30 +562,23 @@ def get_file_strings(sha256, **kwargs):
570
562
  """
571
563
  user = kwargs['user']
572
564
  hlen = request.args.get('len', "6")
573
- file_obj = STORAGE.file.get(sha256, as_obj=False)
565
+ index_type = None
566
+ if ROLES.archive_download in user['roles']:
567
+ # User is allowed to access archive, so we check both hot and archive
568
+ index_type = Index.HOT_AND_ARCHIVE
569
+
570
+ file_obj = STORAGE.file.get(sha256, as_obj=False, index_type=index_type)
574
571
 
575
- if not file_obj or not FILESTORE.exists(sha256):
572
+ if not file_obj:
576
573
  return make_api_response({}, "The file was not found in the system.", 404)
577
574
 
578
575
  if user and Classification.is_accessible(user['classification'], file_obj['classification']):
579
- try:
580
- data = FILESTORE.get(sha256)[:API_MAX_SIZE]
581
- except (FileStoreException, TypeError):
582
- data = None
583
-
584
- # Try to download from archive
585
- if not data and \
586
- ARCHIVESTORE is not None and \
587
- ARCHIVESTORE != FILESTORE and \
588
- ROLES.archive_download in user['roles'] and \
589
- ARCHIVESTORE.exists(sha256):
590
- try:
591
- data = ARCHIVESTORE.get(sha256)
592
- except FileStoreException:
593
- data = None
594
-
576
+ data = retrieve_file_content(file_obj)
595
577
  if not data:
596
578
  return make_api_response({}, "This file was not found in the system.", 404)
579
+ else:
580
+ # Trim data to API max size
581
+ data = data[:API_MAX_SIZE]
597
582
 
598
583
  # Ascii strings (we use decode with replace on to create delimiters)
599
584
  pattern = "[\x20-\x7e]{%s,}" % hlen
@@ -741,11 +726,9 @@ def get_file_results(sha256, **kwargs):
741
726
  "file_viewer_only": True } # UI switch to disable features
742
727
  """
743
728
  user = kwargs['user']
744
-
729
+ index_type = None
745
730
  if str(request.args.get('archive_only', 'false')).lower() in ['true', '']:
746
731
  index_type = Index.ARCHIVE
747
- else:
748
- index_type = None
749
732
 
750
733
  file_obj = STORAGE.file.get(sha256, as_obj=False, index_type=index_type)
751
734
 
@@ -3,16 +3,16 @@
3
3
 
4
4
  import os
5
5
 
6
- from assemblyline_core.submission_client import SubmissionClient, SubmissionException
7
- from cart import get_metadata_only, is_cart
8
- from flask import request
9
-
10
6
  from assemblyline.common import forge
11
7
  from assemblyline.common.bundling import import_bundle
12
8
  from assemblyline.common.str_utils import safe_str
13
9
  from assemblyline.common.uid import get_random_id
14
10
  from assemblyline.odm.messages.submission import Submission
15
11
  from assemblyline.odm.models.user import ROLES
12
+ from assemblyline_core.submission_client import SubmissionClient, SubmissionException
13
+ from cart import get_metadata_only, is_cart
14
+ from flask import request
15
+
16
16
  from assemblyline_ui.api.base import api_login, make_api_response, make_subapi_blueprint
17
17
  from assemblyline_ui.config import (
18
18
  FILESTORE,
@@ -249,7 +249,8 @@ def start_ui_submission(ui_sid, **kwargs):
249
249
  meta = get_metadata_only(submitted_file)
250
250
  if meta.get('al', {}).get('type', 'unknown') == 'archive/bundle/al':
251
251
  try:
252
- submission = import_bundle(submitted_file, allow_incomplete=True, identify=IDENTIFY)
252
+ submission = import_bundle(submitted_file, allow_incomplete=True, identify=IDENTIFY,
253
+ dtl=ui_params.get('ttl'))
253
254
  except Exception as e:
254
255
  return make_api_response("", err=str(e), status_code=400)
255
256
  return make_api_response({"started": True, "sid": submission['sid']})
@@ -198,7 +198,7 @@ def who_am_i(**kwargs):
198
198
  # System configuration
199
199
  user_data['c12nDef'] = classification_definition
200
200
  user_data['classification_aliases'] = {k: v for k, v in CLASSIFICATION_ALIASES.items().items()
201
- if k in user_data['classification'] or user_data['is_admin']}
201
+ if k in user_data['classification'] or user_data['is_admin'] or CLASSIFICATION.is_accessible(user_data['classification'], CLASSIFICATION.RESTRICTED)}
202
202
 
203
203
  # create tag-to-source lookup mapping
204
204
  external_source_tags = {}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: assemblyline-ui
3
- Version: 4.7.0.dev25
3
+ Version: 4.7.0.dev27
4
4
  Summary: Assemblyline 4 - API and Socket IO server
5
5
  Home-page: https://github.com/CybercentreCanada/assemblyline-ui/
6
6
  Author: CCCS Assemblyline development team
@@ -1,4 +1,4 @@
1
- assemblyline_ui/VERSION,sha256=86rnx2n5DlVlISBAT0O8ZIOeE-g_gwhj06QGH74PUGQ,12
1
+ assemblyline_ui/VERSION,sha256=-GJ0HW4qQl8iXAUjY8QNvKgFt95A8kAwDR6TgraTteU,12
2
2
  assemblyline_ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  assemblyline_ui/app.py,sha256=ok96rpL0-Hb5amqa7ojhuB0boQceZG7E32NX6LZm-f4,7849
4
4
  assemblyline_ui/config.py,sha256=4M5wpG_OwJPjZAjRWIUMMyF4KG30oJidNDnFM-IVJCw,8927
@@ -22,7 +22,7 @@ assemblyline_ui/api/v4/badlist.py,sha256=lTqRLs8F745U0biPdC4AHimj0VUiCLcNFEae7Un
22
22
  assemblyline_ui/api/v4/bundle.py,sha256=UcLUpErpiAk5LSYeC0zHDw_WpQiPcM8uhH7NwmWi4hw,5521
23
23
  assemblyline_ui/api/v4/error.py,sha256=RdpnDqM-tiFdG-Qni3-_8kn7VPlB0UW1VafUF2EHw8Q,2586
24
24
  assemblyline_ui/api/v4/federated_lookup.py,sha256=aq7KMBu1x6ZTvSOfSq_L0Y-Q6VFIxsE8IVK0BZ9w0y8,12540
25
- assemblyline_ui/api/v4/file.py,sha256=rHBgN0XaLmuUf64-Z8ca9vHrS_av3VbQRtALXGsDlxY,40009
25
+ assemblyline_ui/api/v4/file.py,sha256=l1bAjORDtt7xWgrxbMbk9MaVVRlA1OvqleGq2QFTdRg,39988
26
26
  assemblyline_ui/api/v4/hash_search.py,sha256=2KidEgffDWoMJzmFC49dN6OctcsjdRo-lNVgx1GorOA,12129
27
27
  assemblyline_ui/api/v4/help.py,sha256=HmCJfBZXv5DM1e_ZEtjq_83UIr-jUyCNtLueXboUAWg,6767
28
28
  assemblyline_ui/api/v4/heuristics.py,sha256=YfTUmDYrilwdNO1Dlr0qfDRTU4fOhPpSCWARLjt1auo,2910
@@ -40,8 +40,8 @@ assemblyline_ui/api/v4/signature.py,sha256=av3FhYkIuXjKX91DX93WcN_U5L2bltDHJSwRb
40
40
  assemblyline_ui/api/v4/submission.py,sha256=WxMY00ePNdOMFXyu9j38sxpe0vT26u-Z_biMiBUOxds,46345
41
41
  assemblyline_ui/api/v4/submit.py,sha256=5nfuX6Ud3FMdDGIOgBAdcb6kpMbINk750Ph5yp90O8c,18372
42
42
  assemblyline_ui/api/v4/system.py,sha256=4JhLhpmPfKzbXiHsBoJxSZP-ibu-lnmk4FrtaLExaRM,24861
43
- assemblyline_ui/api/v4/ui.py,sha256=IlMR77TIgIdoWitKK1CLU20X27x1IxnMFbWgyLVGH4M,11427
44
- assemblyline_ui/api/v4/user.py,sha256=AlSVtbKgPlNtlyKnmz4fyDYgcpD5uBSq-dRI83L3yEY,47760
43
+ assemblyline_ui/api/v4/ui.py,sha256=J3OoLEETlFgeq7DbSlubTPebMQJOUx6UwRIt8mCBYbQ,11508
44
+ assemblyline_ui/api/v4/user.py,sha256=m_xvc59imrxbRBwnNkZeH2vZbcW5smDgLIcIRVobaP0,47848
45
45
  assemblyline_ui/api/v4/webauthn.py,sha256=ouVWMMd0aMnNV5iaKbWY1AnsUE5_BKAtaUg9j77Rvow,4875
46
46
  assemblyline_ui/api/v4/workflow.py,sha256=Uz50960KyvFDm39NKYNSq5OXT0CA0u_FO5xPP61aYiQ,10579
47
47
  assemblyline_ui/helper/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -74,8 +74,8 @@ assemblyline_ui/sio/live_submission.py,sha256=mS0oGO5rEA8PLa8kjBcodOG-Q0CG4SpYAo
74
74
  assemblyline_ui/sio/retrohunt.py,sha256=vlH_x6Rb4pm3GM1sNLH1C42-NVR3VoAsEfkAu3L30fY,2146
75
75
  assemblyline_ui/sio/status.py,sha256=_Bxf1KLPOJEUIk4J9_j9fzvQWUXqSIT9xnJKhT1hhuc,1980
76
76
  assemblyline_ui/sio/submission.py,sha256=IYJuGz73HK9HtYfqc-gWW8tc1lt5VZ62Qn64AaGGtm8,2222
77
- assemblyline_ui-4.7.0.dev25.dist-info/licenses/LICENCE.md,sha256=NSkYo9EH8h5oOkzg4VhjAHF4339MqPP2cQ8msTPgl-c,1396
78
- assemblyline_ui-4.7.0.dev25.dist-info/METADATA,sha256=tRsJk_45BGL4WiNWnLNPQFKoPQ5mkCI8sNXYMuD1rM8,8174
79
- assemblyline_ui-4.7.0.dev25.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
80
- assemblyline_ui-4.7.0.dev25.dist-info/top_level.txt,sha256=WLa7-PKLJTbMUbKKU3q3kg5_uAV67hss5kC71PAbIeg,16
81
- assemblyline_ui-4.7.0.dev25.dist-info/RECORD,,
77
+ assemblyline_ui-4.7.0.dev27.dist-info/licenses/LICENCE.md,sha256=NSkYo9EH8h5oOkzg4VhjAHF4339MqPP2cQ8msTPgl-c,1396
78
+ assemblyline_ui-4.7.0.dev27.dist-info/METADATA,sha256=l1sEFDRV1Tfp5Q89_VCFNJMm0-jAjD13vOkJbTIIBL8,8174
79
+ assemblyline_ui-4.7.0.dev27.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
80
+ assemblyline_ui-4.7.0.dev27.dist-info/top_level.txt,sha256=WLa7-PKLJTbMUbKKU3q3kg5_uAV67hss5kC71PAbIeg,16
81
+ assemblyline_ui-4.7.0.dev27.dist-info/RECORD,,