synapse 2.224.0__py311-none-any.whl → 2.226.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 +10 -5
- synapse/cortex.py +6 -8
- synapse/lib/agenda.py +28 -15
- synapse/lib/ast.py +4 -8
- synapse/lib/cell.py +1 -1
- synapse/lib/const.py +4 -0
- synapse/lib/multislabseqn.py +36 -1
- synapse/lib/nexus.py +67 -8
- synapse/lib/platforms/linux.py +2 -0
- synapse/lib/queue.py +4 -1
- synapse/lib/rstorm.py +2 -2
- synapse/lib/schemas.py +11 -1
- synapse/lib/slabseqn.py +28 -0
- synapse/lib/storm.py +16 -4
- synapse/lib/stormhttp.py +7 -1
- synapse/lib/stormlib/aha.py +3 -3
- synapse/lib/stormtypes.py +10 -3
- synapse/lib/types.py +20 -0
- synapse/lib/version.py +2 -2
- synapse/models/base.py +3 -0
- synapse/models/inet.py +62 -5
- synapse/models/infotech.py +18 -0
- synapse/models/media.py +4 -0
- synapse/models/risk.py +3 -0
- synapse/tests/test_cortex.py +115 -2
- synapse/tests/test_lib_agenda.py +141 -28
- synapse/tests/test_lib_cell.py +1 -1
- synapse/tests/test_lib_certdir.py +1 -1
- synapse/tests/test_lib_httpapi.py +1 -1
- synapse/tests/test_lib_layer.py +1 -1
- synapse/tests/test_lib_lmdbslab.py +2 -0
- synapse/tests/test_lib_multislabseqn.py +22 -0
- synapse/tests/test_lib_nexus.py +42 -1
- synapse/tests/test_lib_platforms_linux.py +4 -0
- synapse/tests/test_lib_slabseqn.py +30 -1
- synapse/tests/test_lib_storm.py +65 -1
- synapse/tests/test_lib_stormhttp.py +16 -0
- synapse/tests/test_lib_stormlib_aha.py +6 -2
- synapse/tests/test_lib_stormlib_oauth.py +1 -1
- synapse/tests/test_lib_stormsvc.py +1 -1
- synapse/tests/test_lib_trigger.py +1 -1
- synapse/tests/test_model_inet.py +37 -0
- synapse/tests/test_model_infotech.py +15 -1
- synapse/tests/test_model_media.py +4 -1
- synapse/tests/test_model_risk.py +2 -0
- synapse/tests/test_tools_aha.py +2 -2
- synapse/tests/{test_tools_axon2axon.py → test_tools_axon_copy.py} +4 -4
- synapse/tests/{test_tools_pullfile.py → test_tools_axon_get.py} +4 -4
- synapse/tests/{test_tools_pushfile.py → test_tools_axon_put.py} +7 -7
- synapse/tests/{test_tools_csvtool.py → test_tools_cortex_csv.py} +12 -3
- synapse/tests/{test_tools_feed.py → test_tools_cortex_feed.py} +2 -2
- synapse/tests/{test_tools_apikey.py → test_tools_service_apikey.py} +1 -4
- synapse/tests/{test_tools_backup.py → test_tools_service_backup.py} +5 -5
- synapse/tests/{test_tools_demote.py → test_tools_service_demote.py} +1 -1
- synapse/tests/{test_tools_healthcheck.py → test_tools_service_healthcheck.py} +1 -1
- synapse/tests/{test_tools_livebackup.py → test_tools_service_livebackup.py} +1 -1
- synapse/tests/{test_tools_modrole.py → test_tools_service_modrole.py} +1 -1
- synapse/tests/{test_tools_moduser.py → test_tools_service_moduser.py} +1 -1
- synapse/tests/{test_tools_promote.py → test_tools_service_promote.py} +1 -1
- synapse/tests/{test_tools_reload.py → test_tools_service_reload.py} +1 -1
- synapse/tests/{test_tools_shutdown.py → test_tools_service_shutdown.py} +1 -1
- synapse/tests/{test_tools_snapshot.py → test_tools_service_snapshot.py} +1 -1
- synapse/tests/{test_tools_storm.py → test_tools_storm_cli.py} +1 -1
- synapse/tests/{test_tools_pkgs_gendocs.py → test_tools_storm_pkg_doc.py} +12 -3
- synapse/tests/{test_tools_genpkg.py → test_tools_storm_pkg_gen.py} +1 -1
- synapse/tests/{test_tools_autodoc.py → test_tools_utils_autodoc.py} +1 -1
- synapse/tests/test_tools_utils_changelog.py +454 -0
- synapse/tests/{test_tools_easycert.py → test_tools_utils_easycert.py} +48 -46
- synapse/tests/{test_tools_guid.py → test_tools_utils_guid.py} +3 -3
- synapse/tests/{test_tools_json2mpk.py → test_tools_utils_json2mpk.py} +3 -3
- synapse/tests/{test_tools_rstorm.py → test_tools_utils_rstorm.py} +6 -1
- synapse/tests/utils.py +15 -1
- synapse/tools/aha/mirror.py +1 -1
- synapse/tools/apikey.py +4 -83
- synapse/tools/autodoc.py +3 -1031
- synapse/tools/axon/copy.py +44 -0
- synapse/tools/axon/get.py +64 -0
- synapse/tools/axon/put.py +122 -0
- synapse/tools/axon2axon.py +3 -36
- synapse/tools/backup.py +6 -176
- synapse/tools/changelog.py +3 -1098
- synapse/tools/cortex/csv.py +236 -0
- synapse/tools/cortex/feed.py +151 -0
- synapse/tools/csvtool.py +3 -227
- synapse/tools/demote.py +4 -40
- synapse/tools/docker/validate.py +3 -3
- synapse/tools/easycert.py +4 -129
- synapse/tools/feed.py +3 -140
- synapse/tools/genpkg.py +3 -307
- synapse/tools/guid.py +7 -6
- synapse/tools/healthcheck.py +3 -101
- synapse/tools/json2mpk.py +6 -38
- synapse/tools/livebackup.py +4 -27
- synapse/tools/modrole.py +3 -108
- synapse/tools/moduser.py +3 -179
- synapse/tools/pkgs/gendocs.py +3 -164
- synapse/tools/promote.py +4 -41
- synapse/tools/pullfile.py +3 -56
- synapse/tools/pushfile.py +3 -114
- synapse/tools/reload.py +4 -61
- synapse/tools/rstorm.py +3 -26
- synapse/tools/service/__init__.py +0 -0
- synapse/tools/service/apikey.py +90 -0
- synapse/tools/service/backup.py +181 -0
- synapse/tools/service/demote.py +47 -0
- synapse/tools/service/healthcheck.py +109 -0
- synapse/tools/service/livebackup.py +34 -0
- synapse/tools/service/modrole.py +116 -0
- synapse/tools/service/moduser.py +184 -0
- synapse/tools/service/promote.py +48 -0
- synapse/tools/service/reload.py +68 -0
- synapse/tools/service/shutdown.py +51 -0
- synapse/tools/service/snapshot.py +64 -0
- synapse/tools/shutdown.py +5 -45
- synapse/tools/snapshot.py +4 -57
- synapse/tools/storm/__init__.py +0 -0
- synapse/tools/storm/__main__.py +5 -0
- synapse/tools/{storm.py → storm/_cli.py} +0 -3
- synapse/tools/storm/pkg/__init__.py +0 -0
- synapse/tools/{pkgs/pandoc_filter.py → storm/pkg/_pandoc_filter.py} +1 -1
- synapse/tools/storm/pkg/doc.py +176 -0
- synapse/tools/storm/pkg/gen.py +315 -0
- synapse/tools/utils/__init__.py +0 -0
- synapse/tools/utils/autodoc.py +1040 -0
- synapse/tools/utils/changelog.py +1124 -0
- synapse/tools/utils/easycert.py +136 -0
- synapse/tools/utils/guid.py +11 -0
- synapse/tools/utils/json2mpk.py +46 -0
- synapse/tools/utils/rstorm.py +35 -0
- {synapse-2.224.0.dist-info → synapse-2.226.0.dist-info}/METADATA +1 -1
- {synapse-2.224.0.dist-info → synapse-2.226.0.dist-info}/RECORD +135 -106
- synapse/tests/test_tools_changelog.py +0 -196
- /synapse/tests/{test_tools_axon.py → test_tools_axon_dump_load.py} +0 -0
- {synapse-2.224.0.dist-info → synapse-2.226.0.dist-info}/WHEEL +0 -0
- {synapse-2.224.0.dist-info → synapse-2.226.0.dist-info}/licenses/LICENSE +0 -0
- {synapse-2.224.0.dist-info → synapse-2.226.0.dist-info}/top_level.txt +0 -0
synapse/axon.py
CHANGED
|
@@ -1651,8 +1651,9 @@ class Axon(s_cell.Cell):
|
|
|
1651
1651
|
filename=field.get('filename'),
|
|
1652
1652
|
content_transfer_encoding=field.get('content_transfer_encoding'))
|
|
1653
1653
|
|
|
1654
|
-
async with sess.request(method, url, headers=headers, params=params,
|
|
1655
|
-
|
|
1654
|
+
async with sess.request(method, url, headers=headers, params=params, data=data, ssl=ssl,
|
|
1655
|
+
max_line_size=s_const.MAX_LINE_SIZE,
|
|
1656
|
+
max_field_size=s_const.MAX_FIELD_SIZE) as resp:
|
|
1656
1657
|
info = {
|
|
1657
1658
|
'ok': True,
|
|
1658
1659
|
'url': str(resp.url),
|
|
@@ -1698,8 +1699,10 @@ class Axon(s_cell.Cell):
|
|
|
1698
1699
|
async with aiohttp.ClientSession(connector=connector, timeout=atimeout) as sess:
|
|
1699
1700
|
try:
|
|
1700
1701
|
await self._reqHas(sha256)
|
|
1701
|
-
async with sess.request(method, url, headers=headers, params=params,
|
|
1702
|
-
data=self.get(sha256),
|
|
1702
|
+
async with sess.request(method, url, headers=headers, params=params, ssl=ssl,
|
|
1703
|
+
data=self.get(sha256),
|
|
1704
|
+
max_line_size=s_const.MAX_LINE_SIZE,
|
|
1705
|
+
max_field_size=s_const.MAX_FIELD_SIZE) as resp:
|
|
1703
1706
|
|
|
1704
1707
|
info = {
|
|
1705
1708
|
'ok': True,
|
|
@@ -1827,7 +1830,9 @@ class Axon(s_cell.Cell):
|
|
|
1827
1830
|
async with aiohttp.ClientSession(connector=connector, timeout=atimeout) as sess:
|
|
1828
1831
|
|
|
1829
1832
|
try:
|
|
1830
|
-
async with sess.request(method, url, headers=headers, params=params, json=json, data=body, ssl=ssl
|
|
1833
|
+
async with sess.request(method, url, headers=headers, params=params, json=json, data=body, ssl=ssl,
|
|
1834
|
+
max_line_size=s_const.MAX_LINE_SIZE,
|
|
1835
|
+
max_field_size=s_const.MAX_FIELD_SIZE) as resp:
|
|
1831
1836
|
|
|
1832
1837
|
info = self._flatten_clientresponse(resp)
|
|
1833
1838
|
|
synapse/cortex.py
CHANGED
|
@@ -1538,11 +1538,9 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
1538
1538
|
'desc': 'Controls access to deleting storm packages.'},
|
|
1539
1539
|
|
|
1540
1540
|
{'perm': ('storm', 'asroot', 'cmd', '<cmdname>'), 'gate': 'cortex',
|
|
1541
|
-
'desc': '
|
|
1542
|
-
'ex': 'storm.asroot.cmd.movetag'},
|
|
1541
|
+
'desc': 'Deprecated. Please use Storm modules to implement functionality requiring root privileges.'},
|
|
1543
1542
|
{'perm': ('storm', 'asroot', 'mod', '<modname>'), 'gate': 'cortex',
|
|
1544
|
-
'desc': '
|
|
1545
|
-
'ex': 'storm.asroot.cmd.synapse-misp.privsep'},
|
|
1543
|
+
'desc': 'Deprecated. Storm modules should use the asroot:perms key to specify the permissions they require.'},
|
|
1546
1544
|
|
|
1547
1545
|
{'perm': ('storm', 'graph', 'add'), 'gate': 'cortex',
|
|
1548
1546
|
'desc': 'Controls access to add a storm graph.',
|
|
@@ -6914,7 +6912,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
6914
6912
|
Delete a cron job
|
|
6915
6913
|
|
|
6916
6914
|
Args:
|
|
6917
|
-
iden (
|
|
6915
|
+
iden (str): The iden of the cron job to be deleted
|
|
6918
6916
|
'''
|
|
6919
6917
|
await self._killCronTask(iden)
|
|
6920
6918
|
try:
|
|
@@ -6931,7 +6929,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
6931
6929
|
Change an existing cron job's query
|
|
6932
6930
|
|
|
6933
6931
|
Args:
|
|
6934
|
-
iden (
|
|
6932
|
+
iden (str): The iden of the cron job to be changed
|
|
6935
6933
|
'''
|
|
6936
6934
|
await self.agenda.mod(iden, query)
|
|
6937
6935
|
await self.feedBeholder('cron:edit:query', {'iden': iden, 'query': query}, gates=[iden])
|
|
@@ -6942,7 +6940,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
6942
6940
|
Enable a cron job
|
|
6943
6941
|
|
|
6944
6942
|
Args:
|
|
6945
|
-
iden (
|
|
6943
|
+
iden (str): The iden of the cron job to be changed
|
|
6946
6944
|
'''
|
|
6947
6945
|
await self.agenda.enable(iden)
|
|
6948
6946
|
await self.feedBeholder('cron:enable', {'iden': iden}, gates=[iden])
|
|
@@ -6954,7 +6952,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
6954
6952
|
Enable a cron job
|
|
6955
6953
|
|
|
6956
6954
|
Args:
|
|
6957
|
-
iden (
|
|
6955
|
+
iden (str): The iden of the cron job to be changed
|
|
6958
6956
|
'''
|
|
6959
6957
|
await self.agenda.disable(iden)
|
|
6960
6958
|
await self._killCronTask(iden)
|
synapse/lib/agenda.py
CHANGED
|
@@ -430,6 +430,9 @@ class _Appt:
|
|
|
430
430
|
|
|
431
431
|
if name == 'lasterrs' and not isinstance(valu, list):
|
|
432
432
|
valu = list(valu)
|
|
433
|
+
elif name == 'nexttime' and valu is None:
|
|
434
|
+
self.recs.clear()
|
|
435
|
+
self.stor._delete_appt_from_heap(self)
|
|
433
436
|
|
|
434
437
|
setattr(self, name, valu)
|
|
435
438
|
|
|
@@ -469,7 +472,6 @@ class Agenda(s_base.Base):
|
|
|
469
472
|
self.apptheap = []
|
|
470
473
|
self.appts = {}
|
|
471
474
|
|
|
472
|
-
to_delete = []
|
|
473
475
|
for iden, info in self.apptdefs.items():
|
|
474
476
|
try:
|
|
475
477
|
appt = _Appt.unpack(self, info)
|
|
@@ -479,18 +481,30 @@ class Agenda(s_base.Base):
|
|
|
479
481
|
self._next_indx = max(self._next_indx, appt.indx + 1)
|
|
480
482
|
except (s_exc.InconsistentStorage, s_exc.BadStorageVersion, s_exc.BadTime, TypeError, KeyError,
|
|
481
483
|
UnicodeDecodeError) as e:
|
|
482
|
-
logger.warning('Invalid appointment %r found in storage: %r.
|
|
483
|
-
to_delete.append(iden)
|
|
484
|
-
continue
|
|
485
|
-
|
|
486
|
-
for iden in to_delete:
|
|
487
|
-
self.apptdefs.pop(iden)
|
|
484
|
+
logger.warning('Invalid appointment %r found in storage: %r. This appointment will be removed.', iden, e)
|
|
488
485
|
|
|
489
486
|
# Make sure we don't assign the same index to 2 appointments
|
|
490
487
|
if self.appts:
|
|
491
488
|
maxindx = max(appt.indx for appt in self.appts.values())
|
|
492
489
|
self._next_indx = maxindx + 1
|
|
493
490
|
|
|
491
|
+
async def _clear_invalid(self):
|
|
492
|
+
|
|
493
|
+
to_delete = []
|
|
494
|
+
for iden, info in self.apptdefs.items():
|
|
495
|
+
try:
|
|
496
|
+
appt = _Appt.unpack(self, info)
|
|
497
|
+
if appt.iden != iden:
|
|
498
|
+
raise s_exc.InconsistentStorage(mesg='iden inconsistency')
|
|
499
|
+
|
|
500
|
+
except (s_exc.InconsistentStorage, s_exc.BadStorageVersion, s_exc.BadTime, TypeError, KeyError,
|
|
501
|
+
UnicodeDecodeError) as e:
|
|
502
|
+
logger.warning('Removing invalid appointment %r.', iden)
|
|
503
|
+
to_delete.append(iden)
|
|
504
|
+
|
|
505
|
+
for iden in to_delete:
|
|
506
|
+
await self.core.delCronJob(iden)
|
|
507
|
+
|
|
494
508
|
def _addappt(self, iden, appt):
|
|
495
509
|
'''
|
|
496
510
|
Updates the data structures to add an appointment
|
|
@@ -685,14 +699,13 @@ class Agenda(s_base.Base):
|
|
|
685
699
|
'''
|
|
686
700
|
Delete an appointment
|
|
687
701
|
'''
|
|
688
|
-
|
|
689
|
-
if appt is None:
|
|
702
|
+
if not self.apptdefs.delete(iden):
|
|
690
703
|
mesg = f'No cron job with iden: {iden}'
|
|
691
704
|
raise s_exc.NoSuchIden(iden=iden, mesg=mesg)
|
|
692
705
|
|
|
693
|
-
self.
|
|
694
|
-
|
|
695
|
-
|
|
706
|
+
if (appt := self.appts.get(iden)) is not None:
|
|
707
|
+
self._delete_appt_from_heap(appt)
|
|
708
|
+
del self.appts[iden]
|
|
696
709
|
|
|
697
710
|
def _delete_appt_from_heap(self, appt):
|
|
698
711
|
try:
|
|
@@ -729,14 +742,14 @@ class Agenda(s_base.Base):
|
|
|
729
742
|
await self.core.addCronEdits(appt.iden, edits)
|
|
730
743
|
await self.core.feedBeholder('cron:stop', {'iden': appt.iden})
|
|
731
744
|
|
|
732
|
-
if appt.nexttime is None:
|
|
733
|
-
self._delete_appt_from_heap(appt)
|
|
734
|
-
|
|
735
745
|
async def runloop(self):
|
|
736
746
|
'''
|
|
737
747
|
Task loop to issue query tasks at the right times.
|
|
738
748
|
'''
|
|
739
749
|
await self.clearRunningStatus()
|
|
750
|
+
|
|
751
|
+
await self._clear_invalid()
|
|
752
|
+
|
|
740
753
|
while not self.isfini:
|
|
741
754
|
|
|
742
755
|
timeout = None
|
synapse/lib/ast.py
CHANGED
|
@@ -3452,10 +3452,6 @@ class PropValue(Value):
|
|
|
3452
3452
|
raise self.kids[0].addExcInfo(exc)
|
|
3453
3453
|
|
|
3454
3454
|
valu = path.node.get(name)
|
|
3455
|
-
if isinstance(valu, (dict, list, tuple)):
|
|
3456
|
-
# these get special cased because changing them affects the node
|
|
3457
|
-
# while it's in the pipeline but the modification doesn't get stored
|
|
3458
|
-
valu = s_msgpack.deepcopy(valu)
|
|
3459
3455
|
return prop, valu
|
|
3460
3456
|
|
|
3461
3457
|
# handle implicit pivot properties
|
|
@@ -3479,10 +3475,6 @@ class PropValue(Value):
|
|
|
3479
3475
|
raise self.kids[0].addExcInfo(exc)
|
|
3480
3476
|
|
|
3481
3477
|
if i >= imax:
|
|
3482
|
-
if isinstance(valu, (dict, list, tuple)):
|
|
3483
|
-
# these get special cased because changing them affects the node
|
|
3484
|
-
# while it's in the pipeline but the modification doesn't get stored
|
|
3485
|
-
valu = s_msgpack.deepcopy(valu)
|
|
3486
3478
|
return prop, valu
|
|
3487
3479
|
|
|
3488
3480
|
form = runt.model.forms.get(prop.type.name)
|
|
@@ -3495,6 +3487,10 @@ class PropValue(Value):
|
|
|
3495
3487
|
|
|
3496
3488
|
async def compute(self, runt, path):
|
|
3497
3489
|
prop, valu = await self.getPropAndValu(runt, path)
|
|
3490
|
+
|
|
3491
|
+
if prop:
|
|
3492
|
+
valu = await prop.type.tostorm(valu)
|
|
3493
|
+
|
|
3498
3494
|
return valu
|
|
3499
3495
|
|
|
3500
3496
|
class RelPropValue(PropValue):
|
synapse/lib/cell.py
CHANGED
synapse/lib/const.py
CHANGED
synapse/lib/multislabseqn.py
CHANGED
|
@@ -353,7 +353,6 @@ class MultiSlabSeqn(s_base.Base):
|
|
|
353
353
|
else:
|
|
354
354
|
indx = self.indx
|
|
355
355
|
|
|
356
|
-
assert self.tailseqn
|
|
357
356
|
retn = self.tailseqn.add(item, indx=indx)
|
|
358
357
|
|
|
359
358
|
if advances:
|
|
@@ -363,6 +362,42 @@ class MultiSlabSeqn(s_base.Base):
|
|
|
363
362
|
|
|
364
363
|
return retn
|
|
365
364
|
|
|
365
|
+
async def addWithPackRetn(self, item, indx=None):
|
|
366
|
+
'''
|
|
367
|
+
Add a single item to the sequence, returning the offset and packed item.
|
|
368
|
+
'''
|
|
369
|
+
advances = True
|
|
370
|
+
|
|
371
|
+
if indx is not None:
|
|
372
|
+
if indx < self.firstindx:
|
|
373
|
+
raise s_exc.BadIndxValu(mesg=f'indx lower than first index in sequence {self.firstindx}')
|
|
374
|
+
|
|
375
|
+
if indx < self._ranges[-1]:
|
|
376
|
+
ridx = self._getRangeIndx(indx)
|
|
377
|
+
assert ridx is not None
|
|
378
|
+
|
|
379
|
+
async with self._getSeqn(ridx) as seqn:
|
|
380
|
+
retn = seqn.addWithPackRetn(item, indx=indx)
|
|
381
|
+
|
|
382
|
+
return retn
|
|
383
|
+
|
|
384
|
+
if indx >= self.indx:
|
|
385
|
+
self.indx = indx
|
|
386
|
+
else:
|
|
387
|
+
advances = False
|
|
388
|
+
else:
|
|
389
|
+
indx = self.indx
|
|
390
|
+
|
|
391
|
+
assert self.tailseqn
|
|
392
|
+
retn = self.tailseqn.addWithPackRetn(item, indx=indx)
|
|
393
|
+
|
|
394
|
+
if advances:
|
|
395
|
+
self.indx += 1
|
|
396
|
+
|
|
397
|
+
self._wake_waiters()
|
|
398
|
+
|
|
399
|
+
return retn
|
|
400
|
+
|
|
366
401
|
async def last(self) -> Optional[Tuple[int, Any]]:
|
|
367
402
|
ridx = self._getRangeIndx(self.indx - 1)
|
|
368
403
|
if ridx is None:
|
synapse/lib/nexus.py
CHANGED
|
@@ -12,6 +12,9 @@ import synapse.common as s_common
|
|
|
12
12
|
import synapse.telepath as s_telepath
|
|
13
13
|
|
|
14
14
|
import synapse.lib.base as s_base
|
|
15
|
+
import synapse.lib.scope as s_scope
|
|
16
|
+
import synapse.lib.queue as s_queue
|
|
17
|
+
import synapse.lib.msgpack as s_msgpack
|
|
15
18
|
|
|
16
19
|
logger = logging.getLogger(__name__)
|
|
17
20
|
|
|
@@ -20,6 +23,9 @@ leaderversion = 'Leader is a higher version than we are.'
|
|
|
20
23
|
# As a mirror follower, amount of time before giving up on a write request
|
|
21
24
|
FOLLOWER_WRITE_WAIT_S = 30.0
|
|
22
25
|
|
|
26
|
+
WINDOW_MAXSIZE = 10_000
|
|
27
|
+
YIELD_PREFIX = b'\x92\xa8t2:yield\x81\xa4retn\x92\xc3\x92'
|
|
28
|
+
|
|
23
29
|
class RegMethType(type):
|
|
24
30
|
'''
|
|
25
31
|
Metaclass that collects all methods in class with _regme prop into a class member called _regclstupls
|
|
@@ -99,6 +105,8 @@ class NexsRoot(s_base.Base):
|
|
|
99
105
|
self._mirready = asyncio.Event() # for testing
|
|
100
106
|
|
|
101
107
|
self._mirrors: List[ChangeDist] = []
|
|
108
|
+
self._linkmirrors: List[s_queue.Window] = []
|
|
109
|
+
|
|
102
110
|
self._nexskids: Dict[str, 'Pusher'] = {}
|
|
103
111
|
|
|
104
112
|
# Used to match pending follower write requests with the responses arriving on the log
|
|
@@ -134,6 +142,11 @@ class NexsRoot(s_base.Base):
|
|
|
134
142
|
self.nexslog.setIndex(maxindx)
|
|
135
143
|
|
|
136
144
|
async def fini():
|
|
145
|
+
for wind in self._linkmirrors:
|
|
146
|
+
await wind.fini()
|
|
147
|
+
|
|
148
|
+
for dist in self._mirrors:
|
|
149
|
+
await dist.fini()
|
|
137
150
|
|
|
138
151
|
for futu in self._futures.values(): # pragma: no cover
|
|
139
152
|
futu.cancel()
|
|
@@ -389,8 +402,16 @@ class NexsRoot(s_base.Base):
|
|
|
389
402
|
async def _eat(self, item, indx=None):
|
|
390
403
|
|
|
391
404
|
if self.donexslog:
|
|
392
|
-
saveindx = await self.nexslog.
|
|
393
|
-
|
|
405
|
+
saveindx, packitem = await self.nexslog.addWithPackRetn(item, indx=indx)
|
|
406
|
+
|
|
407
|
+
if self._linkmirrors:
|
|
408
|
+
tupl = (saveindx, YIELD_PREFIX + s_msgpack.en(saveindx) + packitem)
|
|
409
|
+
for wind in tuple(self._linkmirrors):
|
|
410
|
+
await wind.put(tupl)
|
|
411
|
+
|
|
412
|
+
if self._mirrors:
|
|
413
|
+
for dist in tuple(self._mirrors):
|
|
414
|
+
dist.update()
|
|
394
415
|
|
|
395
416
|
else:
|
|
396
417
|
saveindx = self.nexshot.get('nexs:indx')
|
|
@@ -415,7 +436,15 @@ class NexsRoot(s_base.Base):
|
|
|
415
436
|
|
|
416
437
|
async def iter(self, offs: int, tellready=False, wait=True) -> AsyncIterator[Any]:
|
|
417
438
|
'''
|
|
418
|
-
Returns an iterator of change entries in the log
|
|
439
|
+
Returns an iterator of change entries in the log.
|
|
440
|
+
|
|
441
|
+
Notes:
|
|
442
|
+
If this method is being called in the context of a Telepath call,
|
|
443
|
+
it will directly send messages to the scope "link" object when it
|
|
444
|
+
has caught up to the realtime change window; instead of yielding
|
|
445
|
+
them as a generator. This is an optimization to avoid duplication
|
|
446
|
+
of msgpack'ing the same object over and over again as the number
|
|
447
|
+
of mirrors increases.
|
|
419
448
|
'''
|
|
420
449
|
if not self.donexslog:
|
|
421
450
|
return
|
|
@@ -437,11 +466,41 @@ class NexsRoot(s_base.Base):
|
|
|
437
466
|
if not wait:
|
|
438
467
|
return
|
|
439
468
|
|
|
440
|
-
|
|
441
|
-
async
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
469
|
+
if (link := s_scope.get('link')) is None:
|
|
470
|
+
async with self.getChangeDist(maxoffs) as dist:
|
|
471
|
+
async for item in dist:
|
|
472
|
+
yield item
|
|
473
|
+
|
|
474
|
+
else:
|
|
475
|
+
async with self.getMirrorWindow() as wind:
|
|
476
|
+
|
|
477
|
+
# Ensure we are caught up after grabbing a window
|
|
478
|
+
sync = True
|
|
479
|
+
|
|
480
|
+
async for item in self.nexslog.iter(maxoffs):
|
|
481
|
+
maxoffs = item[0] + 1
|
|
482
|
+
yield item
|
|
483
|
+
|
|
484
|
+
async for offs, item in wind:
|
|
485
|
+
if sync:
|
|
486
|
+
if offs < maxoffs:
|
|
487
|
+
continue
|
|
488
|
+
sync = False
|
|
489
|
+
|
|
490
|
+
await link.send(item)
|
|
491
|
+
|
|
492
|
+
@contextlib.asynccontextmanager
|
|
493
|
+
async def getMirrorWindow(self):
|
|
494
|
+
async with await s_queue.Window.anit(maxsize=WINDOW_MAXSIZE, clearonfini=True) as wind:
|
|
495
|
+
|
|
496
|
+
async def fini():
|
|
497
|
+
self._linkmirrors.remove(wind)
|
|
498
|
+
|
|
499
|
+
wind.onfini(fini)
|
|
500
|
+
|
|
501
|
+
self._linkmirrors.append(wind)
|
|
502
|
+
|
|
503
|
+
yield wind
|
|
445
504
|
|
|
446
505
|
@contextlib.asynccontextmanager
|
|
447
506
|
async def getChangeDist(self, offs: int) -> AsyncIterator[ChangeDist]:
|
synapse/lib/platforms/linux.py
CHANGED
|
@@ -112,7 +112,9 @@ def getSysctls():
|
|
|
112
112
|
('vm.dirty_expire_centisecs', '/proc/sys/vm/dirty_expire_centisecs', int),
|
|
113
113
|
('vm.dirty_writeback_centisecs', '/proc/sys/vm/dirty_writeback_centisecs', int),
|
|
114
114
|
('vm.dirty_background_ratio', '/proc/sys/vm/dirty_background_ratio', int),
|
|
115
|
+
('vm.dirty_background_bytes', '/proc/sys/vm/dirty_background_bytes', int),
|
|
115
116
|
('vm.dirty_ratio', '/proc/sys/vm/dirty_ratio', int),
|
|
117
|
+
('vm.dirty_bytes', '/proc/sys/vm/dirty_bytes', int),
|
|
116
118
|
)
|
|
117
119
|
ret = {}
|
|
118
120
|
for key, fp, func in _sysctls:
|
synapse/lib/queue.py
CHANGED
|
@@ -118,14 +118,17 @@ class Window(s_base.Base):
|
|
|
118
118
|
its maxsize, it will be fini()d. On fini(), the Window will continue to
|
|
119
119
|
yield results until empty and then return.
|
|
120
120
|
'''
|
|
121
|
-
async def __anit__(self, maxsize=None):
|
|
121
|
+
async def __anit__(self, maxsize=None, clearonfini=False):
|
|
122
122
|
await s_base.Base.__anit__(self)
|
|
123
123
|
self.maxsize = maxsize
|
|
124
124
|
self.event = asyncio.Event()
|
|
125
125
|
|
|
126
126
|
self.linklist = collections.deque()
|
|
127
|
+
self.clearonfini = clearonfini
|
|
127
128
|
|
|
128
129
|
async def fini():
|
|
130
|
+
if self.clearonfini:
|
|
131
|
+
self.linklist.clear()
|
|
129
132
|
self.event.set()
|
|
130
133
|
|
|
131
134
|
self.onfini(fini)
|
synapse/lib/rstorm.py
CHANGED
|
@@ -25,8 +25,8 @@ import synapse.lib.stormhttp as s_stormhttp
|
|
|
25
25
|
|
|
26
26
|
import synapse.cmds.cortex as s_cmds_cortex
|
|
27
27
|
|
|
28
|
-
import synapse.tools.storm as s_storm
|
|
29
|
-
import synapse.tools.
|
|
28
|
+
import synapse.tools.storm._cli as s_storm
|
|
29
|
+
import synapse.tools.storm.pkg.gen as s_genpkg
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
re_directive = regex.compile(r'^\.\.\s(shell.*|storm.*|[^:])::(?:\s(.*)$|$)')
|
synapse/lib/schemas.py
CHANGED
|
@@ -393,7 +393,6 @@ _changelogTypes = {'migration': 'Automatic Migrations',
|
|
|
393
393
|
'note': 'Notes',
|
|
394
394
|
'doc': 'Improved documentation',
|
|
395
395
|
'deprecation': 'Deprecations'}
|
|
396
|
-
|
|
397
396
|
_changelogSchema = {
|
|
398
397
|
'type': 'object',
|
|
399
398
|
'properties': {
|
|
@@ -405,6 +404,10 @@ _changelogSchema = {
|
|
|
405
404
|
'type': 'string',
|
|
406
405
|
'minLength': 1,
|
|
407
406
|
},
|
|
407
|
+
'desc:literal': {
|
|
408
|
+
'type': 'boolean',
|
|
409
|
+
'default': False,
|
|
410
|
+
},
|
|
408
411
|
'prs': {
|
|
409
412
|
'type': 'array',
|
|
410
413
|
'items': {
|
|
@@ -948,6 +951,13 @@ _reqValidPkgdefSchema = {
|
|
|
948
951
|
'type': ['array', 'null'],
|
|
949
952
|
'items': {'$ref': '#/definitions/cmdinput'},
|
|
950
953
|
},
|
|
954
|
+
'cmdconf': {
|
|
955
|
+
'type': 'object',
|
|
956
|
+
'properties': {
|
|
957
|
+
'svciden': {'type': 'string', 'pattern': s_config.re_iden},
|
|
958
|
+
},
|
|
959
|
+
'additionalProperties': True,
|
|
960
|
+
},
|
|
951
961
|
'storm': {'type': 'string'},
|
|
952
962
|
'forms': {'$ref': '#/definitions/cmdformhints'},
|
|
953
963
|
'perms': {'type': 'array',
|
synapse/lib/slabseqn.py
CHANGED
|
@@ -87,6 +87,34 @@ class SlabSeqn:
|
|
|
87
87
|
|
|
88
88
|
return indx
|
|
89
89
|
|
|
90
|
+
def addWithPackRetn(self, item, indx=None):
|
|
91
|
+
'''
|
|
92
|
+
Add a single item to the sequence, returning the offset and packed item.
|
|
93
|
+
'''
|
|
94
|
+
packitem = s_msgpack.en(item)
|
|
95
|
+
if indx is not None:
|
|
96
|
+
if indx >= self.indx:
|
|
97
|
+
self.slab.put(s_common.int64en(indx), packitem, append=True, db=self.db)
|
|
98
|
+
self.indx = indx + 1
|
|
99
|
+
self.size += 1
|
|
100
|
+
self._wake_waiters()
|
|
101
|
+
return indx, packitem
|
|
102
|
+
|
|
103
|
+
oldv = self.slab.replace(s_common.int64en(indx), packitem, db=self.db)
|
|
104
|
+
if oldv is None:
|
|
105
|
+
self.size += 1
|
|
106
|
+
return indx, packitem
|
|
107
|
+
|
|
108
|
+
indx = self.indx
|
|
109
|
+
self.slab.put(s_common.int64en(indx), packitem, append=True, db=self.db)
|
|
110
|
+
|
|
111
|
+
self.indx += 1
|
|
112
|
+
self.size += 1
|
|
113
|
+
|
|
114
|
+
self._wake_waiters()
|
|
115
|
+
|
|
116
|
+
return indx, packitem
|
|
117
|
+
|
|
90
118
|
def first(self):
|
|
91
119
|
|
|
92
120
|
for lkey, lval in self.slab.scanByFull(db=self.db):
|
synapse/lib/storm.py
CHANGED
|
@@ -2521,9 +2521,17 @@ class PureCmd(Cmd):
|
|
|
2521
2521
|
perm = ('storm', 'asroot', 'cmd') + tuple(name.split('.'))
|
|
2522
2522
|
|
|
2523
2523
|
asroot = runt.allowed(perm)
|
|
2524
|
-
if self.asroot
|
|
2525
|
-
mesg = f'Command ({name})
|
|
2526
|
-
|
|
2524
|
+
if self.asroot:
|
|
2525
|
+
mesg = f'Command ({name}) requires asroot permission which is deprecated and will be removed in v3.0.0. ' \
|
|
2526
|
+
'Functionality which requires elevated permissions should be implemented in Storm modules and use ' \
|
|
2527
|
+
'asroot:perms to specify the required permissions.'
|
|
2528
|
+
|
|
2529
|
+
s_common.deprecated('Storm command asroot key', curv='2.226.0', eolv='3.0.0')
|
|
2530
|
+
await runt.warnonce(mesg, log=False)
|
|
2531
|
+
|
|
2532
|
+
if not asroot:
|
|
2533
|
+
mesg = f'Command ({name}) elevates privileges. You need perm: storm.asroot.cmd.{name}'
|
|
2534
|
+
raise s_exc.AuthDeny(mesg=mesg, user=runt.user.iden, username=runt.user.name)
|
|
2527
2535
|
|
|
2528
2536
|
# if a command requires perms, check em!
|
|
2529
2537
|
# ( used to create more intuitive perm boundaries )
|
|
@@ -2545,10 +2553,14 @@ class PureCmd(Cmd):
|
|
|
2545
2553
|
|
|
2546
2554
|
cmdopts = s_stormtypes.CmdOpts(self)
|
|
2547
2555
|
|
|
2556
|
+
cmdconf = self.cdef.get('cmdconf', {})
|
|
2557
|
+
if cmdconf:
|
|
2558
|
+
cmdconf = s_msgpack.deepcopy(cmdconf, use_list=True)
|
|
2559
|
+
|
|
2548
2560
|
opts = {
|
|
2549
2561
|
'vars': {
|
|
2550
2562
|
'cmdopts': cmdopts,
|
|
2551
|
-
'cmdconf':
|
|
2563
|
+
'cmdconf': cmdconf,
|
|
2552
2564
|
}
|
|
2553
2565
|
}
|
|
2554
2566
|
|
synapse/lib/stormhttp.py
CHANGED
|
@@ -12,6 +12,7 @@ import synapse.common as s_common
|
|
|
12
12
|
|
|
13
13
|
import synapse.lib.base as s_base
|
|
14
14
|
import synapse.lib.json as s_json
|
|
15
|
+
import synapse.lib.const as s_const
|
|
15
16
|
import synapse.lib.msgpack as s_msgpack
|
|
16
17
|
import synapse.lib.version as s_version
|
|
17
18
|
import synapse.lib.stormtypes as s_stormtypes
|
|
@@ -400,7 +401,12 @@ class LibHttp(s_stormtypes.Lib):
|
|
|
400
401
|
proxy = await s_stormtypes.toprim(proxy)
|
|
401
402
|
ssl_opts = await s_stormtypes.toprim(ssl_opts)
|
|
402
403
|
|
|
403
|
-
kwargs = {
|
|
404
|
+
kwargs = {
|
|
405
|
+
'max_line_size': s_const.MAX_LINE_SIZE,
|
|
406
|
+
'max_field_size': s_const.MAX_FIELD_SIZE,
|
|
407
|
+
'allow_redirects': allow_redirects,
|
|
408
|
+
}
|
|
409
|
+
|
|
404
410
|
if params:
|
|
405
411
|
kwargs['params'] = s_stormtypes.strifyHttpArg(params, multi=True)
|
|
406
412
|
|
synapse/lib/stormlib/aha.py
CHANGED
|
@@ -740,10 +740,10 @@ The ready column indicates that a service has entered into the realtime change w
|
|
|
740
740
|
$info = $cell_infos.$svcname
|
|
741
741
|
$cell_info = $info.cell
|
|
742
742
|
$status.nexs_indx = $cell_info.nexsindx
|
|
743
|
-
if ($cell_info.
|
|
744
|
-
$status.role = 'follower'
|
|
745
|
-
} else {
|
|
743
|
+
if ($cell_info.active) {
|
|
746
744
|
$status.role = 'leader'
|
|
745
|
+
} else {
|
|
746
|
+
$status.role = 'follower'
|
|
747
747
|
}
|
|
748
748
|
$status.version = $info.cell.verstring
|
|
749
749
|
$status.synapse_version = $info.synapse.verstring
|
synapse/lib/stormtypes.py
CHANGED
|
@@ -1499,9 +1499,16 @@ class LibBase(Lib):
|
|
|
1499
1499
|
perm = ('storm', 'asroot', 'mod') + tuple(name.split('.'))
|
|
1500
1500
|
asroot = self.runt.allowed(perm)
|
|
1501
1501
|
|
|
1502
|
-
if mdef.get('asroot', False)
|
|
1503
|
-
mesg = f'Module ({name})
|
|
1504
|
-
|
|
1502
|
+
if mdef.get('asroot', False):
|
|
1503
|
+
mesg = f'Module ({name}) requires asroot permission but does not specify any asroot:perms. ' \
|
|
1504
|
+
'storm.asroot.mod.<modname> style permissons are deprecated and will be removed in v3.0.0.'
|
|
1505
|
+
|
|
1506
|
+
s_common.deprecated('Storm module asroot key', curv='2.226.0', eolv='3.0.0')
|
|
1507
|
+
await self.runt.warnonce(mesg, log=False)
|
|
1508
|
+
|
|
1509
|
+
if not asroot:
|
|
1510
|
+
mesg = f'Module ({name}) elevates privileges. You need perm: storm.asroot.mod.{name}'
|
|
1511
|
+
raise s_exc.AuthDeny(mesg=mesg, user=self.runt.user.iden, username=self.runt.user.name)
|
|
1505
1512
|
|
|
1506
1513
|
modr = await self.runt.getModRuntime(query, opts={'vars': {'modconf': modconf}})
|
|
1507
1514
|
modr.asroot = asroot
|
synapse/lib/types.py
CHANGED
|
@@ -32,6 +32,8 @@ class Type:
|
|
|
32
32
|
# ( due to hot-loop needs in the storm runtime )
|
|
33
33
|
isarray = False
|
|
34
34
|
|
|
35
|
+
ismutable = False
|
|
36
|
+
|
|
35
37
|
def __init__(self, modl, name, info, opts):
|
|
36
38
|
'''
|
|
37
39
|
Construct a new Type object.
|
|
@@ -369,6 +371,17 @@ class Type:
|
|
|
369
371
|
topt.update(opts)
|
|
370
372
|
return self.__class__(self.modl, self.name, self.info, topt)
|
|
371
373
|
|
|
374
|
+
async def tostorm(self, valu):
|
|
375
|
+
'''
|
|
376
|
+
Allows type-specific modifications to values to make them safe for use in the runtime.
|
|
377
|
+
|
|
378
|
+
Args:
|
|
379
|
+
valu (any): The valu to update.
|
|
380
|
+
'''
|
|
381
|
+
if self.ismutable:
|
|
382
|
+
return s_msgpack.deepcopy(valu, use_list=True)
|
|
383
|
+
return valu
|
|
384
|
+
|
|
372
385
|
def __eq__(self, othr):
|
|
373
386
|
if self.name != othr.name:
|
|
374
387
|
return False
|
|
@@ -415,6 +428,7 @@ class Bool(Type):
|
|
|
415
428
|
class Array(Type):
|
|
416
429
|
|
|
417
430
|
isarray = True
|
|
431
|
+
ismutable = True
|
|
418
432
|
|
|
419
433
|
def postTypeInit(self):
|
|
420
434
|
|
|
@@ -534,6 +548,9 @@ class Comp(Type):
|
|
|
534
548
|
|
|
535
549
|
_type = self.tcache[name]
|
|
536
550
|
|
|
551
|
+
if _type.ismutable:
|
|
552
|
+
self.ismutable = True
|
|
553
|
+
|
|
537
554
|
norm, info = _type.norm(valu[i])
|
|
538
555
|
|
|
539
556
|
subs[name] = norm
|
|
@@ -1623,6 +1640,8 @@ class TimeEdge(Edge):
|
|
|
1623
1640
|
|
|
1624
1641
|
class Data(Type):
|
|
1625
1642
|
|
|
1643
|
+
ismutable = True
|
|
1644
|
+
|
|
1626
1645
|
stortype = s_layer.STOR_TYPE_MSGP
|
|
1627
1646
|
|
|
1628
1647
|
def postTypeInit(self):
|
|
@@ -1643,6 +1662,7 @@ class Data(Type):
|
|
|
1643
1662
|
|
|
1644
1663
|
class NodeProp(Type):
|
|
1645
1664
|
|
|
1665
|
+
ismutable = True
|
|
1646
1666
|
stortype = s_layer.STOR_TYPE_MSGP
|
|
1647
1667
|
|
|
1648
1668
|
def postTypeInit(self):
|