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.
- synapse/axon.py +4 -10
- synapse/cortex.py +31 -1
- synapse/exc.py +1 -0
- synapse/lib/aha.py +2 -0
- synapse/lib/base.py +11 -4
- synapse/lib/cell.py +11 -2
- synapse/lib/hive.py +11 -0
- synapse/lib/node.py +4 -2
- synapse/lib/schemas.py +1 -1
- synapse/lib/stormlib/aha.py +366 -16
- synapse/lib/stormlib/macro.py +11 -18
- synapse/lib/stormlib/stix.py +1 -1
- synapse/lib/stormtypes.py +18 -2
- synapse/lib/types.py +2 -0
- synapse/lib/version.py +2 -2
- synapse/lib/view.py +4 -3
- synapse/models/base.py +8 -0
- synapse/models/files.py +3 -0
- synapse/telepath.py +1 -0
- synapse/tests/files/stormpkg/dotstorm/dotstorm.yaml +3 -0
- synapse/tests/test_cortex.py +39 -2
- synapse/tests/test_lib_aha.py +1 -2
- synapse/tests/test_lib_cell.py +6 -2
- synapse/tests/test_lib_grammar.py +62 -64
- synapse/tests/test_lib_httpapi.py +1 -1
- synapse/tests/test_lib_rstorm.py +4 -4
- synapse/tests/test_lib_storm.py +3 -3
- synapse/tests/test_lib_stormlib_aha.py +196 -0
- synapse/tests/test_lib_stormlib_compression.py +12 -12
- synapse/tests/test_lib_stormlib_macro.py +94 -0
- synapse/tests/test_lib_stormlib_spooled.py +1 -1
- synapse/tests/test_lib_stormtypes.py +44 -33
- synapse/tests/test_lib_view.py +50 -3
- synapse/tests/test_model_files.py +3 -0
- synapse/tests/test_tools_genpkg.py +26 -0
- synapse/tests/test_tools_hiveload.py +1 -0
- synapse/tests/test_tools_hivesave.py +1 -0
- synapse/tests/utils.py +22 -3
- synapse/tools/autodoc.py +1 -1
- synapse/tools/hive/load.py +3 -0
- synapse/tools/hive/save.py +3 -0
- {synapse-2.166.0.dist-info → synapse-2.167.0.dist-info}/METADATA +3 -3
- {synapse-2.166.0.dist-info → synapse-2.167.0.dist-info}/RECORD +46 -45
- {synapse-2.166.0.dist-info → synapse-2.167.0.dist-info}/LICENSE +0 -0
- {synapse-2.166.0.dist-info → synapse-2.167.0.dist-info}/WHEEL +0 -0
- {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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
'
|
|
175
|
+
'protected': {'type': 'boolean', 'default': False},
|
|
176
176
|
'merging': {'type': 'boolean'},
|
|
177
177
|
'layers': {
|
|
178
178
|
'type': 'array',
|