synapse 2.160.0__py311-none-any.whl → 2.162.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 +12 -7
- synapse/daemon.py +7 -2
- synapse/lib/agenda.py +8 -2
- synapse/lib/aha.py +4 -4
- synapse/lib/ast.py +3 -3
- synapse/lib/cell.py +20 -1
- synapse/lib/hiveauth.py +1 -1
- synapse/lib/httpapi.py +5 -0
- synapse/lib/layer.py +21 -1
- synapse/lib/nexus.py +9 -5
- synapse/lib/node.py +3 -4
- synapse/lib/rstorm.py +16 -0
- synapse/lib/schemas.py +2 -1
- synapse/lib/snap.py +20 -11
- synapse/lib/storm.py +19 -3
- synapse/lib/stormhttp.py +14 -2
- synapse/lib/stormlib/easyperm.py +5 -2
- synapse/lib/stormlib/gen.py +119 -44
- synapse/lib/stormlib/stix.py +6 -3
- synapse/lib/stormlib/vault.py +32 -15
- synapse/lib/stormtypes.py +187 -21
- synapse/lib/trigger.py +2 -0
- synapse/lib/version.py +2 -2
- synapse/lib/view.py +42 -10
- synapse/models/inet.py +9 -0
- synapse/models/infotech.py +28 -26
- synapse/models/orgs.py +3 -0
- synapse/models/proj.py +9 -2
- synapse/models/risk.py +32 -0
- synapse/telepath.py +6 -2
- synapse/tests/files/rstorm/testsvc.py +8 -1
- synapse/tests/files/stormpkg/testpkg.yaml +4 -0
- synapse/tests/test_axon.py +4 -4
- synapse/tests/test_cortex.py +66 -8
- synapse/tests/test_daemon.py +19 -0
- synapse/tests/test_lib_agenda.py +8 -0
- synapse/tests/test_lib_aha.py +18 -3
- synapse/tests/test_lib_ast.py +38 -16
- synapse/tests/test_lib_cell.py +3 -0
- synapse/tests/test_lib_grammar.py +4 -4
- synapse/tests/test_lib_httpapi.py +59 -0
- synapse/tests/test_lib_nexus.py +63 -0
- synapse/tests/test_lib_rstorm.py +38 -2
- synapse/tests/test_lib_snap.py +10 -0
- synapse/tests/test_lib_storm.py +61 -20
- synapse/tests/test_lib_stormhttp.py +21 -21
- synapse/tests/test_lib_stormlib_auth.py +3 -3
- synapse/tests/test_lib_stormlib_cell.py +1 -1
- synapse/tests/test_lib_stormlib_cortex.py +50 -2
- synapse/tests/test_lib_stormlib_gen.py +77 -0
- synapse/tests/test_lib_stormlib_json.py +2 -2
- synapse/tests/test_lib_stormlib_macro.py +1 -1
- synapse/tests/test_lib_stormlib_modelext.py +37 -37
- synapse/tests/test_lib_stormlib_oauth.py +20 -20
- synapse/tests/test_lib_stormlib_stix.py +3 -1
- synapse/tests/test_lib_stormlib_vault.py +1 -1
- synapse/tests/test_lib_stormtypes.py +159 -47
- synapse/tests/test_lib_stormwhois.py +1 -1
- synapse/tests/test_lib_trigger.py +11 -11
- synapse/tests/test_lib_view.py +23 -1
- synapse/tests/test_model_crypto.py +1 -1
- synapse/tests/test_model_inet.py +6 -0
- synapse/tests/test_model_orgs.py +2 -1
- synapse/tests/test_model_proj.py +6 -0
- synapse/tests/test_model_risk.py +10 -0
- synapse/tests/test_tools_storm.py +1 -1
- {synapse-2.160.0.dist-info → synapse-2.162.0.dist-info}/METADATA +5 -3
- {synapse-2.160.0.dist-info → synapse-2.162.0.dist-info}/RECORD +71 -71
- {synapse-2.160.0.dist-info → synapse-2.162.0.dist-info}/LICENSE +0 -0
- {synapse-2.160.0.dist-info → synapse-2.162.0.dist-info}/WHEEL +0 -0
- {synapse-2.160.0.dist-info → synapse-2.162.0.dist-info}/top_level.txt +0 -0
synapse/cortex.py
CHANGED
|
@@ -1080,7 +1080,8 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
1080
1080
|
mdef = s_msgpack.un(byts)
|
|
1081
1081
|
|
|
1082
1082
|
if user is not None:
|
|
1083
|
-
|
|
1083
|
+
mesg = f'User requires read permission on macro: {name}.'
|
|
1084
|
+
self._reqEasyPerm(mdef, user, s_cell.PERM_READ, mesg=mesg)
|
|
1084
1085
|
|
|
1085
1086
|
return mdef
|
|
1086
1087
|
|
|
@@ -1091,7 +1092,8 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
1091
1092
|
raise s_exc.NoSuchName(mesg=f'Macro name not found: {name}')
|
|
1092
1093
|
|
|
1093
1094
|
if user is not None:
|
|
1094
|
-
|
|
1095
|
+
mesg = f'User requires read permission on macro: {name}.'
|
|
1096
|
+
self._reqEasyPerm(mdef, user, s_cell.PERM_READ, mesg=mesg)
|
|
1095
1097
|
|
|
1096
1098
|
return mdef
|
|
1097
1099
|
|
|
@@ -1645,7 +1647,8 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
1645
1647
|
raise s_exc.AuthDeny(mesg=mesg, user=user.iden, username=user.name)
|
|
1646
1648
|
|
|
1647
1649
|
if user is not None:
|
|
1648
|
-
|
|
1650
|
+
mesg = f'User requires {s_cell.permnames.get(level)} permission on graph: {iden}.'
|
|
1651
|
+
self._reqEasyPerm(gdef, user, level, mesg=mesg)
|
|
1649
1652
|
|
|
1650
1653
|
return gdef
|
|
1651
1654
|
|
|
@@ -5304,7 +5307,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
5304
5307
|
|
|
5305
5308
|
if (nexsoffs := opts.get('nexsoffs')) is not None:
|
|
5306
5309
|
if not await self.waitNexsOffs(nexsoffs, timeout=opts.get('nexstimeout')):
|
|
5307
|
-
raise s_exc.TimeOut(f'Timeout waiting for nexus offset {nexsoffs}.')
|
|
5310
|
+
raise s_exc.TimeOut(mesg=f'Timeout waiting for nexus offset {nexsoffs}.')
|
|
5308
5311
|
|
|
5309
5312
|
view = self._viewFromOpts(opts)
|
|
5310
5313
|
|
|
@@ -5360,7 +5363,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
5360
5363
|
|
|
5361
5364
|
if (nexsoffs := opts.get('nexsoffs')) is not None:
|
|
5362
5365
|
if not await self.waitNexsOffs(nexsoffs, timeout=opts.get('nexstimeout')):
|
|
5363
|
-
raise s_exc.TimeOut(f'Timeout waiting for nexus offset {nexsoffs}.')
|
|
5366
|
+
raise s_exc.TimeOut(mesg=f'Timeout waiting for nexus offset {nexsoffs}.')
|
|
5364
5367
|
|
|
5365
5368
|
view = self._viewFromOpts(opts)
|
|
5366
5369
|
async for mesg in view.storm(text, opts=opts):
|
|
@@ -5387,7 +5390,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
5387
5390
|
|
|
5388
5391
|
if (nexsoffs := opts.get('nexsoffs')) is not None:
|
|
5389
5392
|
if not await self.waitNexsOffs(nexsoffs, timeout=opts.get('nexstimeout')):
|
|
5390
|
-
raise s_exc.TimeOut(f'Timeout waiting for nexus offset {nexsoffs}.')
|
|
5393
|
+
raise s_exc.TimeOut(mesg=f'Timeout waiting for nexus offset {nexsoffs}.')
|
|
5391
5394
|
|
|
5392
5395
|
view = self._viewFromOpts(opts)
|
|
5393
5396
|
return await view.callStorm(text, opts=opts)
|
|
@@ -5415,7 +5418,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
5415
5418
|
|
|
5416
5419
|
if (nexsoffs := opts.get('nexsoffs')) is not None:
|
|
5417
5420
|
if not await self.waitNexsOffs(nexsoffs, timeout=opts.get('nexstimeout')):
|
|
5418
|
-
raise s_exc.TimeOut(f'Timeout waiting for nexus offset {nexsoffs}.')
|
|
5421
|
+
raise s_exc.TimeOut(mesg=f'Timeout waiting for nexus offset {nexsoffs}.')
|
|
5419
5422
|
|
|
5420
5423
|
user = self._userFromOpts(opts)
|
|
5421
5424
|
view = self._viewFromOpts(opts)
|
|
@@ -5940,6 +5943,8 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
5940
5943
|
if not cdef.get('iden'):
|
|
5941
5944
|
cdef['iden'] = s_common.guid()
|
|
5942
5945
|
|
|
5946
|
+
cdef['created'] = s_common.now()
|
|
5947
|
+
|
|
5943
5948
|
opts = {'user': cdef['creator'], 'view': cdef.get('view')}
|
|
5944
5949
|
|
|
5945
5950
|
view = self._viewFromOpts(opts)
|
synapse/daemon.py
CHANGED
|
@@ -218,7 +218,7 @@ async def t2call(link, meth, args, kwargs):
|
|
|
218
218
|
|
|
219
219
|
class Daemon(s_base.Base):
|
|
220
220
|
|
|
221
|
-
async def __anit__(self, certdir=None):
|
|
221
|
+
async def __anit__(self, certdir=None, ahainfo=None):
|
|
222
222
|
|
|
223
223
|
await s_base.Base.__anit__(self)
|
|
224
224
|
|
|
@@ -227,6 +227,8 @@ class Daemon(s_base.Base):
|
|
|
227
227
|
if certdir is None:
|
|
228
228
|
certdir = s_certdir.getCertDir()
|
|
229
229
|
|
|
230
|
+
self.ahainfo = ahainfo
|
|
231
|
+
|
|
230
232
|
self.certdir = certdir
|
|
231
233
|
self.televers = s_telepath.televers
|
|
232
234
|
|
|
@@ -414,13 +416,16 @@ class Daemon(s_base.Base):
|
|
|
414
416
|
async def _getSharedItem(self, name):
|
|
415
417
|
return self.shared.get(name)
|
|
416
418
|
|
|
417
|
-
async def _onTeleSyn(self, link, mesg):
|
|
419
|
+
async def _onTeleSyn(self, link: s_link.Link, mesg):
|
|
418
420
|
|
|
419
421
|
reply = ('tele:syn', {
|
|
420
422
|
'vers': self.televers,
|
|
421
423
|
'retn': (True, None),
|
|
422
424
|
})
|
|
423
425
|
|
|
426
|
+
if self.ahainfo is not None:
|
|
427
|
+
reply[1]['ahainfo'] = self.ahainfo
|
|
428
|
+
|
|
424
429
|
try:
|
|
425
430
|
|
|
426
431
|
vers = mesg[1].get('vers')
|
synapse/lib/agenda.py
CHANGED
|
@@ -259,6 +259,7 @@ class _Appt:
|
|
|
259
259
|
_synced_attrs = {
|
|
260
260
|
'doc',
|
|
261
261
|
'name',
|
|
262
|
+
'created',
|
|
262
263
|
'enabled',
|
|
263
264
|
'errcount',
|
|
264
265
|
'nexttime',
|
|
@@ -270,7 +271,7 @@ class _Appt:
|
|
|
270
271
|
'lastfinishtime',
|
|
271
272
|
}
|
|
272
273
|
|
|
273
|
-
def __init__(self, stor, iden, recur, indx, query, creator, recs, nexttime=None, view=None):
|
|
274
|
+
def __init__(self, stor, iden, recur, indx, query, creator, recs, nexttime=None, view=None, created=None):
|
|
274
275
|
self.doc = ''
|
|
275
276
|
self.name = ''
|
|
276
277
|
self.stor = stor
|
|
@@ -282,6 +283,7 @@ class _Appt:
|
|
|
282
283
|
self.recs = recs # List[ApptRec] list of the individual entries to calculate next time from
|
|
283
284
|
self._recidxnexttime = None # index of rec who is up next
|
|
284
285
|
self.view = view
|
|
286
|
+
self.created = created
|
|
285
287
|
|
|
286
288
|
if self.recur and not self.recs:
|
|
287
289
|
raise s_exc.BadTime(mesg='A recurrent appointment with no records')
|
|
@@ -310,6 +312,7 @@ class _Appt:
|
|
|
310
312
|
'doc': self.doc,
|
|
311
313
|
'name': self.name,
|
|
312
314
|
'storm': self.query,
|
|
315
|
+
'.created': self.created,
|
|
313
316
|
}
|
|
314
317
|
|
|
315
318
|
pnorms = {}
|
|
@@ -343,6 +346,7 @@ class _Appt:
|
|
|
343
346
|
'indx': self.indx,
|
|
344
347
|
'query': self.query,
|
|
345
348
|
'creator': self.creator,
|
|
349
|
+
'created': self.created,
|
|
346
350
|
'recs': [d.pack() for d in self.recs],
|
|
347
351
|
'nexttime': self.nexttime,
|
|
348
352
|
'startcount': self.startcount,
|
|
@@ -362,6 +366,7 @@ class _Appt:
|
|
|
362
366
|
appt = cls(stor, val['iden'], val['recur'], val['indx'], val['query'], val['creator'], recs, nexttime=val['nexttime'], view=val.get('view'))
|
|
363
367
|
appt.doc = val.get('doc', '')
|
|
364
368
|
appt.name = val.get('name', '')
|
|
369
|
+
appt.created = val.get('created', None)
|
|
365
370
|
appt.laststarttime = val['laststarttime']
|
|
366
371
|
appt.lastfinishtime = val['lastfinishtime']
|
|
367
372
|
appt.lastresult = val['lastresult']
|
|
@@ -592,6 +597,7 @@ class Agenda(s_base.Base):
|
|
|
592
597
|
query = cdef.get('storm')
|
|
593
598
|
creator = cdef.get('creator')
|
|
594
599
|
view = cdef.get('view')
|
|
600
|
+
created = cdef.get('created')
|
|
595
601
|
|
|
596
602
|
recur = incunit is not None
|
|
597
603
|
indx = self._next_indx
|
|
@@ -633,7 +639,7 @@ class Agenda(s_base.Base):
|
|
|
633
639
|
incvals = (incvals, )
|
|
634
640
|
recs.extend(ApptRec(rd, incunit, v) for (rd, v) in itertools.product(reqdicts, incvals))
|
|
635
641
|
|
|
636
|
-
appt = _Appt(self, iden, recur, indx, query, creator, recs, nexttime=nexttime, view=view)
|
|
642
|
+
appt = _Appt(self, iden, recur, indx, query, creator, recs, nexttime=nexttime, view=view, created=created)
|
|
637
643
|
self._addappt(iden, appt)
|
|
638
644
|
|
|
639
645
|
appt.doc = cdef.get('doc', '')
|
synapse/lib/aha.py
CHANGED
|
@@ -192,7 +192,7 @@ class AhaApi(s_cell.CellApi):
|
|
|
192
192
|
logger.warning(mesg, await self.cell.getLogExtra(name=svcname, netw=svcnetw))
|
|
193
193
|
return
|
|
194
194
|
|
|
195
|
-
logger.
|
|
195
|
+
logger.info(f'AhaCellApi fini, setting service offline [{name}]',
|
|
196
196
|
extra=await self.cell.getLogExtra(name=svcname, netw=svcnetw))
|
|
197
197
|
coro = self.cell.setAhaSvcDown(name, sess, network=network)
|
|
198
198
|
self.cell.schedCoro(coro) # this will eventually execute or get cancelled.
|
|
@@ -555,7 +555,7 @@ class AhaCell(s_cell.Cell):
|
|
|
555
555
|
network = svc.get('svcnetw')
|
|
556
556
|
linkiden = svc.get('svcinfo').get('online')
|
|
557
557
|
if linkiden not in current_sessions:
|
|
558
|
-
logger.
|
|
558
|
+
logger.info(f'AhaCell activecoro setting service offline [{svcname}.{network}]',
|
|
559
559
|
extra=await self.getLogExtra(name=svcname, netw=network))
|
|
560
560
|
await self.setAhaSvcDown(svcname, linkiden, network=network)
|
|
561
561
|
|
|
@@ -611,7 +611,7 @@ class AhaCell(s_cell.Cell):
|
|
|
611
611
|
path = ('aha', 'services', svcnetw, svcname)
|
|
612
612
|
|
|
613
613
|
unfo = info.get('urlinfo')
|
|
614
|
-
logger.
|
|
614
|
+
logger.info(f'Adding service [{svcfull}] from [{unfo.get("scheme")}://{unfo.get("host")}:{unfo.get("port")}]',
|
|
615
615
|
extra=await self.getLogExtra(name=svcname, netw=svcnetw))
|
|
616
616
|
|
|
617
617
|
svcinfo = {
|
|
@@ -788,7 +788,7 @@ class AhaCell(s_cell.Cell):
|
|
|
788
788
|
|
|
789
789
|
await self.fire('aha:svcdown', svcname=svcname, svcnetw=svcnetw)
|
|
790
790
|
|
|
791
|
-
logger.
|
|
791
|
+
logger.info(f'Set [{svcfull}] offline.',
|
|
792
792
|
extra=await self.getLogExtra(name=svcname, netw=svcnetw))
|
|
793
793
|
|
|
794
794
|
async def getAhaSvc(self, name, filters=None):
|
synapse/lib/ast.py
CHANGED
|
@@ -447,8 +447,8 @@ class SubGraph:
|
|
|
447
447
|
|
|
448
448
|
for pivq in rules.get('pivots', ()):
|
|
449
449
|
indx = 0
|
|
450
|
-
async for
|
|
451
|
-
yield (
|
|
450
|
+
async for n, p in node.storm(runt, pivq):
|
|
451
|
+
yield (n, p, {'type': 'rules', 'scope': scope, 'index': indx})
|
|
452
452
|
indx += 1
|
|
453
453
|
|
|
454
454
|
async def _edgefallback(self, runt, results, node):
|
|
@@ -3776,7 +3776,7 @@ class EmbedQuery(Const):
|
|
|
3776
3776
|
async def compute(self, runt, path):
|
|
3777
3777
|
|
|
3778
3778
|
varz = {}
|
|
3779
|
-
varz.update(runt.
|
|
3779
|
+
varz.update(runt.getScopeVars())
|
|
3780
3780
|
|
|
3781
3781
|
if path is not None:
|
|
3782
3782
|
varz.update(path.vars)
|
synapse/lib/cell.py
CHANGED
|
@@ -2640,6 +2640,16 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
2640
2640
|
if sess is not None:
|
|
2641
2641
|
sess.info[name] = valu
|
|
2642
2642
|
|
|
2643
|
+
@s_nexus.Pusher.onPushAuto('http:sess:update')
|
|
2644
|
+
async def updateHttpSessInfo(self, iden, vals: dict):
|
|
2645
|
+
for name, valu in vals.items():
|
|
2646
|
+
s_msgpack.isok(valu)
|
|
2647
|
+
for name, valu in vals.items():
|
|
2648
|
+
self.sessstor.set(iden, name, valu)
|
|
2649
|
+
sess = self.sessions.get(iden)
|
|
2650
|
+
if sess is not None:
|
|
2651
|
+
sess.info.update(vals)
|
|
2652
|
+
|
|
2643
2653
|
@contextlib.contextmanager
|
|
2644
2654
|
def getTempDir(self):
|
|
2645
2655
|
tdir = s_common.gendir(self.dirn, 'tmp')
|
|
@@ -2830,7 +2840,11 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
2830
2840
|
|
|
2831
2841
|
async def _initCellDmon(self):
|
|
2832
2842
|
|
|
2833
|
-
|
|
2843
|
+
ahainfo = {
|
|
2844
|
+
'name': self.ahasvcname
|
|
2845
|
+
}
|
|
2846
|
+
|
|
2847
|
+
self.dmon = await s_daemon.Daemon.anit(ahainfo=ahainfo)
|
|
2834
2848
|
self.dmon.share('*', self)
|
|
2835
2849
|
|
|
2836
2850
|
self.onfini(self.dmon.fini)
|
|
@@ -3948,6 +3962,11 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
3948
3962
|
'cellvers': dict(self.cellvers.items()),
|
|
3949
3963
|
'nexsindx': await self.getNexsIndx(),
|
|
3950
3964
|
'uplink': self.nexsroot.miruplink.is_set(),
|
|
3965
|
+
'aha': {
|
|
3966
|
+
'name': self.conf.get('aha:name'),
|
|
3967
|
+
'leader': self.conf.get('aha:leader'),
|
|
3968
|
+
'network': self.conf.get('aha:network'),
|
|
3969
|
+
}
|
|
3951
3970
|
},
|
|
3952
3971
|
'features': {
|
|
3953
3972
|
'tellready': True,
|
synapse/lib/hiveauth.py
CHANGED
|
@@ -1032,7 +1032,7 @@ class HiveUser(HiveRuler):
|
|
|
1032
1032
|
for iden in self.info.get('roles', ()):
|
|
1033
1033
|
role = self.auth.role(iden)
|
|
1034
1034
|
if role is None:
|
|
1035
|
-
logger.warning('user {self.iden} has non-existent role: {iden}')
|
|
1035
|
+
logger.warning(f'user {self.iden} has non-existent role: {iden}')
|
|
1036
1036
|
continue
|
|
1037
1037
|
yield role
|
|
1038
1038
|
|
synapse/lib/httpapi.py
CHANGED
|
@@ -42,6 +42,11 @@ class Sess(s_base.Base):
|
|
|
42
42
|
await self.cell.setHttpSessInfo(self.iden, name, valu)
|
|
43
43
|
self.info[name] = valu
|
|
44
44
|
|
|
45
|
+
async def update(self, vals: dict):
|
|
46
|
+
await self.cell.updateHttpSessInfo(self.iden, vals)
|
|
47
|
+
for name, valu in vals.items():
|
|
48
|
+
self.info[name] = valu
|
|
49
|
+
|
|
45
50
|
async def login(self, user):
|
|
46
51
|
self.user = user
|
|
47
52
|
await self.set('user', user.iden)
|
synapse/lib/layer.py
CHANGED
|
@@ -95,6 +95,7 @@ reqValidLdef = s_config.getJsValidator({
|
|
|
95
95
|
'properties': {
|
|
96
96
|
'iden': {'type': 'string', 'pattern': s_config.re_iden},
|
|
97
97
|
'creator': {'type': 'string', 'pattern': s_config.re_iden},
|
|
98
|
+
'created': {'type': 'integer', 'minimum': 0},
|
|
98
99
|
'lockmemory': {'type': 'boolean'},
|
|
99
100
|
'lmdb:growsize': {'type': 'integer'},
|
|
100
101
|
'logedits': {'type': 'boolean', 'default': True},
|
|
@@ -1528,12 +1529,14 @@ class Layer(s_nexus.Pusher):
|
|
|
1528
1529
|
|
|
1529
1530
|
mirror = self.layrinfo.get('mirror')
|
|
1530
1531
|
if mirror is not None:
|
|
1532
|
+
s_common.deprecated('mirror layer configuration option', curv='2.162.0')
|
|
1531
1533
|
conf = {'retrysleep': 2}
|
|
1532
1534
|
self.leader = await s_telepath.Client.anit(mirror, conf=conf)
|
|
1533
1535
|
self.leadtask = self.schedCoro(self._runMirrorLoop())
|
|
1534
1536
|
|
|
1535
1537
|
uplayr = self.layrinfo.get('upstream')
|
|
1536
1538
|
if uplayr is not None:
|
|
1539
|
+
s_common.deprecated('upstream layer configuration option', curv='2.162.0')
|
|
1537
1540
|
if isinstance(uplayr, (tuple, list)):
|
|
1538
1541
|
for layr in uplayr:
|
|
1539
1542
|
await self.initUpstreamSync(layr)
|
|
@@ -4381,9 +4384,14 @@ def getNodeEditPerms(nodeedits):
|
|
|
4381
4384
|
'''
|
|
4382
4385
|
Yields (offs, perm) tuples that can be used in user.allowed()
|
|
4383
4386
|
'''
|
|
4387
|
+
tags = []
|
|
4388
|
+
tagadds = []
|
|
4384
4389
|
|
|
4385
4390
|
for nodeoffs, (buid, form, edits) in enumerate(nodeedits):
|
|
4386
4391
|
|
|
4392
|
+
tags.clear()
|
|
4393
|
+
tagadds.clear()
|
|
4394
|
+
|
|
4387
4395
|
for editoffs, (edit, info, _) in enumerate(edits):
|
|
4388
4396
|
|
|
4389
4397
|
permoffs = (nodeoffs, editoffs)
|
|
@@ -4405,7 +4413,11 @@ def getNodeEditPerms(nodeedits):
|
|
|
4405
4413
|
continue
|
|
4406
4414
|
|
|
4407
4415
|
if edit == EDIT_TAG_SET:
|
|
4408
|
-
|
|
4416
|
+
if info[1] != (None, None):
|
|
4417
|
+
tagadds.append(info[0])
|
|
4418
|
+
yield (permoffs, ('node', 'tag', 'add', *info[0].split('.')))
|
|
4419
|
+
else:
|
|
4420
|
+
tags.append((len(info[0]), editoffs, info[0]))
|
|
4409
4421
|
continue
|
|
4410
4422
|
|
|
4411
4423
|
if edit == EDIT_TAG_DEL:
|
|
@@ -4435,3 +4447,11 @@ def getNodeEditPerms(nodeedits):
|
|
|
4435
4447
|
if edit == EDIT_EDGE_DEL:
|
|
4436
4448
|
yield (permoffs, ('node', 'edge', 'del', info[0]))
|
|
4437
4449
|
continue
|
|
4450
|
+
|
|
4451
|
+
for _, editoffs, tag in sorted(tags, reverse=True):
|
|
4452
|
+
look = tag + '.'
|
|
4453
|
+
if any([tagadd.startswith(look) for tagadd in tagadds]):
|
|
4454
|
+
continue
|
|
4455
|
+
|
|
4456
|
+
yield ((nodeoffs, editoffs), ('node', 'tag', 'add', *tag.split('.')))
|
|
4457
|
+
tagadds.append(tag)
|
synapse/lib/nexus.py
CHANGED
|
@@ -87,6 +87,8 @@ class NexsRoot(s_base.Base):
|
|
|
87
87
|
self.celliden = self.cell.iden
|
|
88
88
|
self.readonly = False
|
|
89
89
|
self.readonlyreason = None
|
|
90
|
+
|
|
91
|
+
self.applytask = None
|
|
90
92
|
self.applylock = asyncio.Lock()
|
|
91
93
|
|
|
92
94
|
self.ready = asyncio.Event()
|
|
@@ -312,7 +314,10 @@ class NexsRoot(s_base.Base):
|
|
|
312
314
|
if meta is None:
|
|
313
315
|
meta = {}
|
|
314
316
|
|
|
315
|
-
|
|
317
|
+
async with self.applylock:
|
|
318
|
+
# Keep a reference to the shielded task to ensure it isn't GC'd
|
|
319
|
+
self.applytask = asyncio.create_task(self._eat((nexsiden, event, args, kwargs, meta)))
|
|
320
|
+
return await asyncio.shield(self.applytask)
|
|
316
321
|
|
|
317
322
|
async def index(self):
|
|
318
323
|
if self.donexslog:
|
|
@@ -365,11 +370,10 @@ class NexsRoot(s_base.Base):
|
|
|
365
370
|
nexus = self._nexskids[nexsiden]
|
|
366
371
|
func, passitem = nexus._nexshands[event]
|
|
367
372
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
return await func(nexus, *args, nexsitem=(indx, mesg), **kwargs)
|
|
373
|
+
if passitem:
|
|
374
|
+
return await func(nexus, *args, nexsitem=(indx, mesg), **kwargs)
|
|
371
375
|
|
|
372
|
-
|
|
376
|
+
return await func(nexus, *args, **kwargs)
|
|
373
377
|
|
|
374
378
|
async def iter(self, offs: int, tellready=False) -> AsyncIterator[Any]:
|
|
375
379
|
'''
|
synapse/lib/node.py
CHANGED
|
@@ -331,8 +331,7 @@ class Node:
|
|
|
331
331
|
if not edits:
|
|
332
332
|
return False
|
|
333
333
|
|
|
334
|
-
await self.snap.applyNodeEdit((self.buid, self.form.name, edits))
|
|
335
|
-
self.props.pop(name, None)
|
|
334
|
+
await self.snap.applyNodeEdit((self.buid, self.form.name, edits), nodecache={self.buid: self})
|
|
336
335
|
return True
|
|
337
336
|
|
|
338
337
|
def repr(self, name=None, defv=None):
|
|
@@ -524,7 +523,7 @@ class Node:
|
|
|
524
523
|
edits = await self._getTagDelEdits(tag, init=init)
|
|
525
524
|
if edits:
|
|
526
525
|
nodeedit = (self.buid, self.form.name, edits)
|
|
527
|
-
await self.snap.applyNodeEdit(nodeedit)
|
|
526
|
+
await self.snap.applyNodeEdit(nodeedit, nodecache={self.buid: self})
|
|
528
527
|
|
|
529
528
|
def _getTagPropDel(self, tag):
|
|
530
529
|
|
|
@@ -585,7 +584,7 @@ class Node:
|
|
|
585
584
|
(s_layer.EDIT_TAGPROP_DEL, (tag, name, None, prop.type.stortype), ()),
|
|
586
585
|
)
|
|
587
586
|
|
|
588
|
-
await self.snap.applyNodeEdit((self.buid, self.form.name, edits))
|
|
587
|
+
await self.snap.applyNodeEdit((self.buid, self.form.name, edits), nodecache={self.buid: self})
|
|
589
588
|
|
|
590
589
|
async def delete(self, force=False):
|
|
591
590
|
'''
|
synapse/lib/rstorm.py
CHANGED
|
@@ -29,6 +29,7 @@ re_directive = regex.compile(r'^\.\.\s(storm.*|[^:])::(?:\s(.*)$|$)')
|
|
|
29
29
|
|
|
30
30
|
logger = logging.getLogger(__name__)
|
|
31
31
|
|
|
32
|
+
ONLOAD_TIMEOUT = int(os.getenv('SYNDEV_PKG_LOAD_TIMEOUT', 30)) # seconds
|
|
32
33
|
|
|
33
34
|
class OutPutRst(s_output.OutPutStr):
|
|
34
35
|
'''
|
|
@@ -413,8 +414,17 @@ class StormRst(s_base.Base):
|
|
|
413
414
|
core = self._reqCore()
|
|
414
415
|
|
|
415
416
|
pkg = s_genpkg.loadPkgProto(text)
|
|
417
|
+
|
|
418
|
+
if pkg.get('onload') is not None:
|
|
419
|
+
waiter = core.waiter(1, 'core:pkg:onload:complete')
|
|
420
|
+
else:
|
|
421
|
+
waiter = None
|
|
422
|
+
|
|
416
423
|
await core.addStormPkg(pkg)
|
|
417
424
|
|
|
425
|
+
if waiter is not None and not await waiter.wait(timeout=ONLOAD_TIMEOUT):
|
|
426
|
+
raise s_exc.SynErr(mesg=f'Package onload failed to run for {pkg.get("name")}')
|
|
427
|
+
|
|
418
428
|
async def _handleStormPre(self, text):
|
|
419
429
|
'''
|
|
420
430
|
Run a Storm query to prepare the Cortex without output.
|
|
@@ -453,6 +463,9 @@ class StormRst(s_base.Base):
|
|
|
453
463
|
|
|
454
464
|
svc = await self._getCell(ctor, conf=svcconf)
|
|
455
465
|
|
|
466
|
+
onloadcnt = len([p for p in svc.cellapi._storm_svc_pkgs if p.get('onload') is not None])
|
|
467
|
+
waiter = core.waiter(onloadcnt, 'core:pkg:onload:complete') if onloadcnt else None
|
|
468
|
+
|
|
456
469
|
svc.dmon.share('svc', svc)
|
|
457
470
|
root = await svc.auth.getUserByName('root')
|
|
458
471
|
await root.setPasswd('root')
|
|
@@ -463,6 +476,9 @@ class StormRst(s_base.Base):
|
|
|
463
476
|
await core.nodes(f'service.add {svcname} {surl}')
|
|
464
477
|
await core.nodes(f'$lib.service.wait({svcname})')
|
|
465
478
|
|
|
479
|
+
if waiter is not None and not await waiter.wait(timeout=ONLOAD_TIMEOUT):
|
|
480
|
+
raise s_exc.SynErr(mesg=f'Package onload failed to run for service {svcname}')
|
|
481
|
+
|
|
466
482
|
async def _handleStormFail(self, text):
|
|
467
483
|
valu = json.loads(text)
|
|
468
484
|
assert valu in (True, False), f'storm-fail must be a boolean: {text}'
|
synapse/lib/schemas.py
CHANGED
|
@@ -118,7 +118,7 @@ _CronJobSchema = {
|
|
|
118
118
|
},
|
|
119
119
|
'additionalProperties': False,
|
|
120
120
|
'required': ['creator', 'storm'],
|
|
121
|
-
'
|
|
121
|
+
'dependencies': {
|
|
122
122
|
'incvals': ['incunit'],
|
|
123
123
|
'incunit': ['incvals'],
|
|
124
124
|
},
|
|
@@ -169,6 +169,7 @@ reqValidView = s_config.getJsValidator({
|
|
|
169
169
|
'name': {'type': 'string'},
|
|
170
170
|
'parent': {'type': ['string', 'null'], 'pattern': s_config.re_iden},
|
|
171
171
|
'creator': {'type': 'string', 'pattern': s_config.re_iden},
|
|
172
|
+
'created': {'type': 'integer', 'minimum': 0},
|
|
172
173
|
'nomerge': {'type': 'boolean'},
|
|
173
174
|
'merging': {'type': 'boolean'},
|
|
174
175
|
'layers': {
|
synapse/lib/snap.py
CHANGED
|
@@ -1085,7 +1085,8 @@ class Snap(s_base.Base):
|
|
|
1085
1085
|
|
|
1086
1086
|
nodeedits = editor.getNodeEdits()
|
|
1087
1087
|
if nodeedits:
|
|
1088
|
-
|
|
1088
|
+
nodecache = {proto.buid: proto.node for proto in editor.protonodes.values()}
|
|
1089
|
+
await self.applyNodeEdits(nodeedits, nodecache=nodecache)
|
|
1089
1090
|
|
|
1090
1091
|
@contextlib.asynccontextmanager
|
|
1091
1092
|
async def getEditor(self):
|
|
@@ -1096,18 +1097,20 @@ class Snap(s_base.Base):
|
|
|
1096
1097
|
|
|
1097
1098
|
nodeedits = editor.getNodeEdits()
|
|
1098
1099
|
if nodeedits:
|
|
1099
|
-
|
|
1100
|
+
nodecache = {proto.buid: proto.node for proto in editor.protonodes.values()}
|
|
1101
|
+
await self.applyNodeEdits(nodeedits, nodecache=nodecache)
|
|
1100
1102
|
|
|
1101
|
-
async def applyNodeEdit(self, edit):
|
|
1102
|
-
nodes = await self.applyNodeEdits((edit,))
|
|
1103
|
-
|
|
1103
|
+
async def applyNodeEdit(self, edit, nodecache=None):
|
|
1104
|
+
nodes = await self.applyNodeEdits((edit,), nodecache=nodecache)
|
|
1105
|
+
if nodes:
|
|
1106
|
+
return nodes[0]
|
|
1104
1107
|
|
|
1105
|
-
async def applyNodeEdits(self, edits):
|
|
1108
|
+
async def applyNodeEdits(self, edits, nodecache=None):
|
|
1106
1109
|
'''
|
|
1107
1110
|
Sends edits to the write layer and evaluates the consequences (triggers, node object updates)
|
|
1108
1111
|
'''
|
|
1109
1112
|
meta = await self.getSnapMeta()
|
|
1110
|
-
saveoff, changes, nodes = await self._applyNodeEdits(edits, meta)
|
|
1113
|
+
saveoff, changes, nodes = await self._applyNodeEdits(edits, meta, nodecache=nodecache)
|
|
1111
1114
|
return nodes
|
|
1112
1115
|
|
|
1113
1116
|
async def saveNodeEdits(self, edits, meta):
|
|
@@ -1124,7 +1127,7 @@ class Snap(s_base.Base):
|
|
|
1124
1127
|
|
|
1125
1128
|
return saveoff, changes
|
|
1126
1129
|
|
|
1127
|
-
async def _applyNodeEdits(self, edits, meta):
|
|
1130
|
+
async def _applyNodeEdits(self, edits, meta, nodecache=None):
|
|
1128
1131
|
|
|
1129
1132
|
if self.readonly:
|
|
1130
1133
|
mesg = 'The snapshot is in read-only mode.'
|
|
@@ -1145,11 +1148,17 @@ class Snap(s_base.Base):
|
|
|
1145
1148
|
|
|
1146
1149
|
cache = {wlyr.iden: sode}
|
|
1147
1150
|
|
|
1148
|
-
node =
|
|
1151
|
+
node = None
|
|
1152
|
+
if nodecache is not None:
|
|
1153
|
+
node = nodecache.get(buid)
|
|
1149
1154
|
|
|
1150
1155
|
if node is None:
|
|
1151
|
-
|
|
1152
|
-
|
|
1156
|
+
node = await self._joinStorNode(buid, cache)
|
|
1157
|
+
if node is None:
|
|
1158
|
+
# We got part of a node but no ndef
|
|
1159
|
+
continue
|
|
1160
|
+
else:
|
|
1161
|
+
await asyncio.sleep(0)
|
|
1153
1162
|
|
|
1154
1163
|
nodes.append(node)
|
|
1155
1164
|
|
synapse/lib/storm.py
CHANGED
|
@@ -181,7 +181,7 @@ wgetdescr = '''Retrieve bytes from a URL and store them in the axon. Yields inet
|
|
|
181
181
|
Examples:
|
|
182
182
|
|
|
183
183
|
# Specify custom headers and parameters
|
|
184
|
-
inet:url=https://vertex.link/foo.bar.txt | wget --headers
|
|
184
|
+
inet:url=https://vertex.link/foo.bar.txt | wget --headers ({"User-Agent": "Foo/Bar"}) --params ({"clientid": "42"})
|
|
185
185
|
|
|
186
186
|
# Download multiple URL targets without inbound nodes
|
|
187
187
|
wget https://vertex.link https://vtx.lk
|
|
@@ -2207,9 +2207,9 @@ class Runtime(s_base.Base):
|
|
|
2207
2207
|
|
|
2208
2208
|
self.user.raisePermDeny(prop.delperms[-1], gateiden=layriden)
|
|
2209
2209
|
|
|
2210
|
-
def confirmEasyPerm(self, item, perm):
|
|
2210
|
+
def confirmEasyPerm(self, item, perm, mesg=None):
|
|
2211
2211
|
if not self.asroot:
|
|
2212
|
-
self.snap.core._reqEasyPerm(item, self.user, perm)
|
|
2212
|
+
self.snap.core._reqEasyPerm(item, self.user, perm, mesg=mesg)
|
|
2213
2213
|
|
|
2214
2214
|
def allowedEasyPerm(self, item, perm):
|
|
2215
2215
|
if self.asroot:
|
|
@@ -3787,7 +3787,23 @@ class MergeCmd(Cmd):
|
|
|
3787
3787
|
runt.confirmPropDel(prop, layriden=layr0)
|
|
3788
3788
|
runt.confirmPropSet(prop, layriden=layr1)
|
|
3789
3789
|
|
|
3790
|
+
tags = []
|
|
3791
|
+
tagadds = []
|
|
3790
3792
|
for tag, valu in sode.get('tags', {}).items():
|
|
3793
|
+
if valu != (None, None):
|
|
3794
|
+
tagadds.append(tag)
|
|
3795
|
+
tagperm = tuple(tag.split('.'))
|
|
3796
|
+
runt.confirm(('node', 'tag', 'del') + tagperm, gateiden=layr0)
|
|
3797
|
+
runt.confirm(('node', 'tag', 'add') + tagperm, gateiden=layr1)
|
|
3798
|
+
else:
|
|
3799
|
+
tags.append((len(tag), tag))
|
|
3800
|
+
|
|
3801
|
+
for _, tag in sorted(tags, reverse=True):
|
|
3802
|
+
look = tag + '.'
|
|
3803
|
+
if any([tagadd.startswith(look) for tagadd in tagadds]):
|
|
3804
|
+
continue
|
|
3805
|
+
|
|
3806
|
+
tagadds.append(tag)
|
|
3791
3807
|
tagperm = tuple(tag.split('.'))
|
|
3792
3808
|
runt.confirm(('node', 'tag', 'del') + tagperm, gateiden=layr0)
|
|
3793
3809
|
runt.confirm(('node', 'tag', 'add') + tagperm, gateiden=layr1)
|
synapse/lib/stormhttp.py
CHANGED
|
@@ -328,11 +328,23 @@ class LibHttp(s_stormtypes.Lib):
|
|
|
328
328
|
connector = aiohttp_socks.ProxyConnector.from_url(proxy)
|
|
329
329
|
|
|
330
330
|
timeout = aiohttp.ClientTimeout(total=timeout)
|
|
331
|
+
kwargs = {'timeout': timeout}
|
|
332
|
+
if params:
|
|
333
|
+
kwargs['params'] = params
|
|
334
|
+
|
|
335
|
+
cadir = self.runt.snap.core.conf.get('tls:ca:dir')
|
|
336
|
+
|
|
337
|
+
if ssl_verify is False:
|
|
338
|
+
kwargs['ssl'] = False
|
|
339
|
+
elif cadir:
|
|
340
|
+
kwargs['ssl'] = s_common.getSslCtx(cadir)
|
|
341
|
+
else:
|
|
342
|
+
# default aiohttp behavior
|
|
343
|
+
kwargs['ssl'] = None
|
|
331
344
|
|
|
332
345
|
try:
|
|
333
346
|
sess = await sock.enter_context(aiohttp.ClientSession(connector=connector, timeout=timeout))
|
|
334
|
-
sock.resp = await sock.enter_context(sess.ws_connect(url, headers=headers,
|
|
335
|
-
params=params, ))
|
|
347
|
+
sock.resp = await sock.enter_context(sess.ws_connect(url, headers=headers, **kwargs))
|
|
336
348
|
|
|
337
349
|
sock._syn_refs = 0
|
|
338
350
|
self.runt.onfini(sock)
|
synapse/lib/stormlib/easyperm.py
CHANGED
|
@@ -47,6 +47,8 @@ class LibEasyPerm(s_stormtypes.Lib):
|
|
|
47
47
|
'args': (
|
|
48
48
|
{'name': 'edef', 'type': 'dict', 'desc': 'The easy perm dictionary to check.'},
|
|
49
49
|
{'name': 'level', 'type': 'str', 'desc': 'The required permission level number.'},
|
|
50
|
+
{'name': 'mesg', 'type': 'str', 'default': None,
|
|
51
|
+
'desc': 'Optional error message to present if user does not have required permission level.'},
|
|
50
52
|
),
|
|
51
53
|
'returns': {'type': 'null'}}},
|
|
52
54
|
)
|
|
@@ -102,11 +104,12 @@ class LibEasyPerm(s_stormtypes.Lib):
|
|
|
102
104
|
|
|
103
105
|
return self.runt.snap.core._hasEasyPerm(edef, self.runt.user, level)
|
|
104
106
|
|
|
105
|
-
async def _confirmEasyPerm(self, edef, level):
|
|
107
|
+
async def _confirmEasyPerm(self, edef, level, mesg=None):
|
|
106
108
|
edef = await s_stormtypes.toprim(edef)
|
|
107
109
|
level = await s_stormtypes.toint(level)
|
|
110
|
+
mesg = await s_stormtypes.tostr(mesg, noneok=True)
|
|
108
111
|
|
|
109
112
|
if not isinstance(edef, dict):
|
|
110
113
|
raise s_exc.BadArg(mesg='Object to check easy perms on must be a dictionary.')
|
|
111
114
|
|
|
112
|
-
self.runt.snap.core._reqEasyPerm(edef, self.runt.user, level)
|
|
115
|
+
self.runt.snap.core._reqEasyPerm(edef, self.runt.user, level, mesg=mesg)
|