synapse 2.184.0__py311-none-any.whl → 2.185.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 +1 -1
- synapse/datamodel.py +41 -6
- synapse/lib/ast.py +82 -21
- synapse/lib/auth.py +13 -0
- synapse/lib/cell.py +13 -0
- synapse/lib/modules.py +1 -0
- synapse/lib/parser.py +1 -0
- synapse/lib/snap.py +1 -0
- synapse/lib/storm.lark +12 -6
- synapse/lib/storm.py +45 -9
- synapse/lib/storm_format.py +1 -0
- synapse/lib/stormlib/stix.py +14 -5
- synapse/lib/stormtypes.py +64 -36
- synapse/lib/version.py +2 -2
- synapse/models/doc.py +93 -0
- synapse/models/infotech.py +2 -1
- synapse/models/media.py +0 -1
- synapse/models/orgs.py +26 -3
- synapse/models/proj.py +56 -36
- synapse/models/syn.py +64 -6
- synapse/tests/test_cortex.py +39 -1
- synapse/tests/test_lib_cell.py +44 -1
- synapse/tests/test_lib_grammar.py +2 -0
- synapse/tests/test_lib_storm.py +54 -1
- synapse/tests/test_lib_stormlib_stix.py +3 -2
- synapse/tests/test_model_doc.py +51 -0
- synapse/tests/test_model_orgs.py +41 -0
- synapse/tests/test_model_syn.py +43 -0
- synapse/tests/test_tools_promote.py +67 -0
- synapse/tools/promote.py +14 -1
- {synapse-2.184.0.dist-info → synapse-2.185.0.dist-info}/METADATA +5 -10
- {synapse-2.184.0.dist-info → synapse-2.185.0.dist-info}/RECORD +35 -32
- {synapse-2.184.0.dist-info → synapse-2.185.0.dist-info}/LICENSE +0 -0
- {synapse-2.184.0.dist-info → synapse-2.185.0.dist-info}/WHEEL +0 -0
- {synapse-2.184.0.dist-info → synapse-2.185.0.dist-info}/top_level.txt +0 -0
synapse/cortex.py
CHANGED
|
@@ -946,7 +946,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
946
946
|
self._exthttpapicache = s_cache.FixedCache(self._getHttpExtApiByPath, size=1000)
|
|
947
947
|
self._initCortexExtHttpApi()
|
|
948
948
|
|
|
949
|
-
self.model = s_datamodel.Model()
|
|
949
|
+
self.model = s_datamodel.Model(core=self)
|
|
950
950
|
|
|
951
951
|
await self._bumpCellVers('cortex:extmodel', (
|
|
952
952
|
(1, self._migrateTaxonomyIface),
|
synapse/datamodel.py
CHANGED
|
@@ -482,8 +482,9 @@ class Model:
|
|
|
482
482
|
'''
|
|
483
483
|
The data model used by a Cortex hypergraph.
|
|
484
484
|
'''
|
|
485
|
-
def __init__(self):
|
|
485
|
+
def __init__(self, core=None):
|
|
486
486
|
|
|
487
|
+
self.core = core
|
|
487
488
|
self.types = {} # name: Type()
|
|
488
489
|
self.forms = {} # name: Form()
|
|
489
490
|
self.props = {} # (form,name): Prop() and full: Prop()
|
|
@@ -653,13 +654,16 @@ class Model:
|
|
|
653
654
|
self.formprefixcache[prefix] = forms
|
|
654
655
|
return forms
|
|
655
656
|
|
|
656
|
-
def reqProp(self, name):
|
|
657
|
+
def reqProp(self, name, extra=None):
|
|
657
658
|
prop = self.prop(name)
|
|
658
659
|
if prop is not None:
|
|
659
660
|
return prop
|
|
660
661
|
|
|
661
|
-
|
|
662
|
-
|
|
662
|
+
exc = s_exc.NoSuchProp.init(name)
|
|
663
|
+
if extra is not None:
|
|
664
|
+
exc = extra(exc)
|
|
665
|
+
|
|
666
|
+
raise exc
|
|
663
667
|
|
|
664
668
|
def reqUniv(self, name):
|
|
665
669
|
prop = self.univ(name)
|
|
@@ -1082,6 +1086,30 @@ class Model:
|
|
|
1082
1086
|
self.props[prop.full] = prop
|
|
1083
1087
|
return prop
|
|
1084
1088
|
|
|
1089
|
+
def _prepFormIface(self, form, iface):
|
|
1090
|
+
|
|
1091
|
+
template = iface.get('template', {})
|
|
1092
|
+
template.update(form.type.info.get('template', {}))
|
|
1093
|
+
|
|
1094
|
+
def convert(item):
|
|
1095
|
+
|
|
1096
|
+
if isinstance(item, str):
|
|
1097
|
+
|
|
1098
|
+
if item == '$self':
|
|
1099
|
+
return form.name
|
|
1100
|
+
|
|
1101
|
+
return item.format(**template)
|
|
1102
|
+
|
|
1103
|
+
if isinstance(item, dict):
|
|
1104
|
+
return {convert(k): convert(v) for (k, v) in item.items()}
|
|
1105
|
+
|
|
1106
|
+
if isinstance(item, (list, tuple)):
|
|
1107
|
+
return tuple([convert(v) for v in item])
|
|
1108
|
+
|
|
1109
|
+
return item
|
|
1110
|
+
|
|
1111
|
+
return convert(iface)
|
|
1112
|
+
|
|
1085
1113
|
def _addFormIface(self, form, name, subifaces=None):
|
|
1086
1114
|
|
|
1087
1115
|
iface = self.ifaces.get(name)
|
|
@@ -1094,9 +1122,14 @@ class Model:
|
|
|
1094
1122
|
mesg = f'Form {form.name} depends on deprecated interface {name} which will be removed in 3.0.0'
|
|
1095
1123
|
logger.warning(mesg)
|
|
1096
1124
|
|
|
1125
|
+
iface = self._prepFormIface(form, iface)
|
|
1126
|
+
|
|
1097
1127
|
for propname, typedef, propinfo in iface.get('props', ()):
|
|
1098
|
-
|
|
1099
|
-
|
|
1128
|
+
|
|
1129
|
+
# allow form props to take precedence
|
|
1130
|
+
if form.prop(propname) is not None:
|
|
1131
|
+
continue
|
|
1132
|
+
|
|
1100
1133
|
prop = self._addFormProp(form, propname, typedef, propinfo)
|
|
1101
1134
|
self.ifaceprops[f'{name}:{propname}'].append(prop.full)
|
|
1102
1135
|
|
|
@@ -1123,6 +1156,8 @@ class Model:
|
|
|
1123
1156
|
if (iface := self.ifaces.get(name)) is None:
|
|
1124
1157
|
return
|
|
1125
1158
|
|
|
1159
|
+
iface = self._prepFormIface(form, iface)
|
|
1160
|
+
|
|
1126
1161
|
for propname, typedef, propinfo in iface.get('props', ()):
|
|
1127
1162
|
fullprop = f'{form.name}:{propname}'
|
|
1128
1163
|
self.delFormProp(form.name, propname)
|
synapse/lib/ast.py
CHANGED
|
@@ -1426,6 +1426,32 @@ class LiftOper(Oper):
|
|
|
1426
1426
|
self.astinfo = astinfo
|
|
1427
1427
|
self.reverse = True
|
|
1428
1428
|
|
|
1429
|
+
def getPivNames(self, runt, prop, pivs):
|
|
1430
|
+
pivnames = []
|
|
1431
|
+
typename = prop.type.name
|
|
1432
|
+
for piv in pivs:
|
|
1433
|
+
pivprop = runt.model.reqProp(f'{typename}:{piv}', extra=self.kids[0].addExcInfo)
|
|
1434
|
+
pivnames.append(pivprop.full)
|
|
1435
|
+
typename = pivprop.type.name
|
|
1436
|
+
|
|
1437
|
+
return pivnames
|
|
1438
|
+
|
|
1439
|
+
async def pivlift(self, runt, props, pivnames, genr):
|
|
1440
|
+
|
|
1441
|
+
async def pivvals(prop, pivgenr):
|
|
1442
|
+
async for node in pivgenr:
|
|
1443
|
+
async for pivo in runt.snap.nodesByPropValu(prop, '=', node.ndef[1], reverse=self.reverse):
|
|
1444
|
+
yield pivo
|
|
1445
|
+
|
|
1446
|
+
for pivname in pivnames[-2::-1]:
|
|
1447
|
+
genr = pivvals(pivname, genr)
|
|
1448
|
+
|
|
1449
|
+
async for node in genr:
|
|
1450
|
+
valu = node.ndef[1]
|
|
1451
|
+
for prop in props:
|
|
1452
|
+
async for node in runt.snap.nodesByPropValu(prop.full, '=', valu, reverse=self.reverse):
|
|
1453
|
+
yield node
|
|
1454
|
+
|
|
1429
1455
|
async def run(self, runt, genr):
|
|
1430
1456
|
|
|
1431
1457
|
if self.isRuntSafe(runt):
|
|
@@ -1584,30 +1610,52 @@ class LiftByArray(LiftOper):
|
|
|
1584
1610
|
cmpr = await self.kids[1].compute(runt, path)
|
|
1585
1611
|
valu = await s_stormtypes.tostor(await self.kids[2].compute(runt, path))
|
|
1586
1612
|
|
|
1587
|
-
|
|
1588
|
-
if
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
return
|
|
1613
|
+
pivs = None
|
|
1614
|
+
if name.find('::') != -1:
|
|
1615
|
+
parts = name.split('::')
|
|
1616
|
+
name, pivs = parts[0], parts[1:]
|
|
1592
1617
|
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1618
|
+
if (prop := runt.model.props.get(name)) is not None:
|
|
1619
|
+
props = (prop,)
|
|
1620
|
+
else:
|
|
1621
|
+
proplist = runt.model.ifaceprops.get(name)
|
|
1622
|
+
if proplist is None:
|
|
1623
|
+
raise self.kids[0].addExcInfo(s_exc.NoSuchProp.init(name))
|
|
1596
1624
|
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1625
|
+
props = []
|
|
1626
|
+
for propname in proplist:
|
|
1627
|
+
props.append(runt.model.props.get(propname))
|
|
1600
1628
|
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1629
|
+
try:
|
|
1630
|
+
if pivs is not None:
|
|
1631
|
+
pivnames = self.getPivNames(runt, props[0], pivs)
|
|
1604
1632
|
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1633
|
+
genr = runt.snap.nodesByPropArray(pivnames[-1], cmpr, valu, reverse=self.reverse)
|
|
1634
|
+
async for node in self.pivlift(runt, props, pivnames, genr):
|
|
1635
|
+
yield node
|
|
1636
|
+
return
|
|
1608
1637
|
|
|
1609
|
-
|
|
1610
|
-
|
|
1638
|
+
if len(props) == 1:
|
|
1639
|
+
async for node in runt.snap.nodesByPropArray(name, cmpr, valu, reverse=self.reverse):
|
|
1640
|
+
yield node
|
|
1641
|
+
return
|
|
1642
|
+
|
|
1643
|
+
relname = props[0].name
|
|
1644
|
+
def cmprkey(node):
|
|
1645
|
+
return node.props.get(relname)
|
|
1646
|
+
|
|
1647
|
+
genrs = []
|
|
1648
|
+
for prop in props:
|
|
1649
|
+
genrs.append(runt.snap.nodesByPropArray(prop.full, cmpr, valu, reverse=self.reverse))
|
|
1650
|
+
|
|
1651
|
+
async for node in s_common.merggenr2(genrs, cmprkey, reverse=self.reverse):
|
|
1652
|
+
yield node
|
|
1653
|
+
|
|
1654
|
+
except s_exc.BadTypeValu as e:
|
|
1655
|
+
raise self.kids[2].addExcInfo(e)
|
|
1656
|
+
|
|
1657
|
+
except s_exc.SynErr as e:
|
|
1658
|
+
raise self.addExcInfo(e)
|
|
1611
1659
|
|
|
1612
1660
|
class LiftTagProp(LiftOper):
|
|
1613
1661
|
'''
|
|
@@ -1839,6 +1887,11 @@ class LiftPropBy(LiftOper):
|
|
|
1839
1887
|
if not isinstance(valu, s_node.Node):
|
|
1840
1888
|
valu = await s_stormtypes.tostor(valu)
|
|
1841
1889
|
|
|
1890
|
+
pivs = None
|
|
1891
|
+
if name.find('::') != -1:
|
|
1892
|
+
parts = name.split('::')
|
|
1893
|
+
name, pivs = parts[0], parts[1:]
|
|
1894
|
+
|
|
1842
1895
|
prop = runt.model.props.get(name)
|
|
1843
1896
|
if prop is not None:
|
|
1844
1897
|
props = (prop,)
|
|
@@ -1852,6 +1905,14 @@ class LiftPropBy(LiftOper):
|
|
|
1852
1905
|
props.append(runt.model.props.get(propname))
|
|
1853
1906
|
|
|
1854
1907
|
try:
|
|
1908
|
+
if pivs is not None:
|
|
1909
|
+
pivnames = self.getPivNames(runt, props[0], pivs)
|
|
1910
|
+
|
|
1911
|
+
genr = runt.snap.nodesByPropValu(pivnames[-1], cmpr, valu, reverse=self.reverse)
|
|
1912
|
+
async for node in self.pivlift(runt, props, pivnames, genr):
|
|
1913
|
+
yield node
|
|
1914
|
+
return
|
|
1915
|
+
|
|
1855
1916
|
if len(props) == 1:
|
|
1856
1917
|
prop = props[0]
|
|
1857
1918
|
async for node in runt.snap.nodesByPropValu(prop.full, cmpr, valu, reverse=self.reverse):
|
|
@@ -3794,7 +3855,7 @@ class ExprDict(Value):
|
|
|
3794
3855
|
|
|
3795
3856
|
def prepare(self):
|
|
3796
3857
|
self.const = None
|
|
3797
|
-
if all(isinstance(k, Const) for k in self.kids):
|
|
3858
|
+
if all(isinstance(k, Const) and not isinstance(k, EmbedQuery) for k in self.kids):
|
|
3798
3859
|
valu = {}
|
|
3799
3860
|
for i in range(0, len(self.kids), 2):
|
|
3800
3861
|
valu[self.kids[i].value()] = self.kids[i + 1].value()
|
|
@@ -3824,7 +3885,7 @@ class ExprList(Value):
|
|
|
3824
3885
|
|
|
3825
3886
|
def prepare(self):
|
|
3826
3887
|
self.const = None
|
|
3827
|
-
if all(isinstance(k, Const) for k in self.kids):
|
|
3888
|
+
if all(isinstance(k, Const) and not isinstance(k, EmbedQuery) for k in self.kids):
|
|
3828
3889
|
self.const = s_msgpack.en([k.value() for k in self.kids])
|
|
3829
3890
|
|
|
3830
3891
|
async def compute(self, runt, path):
|
synapse/lib/auth.py
CHANGED
|
@@ -264,6 +264,19 @@ class Auth(s_nexus.Pusher):
|
|
|
264
264
|
def _getRoleIden(self, name):
|
|
265
265
|
return self.roleidenbyname.get(name)
|
|
266
266
|
|
|
267
|
+
# TODO convert getUserByName() and getRoleByName()
|
|
268
|
+
# back from async? These were plumbed to avoid infecting
|
|
269
|
+
# type norm/repr functions with async...
|
|
270
|
+
def _getRoleByName(self, name):
|
|
271
|
+
roleiden = self.roleidenbynamecache.get(name)
|
|
272
|
+
if roleiden is not None:
|
|
273
|
+
return self.role(roleiden)
|
|
274
|
+
|
|
275
|
+
def _getUserByName(self, name):
|
|
276
|
+
useriden = self.useridenbynamecache.get(name)
|
|
277
|
+
if useriden is not None:
|
|
278
|
+
return self.user(useriden)
|
|
279
|
+
|
|
267
280
|
@s_nexus.Pusher.onPushAuto('user:profile:set')
|
|
268
281
|
async def setUserProfileValu(self, iden, name, valu):
|
|
269
282
|
user = await self.reqUser(iden)
|
synapse/lib/cell.py
CHANGED
|
@@ -2118,6 +2118,13 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
2118
2118
|
Hand off leadership to a mirror in a transactional fashion.
|
|
2119
2119
|
'''
|
|
2120
2120
|
_dispname = f' ahaname={self.conf.get("aha:name")}' if self.conf.get('aha:name') else ''
|
|
2121
|
+
|
|
2122
|
+
if not self.isactive:
|
|
2123
|
+
mesg = f'HANDOFF: {_dispname} is not the current leader and cannot handoff leadership to' \
|
|
2124
|
+
f' {s_urlhelp.sanitizeUrl(turl)}.'
|
|
2125
|
+
logger.error(mesg)
|
|
2126
|
+
raise s_exc.BadState(mesg=mesg, turl=turl, cursvc=_dispname)
|
|
2127
|
+
|
|
2121
2128
|
logger.warning(f'HANDOFF: Performing leadership handoff to {s_urlhelp.sanitizeUrl(turl)}{_dispname}.')
|
|
2122
2129
|
async with await s_telepath.openurl(turl) as cell:
|
|
2123
2130
|
|
|
@@ -4439,6 +4446,11 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
4439
4446
|
Returns:
|
|
4440
4447
|
Dict: A Dictionary of metadata.
|
|
4441
4448
|
'''
|
|
4449
|
+
|
|
4450
|
+
mirror = self.conf.get('mirror')
|
|
4451
|
+
if mirror is not None:
|
|
4452
|
+
mirror = s_urlhelp.sanitizeUrl(mirror)
|
|
4453
|
+
|
|
4442
4454
|
ret = {
|
|
4443
4455
|
'synapse': {
|
|
4444
4456
|
'commit': s_version.commit,
|
|
@@ -4458,6 +4470,7 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
4458
4470
|
'cellvers': dict(self.cellvers.items()),
|
|
4459
4471
|
'nexsindx': await self.getNexsIndx(),
|
|
4460
4472
|
'uplink': self.nexsroot.miruplink.is_set(),
|
|
4473
|
+
'mirror': mirror,
|
|
4461
4474
|
'aha': {
|
|
4462
4475
|
'name': self.conf.get('aha:name'),
|
|
4463
4476
|
'leader': self.conf.get('aha:leader'),
|
synapse/lib/modules.py
CHANGED
synapse/lib/parser.py
CHANGED
synapse/lib/snap.py
CHANGED
|
@@ -1692,6 +1692,7 @@ class Snap(s_base.Base):
|
|
|
1692
1692
|
|
|
1693
1693
|
todo = s_common.todo('runRuntLift', full, valu, cmpr, self.view.iden)
|
|
1694
1694
|
async for sode in self.core.dyniter('cortex', todo):
|
|
1695
|
+
await asyncio.sleep(0)
|
|
1695
1696
|
|
|
1696
1697
|
node = s_node.Node(self, sode)
|
|
1697
1698
|
node.isrunt = True
|
synapse/lib/storm.lark
CHANGED
|
@@ -222,9 +222,9 @@ liftreverse: _REVERSE "(" (liftformtag | liftpropby | liftprop | liftbyarray | l
|
|
|
222
222
|
_DEREF.3: /\*(?=\$)/
|
|
223
223
|
|
|
224
224
|
liftformtag: ((PROPS | UNIVNAME | WILDPROPS) | _DEREF _varvalu) tagname [_cmpr _valu]
|
|
225
|
-
liftpropby: ((PROPS | UNIVNAME) | _DEREF _varvalu) _cmpr _valu
|
|
225
|
+
liftpropby: ((PROPS | EMBEDPROPS | UNIVNAME) | _DEREF _varvalu) _cmpr _valu
|
|
226
226
|
liftprop: ((PROPS | UNIVNAME | WILDPROPS) | _DEREF _varvalu)
|
|
227
|
-
liftbyarray: ((PROPS | UNIVNAME) | _DEREF _varvalu) "*[" _safe_cmpr _valu "]"
|
|
227
|
+
liftbyarray: ((PROPS | EMBEDPROPS | UNIVNAME) | _DEREF _varvalu) "*[" _safe_cmpr _valu "]"
|
|
228
228
|
lifttagtag: (_HASH | _HASHSPACE) tagname [_cmpr _valu]
|
|
229
229
|
liftbytag: (tagname | tagnamewithspace) [_cmpr _valu]
|
|
230
230
|
liftbytagprop: (tagprop | tagpropwithspace) [_cmpr _valu]
|
|
@@ -321,10 +321,10 @@ _valu: _basevalu | NONQUOTEWORD
|
|
|
321
321
|
evalvalu: _valu
|
|
322
322
|
exprdict: "{" ((_exprvalu | VARTOKN) (":" | _EXPRCOLONNOSPACE) (_exprvalu | VARTOKN) ("," (_exprvalu | VARTOKN) (":" | _EXPRCOLONNOSPACE) (_exprvalu | VARTOKN))* ","? )? "}"
|
|
323
323
|
exprlist: "[" ((_exprvalu | VARTOKN) ("," (_exprvalu | VARTOKN))* ","? )? "]"
|
|
324
|
-
// Just like _valu, but doesn't allow valu lists or unquoted strings
|
|
324
|
+
// Just like _valu, but doesn't allow valu lists or unquoted strings
|
|
325
325
|
_exprvalu: NUMBER | HEXNUMBER | OCTNUMBER | BOOL | NULL | exprlist | exprdict | _exprvarvalu | exprrelpropvalu
|
|
326
326
|
| exprunivpropvalu | exprtagvalu | exprtagpropvalu | TRIPLEQUOTEDSTRING | DOUBLEQUOTEDSTRING
|
|
327
|
-
| SINGLEQUOTEDSTRING | formatstring | _innerdollarexprs
|
|
327
|
+
| SINGLEQUOTEDSTRING | formatstring | _innerdollarexprs | embedquery
|
|
328
328
|
|
|
329
329
|
// Expr versions of rules to avoid invalid state merges
|
|
330
330
|
_innerdollarexprs: "$"? innerdollaroper
|
|
@@ -454,8 +454,14 @@ formatstring: "`" (_formatexpr | FORMATTEXT)* "`"
|
|
|
454
454
|
|
|
455
455
|
// Must be kept consistent with same regexes in synapse/lib/grammar.py
|
|
456
456
|
// A full property. Must contain at least 1 colon
|
|
457
|
-
PROPS.
|
|
458
|
-
|
|
457
|
+
PROPS.3: /[a-z_][a-z0-9_]*(:[a-z0-9_]+)+([:.][a-z0-9_]+)*(?![:.a-z0-9_\-])/
|
|
458
|
+
|
|
459
|
+
// A full property containing a wildcard
|
|
460
|
+
WILDPROPS.3: /[a-z_][a-z0-9_]*(:\*|(:[a-z0-9_]+)+([:.][a-z0-9_]+)*:?\*)(?![:.a-z0-9_\-\[])/
|
|
461
|
+
|
|
462
|
+
// A full property with embed properties
|
|
463
|
+
EMBEDPROPS.2: /[a-z_][a-z0-9_]*(:[a-z0-9_]+)+((\:\:|\:|\.)[a-z0-9_]+)*(?![:.a-z0-9_\-])/
|
|
464
|
+
|
|
459
465
|
// A universal property
|
|
460
466
|
UNIVNAME.2: /(?<=^|[\s\|\{\(\[+=-])\.[a-z_][a-z0-9_]*([:.][a-z0-9_]+)*/
|
|
461
467
|
univprop: UNIVNAME | "." _varvalu
|
synapse/lib/storm.py
CHANGED
|
@@ -1778,8 +1778,10 @@ class StormDmon(s_base.Base):
|
|
|
1778
1778
|
|
|
1779
1779
|
text = self.ddef.get('storm')
|
|
1780
1780
|
opts = self.ddef.get('stormopts', {})
|
|
1781
|
-
|
|
1781
|
+
|
|
1782
|
+
vars = await s_stormtypes.toprim(opts.get('vars', {}), use_list=True)
|
|
1782
1783
|
vars.setdefault('auto', {'iden': self.iden, 'type': 'dmon'})
|
|
1784
|
+
opts['vars'] = vars
|
|
1783
1785
|
|
|
1784
1786
|
viewiden = opts.get('view')
|
|
1785
1787
|
|
|
@@ -2732,15 +2734,28 @@ class Parser:
|
|
|
2732
2734
|
self.exited = True
|
|
2733
2735
|
return False
|
|
2734
2736
|
|
|
2737
|
+
def _wrap_text(self, text, width):
|
|
2738
|
+
lines, curline, curlen = [], [], 0
|
|
2739
|
+
for word in text.split():
|
|
2740
|
+
if curlen + len(word) + bool(curline) > width:
|
|
2741
|
+
lines.append(' '.join(curline))
|
|
2742
|
+
curline, curlen = [word], len(word)
|
|
2743
|
+
else:
|
|
2744
|
+
curline.append(word)
|
|
2745
|
+
curlen += len(word) + bool(curline)
|
|
2746
|
+
if curline:
|
|
2747
|
+
lines.append(' '.join(curline))
|
|
2748
|
+
return lines
|
|
2749
|
+
|
|
2735
2750
|
def _print_optarg(self, names, argdef):
|
|
2736
2751
|
|
|
2737
2752
|
dest = self._get_dest_str(argdef)
|
|
2738
2753
|
oact = argdef.get('action', 'store')
|
|
2739
2754
|
|
|
2740
2755
|
if oact in ('store_true', 'store_false'):
|
|
2741
|
-
base = f' {names[0]}'
|
|
2756
|
+
base = f' {names[0]}'
|
|
2742
2757
|
else:
|
|
2743
|
-
base = f' {names[0]} {dest}'
|
|
2758
|
+
base = f' {names[0]} {dest}'
|
|
2744
2759
|
|
|
2745
2760
|
defval = argdef.get('default', s_common.novalu)
|
|
2746
2761
|
choices = argdef.get('choices')
|
|
@@ -2748,12 +2763,14 @@ class Parser:
|
|
|
2748
2763
|
|
|
2749
2764
|
if defval is not s_common.novalu and oact not in ('store_true', 'store_false'):
|
|
2750
2765
|
if isinstance(defval, (tuple, list, dict)):
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
defval = '\n' + defval
|
|
2766
|
+
defval_ls = pprint.pformat(defval, width=120).split('\n')
|
|
2767
|
+
defval = '\n'.join(ln.strip() for ln in defval_ls)
|
|
2754
2768
|
|
|
2755
2769
|
if choices is None:
|
|
2756
|
-
|
|
2770
|
+
if (lambda tst: '\n' in tst if isinstance(tst, str) else False)(defval):
|
|
2771
|
+
helpstr = f'{helpstr} (default: \n{defval})'
|
|
2772
|
+
else:
|
|
2773
|
+
helpstr = f'{helpstr} (default: {defval})'
|
|
2757
2774
|
else:
|
|
2758
2775
|
cstr = ', '.join(str(c) for c in choices)
|
|
2759
2776
|
helpstr = f'{helpstr} (default: {defval}, choices: {cstr})'
|
|
@@ -2762,7 +2779,26 @@ class Parser:
|
|
|
2762
2779
|
cstr = ', '.join(str(c) for c in choices)
|
|
2763
2780
|
helpstr = f'{helpstr} (choices: {cstr})'
|
|
2764
2781
|
|
|
2765
|
-
|
|
2782
|
+
helplst = helpstr.split('\n')
|
|
2783
|
+
if helplst and not helplst[0].strip():
|
|
2784
|
+
helplst = helplst[1:]
|
|
2785
|
+
min_space = min((len(ln) - len(ln.lstrip()) for ln in helplst if ln.strip()), default=0)
|
|
2786
|
+
|
|
2787
|
+
base_w = 32
|
|
2788
|
+
wrap_w = 120 - base_w
|
|
2789
|
+
|
|
2790
|
+
first = helplst[0][min_space:]
|
|
2791
|
+
wrap_first = self._wrap_text(first, wrap_w)
|
|
2792
|
+
self._printf(f'{base:<{base_w-2}}: {wrap_first[0]}')
|
|
2793
|
+
|
|
2794
|
+
for ln in wrap_first[1:]: self._printf(f'{"":<{base_w}}{ln}')
|
|
2795
|
+
for ln in helplst[1:]:
|
|
2796
|
+
lead_s = len(ln) - len(ln.lstrip())
|
|
2797
|
+
rel_ind = lead_s - min_space
|
|
2798
|
+
ind = ' ' * (base_w + rel_ind)
|
|
2799
|
+
wrapped = self._wrap_text(ln.lstrip(), wrap_w - rel_ind)
|
|
2800
|
+
for wl in wrapped:
|
|
2801
|
+
self._printf(f'{ind}{wl}')
|
|
2766
2802
|
|
|
2767
2803
|
def _print_posarg(self, name, argdef):
|
|
2768
2804
|
dest = self._get_dest_str(argdef)
|
|
@@ -5232,7 +5268,7 @@ class BackgroundCmd(Cmd):
|
|
|
5232
5268
|
async for item in genr:
|
|
5233
5269
|
yield item
|
|
5234
5270
|
|
|
5235
|
-
runtprims = await s_stormtypes.toprim(self.runt.getScopeVars())
|
|
5271
|
+
runtprims = await s_stormtypes.toprim(self.runt.getScopeVars(), use_list=True)
|
|
5236
5272
|
runtvars = {k: v for (k, v) in runtprims.items() if s_msgpack.isok(v)}
|
|
5237
5273
|
|
|
5238
5274
|
opts = {
|
synapse/lib/storm_format.py
CHANGED
synapse/lib/stormlib/stix.py
CHANGED
|
@@ -486,7 +486,10 @@ _DefaultConfig = {
|
|
|
486
486
|
},
|
|
487
487
|
}
|
|
488
488
|
|
|
489
|
-
|
|
489
|
+
perm_maxsize = ('storm', 'lib', 'stix', 'export', 'maxsize')
|
|
490
|
+
def _validateConfig(runt, config):
|
|
491
|
+
|
|
492
|
+
core = runt.snap.core
|
|
490
493
|
|
|
491
494
|
maxsize = config.get('maxsize', 10000)
|
|
492
495
|
|
|
@@ -506,9 +509,10 @@ def _validateConfig(core, config):
|
|
|
506
509
|
mesg = f'STIX Bundle config maxsize option must be an integer.'
|
|
507
510
|
raise s_exc.BadConfValu(mesg=mesg)
|
|
508
511
|
|
|
509
|
-
if maxsize > 10000:
|
|
510
|
-
|
|
511
|
-
|
|
512
|
+
if maxsize > 10000 and not runt.allowed(perm_maxsize):
|
|
513
|
+
permstr = '.'.join(perm_maxsize)
|
|
514
|
+
mesg = f'Setting STIX export maxsize > 10,000 requires permission: {permstr}'
|
|
515
|
+
raise s_exc.AuthDeny(mesg=mesg, perm=permstr)
|
|
512
516
|
|
|
513
517
|
formmaps = config.get('forms')
|
|
514
518
|
if formmaps is None:
|
|
@@ -1040,6 +1044,11 @@ class LibStixExport(s_stormtypes.Lib):
|
|
|
1040
1044
|
'''
|
|
1041
1045
|
A Storm Library for exporting to STIX version 2.1 CS02.
|
|
1042
1046
|
'''
|
|
1047
|
+
_storm_lib_perms = (
|
|
1048
|
+
{'perm': ('storm', 'lib', 'stix', 'export', 'maxsize'), 'gate': 'cortex',
|
|
1049
|
+
'desc': 'Controls the ability to specify a STIX export bundle maxsize of greater than 10,000.'},
|
|
1050
|
+
)
|
|
1051
|
+
|
|
1043
1052
|
_storm_locals = ( # type: ignore
|
|
1044
1053
|
{
|
|
1045
1054
|
'name': 'bundle',
|
|
@@ -1172,7 +1181,7 @@ class LibStixExport(s_stormtypes.Lib):
|
|
|
1172
1181
|
config = _DefaultConfig
|
|
1173
1182
|
|
|
1174
1183
|
config = await s_stormtypes.toprim(config)
|
|
1175
|
-
_validateConfig(self.runt
|
|
1184
|
+
_validateConfig(self.runt, config)
|
|
1176
1185
|
|
|
1177
1186
|
return StixBundle(self, self.runt, config)
|
|
1178
1187
|
|