synapse 2.215.0__py311-none-any.whl → 2.216.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/cortex.py +16 -1
- synapse/lib/cell.py +12 -0
- synapse/lib/cmd.py +6 -2
- synapse/lib/layer.py +10 -5
- synapse/lib/schemas.py +9 -2
- synapse/lib/snap.py +15 -5
- synapse/lib/storm.py +1 -1
- synapse/lib/types.py +3 -0
- synapse/lib/version.py +2 -2
- synapse/lib/view.py +16 -7
- synapse/models/inet.py +7 -1
- synapse/models/risk.py +2 -0
- synapse/tests/test_cortex.py +262 -0
- synapse/tests/test_lib_auth.py +2 -0
- synapse/tests/test_lib_storm.py +52 -1
- synapse/tests/test_lib_stormsvc.py +2 -2
- synapse/tests/test_lib_types.py +6 -0
- synapse/tests/test_model_inet.py +2 -0
- synapse/tests/test_tools_cryo_cat.py +3 -8
- synapse/tests/test_tools_storm.py +3 -2
- synapse/tests/utils.py +2 -0
- synapse/tools/aha/clone.py +3 -13
- synapse/tools/aha/easycert.py +5 -18
- synapse/tools/aha/enroll.py +3 -12
- synapse/tools/aha/list.py +2 -15
- synapse/tools/aha/mirror.py +3 -14
- synapse/tools/aha/provision/service.py +3 -13
- synapse/tools/aha/provision/user.py +3 -12
- synapse/tools/apikey.py +3 -13
- synapse/tools/autodoc.py +7 -19
- synapse/tools/axon2axon.py +1 -9
- synapse/tools/cellauth.py +5 -14
- synapse/tools/changelog.py +12 -16
- synapse/tools/cmdr.py +2 -6
- synapse/tools/cryo/cat.py +5 -15
- synapse/tools/cryo/list.py +3 -10
- synapse/tools/csvtool.py +40 -49
- synapse/tools/demote.py +1 -6
- synapse/tools/docker/validate.py +0 -1
- synapse/tools/easycert.py +3 -8
- synapse/tools/feed.py +7 -18
- synapse/tools/genpkg.py +3 -12
- synapse/tools/guid.py +4 -6
- synapse/tools/healthcheck.py +4 -11
- synapse/tools/json2mpk.py +1 -5
- synapse/tools/livebackup.py +3 -13
- synapse/tools/modrole.py +3 -12
- synapse/tools/moduser.py +3 -12
- synapse/tools/pkgs/gendocs.py +1 -1
- synapse/tools/promote.py +3 -13
- synapse/tools/pullfile.py +6 -18
- synapse/tools/pushfile.py +6 -18
- synapse/tools/reload.py +5 -14
- synapse/tools/rstorm.py +4 -12
- synapse/tools/shutdown.py +1 -2
- synapse/tools/snapshot.py +3 -14
- synapse/tools/storm.py +4 -12
- {synapse-2.215.0.dist-info → synapse-2.216.0.dist-info}/METADATA +1 -1
- {synapse-2.215.0.dist-info → synapse-2.216.0.dist-info}/RECORD +62 -62
- {synapse-2.215.0.dist-info → synapse-2.216.0.dist-info}/WHEEL +0 -0
- {synapse-2.215.0.dist-info → synapse-2.216.0.dist-info}/licenses/LICENSE +0 -0
- {synapse-2.215.0.dist-info → synapse-2.216.0.dist-info}/top_level.txt +0 -0
synapse/cortex.py
CHANGED
|
@@ -758,6 +758,12 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
758
758
|
confbase['mirror']['hidedocs'] = False # type: ignore
|
|
759
759
|
confbase['mirror']['hidecmdl'] = False # type: ignore
|
|
760
760
|
|
|
761
|
+
confbase['safemode']['hidecmdl'] = False
|
|
762
|
+
confbase['safemode']['description'] = (
|
|
763
|
+
'Enable safe-mode which disables crons, triggers, dmons, storm '
|
|
764
|
+
'package onload handlers, view merge tasks, and storm pools.'
|
|
765
|
+
)
|
|
766
|
+
|
|
761
767
|
confdefs = {
|
|
762
768
|
'axon': {
|
|
763
769
|
'description': 'A telepath URL for a remote axon.',
|
|
@@ -1572,9 +1578,11 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
1572
1578
|
if self.isactive:
|
|
1573
1579
|
await self._checkLayerModels()
|
|
1574
1580
|
|
|
1575
|
-
self.
|
|
1581
|
+
if not self.safemode:
|
|
1582
|
+
self.addActiveCoro(self.agenda.runloop)
|
|
1576
1583
|
|
|
1577
1584
|
await self._initStormDmons()
|
|
1585
|
+
|
|
1578
1586
|
await self._initStormSvcs()
|
|
1579
1587
|
|
|
1580
1588
|
# share ourself via the cell dmon as "cortex"
|
|
@@ -1621,6 +1629,9 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
1621
1629
|
|
|
1622
1630
|
async def initStormPool(self):
|
|
1623
1631
|
|
|
1632
|
+
if self.safemode:
|
|
1633
|
+
return
|
|
1634
|
+
|
|
1624
1635
|
try:
|
|
1625
1636
|
|
|
1626
1637
|
byts = self.slab.get(b'storm:pool', db='cell:conf')
|
|
@@ -2961,6 +2972,10 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
2961
2972
|
|
|
2962
2973
|
if onload is not None and self.isactive:
|
|
2963
2974
|
async def _onload():
|
|
2975
|
+
if self.safemode:
|
|
2976
|
+
await self.fire('core:pkg:onload:skipped', pkg=name, reason='safemode')
|
|
2977
|
+
return
|
|
2978
|
+
|
|
2964
2979
|
await self.fire('core:pkg:onload:start', pkg=name)
|
|
2965
2980
|
try:
|
|
2966
2981
|
async for mesg in self.storm(onload):
|
synapse/lib/cell.py
CHANGED
|
@@ -930,6 +930,12 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
930
930
|
|
|
931
931
|
confdefs = {} # type: ignore # This should be a JSONSchema properties list for an object.
|
|
932
932
|
confbase = {
|
|
933
|
+
'safemode': {
|
|
934
|
+
'default': False,
|
|
935
|
+
'description': 'Boot the service in safe-mode.',
|
|
936
|
+
'type': 'boolean',
|
|
937
|
+
'hidecmdl': True,
|
|
938
|
+
},
|
|
933
939
|
'cell:guid': {
|
|
934
940
|
'description': 'An optional hard-coded GUID to store as the permanent GUID for the service.',
|
|
935
941
|
'type': 'string',
|
|
@@ -1200,6 +1206,11 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
1200
1206
|
'tasks': 1,
|
|
1201
1207
|
}
|
|
1202
1208
|
|
|
1209
|
+
self.safemode = self.conf.req('safemode')
|
|
1210
|
+
if self.safemode:
|
|
1211
|
+
mesg = f'Booting {self.getCellType()} in safe-mode. Some functionality may be disabled.'
|
|
1212
|
+
logger.warning(mesg)
|
|
1213
|
+
|
|
1203
1214
|
self.minfree = self.conf.get('limit:disk:free')
|
|
1204
1215
|
if self.minfree is not None:
|
|
1205
1216
|
self.minfree = self.minfree / 100
|
|
@@ -4816,6 +4827,7 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
4816
4827
|
'iden': self.getCellIden(),
|
|
4817
4828
|
'paused': self.paused,
|
|
4818
4829
|
'active': self.isactive,
|
|
4830
|
+
'safemode': self.safemode,
|
|
4819
4831
|
'started': self.startms,
|
|
4820
4832
|
'ready': self.nexsroot.ready.is_set(),
|
|
4821
4833
|
'commit': self.COMMIT,
|
synapse/lib/cmd.py
CHANGED
|
@@ -3,15 +3,19 @@ import asyncio
|
|
|
3
3
|
import argparse
|
|
4
4
|
|
|
5
5
|
import synapse.exc as s_exc
|
|
6
|
-
import synapse.common as s_common
|
|
7
6
|
|
|
8
7
|
import synapse.lib.coro as s_coro
|
|
9
8
|
import synapse.lib.output as s_output
|
|
10
9
|
|
|
11
10
|
class Parser(argparse.ArgumentParser):
|
|
11
|
+
'''
|
|
12
|
+
argparse.ArgumentParser helper class.
|
|
12
13
|
|
|
14
|
+
- exit() is overriden to raise a SynErr ( ParserExit )
|
|
15
|
+
- _print_message prints to an outp object
|
|
16
|
+
- description formatter uses argparse.RawDescriptionHelpFormatter
|
|
17
|
+
'''
|
|
13
18
|
def __init__(self, prog=None, outp=s_output.stdout, **kwargs):
|
|
14
|
-
|
|
15
19
|
self.outp = outp
|
|
16
20
|
self.exited = False
|
|
17
21
|
|
synapse/lib/layer.py
CHANGED
|
@@ -3489,7 +3489,10 @@ class Layer(s_nexus.Pusher):
|
|
|
3489
3489
|
|
|
3490
3490
|
valt = edit[1]
|
|
3491
3491
|
valu, stortype = valt
|
|
3492
|
-
|
|
3492
|
+
|
|
3493
|
+
isarray = stortype & STOR_FLAG_ARRAY
|
|
3494
|
+
|
|
3495
|
+
if not isarray and sode.get('valu') == valt:
|
|
3493
3496
|
return ()
|
|
3494
3497
|
|
|
3495
3498
|
abrv = self.setPropAbrv(form, None)
|
|
@@ -3500,7 +3503,7 @@ class Layer(s_nexus.Pusher):
|
|
|
3500
3503
|
sode['valu'] = valt
|
|
3501
3504
|
self.setSodeDirty(buid, sode, form)
|
|
3502
3505
|
|
|
3503
|
-
if
|
|
3506
|
+
if isarray:
|
|
3504
3507
|
|
|
3505
3508
|
for indx in self.getStorIndx(stortype, valu):
|
|
3506
3509
|
self.layrslab.put(abrv + indx, buid, db=self.byarray)
|
|
@@ -3587,6 +3590,8 @@ class Layer(s_nexus.Pusher):
|
|
|
3587
3590
|
if prop[0] == '.': # '.' to detect universal props (as quickly as possible)
|
|
3588
3591
|
univabrv = self.setPropAbrv(None, prop)
|
|
3589
3592
|
|
|
3593
|
+
isarray = stortype & STOR_FLAG_ARRAY
|
|
3594
|
+
|
|
3590
3595
|
if oldv is not None:
|
|
3591
3596
|
|
|
3592
3597
|
# merge intervals and min times
|
|
@@ -3599,7 +3604,7 @@ class Layer(s_nexus.Pusher):
|
|
|
3599
3604
|
elif stortype == STOR_TYPE_MAXTIME:
|
|
3600
3605
|
valu = max(valu, oldv)
|
|
3601
3606
|
|
|
3602
|
-
if valu == oldv and stortype == oldt:
|
|
3607
|
+
if not isarray and valu == oldv and stortype == oldt:
|
|
3603
3608
|
return ()
|
|
3604
3609
|
|
|
3605
3610
|
if oldt & STOR_FLAG_ARRAY:
|
|
@@ -3638,7 +3643,7 @@ class Layer(s_nexus.Pusher):
|
|
|
3638
3643
|
sode['props'][prop] = (valu, stortype)
|
|
3639
3644
|
self.setSodeDirty(buid, sode, form)
|
|
3640
3645
|
|
|
3641
|
-
if
|
|
3646
|
+
if isarray:
|
|
3642
3647
|
|
|
3643
3648
|
realtype = stortype & 0x7fff
|
|
3644
3649
|
|
|
@@ -3828,7 +3833,7 @@ class Layer(s_nexus.Pusher):
|
|
|
3828
3833
|
kvpairs.append((tp_abrv + indx, buid))
|
|
3829
3834
|
kvpairs.append((ftp_abrv + indx, buid))
|
|
3830
3835
|
|
|
3831
|
-
|
|
3836
|
+
self.layrslab._putmulti(kvpairs, db=self.bytagprop)
|
|
3832
3837
|
|
|
3833
3838
|
return (
|
|
3834
3839
|
(EDIT_TAGPROP_SET, (tag, prop, valu, oldv, stortype), ()),
|
synapse/lib/schemas.py
CHANGED
|
@@ -297,11 +297,18 @@ _authRulesSchema = {
|
|
|
297
297
|
'type': 'array',
|
|
298
298
|
'items': [
|
|
299
299
|
{'type': 'boolean'},
|
|
300
|
-
{
|
|
300
|
+
{
|
|
301
|
+
'type': 'array',
|
|
302
|
+
'items': {
|
|
303
|
+
'type': 'string',
|
|
304
|
+
'minLength': 1
|
|
305
|
+
},
|
|
306
|
+
'minItems': 1
|
|
307
|
+
},
|
|
301
308
|
],
|
|
302
309
|
'minItems': 2,
|
|
303
310
|
'maxItems': 2,
|
|
304
|
-
}
|
|
311
|
+
},
|
|
305
312
|
}
|
|
306
313
|
reqValidRules = s_config.getJsValidator(_authRulesSchema)
|
|
307
314
|
|
synapse/lib/snap.py
CHANGED
|
@@ -384,12 +384,22 @@ class ProtoNode:
|
|
|
384
384
|
|
|
385
385
|
if norminfo is None:
|
|
386
386
|
try:
|
|
387
|
-
valu,
|
|
387
|
+
if (isinstance(valu, dict) and isinstance(prop.type, s_types.Guid)
|
|
388
|
+
and (form := self.ctx.snap.core.model.form(prop.type.name)) is not None):
|
|
389
|
+
|
|
390
|
+
norms, props = await self.ctx.snap._normGuidNodeDict(form, valu)
|
|
391
|
+
valu = await self.ctx.snap._addGuidNodeByDict(form, norms, props)
|
|
392
|
+
norminfo = {}
|
|
393
|
+
else:
|
|
394
|
+
valu, norminfo = prop.type.norm(valu)
|
|
395
|
+
|
|
388
396
|
except s_exc.BadTypeValu as e:
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
397
|
+
if 'prop' not in e.errinfo:
|
|
398
|
+
oldm = e.get('mesg')
|
|
399
|
+
e.update({'prop': prop.name,
|
|
400
|
+
'form': prop.form.name,
|
|
401
|
+
'mesg': f'Bad prop value {prop.full}={valu!r} : {oldm}'})
|
|
402
|
+
|
|
393
403
|
if self.ctx.snap.strict:
|
|
394
404
|
raise e
|
|
395
405
|
await self.ctx.snap.warn(e)
|
synapse/lib/storm.py
CHANGED
synapse/lib/types.py
CHANGED
|
@@ -625,6 +625,9 @@ class Guid(Type):
|
|
|
625
625
|
)
|
|
626
626
|
|
|
627
627
|
def _normPyList(self, valu):
|
|
628
|
+
if not valu:
|
|
629
|
+
mesg = 'Guid list values cannot be empty.'
|
|
630
|
+
raise s_exc.BadTypeValu(name=self.name, valu=valu, mesg=mesg)
|
|
628
631
|
return s_common.guid(valu), {}
|
|
629
632
|
|
|
630
633
|
def _normPyStr(self, valu):
|
synapse/lib/version.py
CHANGED
|
@@ -223,6 +223,6 @@ def reqVersion(valu, reqver,
|
|
|
223
223
|
##############################################################################
|
|
224
224
|
# The following are touched during the release process by bumpversion.
|
|
225
225
|
# Do not modify these directly.
|
|
226
|
-
version = (2,
|
|
226
|
+
version = (2, 216, 0)
|
|
227
227
|
verstring = '.'.join([str(x) for x in version])
|
|
228
|
-
commit = '
|
|
228
|
+
commit = '2a44a91a495a7daf2e4e6e44d32c1c3030db3fd2'
|
synapse/lib/view.py
CHANGED
|
@@ -260,6 +260,9 @@ class View(s_nexus.Pusher): # type: ignore
|
|
|
260
260
|
if self.merging: # pragma: no cover
|
|
261
261
|
return
|
|
262
262
|
|
|
263
|
+
if self.core.safemode:
|
|
264
|
+
return
|
|
265
|
+
|
|
263
266
|
if not await self.isMergeReady():
|
|
264
267
|
return
|
|
265
268
|
|
|
@@ -380,6 +383,9 @@ class View(s_nexus.Pusher): # type: ignore
|
|
|
380
383
|
if not await self.core.isCellActive():
|
|
381
384
|
return
|
|
382
385
|
|
|
386
|
+
if self.core.safemode:
|
|
387
|
+
return
|
|
388
|
+
|
|
383
389
|
self.mergetask = self.core.schedCoro(self.runViewMerge())
|
|
384
390
|
|
|
385
391
|
async def finiMergeTask(self):
|
|
@@ -568,6 +574,9 @@ class View(s_nexus.Pusher): # type: ignore
|
|
|
568
574
|
if not await self.core.isCellActive():
|
|
569
575
|
return
|
|
570
576
|
|
|
577
|
+
if self.core.safemode:
|
|
578
|
+
return
|
|
579
|
+
|
|
571
580
|
self.trigtask = self.schedCoro(self._trigQueueLoop())
|
|
572
581
|
|
|
573
582
|
async def finiTrigTask(self):
|
|
@@ -1577,7 +1586,7 @@ class View(s_nexus.Pusher): # type: ignore
|
|
|
1577
1586
|
|
|
1578
1587
|
async def runTagAdd(self, node, tag, valu):
|
|
1579
1588
|
|
|
1580
|
-
if self.core.migration:
|
|
1589
|
+
if self.core.migration or self.core.safemode:
|
|
1581
1590
|
return
|
|
1582
1591
|
|
|
1583
1592
|
# Run any trigger handlers
|
|
@@ -1585,21 +1594,21 @@ class View(s_nexus.Pusher): # type: ignore
|
|
|
1585
1594
|
|
|
1586
1595
|
async def runTagDel(self, node, tag, valu):
|
|
1587
1596
|
|
|
1588
|
-
if self.core.migration:
|
|
1597
|
+
if self.core.migration or self.core.safemode:
|
|
1589
1598
|
return
|
|
1590
1599
|
|
|
1591
1600
|
await self.triggers.runTagDel(node, tag)
|
|
1592
1601
|
|
|
1593
1602
|
async def runNodeAdd(self, node):
|
|
1594
1603
|
|
|
1595
|
-
if self.core.migration:
|
|
1604
|
+
if self.core.migration or self.core.safemode:
|
|
1596
1605
|
return
|
|
1597
1606
|
|
|
1598
1607
|
await self.triggers.runNodeAdd(node)
|
|
1599
1608
|
|
|
1600
1609
|
async def runNodeDel(self, node):
|
|
1601
1610
|
|
|
1602
|
-
if self.core.migration:
|
|
1611
|
+
if self.core.migration or self.core.safemode:
|
|
1603
1612
|
return
|
|
1604
1613
|
|
|
1605
1614
|
await self.triggers.runNodeDel(node)
|
|
@@ -1608,21 +1617,21 @@ class View(s_nexus.Pusher): # type: ignore
|
|
|
1608
1617
|
'''
|
|
1609
1618
|
Handle when a prop set trigger event fired
|
|
1610
1619
|
'''
|
|
1611
|
-
if self.core.migration:
|
|
1620
|
+
if self.core.migration or self.core.safemode:
|
|
1612
1621
|
return
|
|
1613
1622
|
|
|
1614
1623
|
await self.triggers.runPropSet(node, prop, oldv)
|
|
1615
1624
|
|
|
1616
1625
|
async def runEdgeAdd(self, n1, edge, n2):
|
|
1617
1626
|
|
|
1618
|
-
if self.core.migration:
|
|
1627
|
+
if self.core.migration or self.core.safemode:
|
|
1619
1628
|
return
|
|
1620
1629
|
|
|
1621
1630
|
await self.triggers.runEdgeAdd(n1, edge, n2)
|
|
1622
1631
|
|
|
1623
1632
|
async def runEdgeDel(self, n1, edge, n2):
|
|
1624
1633
|
|
|
1625
|
-
if self.core.migration:
|
|
1634
|
+
if self.core.migration or self.core.safemode:
|
|
1626
1635
|
return
|
|
1627
1636
|
|
|
1628
1637
|
await self.triggers.runEdgeDel(n1, edge, n2)
|
synapse/models/inet.py
CHANGED
|
@@ -1542,7 +1542,7 @@ class InetModule(s_module.CoreModule):
|
|
|
1542
1542
|
('inet:service:app', ('guid', {}), {
|
|
1543
1543
|
'interfaces': ('inet:service:object',),
|
|
1544
1544
|
'template': {'service:base': 'application'},
|
|
1545
|
-
'doc': '
|
|
1545
|
+
'doc': 'An application which is part of a service architecture.'}),
|
|
1546
1546
|
|
|
1547
1547
|
('inet:service:instance', ('guid', {}), {
|
|
1548
1548
|
'doc': 'An instance of the platform such as Slack or Discord instances.'}),
|
|
@@ -3769,6 +3769,12 @@ class InetModule(s_module.CoreModule):
|
|
|
3769
3769
|
('desc', ('str', {}), {
|
|
3770
3770
|
'disp': {'hint': 'text'},
|
|
3771
3771
|
'doc': 'A description of the platform specific application.'}),
|
|
3772
|
+
|
|
3773
|
+
('provider', ('ou:org', {}), {
|
|
3774
|
+
'doc': 'The organization which provides the application.'}),
|
|
3775
|
+
|
|
3776
|
+
('provider:name', ('ou:name', {}), {
|
|
3777
|
+
'doc': 'The name of the organization which provides the application.'}),
|
|
3772
3778
|
)),
|
|
3773
3779
|
|
|
3774
3780
|
('inet:service:account', {}, (
|
synapse/models/risk.py
CHANGED
|
@@ -220,6 +220,8 @@ class RiskModule(s_module.CoreModule):
|
|
|
220
220
|
'doc': 'The threat cluster targeted the target node.'}),
|
|
221
221
|
(('risk:threat', 'uses', None), {
|
|
222
222
|
'doc': 'The threat cluster uses the target node.'}),
|
|
223
|
+
(('risk:threat', 'uses', 'inet:service:app'), {
|
|
224
|
+
'doc': 'The threat cluster uses the online application.'}),
|
|
223
225
|
(('risk:attack', 'targets', None), {
|
|
224
226
|
'doc': 'The attack targeted the target node.'}),
|
|
225
227
|
(('risk:attack', 'uses', None), {
|
synapse/tests/test_cortex.py
CHANGED
|
@@ -8776,6 +8776,268 @@ class CortexBasicTest(s_t_utils.SynTest):
|
|
|
8776
8776
|
self.eq(core._test_pre_nexus_index, offs)
|
|
8777
8777
|
self.ge(core._test_post_nexus_index, core._test_pre_nexus_index)
|
|
8778
8778
|
|
|
8779
|
+
async def test_cortex_safemode(self):
|
|
8780
|
+
safemode = {'safemode': True}
|
|
8781
|
+
nosafe = {'safemode': False}
|
|
8782
|
+
|
|
8783
|
+
# Cortex safemode disables the following functionality:
|
|
8784
|
+
# - crons
|
|
8785
|
+
# - triggers
|
|
8786
|
+
# - dmons
|
|
8787
|
+
# - storm package onloads
|
|
8788
|
+
# - merge tasks (e.g. for quorum)
|
|
8789
|
+
# - storm pools
|
|
8790
|
+
|
|
8791
|
+
# Make sure we're logging the message
|
|
8792
|
+
with self.getStructuredAsyncLoggerStream('synapse.lib.cell', 'Booting cortex in safe-mode.') as stream:
|
|
8793
|
+
async with self.getTestCore(conf=safemode) as core:
|
|
8794
|
+
self.true(core.safemode)
|
|
8795
|
+
self.true(await stream.wait(10))
|
|
8796
|
+
msgs = stream.jsonlines()
|
|
8797
|
+
self.len(1, msgs)
|
|
8798
|
+
self.eq(msgs[0].get('message'), 'Booting cortex in safe-mode. Some functionality may be disabled.')
|
|
8799
|
+
self.eq(msgs[0].get('level'), 'WARNING')
|
|
8800
|
+
|
|
8801
|
+
# Check crons, triggers, dmons in this section
|
|
8802
|
+
with self.getTestDir() as dirn:
|
|
8803
|
+
|
|
8804
|
+
# Setup the cortex
|
|
8805
|
+
async with self.getTestCore(dirn=dirn) as core:
|
|
8806
|
+
await core.addCoreQueue('queue:safemode:done', {})
|
|
8807
|
+
# Add a cron job and immediately disable it
|
|
8808
|
+
q = '''
|
|
8809
|
+
cron.add --minute +1 {
|
|
8810
|
+
$now = $lib.cast(time, now)
|
|
8811
|
+
$lib.log.warning(`SAFEMODE CRON: {$now}`)
|
|
8812
|
+
[ test:str=CRON :tick=$now ]
|
|
8813
|
+
} |
|
|
8814
|
+
$job = $lib.cron.list().0
|
|
8815
|
+
cron.disable $job.iden
|
|
8816
|
+
'''
|
|
8817
|
+
await core.callStorm(q)
|
|
8818
|
+
jobs = await core.listCronJobs()
|
|
8819
|
+
self.len(1, jobs)
|
|
8820
|
+
self.eq(jobs[0].get('enabled'), False)
|
|
8821
|
+
|
|
8822
|
+
# Add a regular trigger
|
|
8823
|
+
q = '''
|
|
8824
|
+
$lib.log.warning(`SAFEMODE TRIGGER: {$node}`)
|
|
8825
|
+
$tick = :tick
|
|
8826
|
+
$str = { [( test:str=TRIGGER :hehe=$tick )] }
|
|
8827
|
+
$queue = $lib.queue.gen(queue:safemode)
|
|
8828
|
+
$queue.put($tick)
|
|
8829
|
+
'''
|
|
8830
|
+
opts = {'vars': {'query': q}}
|
|
8831
|
+
await core.callStorm(f'trigger.add prop:set --prop test:str:tick --query {{{q}}}')
|
|
8832
|
+
|
|
8833
|
+
# Add an async trigger
|
|
8834
|
+
q = '''
|
|
8835
|
+
$lib.log.warning(`SAFEMODE ATRIGGER: {$node}`)
|
|
8836
|
+
$tick = :tick
|
|
8837
|
+
$str = { [( test:str=ATRIGGER :hehe=$tick )] }
|
|
8838
|
+
$queue = $lib.queue.gen(queue:safemode)
|
|
8839
|
+
$queue.put($tick)
|
|
8840
|
+
'''
|
|
8841
|
+
opts = {'vars': {'query': q}}
|
|
8842
|
+
await core.callStorm(f'trigger.add prop:set --prop test:str:tick --async --query {{{q}}}')
|
|
8843
|
+
|
|
8844
|
+
# Add a dmon
|
|
8845
|
+
q = '''
|
|
8846
|
+
$queue = $lib.queue.gen(queue:safemode)
|
|
8847
|
+
$queue2 = $lib.queue.gen(queue:safemode:done)
|
|
8848
|
+
while (true) {
|
|
8849
|
+
($offs, $item) = $queue.get()
|
|
8850
|
+
$lib.log.warning(`SAFEMODE DMON: {$item}`)
|
|
8851
|
+
[ test:str=DMON :hehe=$item ]
|
|
8852
|
+
$queue2.put($item)
|
|
8853
|
+
}
|
|
8854
|
+
'''
|
|
8855
|
+
await core.callStorm(f'$iden = $lib.dmon.add(${{{q}}}) $lib.dmon.start($iden)')
|
|
8856
|
+
|
|
8857
|
+
nodes = await core.nodes('test:str')
|
|
8858
|
+
self.len(0, nodes)
|
|
8859
|
+
|
|
8860
|
+
# Run in safemode and verify cron, trigger, and dmons don't execute
|
|
8861
|
+
with self.getLoggerStream('synapse.storm') as stream:
|
|
8862
|
+
async with self.getTestCore(dirn=dirn, conf=safemode) as core:
|
|
8863
|
+
await core.callStorm('cron.enable $lib.cron.list().0.iden')
|
|
8864
|
+
# Increment the cron tick to get it to fire
|
|
8865
|
+
core.agenda._addTickOff(60)
|
|
8866
|
+
|
|
8867
|
+
# Add a test:str:tick to get the trigger to fire
|
|
8868
|
+
await core.callStorm('[ test:str=newp :tick=1234 ]')
|
|
8869
|
+
|
|
8870
|
+
# Check for test:strs
|
|
8871
|
+
nodes = await core.nodes('test:str')
|
|
8872
|
+
self.len(1, nodes)
|
|
8873
|
+
self.eq(nodes[0].repr(), 'newp')
|
|
8874
|
+
|
|
8875
|
+
with self.raises(TimeoutError):
|
|
8876
|
+
await s_common.wait_for(core.coreQueueGet('queue:safemode:done', wait=True), timeout=2)
|
|
8877
|
+
|
|
8878
|
+
# Add a dmon to make sure it doesn't start
|
|
8879
|
+
await core.addCoreQueue('queue:safemode:started', {})
|
|
8880
|
+
q = '''
|
|
8881
|
+
$queue = $lib.queue.gen(queue:safemode)
|
|
8882
|
+
$queue2 = $lib.queue.get(queue:safemode:started)
|
|
8883
|
+
while (true) {
|
|
8884
|
+
$queue2.put(foo)
|
|
8885
|
+
$lib.log.warning(`SAFEMODE DMON START`)
|
|
8886
|
+
($offs, $item) = $queue.get()
|
|
8887
|
+
}
|
|
8888
|
+
'''
|
|
8889
|
+
await core.callStorm(f'$iden = $lib.dmon.add(${{{q}}}) $lib.dmon.start($iden)')
|
|
8890
|
+
|
|
8891
|
+
with self.raises(TimeoutError):
|
|
8892
|
+
await s_common.wait_for(core.coreQueueGet('queue:safemode:started', wait=True), timeout=2)
|
|
8893
|
+
|
|
8894
|
+
stream.seek(0)
|
|
8895
|
+
data = stream.read()
|
|
8896
|
+
self.notin('SAFEMODE CRON', data)
|
|
8897
|
+
self.notin('SAFEMODE TRIGGER', data)
|
|
8898
|
+
self.notin('SAFEMODE ATRIGGER', data)
|
|
8899
|
+
self.notin('SAFEMODE DMON', data)
|
|
8900
|
+
|
|
8901
|
+
with self.getLoggerStream('synapse.storm') as stream:
|
|
8902
|
+
async with self.getTestCore(dirn=dirn) as core:
|
|
8903
|
+
core.agenda._addTickOff(60)
|
|
8904
|
+
|
|
8905
|
+
item = await s_common.wait_for(core.coreQueueGet('queue:safemode:done', wait=True), timeout=5)
|
|
8906
|
+
self.len(2, item)
|
|
8907
|
+
|
|
8908
|
+
nodes = await core.nodes('test:str')
|
|
8909
|
+
self.len(5, nodes)
|
|
8910
|
+
self.sorteq(
|
|
8911
|
+
['newp', 'CRON', 'TRIGGER', 'DMON', 'ATRIGGER'],
|
|
8912
|
+
[k.repr() for k in nodes]
|
|
8913
|
+
)
|
|
8914
|
+
|
|
8915
|
+
stream.seek(0)
|
|
8916
|
+
data = stream.read()
|
|
8917
|
+
self.isin('SAFEMODE CRON', data)
|
|
8918
|
+
self.isin('SAFEMODE TRIGGER', data)
|
|
8919
|
+
self.isin('SAFEMODE ATRIGGER', data)
|
|
8920
|
+
self.isin('SAFEMODE DMON', data)
|
|
8921
|
+
|
|
8922
|
+
# Check storm package onload handlers are not executed
|
|
8923
|
+
with self.getTestDir() as dirn:
|
|
8924
|
+
async with self.getTestCore(dirn=dirn, conf=safemode) as core:
|
|
8925
|
+
pkgdef = {
|
|
8926
|
+
'name': 'foopkg',
|
|
8927
|
+
'version': (0, 0, 1),
|
|
8928
|
+
'onload': '$lib.import(foo.setup).onload()',
|
|
8929
|
+
'modules': (
|
|
8930
|
+
{
|
|
8931
|
+
'name': 'foo.setup',
|
|
8932
|
+
'storm': '''
|
|
8933
|
+
function onload() {
|
|
8934
|
+
$lib.warn('foopkg onload')
|
|
8935
|
+
}
|
|
8936
|
+
''',
|
|
8937
|
+
},
|
|
8938
|
+
)
|
|
8939
|
+
}
|
|
8940
|
+
|
|
8941
|
+
waiter = core.waiter(1, 'core:pkg:onload:skipped')
|
|
8942
|
+
await core.addStormPkg(pkgdef)
|
|
8943
|
+
events = await waiter.wait(timeout=10)
|
|
8944
|
+
self.nn(events)
|
|
8945
|
+
self.len(1, events)
|
|
8946
|
+
self.eq(events, (('core:pkg:onload:skipped', {'pkg': 'foopkg', 'reason': 'safemode'}),))
|
|
8947
|
+
|
|
8948
|
+
with self.getAsyncLoggerStream('synapse.cortex', 'foopkg onload output: foopkg onload') as stream:
|
|
8949
|
+
async with self.getTestCore(dirn=dirn, conf=nosafe) as core:
|
|
8950
|
+
self.false(core.safemode)
|
|
8951
|
+
await stream.wait(timeout=10)
|
|
8952
|
+
|
|
8953
|
+
# Check merge tasks are not executed
|
|
8954
|
+
with self.getTestDir() as dirn:
|
|
8955
|
+
async with self.getTestCore(dirn=dirn, conf=safemode) as core:
|
|
8956
|
+
alliden = core.auth.allrole.iden
|
|
8957
|
+
|
|
8958
|
+
blackout = await core.auth.addUser('blackout')
|
|
8959
|
+
await blackout.allow(('view', 'read'))
|
|
8960
|
+
|
|
8961
|
+
await core.auth.rootuser.grant(alliden)
|
|
8962
|
+
|
|
8963
|
+
view = core.getView()
|
|
8964
|
+
qnfo = {
|
|
8965
|
+
'count': 1,
|
|
8966
|
+
'roles': [alliden],
|
|
8967
|
+
}
|
|
8968
|
+
await view.setViewInfo('quorum', qnfo)
|
|
8969
|
+
|
|
8970
|
+
forkiden = (await view.fork()).get('iden')
|
|
8971
|
+
|
|
8972
|
+
opts = {'view': forkiden}
|
|
8973
|
+
|
|
8974
|
+
nodes = await core.nodes('[ test:str=fork ]', opts=opts)
|
|
8975
|
+
self.len(1, nodes)
|
|
8976
|
+
|
|
8977
|
+
await core.callStorm('$lib.view.get().setMergeRequest()', opts=opts)
|
|
8978
|
+
await core.callStorm('$lib.view.get().setMergeVote()', opts=opts | {'user': blackout.iden})
|
|
8979
|
+
|
|
8980
|
+
fork = core.getView(forkiden)
|
|
8981
|
+
|
|
8982
|
+
self.true(await fork.isMergeReady())
|
|
8983
|
+
self.none(fork.mergetask)
|
|
8984
|
+
|
|
8985
|
+
self.len(0, await core.nodes('test:str'))
|
|
8986
|
+
|
|
8987
|
+
async with self.getTestCore(dirn=dirn, conf=nosafe) as core:
|
|
8988
|
+
nodes = await core.nodes('test:str')
|
|
8989
|
+
self.len(1, nodes)
|
|
8990
|
+
self.eq(nodes[0].repr(), 'fork')
|
|
8991
|
+
|
|
8992
|
+
# Check storm pools are not enabled
|
|
8993
|
+
async with self.getTestAha() as aha:
|
|
8994
|
+
|
|
8995
|
+
ahanet = aha.conf.req('aha:network')
|
|
8996
|
+
|
|
8997
|
+
async with await s_base.Base.anit() as base:
|
|
8998
|
+
|
|
8999
|
+
with self.getTestDir() as dirn:
|
|
9000
|
+
|
|
9001
|
+
dirn00 = s_common.genpath(dirn, 'cell00')
|
|
9002
|
+
dirn01 = s_common.genpath(dirn, 'cell01')
|
|
9003
|
+
|
|
9004
|
+
core00 = await base.enter_context(self.addSvcToAha(aha, '00.core', s_cortex.Cortex, dirn=dirn00,
|
|
9005
|
+
conf=safemode))
|
|
9006
|
+
provinfo = {'mirror': 'core'}
|
|
9007
|
+
core01 = await base.enter_context(self.addSvcToAha(aha, '01.core', s_cortex.Cortex, dirn=dirn01,
|
|
9008
|
+
provinfo=provinfo))
|
|
9009
|
+
|
|
9010
|
+
msgs = await core01.stormlist('aha.pool.add pool00...')
|
|
9011
|
+
self.stormHasNoWarnErr(msgs)
|
|
9012
|
+
self.stormIsInPrint('Created AHA service pool: pool00.synapse', msgs)
|
|
9013
|
+
|
|
9014
|
+
msgs = await core01.stormlist('aha.pool.svc.add pool00... 01.core...')
|
|
9015
|
+
self.stormHasNoWarnErr(msgs)
|
|
9016
|
+
self.stormIsInPrint('AHA service (01.core...) added to service pool (pool00.synapse)', msgs)
|
|
9017
|
+
|
|
9018
|
+
msgs = await core00.stormlist('cortex.storm.pool.set --connection-timeout 1 --sync-timeout 1 aha://pool00...')
|
|
9019
|
+
self.stormHasNoWarnErr(msgs)
|
|
9020
|
+
self.stormIsInPrint('Storm pool configuration set.', msgs)
|
|
9021
|
+
|
|
9022
|
+
# Make sure queries still work
|
|
9023
|
+
nodes = await core00.nodes('[ it:dev:str="stormpools!" ]', opts={'mirror': True})
|
|
9024
|
+
self.len(1, nodes)
|
|
9025
|
+
|
|
9026
|
+
self.none(core00.stormpool)
|
|
9027
|
+
|
|
9028
|
+
await core00.fini()
|
|
9029
|
+
|
|
9030
|
+
# Now disable safemode and check that the stormpool is enabled
|
|
9031
|
+
core00 = await base.enter_context(self.getTestCore(dirn=dirn00, conf=nosafe))
|
|
9032
|
+
|
|
9033
|
+
nodes = await core00.nodes('it:dev:str', opts={'mirror': True})
|
|
9034
|
+
self.len(1, nodes)
|
|
9035
|
+
|
|
9036
|
+
self.nn(core00.stormpool)
|
|
9037
|
+
|
|
9038
|
+
await core00.fini()
|
|
9039
|
+
await core01.fini()
|
|
9040
|
+
|
|
8779
9041
|
async def test_cortex_queue_mirror_authgates(self):
|
|
8780
9042
|
async with self.getRegrCore('2.213.0-queue-authgates') as core:
|
|
8781
9043
|
self.nn(await core.getAuthGate('queue:stillhere'))
|
synapse/tests/test_lib_auth.py
CHANGED
|
@@ -431,6 +431,8 @@ class AuthTest(s_test.SynTest):
|
|
|
431
431
|
await core.auth.allrole.setRules([(True, ('hehe', 'haha'), 'newp')])
|
|
432
432
|
with self.raises(s_exc.SchemaViolation):
|
|
433
433
|
await core.auth.allrole.setRules([(True, )])
|
|
434
|
+
with self.raises(s_exc.SchemaViolation):
|
|
435
|
+
await core.auth.allrole.setRules([(True, '')])
|
|
434
436
|
|
|
435
437
|
async def test_auth_archived_locked_interaction(self):
|
|
436
438
|
|