synapse 2.166.0__py311-none-any.whl → 2.168.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 +4 -10
- synapse/cortex.py +55 -12
- synapse/exc.py +1 -0
- synapse/lib/aha.py +4 -1
- synapse/lib/base.py +11 -4
- synapse/lib/cell.py +11 -2
- synapse/lib/hive.py +11 -0
- synapse/lib/layer.py +2 -0
- synapse/lib/modelrev.py +6 -0
- synapse/lib/modules.py +1 -0
- synapse/lib/node.py +4 -2
- synapse/lib/schemas.py +1 -1
- synapse/lib/stormlib/aha.py +385 -20
- synapse/lib/stormlib/easyperm.py +8 -0
- synapse/lib/stormlib/macro.py +11 -18
- synapse/lib/stormlib/stix.py +1 -1
- synapse/lib/stormtypes.py +25 -2
- synapse/lib/types.py +2 -0
- synapse/lib/version.py +2 -2
- synapse/lib/view.py +5 -3
- synapse/models/base.py +8 -0
- synapse/models/files.py +3 -0
- synapse/models/planning.py +161 -0
- synapse/telepath.py +1 -0
- synapse/tests/files/stormpkg/dotstorm/dotstorm.yaml +3 -0
- synapse/tests/test_cortex.py +40 -3
- synapse/tests/test_lib_aha.py +8 -4
- synapse/tests/test_lib_cell.py +6 -2
- synapse/tests/test_lib_grammar.py +62 -64
- synapse/tests/test_lib_httpapi.py +1 -1
- synapse/tests/test_lib_rstorm.py +4 -4
- synapse/tests/test_lib_storm.py +3 -3
- synapse/tests/test_lib_stormlib_aha.py +196 -0
- synapse/tests/test_lib_stormlib_compression.py +12 -12
- synapse/tests/test_lib_stormlib_macro.py +94 -0
- synapse/tests/test_lib_stormlib_spooled.py +1 -1
- synapse/tests/test_lib_stormtypes.py +44 -33
- synapse/tests/test_lib_trigger.py +3 -3
- synapse/tests/test_lib_view.py +50 -3
- synapse/tests/test_model_files.py +3 -0
- synapse/tests/test_model_planning.py +126 -0
- synapse/tests/test_tools_genpkg.py +26 -0
- synapse/tests/test_tools_hiveload.py +1 -0
- synapse/tests/test_tools_hivesave.py +1 -0
- synapse/tests/utils.py +22 -3
- synapse/tools/autodoc.py +1 -1
- synapse/tools/hive/load.py +3 -0
- synapse/tools/hive/save.py +3 -0
- {synapse-2.166.0.dist-info → synapse-2.168.0.dist-info}/METADATA +3 -3
- {synapse-2.166.0.dist-info → synapse-2.168.0.dist-info}/RECORD +53 -50
- {synapse-2.166.0.dist-info → synapse-2.168.0.dist-info}/LICENSE +0 -0
- {synapse-2.166.0.dist-info → synapse-2.168.0.dist-info}/WHEEL +0 -0
- {synapse-2.166.0.dist-info → synapse-2.168.0.dist-info}/top_level.txt +0 -0
|
@@ -53,6 +53,27 @@ class MacroTest(s_test.SynTest):
|
|
|
53
53
|
with self.raises(s_exc.AuthDeny):
|
|
54
54
|
await core.nodes('$lib.macro.del(hehe)', opts=asvisi)
|
|
55
55
|
|
|
56
|
+
with self.raises(s_exc.BadArg):
|
|
57
|
+
await core.nodes('$lib.macro.set("", ${ inet:ipv4 })')
|
|
58
|
+
|
|
59
|
+
with self.raises(s_exc.BadArg):
|
|
60
|
+
await core.nodes('$lib.macro.get("")')
|
|
61
|
+
|
|
62
|
+
with self.raises(s_exc.BadArg):
|
|
63
|
+
await core.nodes('$lib.macro.del("")')
|
|
64
|
+
|
|
65
|
+
with self.raises(s_exc.BadArg):
|
|
66
|
+
await core.delStormMacro('', user=None)
|
|
67
|
+
|
|
68
|
+
with self.raises(s_exc.BadArg):
|
|
69
|
+
await core.nodes('$lib.macro.grant("", users, hehe, 3)')
|
|
70
|
+
|
|
71
|
+
with self.raises(s_exc.SchemaViolation):
|
|
72
|
+
await core.nodes('$lib.macro.mod("hehe", ({"name": ""}))')
|
|
73
|
+
|
|
74
|
+
with self.raises(s_exc.BadArg):
|
|
75
|
+
await core.nodes('$lib.macro.mod("", ({"name": "foobar"}))')
|
|
76
|
+
|
|
56
77
|
with self.raises(s_exc.AuthDeny):
|
|
57
78
|
await core.nodes('$lib.macro.set(hehe, ${ inet:ipv6 })', opts=asvisi)
|
|
58
79
|
|
|
@@ -118,6 +139,14 @@ class MacroTest(s_test.SynTest):
|
|
|
118
139
|
msgs = await core.stormlist('macro.del print', opts={'readonly': True})
|
|
119
140
|
self.stormIsInErr('not marked readonly safe', msgs)
|
|
120
141
|
|
|
142
|
+
msgs = await core.stormlist('macro.set blorpblorp "+#foo"', opts=asvisi)
|
|
143
|
+
self.stormHasNoWarnErr(msgs)
|
|
144
|
+
|
|
145
|
+
await core.auth.delUser(visi.iden)
|
|
146
|
+
msgs = await core.stormlist('macro.list')
|
|
147
|
+
self.stormIsInPrint("User not found", msgs)
|
|
148
|
+
self.stormIsInPrint(visi.iden, msgs)
|
|
149
|
+
|
|
121
150
|
async def test_stormlib_macro_vars(self):
|
|
122
151
|
|
|
123
152
|
async with self.getTestCore() as core:
|
|
@@ -319,3 +348,68 @@ class MacroTest(s_test.SynTest):
|
|
|
319
348
|
await visi.addRule((True, ('storm', 'macro', 'admin')))
|
|
320
349
|
msgs = await core.stormlist('macro.del asdf', opts={'user': visi.iden})
|
|
321
350
|
self.stormHasNoWarnErr(msgs)
|
|
351
|
+
|
|
352
|
+
async def test_stormlib_behold_macro(self):
|
|
353
|
+
self.skipIfNexusReplay()
|
|
354
|
+
async with self.getTestCore() as core:
|
|
355
|
+
host, port = await core.addHttpsPort(0, host='127.0.0.1')
|
|
356
|
+
|
|
357
|
+
visi = await core.auth.addUser('visi')
|
|
358
|
+
await visi.setPasswd('secret')
|
|
359
|
+
await visi.setAdmin(True)
|
|
360
|
+
|
|
361
|
+
async with self.getHttpSess() as sess:
|
|
362
|
+
async with sess.post(f'https://localhost:{port}/api/v1/login', json={'user': 'visi', 'passwd': 'secret'}) as resp:
|
|
363
|
+
retn = await resp.json()
|
|
364
|
+
self.eq('ok', retn.get('status'))
|
|
365
|
+
self.eq('visi', retn['result']['name'])
|
|
366
|
+
|
|
367
|
+
async with sess.ws_connect(f'wss://localhost:{port}/api/v1/behold') as sock:
|
|
368
|
+
await sock.send_json({'type': 'call:init'})
|
|
369
|
+
mesg = await sock.receive_json()
|
|
370
|
+
self.eq(mesg['type'], 'init')
|
|
371
|
+
|
|
372
|
+
await core.callStorm('''
|
|
373
|
+
$lib.macro.set('foobar', ${ file:bytes | [+#neato] })
|
|
374
|
+
$lib.macro.set('foobar', ${ inet:ipv4 | [+#burrito] })
|
|
375
|
+
$lib.macro.mod('foobar', ({'name': 'bizbaz'}))
|
|
376
|
+
$lib.macro.grant('bizbaz', users, $visi, 3)
|
|
377
|
+
$lib.macro.del('bizbaz')
|
|
378
|
+
''', opts={'vars': {'visi': visi.iden}})
|
|
379
|
+
|
|
380
|
+
addmesg = await sock.receive_json()
|
|
381
|
+
self.eq('storm:macro:add', addmesg['data']['event'])
|
|
382
|
+
macro = addmesg['data']['info']['macro']
|
|
383
|
+
self.eq(macro['name'], 'foobar')
|
|
384
|
+
self.eq(macro['storm'], 'file:bytes | [+#neato]')
|
|
385
|
+
self.ne(visi.iden, macro['user'])
|
|
386
|
+
self.ne(visi.iden, macro['creator'])
|
|
387
|
+
self.nn(macro['iden'])
|
|
388
|
+
|
|
389
|
+
setmesg = await sock.receive_json()
|
|
390
|
+
self.eq('storm:macro:mod', setmesg['data']['event'])
|
|
391
|
+
event = setmesg['data']['info']
|
|
392
|
+
self.nn(event['macro'])
|
|
393
|
+
self.eq(event['info']['storm'], 'inet:ipv4 | [+#burrito]')
|
|
394
|
+
self.nn(event['info']['updated'])
|
|
395
|
+
|
|
396
|
+
modmesg = await sock.receive_json()
|
|
397
|
+
self.eq('storm:macro:mod', modmesg['data']['event'])
|
|
398
|
+
event = modmesg['data']['info']
|
|
399
|
+
self.nn(event['macro'])
|
|
400
|
+
self.eq(event['info']['name'], 'bizbaz')
|
|
401
|
+
self.nn(event['info']['updated'])
|
|
402
|
+
|
|
403
|
+
grantmesg = await sock.receive_json()
|
|
404
|
+
self.eq('storm:macro:set:perm', grantmesg['data']['event'])
|
|
405
|
+
event = grantmesg['data']['info']
|
|
406
|
+
self.nn(event['macro'])
|
|
407
|
+
self.eq(event['info']['level'], 3)
|
|
408
|
+
self.eq(event['info']['scope'], 'users')
|
|
409
|
+
self.eq(event['info']['iden'], visi.iden)
|
|
410
|
+
|
|
411
|
+
delmesg = await sock.receive_json()
|
|
412
|
+
self.eq('storm:macro:del', delmesg['data']['event'])
|
|
413
|
+
event = delmesg['data']['info']
|
|
414
|
+
self.nn(event['iden'])
|
|
415
|
+
self.eq(event['name'], 'bizbaz')
|
|
@@ -29,7 +29,7 @@ class StormlibSpooledTest(s_test.SynTest):
|
|
|
29
29
|
$set = $lib.spooled.set()
|
|
30
30
|
inet:ipv4 $set.add(:asn)
|
|
31
31
|
$set.rems((:asn,:asn))
|
|
32
|
-
[
|
|
32
|
+
[ tel:mob:telem="*" ] +tel:mob:telem [ :data=$set.list() ]
|
|
33
33
|
'''
|
|
34
34
|
nodes = await core.nodes(q)
|
|
35
35
|
self.len(1, nodes)
|
|
@@ -1343,34 +1343,34 @@ class StormTypesTest(s_test.SynTest):
|
|
|
1343
1343
|
n2 = s_common.guid()
|
|
1344
1344
|
n3 = s_common.guid()
|
|
1345
1345
|
|
|
1346
|
-
nodes = await core.nodes('[
|
|
1346
|
+
nodes = await core.nodes('[tel:mob:telem="*" :data=$data]', opts={'vars': {'data': ghstr}})
|
|
1347
1347
|
self.len(1, nodes)
|
|
1348
1348
|
node1 = nodes[0]
|
|
1349
1349
|
|
|
1350
|
-
nodes = await core.nodes('[
|
|
1350
|
+
nodes = await core.nodes('[tel:mob:telem="*" :data=$data]', opts={'vars': {'data': mstr}})
|
|
1351
1351
|
self.len(1, nodes)
|
|
1352
1352
|
node2 = nodes[0]
|
|
1353
|
-
q = '''
|
|
1353
|
+
q = '''tel:mob:telem=$n1 $gzthing = :data
|
|
1354
1354
|
$foo = $lib.base64.decode($gzthing).gunzip()
|
|
1355
1355
|
$lib.print($foo)
|
|
1356
|
-
[(
|
|
1356
|
+
[( tel:mob:telem=$n2 :data=$foo.decode() )]'''
|
|
1357
1357
|
|
|
1358
1358
|
msgs = await core.stormlist(q, opts={'vars': {'n1': node1.ndef[1], 'n2': n2}})
|
|
1359
1359
|
self.stormHasNoWarnErr(msgs)
|
|
1360
1360
|
self.stormIsInPrint('ohhai', msgs)
|
|
1361
1361
|
|
|
1362
1362
|
# make sure we gunzip correctly
|
|
1363
|
-
nodes = await core.nodes('
|
|
1363
|
+
nodes = await core.nodes('tel:mob:telem=$valu', opts={'vars': {'valu': n2}})
|
|
1364
1364
|
self.len(1, nodes)
|
|
1365
1365
|
self.eq(hstr, nodes[0].get('data'))
|
|
1366
1366
|
|
|
1367
|
-
text = f'''
|
|
1368
|
-
[(
|
|
1367
|
+
text = f'''tel:mob:telem=$n2 $bar = :data
|
|
1368
|
+
[( tel:mob:telem=$n3 :data=$lib.base64.encode($bar.encode().gzip()) )]'''
|
|
1369
1369
|
msgs = await core.stormlist(text, opts={'vars': {'n2': node2.ndef[1], 'n3': n3}})
|
|
1370
1370
|
self.stormHasNoWarnErr(msgs)
|
|
1371
1371
|
|
|
1372
1372
|
# make sure we gzip correctly
|
|
1373
|
-
nodes = await core.nodes('
|
|
1373
|
+
nodes = await core.nodes('tel:mob:telem=$valu', opts={'vars': {'valu': n3}})
|
|
1374
1374
|
self.len(1, nodes)
|
|
1375
1375
|
self.eq(mstr.encode(), gzip.decompress(base64.urlsafe_b64decode(nodes[0].props['data'])))
|
|
1376
1376
|
|
|
@@ -1383,30 +1383,30 @@ class StormTypesTest(s_test.SynTest):
|
|
|
1383
1383
|
n2 = s_common.guid()
|
|
1384
1384
|
n3 = s_common.guid()
|
|
1385
1385
|
|
|
1386
|
-
nodes = await core.nodes('[
|
|
1386
|
+
nodes = await core.nodes('[tel:mob:telem="*" :data=$data]', opts={'vars': {'data': ghstr}})
|
|
1387
1387
|
self.len(1, nodes)
|
|
1388
1388
|
node1 = nodes[0]
|
|
1389
|
-
nodes = await core.nodes('[
|
|
1389
|
+
nodes = await core.nodes('[tel:mob:telem="*" :data=$data]', opts={'vars': {'data': mstr}})
|
|
1390
1390
|
self.len(1, nodes)
|
|
1391
1391
|
node2 = nodes[0]
|
|
1392
1392
|
|
|
1393
|
-
q = '''
|
|
1393
|
+
q = '''tel:mob:telem=$valu $bzthing = :data $foo = $lib.base64.decode($bzthing).bunzip()
|
|
1394
1394
|
$lib.print($foo)
|
|
1395
|
-
[(
|
|
1395
|
+
[( tel:mob:telem=$n2 :data=$foo.decode() )] -tel:mob:telem=$valu'''
|
|
1396
1396
|
msgs = await core.stormlist(q, opts={'vars': {'valu': node1.ndef[1], 'n2': n2}})
|
|
1397
1397
|
self.stormHasNoWarnErr(msgs)
|
|
1398
1398
|
self.stormIsInPrint('ohhai', msgs)
|
|
1399
1399
|
|
|
1400
1400
|
# make sure we bunzip correctly
|
|
1401
1401
|
opts = {'vars': {'iden': n2}}
|
|
1402
|
-
nodes = await core.nodes('
|
|
1402
|
+
nodes = await core.nodes('tel:mob:telem=$iden', opts=opts)
|
|
1403
1403
|
self.len(1, nodes)
|
|
1404
1404
|
node = nodes[0]
|
|
1405
1405
|
self.eq(node.get('data'), hstr)
|
|
1406
1406
|
|
|
1407
1407
|
# bzip
|
|
1408
|
-
q = '''
|
|
1409
|
-
[(
|
|
1408
|
+
q = '''tel:mob:telem=$valu $bar = :data
|
|
1409
|
+
[( tel:mob:telem=$n3 :data=$lib.base64.encode($bar.encode().bzip()) )] -tel:mob:telem=$valu'''
|
|
1410
1410
|
nodes = await core.nodes(q, opts={'vars': {'valu': node2.ndef[1], 'n3': n3}})
|
|
1411
1411
|
self.len(1, nodes)
|
|
1412
1412
|
node = nodes[0]
|
|
@@ -1420,13 +1420,13 @@ class StormTypesTest(s_test.SynTest):
|
|
|
1420
1420
|
valu = s_common.guid()
|
|
1421
1421
|
n2 = s_common.guid()
|
|
1422
1422
|
|
|
1423
|
-
nodes = await core.nodes('[
|
|
1423
|
+
nodes = await core.nodes('[tel:mob:telem=$valu :data=$data]', opts={'vars': {'valu': valu, 'data': ghstr}})
|
|
1424
1424
|
self.len(1, nodes)
|
|
1425
1425
|
node1 = nodes[0]
|
|
1426
1426
|
self.eq(node1.get('data'), ghstr)
|
|
1427
1427
|
|
|
1428
|
-
q = '''
|
|
1429
|
-
-
|
|
1428
|
+
q = '''tel:mob:telem=$valu $jzthing=:data $foo=$jzthing.encode().json() [(tel:mob:telem=$n2 :data=$foo)]
|
|
1429
|
+
-tel:mob:telem=$valu'''
|
|
1430
1430
|
nodes = await core.nodes(q, opts={'vars': {'valu': valu, 'n2': n2}})
|
|
1431
1431
|
self.len(1, nodes)
|
|
1432
1432
|
node2 = nodes[0]
|
|
@@ -1720,7 +1720,7 @@ class StormTypesTest(s_test.SynTest):
|
|
|
1720
1720
|
q = '''
|
|
1721
1721
|
$set = $lib.set()
|
|
1722
1722
|
inet:ipv4 $set.add(:asn)
|
|
1723
|
-
[
|
|
1723
|
+
[ tel:mob:telem="*" ] +tel:mob:telem [ :data=$set.list() ]
|
|
1724
1724
|
'''
|
|
1725
1725
|
nodes = await core.nodes(q)
|
|
1726
1726
|
self.len(1, nodes)
|
|
@@ -1729,7 +1729,7 @@ class StormTypesTest(s_test.SynTest):
|
|
|
1729
1729
|
q = '''
|
|
1730
1730
|
$set = $lib.set()
|
|
1731
1731
|
inet:ipv4 $set.adds((:asn,:asn))
|
|
1732
|
-
[
|
|
1732
|
+
[ tel:mob:telem="*" ] +tel:mob:telem [ :data=$set.list() ]
|
|
1733
1733
|
'''
|
|
1734
1734
|
nodes = await core.nodes(q)
|
|
1735
1735
|
self.len(1, nodes)
|
|
@@ -1739,7 +1739,7 @@ class StormTypesTest(s_test.SynTest):
|
|
|
1739
1739
|
$set = $lib.set()
|
|
1740
1740
|
inet:ipv4 $set.adds((:asn,:asn))
|
|
1741
1741
|
{ +:asn=20 $set.rem(:asn) }
|
|
1742
|
-
[
|
|
1742
|
+
[ tel:mob:telem="*" ] +tel:mob:telem [ :data=$set.list() ]
|
|
1743
1743
|
'''
|
|
1744
1744
|
nodes = await core.nodes(q)
|
|
1745
1745
|
self.len(1, nodes)
|
|
@@ -1749,7 +1749,7 @@ class StormTypesTest(s_test.SynTest):
|
|
|
1749
1749
|
$set = $lib.set()
|
|
1750
1750
|
inet:ipv4 $set.add(:asn)
|
|
1751
1751
|
$set.rems((:asn,:asn))
|
|
1752
|
-
[
|
|
1752
|
+
[ tel:mob:telem="*" ] +tel:mob:telem [ :data=$set.list() ]
|
|
1753
1753
|
'''
|
|
1754
1754
|
nodes = await core.nodes(q)
|
|
1755
1755
|
self.len(1, nodes)
|
|
@@ -2151,7 +2151,7 @@ class StormTypesTest(s_test.SynTest):
|
|
|
2151
2151
|
q = '''
|
|
2152
2152
|
inet:fqdn=vertex.link -> inet:dns:a -> inet:ipv4
|
|
2153
2153
|
$idens = $path.idens()
|
|
2154
|
-
[
|
|
2154
|
+
[ tel:mob:telem="*" ] +tel:mob:telem [ :data=$idens ]
|
|
2155
2155
|
'''
|
|
2156
2156
|
|
|
2157
2157
|
idens = (
|
|
@@ -2699,6 +2699,17 @@ class StormTypesTest(s_test.SynTest):
|
|
|
2699
2699
|
await core.addUserRule(user, (True, ('storm', 'lib', 'telepath', 'open', 'cell')))
|
|
2700
2700
|
self.len(2, await core.callStorm('return ( $lib.telepath.open($url).ipv4s() )', opts=opts))
|
|
2701
2701
|
|
|
2702
|
+
# SynErr exceptions are allowed through. They can be caught by storm.
|
|
2703
|
+
with self.raises(s_exc.BadUrl):
|
|
2704
|
+
await core.callStorm('$prox=$lib.telepath.open("weeeeeeeeeeeeee")')
|
|
2705
|
+
|
|
2706
|
+
# Python exceptions are caught and raised as StormRuntimeError exceptions.
|
|
2707
|
+
with self.raises(s_exc.StormRuntimeError) as cm:
|
|
2708
|
+
await core.callStorm('$prox=$lib.telepath.open("tcp://0.0.0.0:60000")')
|
|
2709
|
+
emsg = cm.exception.get('mesg')
|
|
2710
|
+
self.isin('Failed to connect to Telepath service: "tcp://0.0.0.0:60000" error:', emsg)
|
|
2711
|
+
self.isin('Connect call failed', emsg)
|
|
2712
|
+
|
|
2702
2713
|
async def test_storm_lib_queue(self):
|
|
2703
2714
|
|
|
2704
2715
|
async with self.getTestCore() as core:
|
|
@@ -4474,7 +4485,7 @@ class StormTypesTest(s_test.SynTest):
|
|
|
4474
4485
|
|
|
4475
4486
|
async with self.getTestCore() as core:
|
|
4476
4487
|
|
|
4477
|
-
cdef = await core.callStorm('return($lib.cron.add(query="{[
|
|
4488
|
+
cdef = await core.callStorm('return($lib.cron.add(query="{[tel:mob:telem=*]}", hourly=30).pack())')
|
|
4478
4489
|
self.eq('', cdef.get('doc'))
|
|
4479
4490
|
self.eq('', cdef.get('name'))
|
|
4480
4491
|
|
|
@@ -4490,7 +4501,7 @@ class StormTypesTest(s_test.SynTest):
|
|
|
4490
4501
|
with self.raises(s_exc.BadArg):
|
|
4491
4502
|
await core.callStorm('return($lib.cron.get($iden).set(hehe, haha))', opts=opts)
|
|
4492
4503
|
|
|
4493
|
-
mesgs = await core.stormlist('cron.add --hour +1 {[
|
|
4504
|
+
mesgs = await core.stormlist('cron.add --hour +1 {[tel:mob:telem=*]} --name myname --doc mydoc')
|
|
4494
4505
|
for mesg in mesgs:
|
|
4495
4506
|
if mesg[0] == 'print':
|
|
4496
4507
|
iden0 = mesg[1]['mesg'].split(' ')[-1]
|
|
@@ -4595,7 +4606,7 @@ class StormTypesTest(s_test.SynTest):
|
|
|
4595
4606
|
nextlayroffs = await layr.getEditOffs() + 1
|
|
4596
4607
|
|
|
4597
4608
|
# Start simple: add a cron job that creates a node every minute
|
|
4598
|
-
q = "cron.add --minute +1 {[
|
|
4609
|
+
q = "cron.add --minute +1 {[meta:note='*' :type=m1]}"
|
|
4599
4610
|
mesgs = await core.stormlist(q)
|
|
4600
4611
|
self.stormIsInPrint('Created cron job', mesgs)
|
|
4601
4612
|
for mesg in mesgs:
|
|
@@ -4637,24 +4648,24 @@ class StormTypesTest(s_test.SynTest):
|
|
|
4637
4648
|
|
|
4638
4649
|
# Make sure it ran
|
|
4639
4650
|
await layr.waitEditOffs(nextlayroffs, timeout=5)
|
|
4640
|
-
self.eq(1, await prox.count('
|
|
4651
|
+
self.eq(1, await prox.count('meta:note:type=m1'))
|
|
4641
4652
|
|
|
4642
|
-
q = "cron.mod $guid { [
|
|
4653
|
+
q = "cron.mod $guid { [meta:note='*' :type=m2] }"
|
|
4643
4654
|
mesgs = await core.stormlist(q, opts={'vars': {'guid': guid[:6]}})
|
|
4644
4655
|
self.stormIsInPrint(f'Modified cron job: {guid}', mesgs)
|
|
4645
4656
|
|
|
4646
|
-
q = "cron.mod xxx { [
|
|
4657
|
+
q = "cron.mod xxx { [meta:note='*' :type=m2] }"
|
|
4647
4658
|
mesgs = await core.stormlist(q)
|
|
4648
4659
|
self.stormIsInErr('does not match', mesgs)
|
|
4649
4660
|
|
|
4650
4661
|
# Make sure the old one didn't run and the new query ran
|
|
4651
4662
|
unixtime += 60
|
|
4652
4663
|
await asyncio.sleep(0)
|
|
4653
|
-
self.eq(1, await prox.count('
|
|
4664
|
+
self.eq(1, await prox.count('meta:note:type=m1'))
|
|
4654
4665
|
# UNG WTF
|
|
4655
4666
|
await asyncio.sleep(0)
|
|
4656
4667
|
await asyncio.sleep(0)
|
|
4657
|
-
self.eq(1, await prox.count('
|
|
4668
|
+
self.eq(1, await prox.count('meta:note:type=m2'))
|
|
4658
4669
|
|
|
4659
4670
|
# Delete the job
|
|
4660
4671
|
q = f"cron.del {guid}"
|
|
@@ -4667,8 +4678,8 @@ class StormTypesTest(s_test.SynTest):
|
|
|
4667
4678
|
|
|
4668
4679
|
# Make sure deleted job didn't run
|
|
4669
4680
|
unixtime += 60
|
|
4670
|
-
self.eq(1, await prox.count('
|
|
4671
|
-
self.eq(1, await prox.count('
|
|
4681
|
+
self.eq(1, await prox.count('meta:note:type=m1'))
|
|
4682
|
+
self.eq(1, await prox.count('meta:note:type=m2'))
|
|
4672
4683
|
|
|
4673
4684
|
# Test fixed minute, i.e. every hour at 17 past
|
|
4674
4685
|
unixtime = datetime.datetime(year=2018, month=12, day=5, hour=7, minute=10,
|
|
@@ -369,7 +369,7 @@ class TrigTest(s_t_utils.SynTest):
|
|
|
369
369
|
|
|
370
370
|
# coverage for migration mode
|
|
371
371
|
await core.nodes('[inet:fqdn=vertex.link +#foo]') # for additional migration mode trigger tests below
|
|
372
|
-
with core.enterMigrationMode():
|
|
372
|
+
async with core.enterMigrationMode():
|
|
373
373
|
await core.nodes('inet:fqdn=vertex.link [ +#bar -#foo ]')
|
|
374
374
|
|
|
375
375
|
async def test_trigger_delete(self):
|
|
@@ -774,7 +774,7 @@ class TrigTest(s_t_utils.SynTest):
|
|
|
774
774
|
await core.nodes('trigger.add edge:add --verb r* --n2form test:int --query { [ +#n2 ] }')
|
|
775
775
|
await core.nodes('trigger.add edge:add --verb no** --form test:int --n2form test:str --query { [ +#both ] }')
|
|
776
776
|
|
|
777
|
-
with core.enterMigrationMode():
|
|
777
|
+
async with core.enterMigrationMode():
|
|
778
778
|
nodes = await core.nodes('[test:int=123 +(foo:beep:boop)> { [test:str=neato] }]')
|
|
779
779
|
self.len(1, nodes)
|
|
780
780
|
self.notin('foo', nodes[0].tags)
|
|
@@ -834,7 +834,7 @@ class TrigTest(s_t_utils.SynTest):
|
|
|
834
834
|
await core.nodes('trigger.add edge:del --verb r* --n2form test:int --query { [ +#del.two ] }')
|
|
835
835
|
await core.nodes('trigger.add edge:del --verb no** --form test:int --n2form test:str --query { [ +#del.all ] }')
|
|
836
836
|
|
|
837
|
-
with core.enterMigrationMode():
|
|
837
|
+
async with core.enterMigrationMode():
|
|
838
838
|
nodes = await core.nodes('test:int=123 | [ -(foo:beep:boop)> { test:str=neato } ]')
|
|
839
839
|
self.len(1, nodes)
|
|
840
840
|
self.notin('del.none', nodes[0].tags)
|
synapse/tests/test_lib_view.py
CHANGED
|
@@ -11,18 +11,21 @@ from synapse.tests.utils import alist
|
|
|
11
11
|
|
|
12
12
|
class ViewTest(s_t_utils.SynTest):
|
|
13
13
|
|
|
14
|
-
async def
|
|
14
|
+
async def test_view_protected(self):
|
|
15
15
|
async with self.getTestCore() as core:
|
|
16
16
|
view = await core.callStorm('return($lib.view.get().fork().iden)')
|
|
17
17
|
opts = {'view': view}
|
|
18
18
|
|
|
19
19
|
await core.nodes('[ ou:org=* ]', opts=opts)
|
|
20
|
-
await core.nodes('$lib.view.get().set(
|
|
20
|
+
await core.nodes('$lib.view.get().set(protected, $lib.true)', opts=opts)
|
|
21
21
|
|
|
22
22
|
with self.raises(s_exc.CantMergeView):
|
|
23
23
|
await core.nodes('$lib.view.get().merge()', opts=opts)
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
with self.raises(s_exc.CantDelView):
|
|
26
|
+
await core.nodes('$lib.view.del($lib.view.get().iden)', opts=opts)
|
|
27
|
+
|
|
28
|
+
await core.nodes('$lib.view.get().set(protected, $lib.false)', opts=opts)
|
|
26
29
|
await core.nodes('$lib.view.get().merge()', opts=opts)
|
|
27
30
|
|
|
28
31
|
self.len(1, await core.nodes('ou:org'))
|
|
@@ -31,6 +34,50 @@ class ViewTest(s_t_utils.SynTest):
|
|
|
31
34
|
with self.raises(s_exc.BadOptValu):
|
|
32
35
|
await core.view.setViewInfo('hehe', 10)
|
|
33
36
|
|
|
37
|
+
async with self.getTestCore() as core:
|
|
38
|
+
# Delete this block when nomerge is removed
|
|
39
|
+
view = await core.callStorm('return($lib.view.get().fork().iden)')
|
|
40
|
+
opts = {'view': view}
|
|
41
|
+
|
|
42
|
+
# Setting/getting nomerge should be redirected to protected
|
|
43
|
+
getnomerge = 'return($lib.view.get().get(nomerge))'
|
|
44
|
+
setnomerge = '$lib.view.get().set(nomerge, $valu)'
|
|
45
|
+
|
|
46
|
+
getprotected = 'return($lib.view.get().get(protected))'
|
|
47
|
+
setprotected = '$lib.view.get().set(protected, $valu)'
|
|
48
|
+
|
|
49
|
+
nomerge = await core.callStorm(getnomerge, opts=opts)
|
|
50
|
+
protected = await core.callStorm(getprotected, opts=opts)
|
|
51
|
+
self.false(nomerge)
|
|
52
|
+
self.false(protected)
|
|
53
|
+
|
|
54
|
+
opts['vars'] = {'valu': True}
|
|
55
|
+
await core.callStorm(setnomerge, opts=opts)
|
|
56
|
+
|
|
57
|
+
nomerge = await core.callStorm(getnomerge, opts=opts)
|
|
58
|
+
protected = await core.callStorm(getprotected, opts=opts)
|
|
59
|
+
self.true(nomerge)
|
|
60
|
+
self.true(protected)
|
|
61
|
+
|
|
62
|
+
opts['vars'] = {'valu': False}
|
|
63
|
+
await core.callStorm(setprotected, opts=opts)
|
|
64
|
+
|
|
65
|
+
nomerge = await core.callStorm(getnomerge, opts=opts)
|
|
66
|
+
protected = await core.callStorm(getprotected, opts=opts)
|
|
67
|
+
self.false(nomerge)
|
|
68
|
+
self.false(protected)
|
|
69
|
+
|
|
70
|
+
async def test_view_nomerge_migration(self):
|
|
71
|
+
async with self.getRegrCore('cortex-defaults-v2') as core:
|
|
72
|
+
view = core.getView('0df16dd693c74109da0d58ab87ba768a')
|
|
73
|
+
self.none(view.info.get('nomerge'))
|
|
74
|
+
self.true(view.info.get('protected'))
|
|
75
|
+
|
|
76
|
+
with self.raises(s_exc.CantMergeView):
|
|
77
|
+
await core.callStorm('return($lib.view.get(0df16dd693c74109da0d58ab87ba768a).merge())')
|
|
78
|
+
with self.raises(s_exc.CantDelView):
|
|
79
|
+
await core.callStorm('return($lib.view.del(0df16dd693c74109da0d58ab87ba768a))')
|
|
80
|
+
|
|
34
81
|
async def test_view_set_parent(self):
|
|
35
82
|
|
|
36
83
|
async with self.getTestCore() as core:
|
|
@@ -247,6 +247,9 @@ class FileTest(s_t_utils.SynTest):
|
|
|
247
247
|
self.raises(s_exc.BadTypeValu, base.norm, 'foo/bar.exe')
|
|
248
248
|
self.raises(s_exc.BadTypeValu, base.norm, '/haha')
|
|
249
249
|
|
|
250
|
+
norm, info = path.norm('../.././..')
|
|
251
|
+
self.eq(norm, '')
|
|
252
|
+
|
|
250
253
|
norm, info = path.norm('c:\\Windows\\System32\\calc.exe')
|
|
251
254
|
|
|
252
255
|
self.eq(norm, 'c:/windows/system32/calc.exe')
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import synapse.exc as s_exc
|
|
2
|
+
import synapse.common as s_common
|
|
3
|
+
import synapse.tests.utils as s_t_utils
|
|
4
|
+
|
|
5
|
+
class PlanModelTest(s_t_utils.SynTest):
|
|
6
|
+
|
|
7
|
+
async def test_model_planning(self):
|
|
8
|
+
|
|
9
|
+
async with self.getTestCore() as core:
|
|
10
|
+
nodes = await core.nodes('''
|
|
11
|
+
[ plan:system=*
|
|
12
|
+
:name="Woot CNO Planner"
|
|
13
|
+
:author={[ ps:contact=* :name=visi ]}
|
|
14
|
+
:created=20240202
|
|
15
|
+
:updated=20240203
|
|
16
|
+
:version=1.0.0
|
|
17
|
+
:url=https://vertex.link
|
|
18
|
+
]
|
|
19
|
+
''')
|
|
20
|
+
self.len(1, nodes)
|
|
21
|
+
self.eq('woot cno planner', nodes[0].get('name'))
|
|
22
|
+
self.eq(1706832000000, nodes[0].get('created'))
|
|
23
|
+
self.eq(1706918400000, nodes[0].get('updated'))
|
|
24
|
+
self.eq(1099511627776, nodes[0].get('version'))
|
|
25
|
+
self.eq('https://vertex.link', nodes[0].get('url'))
|
|
26
|
+
|
|
27
|
+
self.len(1, await core.nodes('plan:system :author -> ps:contact +:name=visi'))
|
|
28
|
+
|
|
29
|
+
nodes = await core.nodes('''
|
|
30
|
+
[ plan:phase=*
|
|
31
|
+
:system={ plan:system:name="Woot CNO Planner"}
|
|
32
|
+
:title="Recon"
|
|
33
|
+
:summary="Do some recon."
|
|
34
|
+
:index=17
|
|
35
|
+
:url=https://vertex.link/recon
|
|
36
|
+
]
|
|
37
|
+
''')
|
|
38
|
+
|
|
39
|
+
self.len(1, nodes)
|
|
40
|
+
self.eq('Recon', nodes[0].get('title'))
|
|
41
|
+
self.eq('Do some recon.', nodes[0].get('summary'))
|
|
42
|
+
self.eq(17, nodes[0].get('index'))
|
|
43
|
+
self.eq('https://vertex.link/recon', nodes[0].get('url'))
|
|
44
|
+
|
|
45
|
+
self.len(1, await core.nodes('plan:phase :system -> plan:system +:name="Woot CNO Planner"'))
|
|
46
|
+
|
|
47
|
+
nodes = await core.nodes('''
|
|
48
|
+
[ plan:procedure=*
|
|
49
|
+
:system={ plan:system:name="Woot CNO Planner"}
|
|
50
|
+
:title="Pwn Some Boxes"
|
|
51
|
+
:summary="Yoink."
|
|
52
|
+
:author={ ps:contact:name=visi }
|
|
53
|
+
:created=20240202
|
|
54
|
+
:updated=20240203
|
|
55
|
+
:version=1.0.0
|
|
56
|
+
:type=cno.offense
|
|
57
|
+
:system={ plan:system:name="Woot CNO Planner" }
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
$guid = $node.value()
|
|
61
|
+
|
|
62
|
+
[
|
|
63
|
+
:inputs={[ plan:procedure:variable=*
|
|
64
|
+
:name=network
|
|
65
|
+
:type=cidr
|
|
66
|
+
:default=127.0.0.0/24
|
|
67
|
+
:procedure=$guid
|
|
68
|
+
]}
|
|
69
|
+
|
|
70
|
+
:firststep={[ plan:procedure:step=*
|
|
71
|
+
:title="Are there vulnerable services?"
|
|
72
|
+
:summary="Scan the target network and identify available services."
|
|
73
|
+
:procedure=$guid
|
|
74
|
+
:phase={ plan:phase:title=Recon }
|
|
75
|
+
:outputs={[ plan:procedure:variable=* :name=services ]}
|
|
76
|
+
:techniques={[ ou:technique=* :name=netscan ]}
|
|
77
|
+
|
|
78
|
+
:links={[ plan:procedure:link=*
|
|
79
|
+
:condition=(true)
|
|
80
|
+
:procedure=$guid
|
|
81
|
+
:next={[ plan:procedure:step=*
|
|
82
|
+
:title="Exploit Services"
|
|
83
|
+
:summary="Gank that stuff."
|
|
84
|
+
:procedure=$guid
|
|
85
|
+
:outputs={[ plan:procedure:variable=* :name=shellz ]}
|
|
86
|
+
]}
|
|
87
|
+
|
|
88
|
+
]}
|
|
89
|
+
]}
|
|
90
|
+
]
|
|
91
|
+
''')
|
|
92
|
+
|
|
93
|
+
self.len(1, nodes)
|
|
94
|
+
self.eq('Pwn Some Boxes', nodes[0].get('title'))
|
|
95
|
+
self.eq('Yoink.', nodes[0].get('summary'))
|
|
96
|
+
self.nn(nodes[0].get('author'))
|
|
97
|
+
self.eq(1706832000000, nodes[0].get('created'))
|
|
98
|
+
self.eq(1706918400000, nodes[0].get('updated'))
|
|
99
|
+
self.eq(1099511627776, nodes[0].get('version'))
|
|
100
|
+
|
|
101
|
+
self.len(1, await core.nodes('plan:procedure :type -> plan:procedure:type:taxonomy'))
|
|
102
|
+
self.len(1, await core.nodes('plan:procedure :system -> plan:system +:name="Woot CNO Planner"'))
|
|
103
|
+
self.len(1, await core.nodes('plan:procedure :firststep -> plan:procedure:step -> plan:procedure:link'))
|
|
104
|
+
|
|
105
|
+
nodes = await core.nodes('plan:procedure :inputs -> plan:procedure:variable')
|
|
106
|
+
self.len(1, nodes)
|
|
107
|
+
self.eq('network', nodes[0].get('name'))
|
|
108
|
+
self.eq('cidr', nodes[0].get('type'))
|
|
109
|
+
self.eq('127.0.0.0/24', nodes[0].get('default'))
|
|
110
|
+
self.nn(nodes[0].get('procedure'))
|
|
111
|
+
|
|
112
|
+
nodes = await core.nodes('plan:procedure :firststep -> plan:procedure:step')
|
|
113
|
+
self.len(1, nodes)
|
|
114
|
+
self.eq('Are there vulnerable services?', nodes[0].get('title'))
|
|
115
|
+
self.eq('Scan the target network and identify available services.', nodes[0].get('summary'))
|
|
116
|
+
self.nn(nodes[0].get('procedure'))
|
|
117
|
+
|
|
118
|
+
self.len(1, await core.nodes('plan:procedure :firststep -> plan:procedure:step -> plan:phase'))
|
|
119
|
+
self.len(1, await core.nodes('plan:procedure :firststep -> plan:procedure:step :techniques -> ou:technique'))
|
|
120
|
+
self.len(1, await core.nodes('plan:procedure :firststep -> plan:procedure:step :outputs -> plan:procedure:variable'))
|
|
121
|
+
|
|
122
|
+
nodes = await core.nodes('plan:procedure :firststep -> plan:procedure:step -> plan:procedure:link')
|
|
123
|
+
self.len(1, nodes)
|
|
124
|
+
self.eq(True, nodes[0].get('condition'))
|
|
125
|
+
self.nn(nodes[0].get('next'))
|
|
126
|
+
self.nn(nodes[0].get('procedure'))
|
|
@@ -254,7 +254,33 @@ class TestStormPkgTest(s_test.StormPkgTest):
|
|
|
254
254
|
assetdir = s_common.genpath(dirname, 'files', 'stormpkg', 'dotstorm', 'testassets')
|
|
255
255
|
pkgprotos = (s_common.genpath(dirname, 'files', 'stormpkg', 'dotstorm', 'dotstorm.yaml'),)
|
|
256
256
|
|
|
257
|
+
async def initTestCore(self, core):
|
|
258
|
+
await core.callStorm('$lib.globals.set(inittestcore, frob)')
|
|
259
|
+
|
|
257
260
|
async def test_stormpkg_base(self):
|
|
258
261
|
async with self.getTestCore() as core:
|
|
259
262
|
msgs = await core.stormlist('dotstorm.bar')
|
|
260
263
|
self.stormHasNoWarnErr(msgs)
|
|
264
|
+
self.eq('frob', await core.callStorm('return($lib.globals.get(inittestcore))'))
|
|
265
|
+
|
|
266
|
+
async def stormpkg_preppkghook(self, core):
|
|
267
|
+
await core.callStorm('$lib.globals.set(stormpkg_preppkghook, boundmethod)')
|
|
268
|
+
|
|
269
|
+
async def test_stormpkg_preppkghook(self):
|
|
270
|
+
|
|
271
|
+
# inline example
|
|
272
|
+
async def hook(core):
|
|
273
|
+
await core.callStorm('$lib.globals.set(inlinehook, haha)')
|
|
274
|
+
|
|
275
|
+
async with self.getTestCore(prepkghook=hook) as core:
|
|
276
|
+
msgs = await core.stormlist('dotstorm.bar')
|
|
277
|
+
self.stormHasNoWarnErr(msgs)
|
|
278
|
+
self.eq('haha', await core.callStorm('return($lib.globals.get(inlinehook))'))
|
|
279
|
+
self.eq('frob', await core.callStorm('return($lib.globals.get(inittestcore))'))
|
|
280
|
+
|
|
281
|
+
# bound method example
|
|
282
|
+
async with self.getTestCore(prepkghook=self.stormpkg_preppkghook) as core:
|
|
283
|
+
msgs = await core.stormlist('dotstorm.bar')
|
|
284
|
+
self.stormHasNoWarnErr(msgs)
|
|
285
|
+
self.eq('boundmethod', await core.callStorm('return($lib.globals.get(stormpkg_preppkghook))'))
|
|
286
|
+
self.eq('frob', await core.callStorm('return($lib.globals.get(inittestcore))'))
|
|
@@ -48,6 +48,7 @@ class HiveLoadTest(s_test.SynTest):
|
|
|
48
48
|
with mock.patch('synapse.telepath.Proxy._getSynVers', _getOldSynVers):
|
|
49
49
|
outp = self.getTestOutp()
|
|
50
50
|
retn = await s_hiveload.main(argv, outp=outp)
|
|
51
|
+
outp.expect('WARNING: "synapse.tools.hive.load" is deprecated in 2.167.0 and will be removed in 3.0.0')
|
|
51
52
|
outp.expect('Hive version 0.0.0 is outside of the hive.load supported range')
|
|
52
53
|
self.eq(1, retn)
|
|
53
54
|
|
|
@@ -28,6 +28,7 @@ class HiveSaveTest(s_test.SynTest):
|
|
|
28
28
|
with mock.patch('synapse.telepath.Proxy._getSynVers', _getOldSynVers):
|
|
29
29
|
outp = self.getTestOutp()
|
|
30
30
|
retn = await s_hivesave.main(argv, outp=outp)
|
|
31
|
+
outp.expect('WARNING: "synapse.tools.hive.save" is deprecated in 2.167.0 and will be removed in 3.0.0')
|
|
31
32
|
outp.expect('Hive version 0.0.0 is outside of the hive.save supported range')
|
|
32
33
|
self.eq(1, retn)
|
|
33
34
|
|