synapse 2.197.0__py311-none-any.whl → 2.199.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 +3 -0
- synapse/common.py +3 -0
- synapse/cortex.py +1 -3
- synapse/lib/aha.py +3 -0
- synapse/lib/ast.py +277 -165
- synapse/lib/auth.py +39 -11
- synapse/lib/cell.py +22 -4
- synapse/lib/hive.py +2 -1
- synapse/lib/hiveauth.py +10 -1
- synapse/lib/jsonstor.py +6 -5
- synapse/lib/layer.py +6 -5
- synapse/lib/node.py +10 -4
- synapse/lib/parser.py +46 -21
- synapse/lib/schemas.py +13 -0
- synapse/lib/snap.py +112 -36
- synapse/lib/storm.lark +13 -11
- synapse/lib/storm.py +11 -10
- synapse/lib/storm_format.py +3 -2
- synapse/lib/stormtypes.py +13 -4
- synapse/lib/version.py +2 -2
- synapse/lib/view.py +2 -1
- synapse/models/infotech.py +18 -0
- synapse/models/risk.py +9 -0
- synapse/models/syn.py +18 -2
- synapse/tests/files/stormpkg/badendpoints.yaml +7 -0
- synapse/tests/files/stormpkg/testpkg.yaml +8 -0
- synapse/tests/test_cortex.py +108 -0
- synapse/tests/test_datamodel.py +27 -5
- synapse/tests/test_lib_aha.py +22 -12
- synapse/tests/test_lib_ast.py +57 -0
- synapse/tests/test_lib_auth.py +143 -2
- synapse/tests/test_lib_grammar.py +54 -2
- synapse/tests/test_lib_lmdbslab.py +24 -0
- synapse/tests/test_lib_storm.py +24 -0
- synapse/tests/test_lib_stormlib_macro.py +3 -3
- synapse/tests/test_lib_stormtypes.py +14 -2
- synapse/tests/test_model_infotech.py +13 -0
- synapse/tests/test_model_risk.py +6 -0
- synapse/tests/test_model_syn.py +58 -0
- synapse/tests/test_tools_genpkg.py +10 -0
- synapse/tests/utils.py +17 -0
- synapse/tools/hive/load.py +1 -0
- {synapse-2.197.0.dist-info → synapse-2.199.0.dist-info}/METADATA +1 -1
- {synapse-2.197.0.dist-info → synapse-2.199.0.dist-info}/RECORD +47 -46
- {synapse-2.197.0.dist-info → synapse-2.199.0.dist-info}/LICENSE +0 -0
- {synapse-2.197.0.dist-info → synapse-2.199.0.dist-info}/WHEEL +0 -0
- {synapse-2.197.0.dist-info → synapse-2.199.0.dist-info}/top_level.txt +0 -0
synapse/lib/snap.py
CHANGED
|
@@ -138,10 +138,30 @@ class ProtoNode:
|
|
|
138
138
|
|
|
139
139
|
if not await self.ctx.snap.hasNodeEdge(self.buid, verb, s_common.uhex(n2iden)):
|
|
140
140
|
self.edges.add(tupl)
|
|
141
|
+
if len(self.edges) >= 1000:
|
|
142
|
+
await self.flushEdits()
|
|
141
143
|
return True
|
|
142
144
|
|
|
143
145
|
return False
|
|
144
146
|
|
|
147
|
+
async def flushEdits(self):
|
|
148
|
+
if (nodeedit := self.getNodeEdit()) is not None:
|
|
149
|
+
nodecache = {self.buid: self.node}
|
|
150
|
+
nodes = await self.ctx.snap.applyNodeEdits((nodeedit,), nodecache=nodecache, meta=self.ctx.meta)
|
|
151
|
+
|
|
152
|
+
if self.node is None:
|
|
153
|
+
if nodes and nodes[0].buid == self.buid:
|
|
154
|
+
self.node = nodes[0]
|
|
155
|
+
else: # pragma: no cover
|
|
156
|
+
self.node = await self.ctx.snap.getNodeByBuid(self.buid)
|
|
157
|
+
|
|
158
|
+
self.tags.clear()
|
|
159
|
+
self.props.clear()
|
|
160
|
+
self.tagprops.clear()
|
|
161
|
+
self.edges.clear()
|
|
162
|
+
self.edgedels.clear()
|
|
163
|
+
self.nodedata.clear()
|
|
164
|
+
|
|
145
165
|
async def delEdge(self, verb, n2iden):
|
|
146
166
|
|
|
147
167
|
if not isinstance(verb, str):
|
|
@@ -169,6 +189,8 @@ class ProtoNode:
|
|
|
169
189
|
|
|
170
190
|
if await self.ctx.snap.layers[-1].hasNodeEdge(self.buid, verb, s_common.uhex(n2iden)):
|
|
171
191
|
self.edgedels.add(tupl)
|
|
192
|
+
if len(self.edgedels) >= 1000:
|
|
193
|
+
await self.flushEdits()
|
|
172
194
|
return True
|
|
173
195
|
|
|
174
196
|
return False
|
|
@@ -417,6 +439,9 @@ class ProtoNode:
|
|
|
417
439
|
full = f'{prop.name}:{subname}'
|
|
418
440
|
subprop = self.form.props.get(full)
|
|
419
441
|
if subprop is not None and not subprop.locked:
|
|
442
|
+
if subprop.deprecated:
|
|
443
|
+
self.ctx.snap._skipPropDeprWarn(subprop.full)
|
|
444
|
+
|
|
420
445
|
await self.set(full, subvalu)
|
|
421
446
|
|
|
422
447
|
propadds = norminfo.get('adds')
|
|
@@ -426,11 +451,14 @@ class ProtoNode:
|
|
|
426
451
|
|
|
427
452
|
return True
|
|
428
453
|
|
|
429
|
-
async def
|
|
454
|
+
async def getSetSubOps(self, name, valu, norminfo=None):
|
|
430
455
|
prop = self.form.props.get(name)
|
|
431
|
-
if prop is None:
|
|
456
|
+
if prop is None or prop.locked:
|
|
432
457
|
return ()
|
|
433
458
|
|
|
459
|
+
if prop.deprecated:
|
|
460
|
+
self.ctx.snap._skipPropDeprWarn(prop.full)
|
|
461
|
+
|
|
434
462
|
retn = await self._set(prop, valu, norminfo=norminfo)
|
|
435
463
|
if retn is False:
|
|
436
464
|
return ()
|
|
@@ -447,9 +475,7 @@ class ProtoNode:
|
|
|
447
475
|
if propsubs is not None:
|
|
448
476
|
for subname, subvalu in propsubs.items():
|
|
449
477
|
full = f'{prop.name}:{subname}'
|
|
450
|
-
|
|
451
|
-
if subprop is not None and not subprop.locked:
|
|
452
|
-
ops.append(self.getSetOps(full, subvalu))
|
|
478
|
+
ops.append(self.getSetSubOps(full, subvalu))
|
|
453
479
|
|
|
454
480
|
propadds = norminfo.get('adds')
|
|
455
481
|
if propadds is not None:
|
|
@@ -462,7 +488,8 @@ class SnapEditor:
|
|
|
462
488
|
'''
|
|
463
489
|
A SnapEditor allows tracking node edits with subs/deps as a transaction.
|
|
464
490
|
'''
|
|
465
|
-
def __init__(self, snap):
|
|
491
|
+
def __init__(self, snap, meta=None):
|
|
492
|
+
self.meta = meta
|
|
466
493
|
self.snap = snap
|
|
467
494
|
self.protonodes = {}
|
|
468
495
|
self.maxnodes = snap.core.maxnodes
|
|
@@ -480,6 +507,19 @@ class SnapEditor:
|
|
|
480
507
|
nodeedits.append(nodeedit)
|
|
481
508
|
return nodeedits
|
|
482
509
|
|
|
510
|
+
async def flushEdits(self):
|
|
511
|
+
nodecache = {}
|
|
512
|
+
nodeedits = []
|
|
513
|
+
for protonode in self.protonodes.values():
|
|
514
|
+
if (nodeedit := protonode.getNodeEdit()) is not None:
|
|
515
|
+
nodeedits.append(nodeedit)
|
|
516
|
+
nodecache[protonode.buid] = protonode.node
|
|
517
|
+
|
|
518
|
+
if nodeedits:
|
|
519
|
+
await self.snap.applyNodeEdits(nodeedits, nodecache=nodecache, meta=self.meta)
|
|
520
|
+
|
|
521
|
+
self.protonodes.clear()
|
|
522
|
+
|
|
483
523
|
async def _addNode(self, form, valu, props=None, norminfo=None):
|
|
484
524
|
|
|
485
525
|
self.snap.core._checkMaxNodes()
|
|
@@ -556,7 +596,7 @@ class SnapEditor:
|
|
|
556
596
|
subs = norminfo.get('subs')
|
|
557
597
|
if subs is not None:
|
|
558
598
|
for prop, valu in subs.items():
|
|
559
|
-
ops.append(protonode.
|
|
599
|
+
ops.append(protonode.getSetSubOps(prop, valu))
|
|
560
600
|
|
|
561
601
|
adds = norminfo.get('adds')
|
|
562
602
|
if adds is not None:
|
|
@@ -592,7 +632,7 @@ class SnapEditor:
|
|
|
592
632
|
subs = norminfo.get('subs')
|
|
593
633
|
if subs is not None:
|
|
594
634
|
for prop, valu in subs.items():
|
|
595
|
-
ops.append(protonode.
|
|
635
|
+
ops.append(protonode.getSetSubOps(prop, valu))
|
|
596
636
|
|
|
597
637
|
while ops:
|
|
598
638
|
oset = ops.popleft()
|
|
@@ -849,6 +889,10 @@ class Snap(s_base.Base):
|
|
|
849
889
|
self._warnonce_keys.add(mesg)
|
|
850
890
|
await self.warn(mesg, log, **info)
|
|
851
891
|
|
|
892
|
+
def _skipPropDeprWarn(self, name):
|
|
893
|
+
mesg = f'The property {name} is deprecated or using a deprecated type and will be removed in 3.0.0'
|
|
894
|
+
self._warnonce_keys.add(mesg)
|
|
895
|
+
|
|
852
896
|
async def getNodeByBuid(self, buid):
|
|
853
897
|
'''
|
|
854
898
|
Retrieve a node tuple by binary id.
|
|
@@ -1062,6 +1106,23 @@ class Snap(s_base.Base):
|
|
|
1062
1106
|
mesg = f'No property named "{full}".'
|
|
1063
1107
|
raise s_exc.NoSuchProp(mesg=mesg)
|
|
1064
1108
|
|
|
1109
|
+
if isinstance(valu, dict) and isinstance(prop.type, s_types.Guid) and cmpr == '=':
|
|
1110
|
+
if prop.isform:
|
|
1111
|
+
if (node := await self._getGuidNodeByDict(prop, valu)) is not None:
|
|
1112
|
+
yield node
|
|
1113
|
+
return
|
|
1114
|
+
|
|
1115
|
+
fname = prop.type.name
|
|
1116
|
+
if (form := prop.modl.form(fname)) is None:
|
|
1117
|
+
mesg = f'The property "{full}" type "{fname}" is not a form and cannot be lifted using a dictionary.'
|
|
1118
|
+
raise s_exc.BadTypeValu(mesg=mesg)
|
|
1119
|
+
|
|
1120
|
+
if (node := await self._getGuidNodeByDict(form, valu)) is None:
|
|
1121
|
+
return
|
|
1122
|
+
|
|
1123
|
+
norm = False
|
|
1124
|
+
valu = node.ndef[1]
|
|
1125
|
+
|
|
1065
1126
|
if norm:
|
|
1066
1127
|
cmprvals = prop.type.getStorCmprs(cmpr, valu)
|
|
1067
1128
|
# an empty return probably means ?= with invalid value
|
|
@@ -1189,11 +1250,13 @@ class Snap(s_base.Base):
|
|
|
1189
1250
|
if nodes:
|
|
1190
1251
|
return nodes[0]
|
|
1191
1252
|
|
|
1192
|
-
async def applyNodeEdits(self, edits, nodecache=None):
|
|
1253
|
+
async def applyNodeEdits(self, edits, nodecache=None, meta=None):
|
|
1193
1254
|
'''
|
|
1194
1255
|
Sends edits to the write layer and evaluates the consequences (triggers, node object updates)
|
|
1195
1256
|
'''
|
|
1196
|
-
meta
|
|
1257
|
+
if meta is None:
|
|
1258
|
+
meta = await self.getSnapMeta()
|
|
1259
|
+
|
|
1197
1260
|
saveoff, changes, nodes = await self._applyNodeEdits(edits, meta, nodecache=nodecache)
|
|
1198
1261
|
return nodes
|
|
1199
1262
|
|
|
@@ -1398,10 +1461,6 @@ class Snap(s_base.Base):
|
|
|
1398
1461
|
|
|
1399
1462
|
async def _addGuidNodeByDict(self, form, vals, props=None):
|
|
1400
1463
|
|
|
1401
|
-
norms = {}
|
|
1402
|
-
counts = []
|
|
1403
|
-
proplist = []
|
|
1404
|
-
|
|
1405
1464
|
if props is None:
|
|
1406
1465
|
props = {}
|
|
1407
1466
|
|
|
@@ -1439,7 +1498,32 @@ class Snap(s_base.Base):
|
|
|
1439
1498
|
raise e
|
|
1440
1499
|
await self.warn(f'Skipping bad value for prop {form.name}:{name}: {mesg}')
|
|
1441
1500
|
|
|
1442
|
-
|
|
1501
|
+
norms, proplist = self._normGuidNodeDict(form, vals)
|
|
1502
|
+
|
|
1503
|
+
iden = s_common.guid(proplist)
|
|
1504
|
+
node = await self._getGuidNodeByNorms(form, iden, norms)
|
|
1505
|
+
|
|
1506
|
+
async with self.getEditor() as editor:
|
|
1507
|
+
|
|
1508
|
+
if node is not None:
|
|
1509
|
+
proto = editor.loadNode(node)
|
|
1510
|
+
else:
|
|
1511
|
+
proto = await editor.addNode(form.name, iden)
|
|
1512
|
+
for name, (prop, valu, info) in norms.items():
|
|
1513
|
+
await proto.set(name, valu, norminfo=info)
|
|
1514
|
+
|
|
1515
|
+
# ensure the non-deconf props are set
|
|
1516
|
+
for name, (valu, info) in props.items():
|
|
1517
|
+
await proto.set(name, valu, norminfo=info)
|
|
1518
|
+
|
|
1519
|
+
return await self.getNodeByBuid(proto.buid)
|
|
1520
|
+
|
|
1521
|
+
def _normGuidNodeDict(self, form, props):
|
|
1522
|
+
|
|
1523
|
+
norms = {}
|
|
1524
|
+
proplist = []
|
|
1525
|
+
|
|
1526
|
+
for name, valu in props.items():
|
|
1443
1527
|
|
|
1444
1528
|
try:
|
|
1445
1529
|
prop = form.reqProp(name)
|
|
@@ -1458,22 +1542,24 @@ class Snap(s_base.Base):
|
|
|
1458
1542
|
|
|
1459
1543
|
proplist.sort()
|
|
1460
1544
|
|
|
1545
|
+
return norms, proplist
|
|
1546
|
+
|
|
1547
|
+
async def _getGuidNodeByDict(self, form, props):
|
|
1548
|
+
norms, proplist = self._normGuidNodeDict(form, props)
|
|
1549
|
+
return await self._getGuidNodeByNorms(form, s_common.guid(proplist), norms)
|
|
1550
|
+
|
|
1551
|
+
async def _getGuidNodeByNorms(self, form, iden, norms):
|
|
1552
|
+
|
|
1461
1553
|
# check first for an exact match via our same deconf strategy
|
|
1462
|
-
iden = s_common.guid(proplist)
|
|
1463
1554
|
|
|
1464
1555
|
node = await self.getNodeByNdef((form.full, iden))
|
|
1465
1556
|
if node is not None:
|
|
1466
1557
|
|
|
1467
1558
|
# ensure we still match the property deconf criteria
|
|
1468
|
-
for
|
|
1559
|
+
for (prop, norm, info) in norms.values():
|
|
1469
1560
|
if not self._filtByPropAlts(node, prop, norm):
|
|
1470
1561
|
break
|
|
1471
1562
|
else:
|
|
1472
|
-
# ensure the non-deconf props are set
|
|
1473
|
-
async with self.getEditor() as editor:
|
|
1474
|
-
proto = editor.loadNode(node)
|
|
1475
|
-
for name, (valu, info) in props.items():
|
|
1476
|
-
await proto.set(name, valu, norminfo=info)
|
|
1477
1563
|
return node
|
|
1478
1564
|
|
|
1479
1565
|
# TODO there is an opportunity here to populate
|
|
@@ -1482,8 +1568,10 @@ class Snap(s_base.Base):
|
|
|
1482
1568
|
# if we lookup a node and it no longer passes the
|
|
1483
1569
|
# filter...
|
|
1484
1570
|
|
|
1571
|
+
counts = []
|
|
1572
|
+
|
|
1485
1573
|
# no exact match. lets do some counting.
|
|
1486
|
-
for
|
|
1574
|
+
for (prop, norm, info) in norms.values():
|
|
1487
1575
|
count = await self._getPropAltCount(prop, norm)
|
|
1488
1576
|
counts.append((count, prop, norm))
|
|
1489
1577
|
|
|
@@ -1499,21 +1587,9 @@ class Snap(s_base.Base):
|
|
|
1499
1587
|
if not self._filtByPropAlts(node, prop, norm):
|
|
1500
1588
|
break
|
|
1501
1589
|
else:
|
|
1502
|
-
# ensure the non-deconf props are set
|
|
1503
|
-
async with self.getEditor() as editor:
|
|
1504
|
-
proto = editor.loadNode(node)
|
|
1505
|
-
for name, (valu, info) in props.items():
|
|
1506
|
-
await proto.set(name, valu, norminfo=info)
|
|
1507
1590
|
return node
|
|
1508
1591
|
|
|
1509
|
-
|
|
1510
|
-
proto = await editor.addNode(form.name, iden)
|
|
1511
|
-
for name, (prop, valu, info) in norms.items():
|
|
1512
|
-
await proto.set(name, valu, norminfo=info)
|
|
1513
|
-
for name, (valu, info) in props.items():
|
|
1514
|
-
await proto.set(name, valu, norminfo=info)
|
|
1515
|
-
|
|
1516
|
-
return await self.getNodeByBuid(proto.buid)
|
|
1592
|
+
return None
|
|
1517
1593
|
|
|
1518
1594
|
async def _getPropAltCount(self, prop, valu):
|
|
1519
1595
|
count = 0
|
synapse/lib/storm.lark
CHANGED
|
@@ -40,7 +40,7 @@ _editblock: "[" _editoper* "]"
|
|
|
40
40
|
// A single edit operation
|
|
41
41
|
_editoper: editnodeadd
|
|
42
42
|
| editpropset | editunivset | edittagpropset | edittagadd | editcondpropset
|
|
43
|
-
| editpropdel | editunivdel | edittagpropdel | edittagdel
|
|
43
|
+
| editpropsetmulti | editpropdel | editunivdel | edittagpropdel | edittagdel
|
|
44
44
|
| editparens | edgeaddn1 | edgedeln1 | edgeaddn2 | edgedeln2
|
|
45
45
|
|
|
46
46
|
// Parenthesis in an edit block don't have incoming nodes
|
|
@@ -48,18 +48,20 @@ editparens: "(" editnodeadd _editoper* ")"
|
|
|
48
48
|
edittagadd: "+" [SETTAGOPER] tagname [(EQSPACE | EQNOSPACE) _valu]
|
|
49
49
|
editunivdel: EXPRMINUS univprop
|
|
50
50
|
edittagdel: EXPRMINUS tagname
|
|
51
|
-
editpropset: relprop (EQSPACE | EQNOSPACE | MODSET | TRYSET |
|
|
51
|
+
editpropset: relprop (EQSPACE | EQNOSPACE | MODSET | TRYSET | TRYMODSET) _valu
|
|
52
52
|
editcondpropset: relprop condsetoper _valu
|
|
53
|
+
editpropsetmulti: relprop (MODSETMULTI | TRYMODSETMULTI) _valu
|
|
53
54
|
editpropdel: EXPRMINUS relprop
|
|
54
|
-
editunivset: univprop (EQSPACE | EQNOSPACE | MODSET | TRYSET |
|
|
55
|
-
editnodeadd: formname (EQSPACE | EQNOSPACE | MODSET | TRYSET |
|
|
56
|
-
edittagpropset: "+" tagprop (EQSPACE | EQNOSPACE | MODSET | TRYSET |
|
|
55
|
+
editunivset: univprop (EQSPACE | EQNOSPACE | MODSET | TRYSET | TRYMODSET) _valu
|
|
56
|
+
editnodeadd: formname (EQSPACE | EQNOSPACE | MODSET | TRYSET | TRYMODSET) _valu
|
|
57
|
+
edittagpropset: "+" tagprop (EQSPACE | EQNOSPACE | MODSET | TRYSET | TRYMODSET) _valu
|
|
57
58
|
edittagpropdel: EXPRMINUS tagprop
|
|
58
59
|
|
|
59
60
|
EQSPACE: /((?<=\s)=|=(?=\s))/
|
|
60
61
|
MODSET.4: "+=" | "-="
|
|
61
|
-
|
|
62
|
-
|
|
62
|
+
TRYMODSET.1: "?+=" | "?-="
|
|
63
|
+
MODSETMULTI.4: "++=" | "--="
|
|
64
|
+
TRYMODSETMULTI.1: "?++=" | "?--="
|
|
63
65
|
TRYSET.1: "?="
|
|
64
66
|
SETTAGOPER: "?"
|
|
65
67
|
|
|
@@ -226,10 +228,10 @@ _EDGEN2JOININIT: "<+("
|
|
|
226
228
|
// comparisons to an expression like '<(2)'
|
|
227
229
|
_EDGEN2INIT: /\<\((?=(?>(?<EDGEN2INITRECUR>\(((?>[^()"'`]+|(?&EDGEN2INITRECUR)|`(?:[^`\\]|\\.)*`|"(?:[^"\\]|\\.)*"|'''.*?'''|'[^']*'(?!'))*)\))|'''.*?'''|`(?:[^`\\]|\\.)*`|"(?:[^"\\]|\\.)*"|'[^']*'(?!')|[^)])*\)[\-\+])/
|
|
228
230
|
|
|
229
|
-
edgeaddn1: _EDGEADDN1INIT _valu _EDGEN1FINI baresubquery
|
|
230
|
-
edgedeln1: _EDGEN1INIT _valu _EDGEN1FINI baresubquery
|
|
231
|
-
edgeaddn2: _EDGEN2INIT _valu _EDGEADDN2FINI baresubquery
|
|
232
|
-
edgedeln2: _EDGEN2INIT _valu _EDGEN2FINI baresubquery
|
|
231
|
+
edgeaddn1: _EDGEADDN1INIT _valu _EDGEN1FINI (baresubquery | _varvalu)
|
|
232
|
+
edgedeln1: _EDGEN1INIT _valu _EDGEN1FINI (baresubquery | _varvalu)
|
|
233
|
+
edgeaddn2: _EDGEN2INIT _valu _EDGEADDN2FINI (baresubquery | _varvalu)
|
|
234
|
+
edgedeln2: _EDGEN2INIT _valu _EDGEN2FINI (baresubquery | _varvalu)
|
|
233
235
|
|
|
234
236
|
_REVERSE: /reverse(?=[\s\(])/
|
|
235
237
|
liftreverse: _REVERSE "(" (liftformtag | liftpropby | liftprop | liftbyarray | lifttagtag | liftbytag | liftbytagprop | liftbyformtagprop) ")"
|
synapse/lib/storm.py
CHANGED
|
@@ -1299,7 +1299,7 @@ stormcmds = (
|
|
|
1299
1299
|
|
|
1300
1300
|
@s_cache.memoize(size=1024)
|
|
1301
1301
|
def queryhash(text):
|
|
1302
|
-
return
|
|
1302
|
+
return s_common.queryhash(text)
|
|
1303
1303
|
|
|
1304
1304
|
class DmonManager(s_base.Base):
|
|
1305
1305
|
'''
|
|
@@ -3653,23 +3653,26 @@ class MergeCmd(Cmd):
|
|
|
3653
3653
|
|
|
3654
3654
|
genr = diffgenr()
|
|
3655
3655
|
|
|
3656
|
-
async with await runt.snap.view.parent.snap(user=runt.user
|
|
3656
|
+
async with await runt.snap.view.parent.snap(user=runt.user) as snap:
|
|
3657
3657
|
snap.strict = False
|
|
3658
3658
|
|
|
3659
3659
|
snap.on('warn', runt.snap.dist)
|
|
3660
3660
|
|
|
3661
|
+
meta = {'user': runt.user.iden}
|
|
3662
|
+
|
|
3663
|
+
if doapply:
|
|
3664
|
+
editor = s_snap.SnapEditor(snap, meta=meta)
|
|
3665
|
+
|
|
3661
3666
|
async for node, path in genr:
|
|
3662
3667
|
|
|
3663
3668
|
# the timestamp for the adds/subs of each node merge will match
|
|
3664
3669
|
nodeiden = node.iden()
|
|
3665
|
-
|
|
3670
|
+
|
|
3671
|
+
meta['time'] = s_common.now()
|
|
3666
3672
|
|
|
3667
3673
|
sodes = await node.getStorNodes()
|
|
3668
3674
|
sode = sodes[0]
|
|
3669
3675
|
|
|
3670
|
-
if doapply:
|
|
3671
|
-
editor = s_snap.SnapEditor(snap)
|
|
3672
|
-
|
|
3673
3676
|
subs = []
|
|
3674
3677
|
|
|
3675
3678
|
# check all node perms first
|
|
@@ -3818,13 +3821,11 @@ class MergeCmd(Cmd):
|
|
|
3818
3821
|
subs.append((s_layer.EDIT_NODE_DEL, valu, ()))
|
|
3819
3822
|
|
|
3820
3823
|
if doapply:
|
|
3821
|
-
|
|
3822
|
-
if addedits:
|
|
3823
|
-
await runt.snap.view.parent.storNodeEdits(addedits, meta=meta)
|
|
3824
|
+
await editor.flushEdits()
|
|
3824
3825
|
|
|
3825
3826
|
if subs:
|
|
3826
3827
|
subedits = [(node.buid, node.form.name, subs)]
|
|
3827
|
-
await runt.snap.
|
|
3828
|
+
await runt.snap.applyNodeEdits(subedits, nodecache={node.buid: node}, meta=meta)
|
|
3828
3829
|
|
|
3829
3830
|
runt.snap.clearCachedNode(node.buid)
|
|
3830
3831
|
yield await runt.snap.getNodeByBuid(node.buid), path
|
synapse/lib/storm_format.py
CHANGED
|
@@ -55,6 +55,7 @@ TerminalPygMap = {
|
|
|
55
55
|
'LSQB': p_t.Punctuation,
|
|
56
56
|
'MCASEBARE': p_t.Literal.String,
|
|
57
57
|
'MODSET': p_t.Operator,
|
|
58
|
+
'MODSETMULTI': p_t.Operator,
|
|
58
59
|
'NONQUOTEWORD': p_t.Literal,
|
|
59
60
|
'NOT': p_t.Keyword,
|
|
60
61
|
'NULL': p_t.Keyword,
|
|
@@ -74,8 +75,8 @@ TerminalPygMap = {
|
|
|
74
75
|
'TAGSEGNOVAR': p_t.Name,
|
|
75
76
|
'TRIPLEQUOTEDSTRING': p_t.Literal.String,
|
|
76
77
|
'TRYSET': p_t.Operator,
|
|
77
|
-
'
|
|
78
|
-
'
|
|
78
|
+
'TRYMODSET': p_t.Operator,
|
|
79
|
+
'TRYMODSETMULTI': p_t.Operator,
|
|
79
80
|
'UNIVNAME': p_t.Name,
|
|
80
81
|
'UNSET': p_t.Operator,
|
|
81
82
|
'EXPRUNIVNAME': p_t.Name,
|
synapse/lib/stormtypes.py
CHANGED
|
@@ -3490,7 +3490,11 @@ class LibRegx(Lib):
|
|
|
3490
3490
|
lkey = (pattern, flags)
|
|
3491
3491
|
regx = self.compiled.get(lkey)
|
|
3492
3492
|
if regx is None:
|
|
3493
|
-
|
|
3493
|
+
try:
|
|
3494
|
+
regx = self.compiled[lkey] = regex.compile(pattern, flags=flags)
|
|
3495
|
+
except (regex.error, ValueError) as e:
|
|
3496
|
+
mesg = f'Error compiling regex pattern: {e}: pattern="{s_common.trimText(pattern)}"'
|
|
3497
|
+
raise s_exc.BadArg(mesg=mesg) from None
|
|
3494
3498
|
return regx
|
|
3495
3499
|
|
|
3496
3500
|
@stormfunc(readonly=True)
|
|
@@ -3500,7 +3504,12 @@ class LibRegx(Lib):
|
|
|
3500
3504
|
pattern = await tostr(pattern)
|
|
3501
3505
|
replace = await tostr(replace)
|
|
3502
3506
|
regx = await self._getRegx(pattern, flags)
|
|
3503
|
-
|
|
3507
|
+
|
|
3508
|
+
try:
|
|
3509
|
+
return regx.sub(replace, text)
|
|
3510
|
+
except (regex.error, IndexError) as e:
|
|
3511
|
+
mesg = f'$lib.regex.replace() error: {e}'
|
|
3512
|
+
raise s_exc.BadArg(mesg=mesg) from None
|
|
3504
3513
|
|
|
3505
3514
|
@stormfunc(readonly=True)
|
|
3506
3515
|
async def matches(self, pattern, text, flags=0):
|
|
@@ -9868,7 +9877,7 @@ async def tostor(valu, isndef=False):
|
|
|
9868
9877
|
retn = []
|
|
9869
9878
|
for v in valu:
|
|
9870
9879
|
try:
|
|
9871
|
-
retn.append(await tostor(v))
|
|
9880
|
+
retn.append(await tostor(v, isndef=isndef))
|
|
9872
9881
|
except s_exc.NoSuchType:
|
|
9873
9882
|
pass
|
|
9874
9883
|
return tuple(retn)
|
|
@@ -9877,7 +9886,7 @@ async def tostor(valu, isndef=False):
|
|
|
9877
9886
|
retn = {}
|
|
9878
9887
|
for k, v in valu.items():
|
|
9879
9888
|
try:
|
|
9880
|
-
retn[k] = await tostor(v)
|
|
9889
|
+
retn[k] = await tostor(v, isndef=isndef)
|
|
9881
9890
|
except s_exc.NoSuchType:
|
|
9882
9891
|
pass
|
|
9883
9892
|
return retn
|
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, 199, 0)
|
|
227
227
|
verstring = '.'.join([str(x) for x in version])
|
|
228
|
-
commit = '
|
|
228
|
+
commit = 'c256bd46a9df8621fd05fd6a0f36ca476ad29942'
|
synapse/lib/view.py
CHANGED
|
@@ -1474,7 +1474,8 @@ class View(s_nexus.Pusher): # type: ignore
|
|
|
1474
1474
|
|
|
1475
1475
|
meta = await snap.getSnapMeta()
|
|
1476
1476
|
async for nodeedits in fromlayr.iterLayerNodeEdits():
|
|
1477
|
-
|
|
1477
|
+
meta['time'] = s_common.now()
|
|
1478
|
+
await snap.saveNodeEdits([nodeedits], meta)
|
|
1478
1479
|
|
|
1479
1480
|
async def swapLayer(self):
|
|
1480
1481
|
oldlayr = self.layers[0]
|
synapse/models/infotech.py
CHANGED
|
@@ -1252,6 +1252,15 @@ class ItModule(s_module.CoreModule):
|
|
|
1252
1252
|
('product', ('it:prod:softver', {}), {
|
|
1253
1253
|
'doc': 'The software which produced the log entry.'}),
|
|
1254
1254
|
|
|
1255
|
+
('service:platform', ('inet:service:platform', {}), {
|
|
1256
|
+
'doc': 'The service platform which generated the log event.'}),
|
|
1257
|
+
|
|
1258
|
+
('service:instance', ('inet:service:instance', {}), {
|
|
1259
|
+
'doc': 'The service instance which generated the log event.'}),
|
|
1260
|
+
|
|
1261
|
+
('service:account', ('inet:service:account', {}), {
|
|
1262
|
+
'doc': 'The service account which generated the log event.'}),
|
|
1263
|
+
|
|
1255
1264
|
)),
|
|
1256
1265
|
('it:domain', {}, (
|
|
1257
1266
|
('name', ('str', {'lower': True, 'onespace': True}), {
|
|
@@ -2587,6 +2596,15 @@ class ItModule(s_module.CoreModule):
|
|
|
2587
2596
|
|
|
2588
2597
|
('synuser', ('syn:user', {}), {
|
|
2589
2598
|
'doc': 'The synapse user who executed the query.'}),
|
|
2599
|
+
|
|
2600
|
+
('service:platform', ('inet:service:platform', {}), {
|
|
2601
|
+
'doc': 'The service platform which was queried.'}),
|
|
2602
|
+
|
|
2603
|
+
('service:instance', ('inet:service:instance', {}), {
|
|
2604
|
+
'doc': 'The service instance which was queried.'}),
|
|
2605
|
+
|
|
2606
|
+
('service:account', ('inet:service:account', {}), {
|
|
2607
|
+
'doc': 'The service account which ran the query.'}),
|
|
2590
2608
|
)),
|
|
2591
2609
|
('it:exec:thread', {}, (
|
|
2592
2610
|
('proc', ('it:exec:proc', {}), {
|
synapse/models/risk.py
CHANGED
|
@@ -810,6 +810,15 @@ class RiskModule(s_module.CoreModule):
|
|
|
810
810
|
|
|
811
811
|
('host', ('it:host', {}), {
|
|
812
812
|
'doc': 'The host which generated the alert.'}),
|
|
813
|
+
|
|
814
|
+
('service:platform', ('inet:service:platform', {}), {
|
|
815
|
+
'doc': 'The service platform which generated the alert.'}),
|
|
816
|
+
|
|
817
|
+
('service:instance', ('inet:service:instance', {}), {
|
|
818
|
+
'doc': 'The service instance which generated the alert.'}),
|
|
819
|
+
|
|
820
|
+
('service:account', ('inet:service:account', {}), {
|
|
821
|
+
'doc': 'The service account which generated the alert.'}),
|
|
813
822
|
)),
|
|
814
823
|
('risk:compromisetype', {}, ()),
|
|
815
824
|
('risk:compromise', {}, (
|
synapse/models/syn.py
CHANGED
|
@@ -23,7 +23,15 @@ class SynUser(s_types.Guid):
|
|
|
23
23
|
if user is not None:
|
|
24
24
|
return user.iden, {}
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
if text == '*':
|
|
27
|
+
mesg = f'{self.name} values must be a valid username or a guid.'
|
|
28
|
+
raise s_exc.BadTypeValu(mesg=mesg, name=self.name, valu=text)
|
|
29
|
+
|
|
30
|
+
try:
|
|
31
|
+
return s_types.Guid._normPyStr(self, text)
|
|
32
|
+
except s_exc.BadTypeValu:
|
|
33
|
+
mesg = f'No user named {text} and value is not a guid.'
|
|
34
|
+
raise s_exc.BadTypeValu(mesg=mesg, name=self.name, valu=text) from None
|
|
27
35
|
|
|
28
36
|
def repr(self, iden):
|
|
29
37
|
|
|
@@ -51,7 +59,15 @@ class SynRole(s_types.Guid):
|
|
|
51
59
|
if role is not None:
|
|
52
60
|
return role.iden, {}
|
|
53
61
|
|
|
54
|
-
|
|
62
|
+
if text == '*':
|
|
63
|
+
mesg = f'{self.name} values must be a valid rolename or a guid.'
|
|
64
|
+
raise s_exc.BadTypeValu(mesg=mesg, name=self.name, valu=text)
|
|
65
|
+
|
|
66
|
+
try:
|
|
67
|
+
return s_types.Guid._normPyStr(self, text)
|
|
68
|
+
except s_exc.BadTypeValu:
|
|
69
|
+
mesg = f'No role named {text} and value is not a guid.'
|
|
70
|
+
raise s_exc.BadTypeValu(mesg=mesg, name=self.name, valu=text) from None
|
|
55
71
|
|
|
56
72
|
def repr(self, iden):
|
|
57
73
|
|
|
@@ -113,6 +113,14 @@ commands:
|
|
|
113
113
|
- help: Help on foo opt
|
|
114
114
|
- - --bar
|
|
115
115
|
- help: Help on bar opt
|
|
116
|
+
storm: |
|
|
117
|
+
test:str
|
|
118
|
+
endpoints:
|
|
119
|
+
- path: /v1/test/one
|
|
120
|
+
- path: /v1/test/two
|
|
121
|
+
host: vertex.link
|
|
122
|
+
- path: /v1/test/three
|
|
123
|
+
desc: endpoint three
|
|
116
124
|
|
|
117
125
|
- name: testpkg.baz
|
|
118
126
|
descr: |
|