synapse 2.166.0__py311-none-any.whl → 2.167.0__py311-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 synapse might be problematic. Click here for more details.

Files changed (46) hide show
  1. synapse/axon.py +4 -10
  2. synapse/cortex.py +31 -1
  3. synapse/exc.py +1 -0
  4. synapse/lib/aha.py +2 -0
  5. synapse/lib/base.py +11 -4
  6. synapse/lib/cell.py +11 -2
  7. synapse/lib/hive.py +11 -0
  8. synapse/lib/node.py +4 -2
  9. synapse/lib/schemas.py +1 -1
  10. synapse/lib/stormlib/aha.py +366 -16
  11. synapse/lib/stormlib/macro.py +11 -18
  12. synapse/lib/stormlib/stix.py +1 -1
  13. synapse/lib/stormtypes.py +18 -2
  14. synapse/lib/types.py +2 -0
  15. synapse/lib/version.py +2 -2
  16. synapse/lib/view.py +4 -3
  17. synapse/models/base.py +8 -0
  18. synapse/models/files.py +3 -0
  19. synapse/telepath.py +1 -0
  20. synapse/tests/files/stormpkg/dotstorm/dotstorm.yaml +3 -0
  21. synapse/tests/test_cortex.py +39 -2
  22. synapse/tests/test_lib_aha.py +1 -2
  23. synapse/tests/test_lib_cell.py +6 -2
  24. synapse/tests/test_lib_grammar.py +62 -64
  25. synapse/tests/test_lib_httpapi.py +1 -1
  26. synapse/tests/test_lib_rstorm.py +4 -4
  27. synapse/tests/test_lib_storm.py +3 -3
  28. synapse/tests/test_lib_stormlib_aha.py +196 -0
  29. synapse/tests/test_lib_stormlib_compression.py +12 -12
  30. synapse/tests/test_lib_stormlib_macro.py +94 -0
  31. synapse/tests/test_lib_stormlib_spooled.py +1 -1
  32. synapse/tests/test_lib_stormtypes.py +44 -33
  33. synapse/tests/test_lib_view.py +50 -3
  34. synapse/tests/test_model_files.py +3 -0
  35. synapse/tests/test_tools_genpkg.py +26 -0
  36. synapse/tests/test_tools_hiveload.py +1 -0
  37. synapse/tests/test_tools_hivesave.py +1 -0
  38. synapse/tests/utils.py +22 -3
  39. synapse/tools/autodoc.py +1 -1
  40. synapse/tools/hive/load.py +3 -0
  41. synapse/tools/hive/save.py +3 -0
  42. {synapse-2.166.0.dist-info → synapse-2.167.0.dist-info}/METADATA +3 -3
  43. {synapse-2.166.0.dist-info → synapse-2.167.0.dist-info}/RECORD +46 -45
  44. {synapse-2.166.0.dist-info → synapse-2.167.0.dist-info}/LICENSE +0 -0
  45. {synapse-2.166.0.dist-info → synapse-2.167.0.dist-info}/WHEEL +0 -0
  46. {synapse-2.166.0.dist-info → synapse-2.167.0.dist-info}/top_level.txt +0 -0
synapse/axon.py CHANGED
@@ -1509,7 +1509,6 @@ class Axon(s_cell.Cell):
1509
1509
  atimeout = aiohttp.ClientTimeout(total=timeout)
1510
1510
 
1511
1511
  async with aiohttp.ClientSession(connector=connector, timeout=atimeout) as sess:
1512
-
1513
1512
  try:
1514
1513
  data = aiohttp.FormData()
1515
1514
  data._is_multipart = True
@@ -1523,7 +1522,9 @@ class Axon(s_cell.Cell):
1523
1522
 
1524
1523
  sha256 = field.get('sha256')
1525
1524
  if sha256:
1526
- valu = self.get(s_common.uhex(sha256))
1525
+ sha256b = s_common.uhex(sha256)
1526
+ await self._reqHas(sha256b)
1527
+ valu = self.get(sha256b)
1527
1528
  else:
1528
1529
  valu = field.get('value')
1529
1530
  if not isinstance(valu, (bytes, str)):
@@ -1547,9 +1548,6 @@ class Axon(s_cell.Cell):
1547
1548
  }
1548
1549
  return info
1549
1550
 
1550
- except asyncio.CancelledError: # pramga: no cover
1551
- raise
1552
-
1553
1551
  except Exception as e:
1554
1552
  logger.exception(f'Error POSTing files to [{s_urlhelp.sanitizeUrl(url)}]')
1555
1553
  err = s_common.err(e)
@@ -1586,9 +1584,8 @@ class Axon(s_cell.Cell):
1586
1584
  atimeout = aiohttp.ClientTimeout(total=timeout)
1587
1585
 
1588
1586
  async with aiohttp.ClientSession(connector=connector, timeout=atimeout) as sess:
1589
-
1590
1587
  try:
1591
-
1588
+ await self._reqHas(sha256)
1592
1589
  async with sess.request(method, url, headers=headers, params=params,
1593
1590
  data=self.get(sha256), ssl=ssl) as resp:
1594
1591
 
@@ -1601,9 +1598,6 @@ class Axon(s_cell.Cell):
1601
1598
  }
1602
1599
  return info
1603
1600
 
1604
- except asyncio.CancelledError: # pramga: no cover
1605
- raise
1606
-
1607
1601
  except Exception as e:
1608
1602
  logger.exception(f'Error streaming [{sha256}] to [{s_urlhelp.sanitizeUrl(url)}]')
1609
1603
  err = s_common.err(e)
synapse/cortex.py CHANGED
@@ -1016,6 +1016,12 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
1016
1016
  (2, self._storLayrFeedDefaults),
1017
1017
  ), nexs=False)
1018
1018
 
1019
+ async def _viewNomergeToProtected(self):
1020
+ for view in self.views.values():
1021
+ nomerge = view.info.get('nomerge', False)
1022
+ await view.setViewInfo('protected', nomerge)
1023
+ await view.setViewInfo('nomerge', None)
1024
+
1019
1025
  async def _storUpdateMacros(self):
1020
1026
  for name, node in await self.hive.open(('cortex', 'storm', 'macros')):
1021
1027
 
@@ -1050,6 +1056,9 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
1050
1056
 
1051
1057
  def getStormMacro(self, name, user=None):
1052
1058
 
1059
+ if not name:
1060
+ raise s_exc.BadArg(mesg=f'Macro names must be at least 1 character long')
1061
+
1053
1062
  if len(name) > 491:
1054
1063
  raise s_exc.BadArg(mesg='Macro names may only be up to 491 chars.')
1055
1064
 
@@ -1140,6 +1149,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
1140
1149
  raise s_exc.BadArg(mesg=f'Duplicate macro name: {name}')
1141
1150
 
1142
1151
  self.slab.put(name.encode(), s_msgpack.en(mdef), db=self.macrodb)
1152
+ await self.feedBeholder('storm:macro:add', {'macro': mdef})
1143
1153
  return mdef
1144
1154
 
1145
1155
  async def delStormMacro(self, name, user=None):
@@ -1151,9 +1161,15 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
1151
1161
 
1152
1162
  @s_nexus.Pusher.onPush('storm:macro:del')
1153
1163
  async def _delStormMacro(self, name):
1164
+ if not name:
1165
+ raise s_exc.BadArg(mesg=f'Macro names must be at least 1 character long')
1166
+
1154
1167
  byts = self.slab.pop(name.encode(), db=self.macrodb)
1168
+
1155
1169
  if byts is not None:
1156
- return s_msgpack.un(byts)
1170
+ macro = s_msgpack.un(byts)
1171
+ await self.feedBeholder('storm:macro:del', {'name': name, 'iden': macro.get('iden')})
1172
+ return macro
1157
1173
 
1158
1174
  async def modStormMacro(self, name, info, user=None):
1159
1175
  if user is not None:
@@ -1183,6 +1199,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
1183
1199
  else:
1184
1200
  self.slab.put(name.encode(), s_msgpack.en(mdef), db=self.macrodb)
1185
1201
 
1202
+ await self.feedBeholder('storm:macro:mod', {'macro': mdef, 'info': info})
1186
1203
  return mdef
1187
1204
 
1188
1205
  async def setStormMacroPerm(self, name, scope, iden, level, user=None):
@@ -1201,6 +1218,14 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
1201
1218
  reqValidStormMacro(mdef)
1202
1219
 
1203
1220
  self.slab.put(name.encode(), s_msgpack.en(mdef), db=self.macrodb)
1221
+
1222
+ info = {
1223
+ 'scope': scope,
1224
+ 'iden': iden,
1225
+ 'level': level
1226
+ }
1227
+
1228
+ await self.feedBeholder('storm:macro:set:perm', {'macro': mdef, 'info': info})
1204
1229
  return mdef
1205
1230
 
1206
1231
  async def getStormMacros(self, user=None):
@@ -1400,6 +1425,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
1400
1425
 
1401
1426
  await self._bumpCellVers('cortex:defaults', (
1402
1427
  (1, self._addAllLayrRead),
1428
+ (2, self._viewNomergeToProtected),
1403
1429
  ))
1404
1430
 
1405
1431
  async def _addAllLayrRead(self):
@@ -4458,6 +4484,10 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
4458
4484
  if view is None:
4459
4485
  raise s_exc.NoSuchView(mesg=f'No such view {iden=}', iden=iden)
4460
4486
 
4487
+ if view.info.get('protected'):
4488
+ mesg = f'Cannot delete view ({iden}) that has protected set.'
4489
+ raise s_exc.CantDelView(mesg=mesg)
4490
+
4461
4491
  return await self._push('view:del', iden)
4462
4492
 
4463
4493
  @s_nexus.Pusher.onPush('view:del')
synapse/exc.py CHANGED
@@ -145,6 +145,7 @@ class CantDelForm(SynErr): pass
145
145
  class CantDelProp(SynErr): pass
146
146
  class CantDelType(SynErr): pass
147
147
  class CantDelUniv(SynErr): pass
148
+ class CantDelView(SynErr): pass
148
149
  class CantMergeView(SynErr): pass
149
150
  class CantRevLayer(SynErr): pass
150
151
  class CliFini(SynErr):
synapse/lib/aha.py CHANGED
@@ -782,6 +782,8 @@ class AhaCell(s_cell.Cell):
782
782
 
783
783
  svcname, svcnetw, svcfull = self._nameAndNetwork(name, network)
784
784
 
785
+ logger.info(f'Deleting service [{svcfull}].', extra=await self.getLogExtra(name=svcname, netw=svcnetw))
786
+
785
787
  full = ('aha', 'svcfull', svcfull)
786
788
  path = ('aha', 'services', svcnetw, svcname)
787
789
 
synapse/lib/base.py CHANGED
@@ -143,6 +143,7 @@ class Base:
143
143
  self._fini_atexit = False
144
144
  self._active_tasks = None # the set of free running tasks associated with me
145
145
  self._context_managers = None # the set of context managers i must fini
146
+ self._syn_signal_tasks = None # initialized as a Set when addSignalHandlers is called.
146
147
 
147
148
  async def postAnit(self):
148
149
  '''
@@ -559,14 +560,20 @@ class Base:
559
560
  '''
560
561
  Register SIGTERM/SIGINT signal handlers with the ioloop to fini this object.
561
562
  '''
563
+ if self._syn_signal_tasks is None:
564
+ self._syn_signal_tasks = set()
562
565
 
563
566
  def sigterm():
564
- print('Caught SIGTERM, shutting down.')
565
- asyncio.create_task(self.fini())
567
+ logger.warning('Caught SIGTERM, shutting down.')
568
+ task = asyncio.create_task(self.fini())
569
+ self._syn_signal_tasks.add(task)
570
+ task.add_done_callback(self._syn_signal_tasks.discard)
566
571
 
567
572
  def sigint():
568
- print('Caught SIGINT, shutting down.')
569
- asyncio.create_task(self.fini())
573
+ logger.warning('Caught SIGINT, shutting down.')
574
+ task = asyncio.create_task(self.fini())
575
+ self._syn_signal_tasks.add(task)
576
+ task.add_done_callback(self._syn_signal_tasks.discard)
570
577
 
571
578
  loop = asyncio.get_running_loop()
572
579
  loop.add_signal_handler(signal.SIGINT, sigint)
synapse/lib/cell.py CHANGED
@@ -668,26 +668,32 @@ class CellApi(s_base.Base):
668
668
 
669
669
  @adminapi()
670
670
  async def listHiveKey(self, path=None):
671
+ s_common.deprecated('CellApi.listHiveKey', curv='2.167.0')
671
672
  return await self.cell.listHiveKey(path=path)
672
673
 
673
674
  @adminapi(log=True)
674
675
  async def getHiveKeys(self, path):
676
+ s_common.deprecated('CellApi.getHiveKeys', curv='2.167.0')
675
677
  return await self.cell.getHiveKeys(path)
676
678
 
677
679
  @adminapi(log=True)
678
680
  async def getHiveKey(self, path):
681
+ s_common.deprecated('CellApi.getHiveKey', curv='2.167.0')
679
682
  return await self.cell.getHiveKey(path)
680
683
 
681
684
  @adminapi(log=True)
682
685
  async def setHiveKey(self, path, valu):
686
+ s_common.deprecated('CellApi.setHiveKey', curv='2.167.0')
683
687
  return await self.cell.setHiveKey(path, valu)
684
688
 
685
689
  @adminapi(log=True)
686
690
  async def popHiveKey(self, path):
691
+ s_common.deprecated('CellApi.popHiveKey', curv='2.167.0')
687
692
  return await self.cell.popHiveKey(path)
688
693
 
689
694
  @adminapi(log=True)
690
695
  async def saveHiveTree(self, path=()):
696
+ s_common.deprecated('CellApi.saveHiveTree', curv='2.167.0')
691
697
  return await self.cell.saveHiveTree(path=path)
692
698
 
693
699
  @adminapi()
@@ -1419,7 +1425,6 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
1419
1425
  if ahaurl is not None:
1420
1426
 
1421
1427
  info = await s_telepath.addAhaUrl(ahaurl)
1422
- self.ahaclient = info.get('client')
1423
1428
  if self.ahaclient is None:
1424
1429
  self.ahaclient = await s_telepath.Client.anit(info.get('url'))
1425
1430
  self.ahaclient._fini_atexit = True
@@ -2895,6 +2900,7 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
2895
2900
  if isnew:
2896
2901
  path = os.path.join(self.dirn, 'hiveboot.yaml')
2897
2902
  if os.path.isfile(path):
2903
+ s_common.deprdate('Initial hive config from hiveboot.yaml', '2024-05-05')
2898
2904
  logger.debug(f'Loading cell hive from {path}')
2899
2905
  tree = s_common.yamlload(path)
2900
2906
  if tree is not None:
@@ -4079,7 +4085,10 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
4079
4085
  await s_base.Base.addSignalHandlers(self)
4080
4086
 
4081
4087
  def sighup():
4082
- asyncio.create_task(self.reload())
4088
+ logger.info('Caught SIGHUP, running reloadable subsystems.')
4089
+ task = asyncio.create_task(self.reload())
4090
+ self._syn_signal_tasks.add(task)
4091
+ task.add_done_callback(self._syn_signal_tasks.discard)
4083
4092
 
4084
4093
  loop = asyncio.get_running_loop()
4085
4094
  loop.add_signal_handler(signal.SIGHUP, sighup)
synapse/lib/hive.py CHANGED
@@ -473,12 +473,15 @@ class HiveApi(s_base.Base):
473
473
  self.onfini(self._onHapiFini)
474
474
 
475
475
  async def loadHiveTree(self, tree, path=(), trim=False):
476
+ s_common.deprecated('HiveApi.loadHiveTree', curv='2.167.0')
476
477
  return await self.hive.loadHiveTree(tree, path=path, trim=trim)
477
478
 
478
479
  async def saveHiveTree(self, path=()):
480
+ s_common.deprecated('HiveApi.saveHiveTree', curv='2.167.0')
479
481
  return await self.hive.saveHiveTree(path=path)
480
482
 
481
483
  async def treeAndSync(self, path, iden):
484
+ s_common.deprecated('HiveApi.treeAndSync', curv='2.167.0')
482
485
 
483
486
  node = await self.hive.open(path)
484
487
 
@@ -510,16 +513,22 @@ class HiveApi(s_base.Base):
510
513
  return
511
514
 
512
515
  async def setAndSync(self, path, valu, iden, nexs=False):
516
+ s_common.deprecated('HiveApi.setAndSync', curv='2.167.0')
517
+
513
518
  valu = await self.hive.set(path, valu, nexs=nexs)
514
519
  await self.msgq.put(('hive:sync', {'iden': iden}))
515
520
  return valu
516
521
 
517
522
  async def addAndSync(self, path, valu, iden):
523
+ s_common.deprecated('HiveApi.addAndSync', curv='2.167.0')
524
+
518
525
  valu = await self.hive.add(path, valu)
519
526
  await self.msgq.put(('hive:sync', {'iden': iden}))
520
527
  return valu
521
528
 
522
529
  async def popAndSync(self, path, iden, nexs=False):
530
+ s_common.deprecated('HiveApi.popAndSync', curv='2.167.0')
531
+
523
532
  valu = await self.hive.pop(path, nexs=nexs)
524
533
  await self.msgq.put(('hive:sync', {'iden': iden}))
525
534
  return valu
@@ -531,9 +540,11 @@ class HiveApi(s_base.Base):
531
540
  self.msgq.put_nowait(mesg)
532
541
 
533
542
  async def get(self, full):
543
+ s_common.deprecated('HiveApi.get', curv='2.167.0')
534
544
  return await self.hive.get(full)
535
545
 
536
546
  async def edits(self):
547
+ s_common.deprecated('HiveApi.edits', curv='2.167.0')
537
548
 
538
549
  while not self.isfini:
539
550
 
synapse/lib/node.py CHANGED
@@ -472,10 +472,12 @@ class Node:
472
472
  form=self.form.full, tag=tag)
473
473
 
474
474
  pref = name + '.'
475
+ exists = self.tags.get(name, s_common.novalu) is not s_common.novalu
475
476
 
476
477
  todel = [(len(t), t) for t in self.tags.keys() if t.startswith(pref)]
477
478
 
478
- if len(path) > 1:
479
+ # only prune when we're actually deleting a tag
480
+ if len(path) > 1 and exists:
479
481
 
480
482
  parent = '.'.join(path[:-1])
481
483
 
@@ -511,7 +513,7 @@ class Node:
511
513
  edits.append((s_layer.EDIT_TAG_DEL, (subtag, None), ()))
512
514
 
513
515
  edits.extend(self._getTagPropDel(name))
514
- if self.getTag(name, defval=s_common.novalu) is not s_common.novalu:
516
+ if exists:
515
517
  edits.append((s_layer.EDIT_TAG_DEL, (name, None), ()))
516
518
 
517
519
  return edits
synapse/lib/schemas.py CHANGED
@@ -172,7 +172,7 @@ reqValidView = s_config.getJsValidator({
172
172
  'parent': {'type': ['string', 'null'], 'pattern': s_config.re_iden},
173
173
  'creator': {'type': 'string', 'pattern': s_config.re_iden},
174
174
  'created': {'type': 'integer', 'minimum': 0},
175
- 'nomerge': {'type': 'boolean'},
175
+ 'protected': {'type': 'boolean', 'default': False},
176
176
  'merging': {'type': 'boolean'},
177
177
  'layers': {
178
178
  'type': 'array',