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.

Files changed (53) hide show
  1. synapse/axon.py +4 -10
  2. synapse/cortex.py +55 -12
  3. synapse/exc.py +1 -0
  4. synapse/lib/aha.py +4 -1
  5. synapse/lib/base.py +11 -4
  6. synapse/lib/cell.py +11 -2
  7. synapse/lib/hive.py +11 -0
  8. synapse/lib/layer.py +2 -0
  9. synapse/lib/modelrev.py +6 -0
  10. synapse/lib/modules.py +1 -0
  11. synapse/lib/node.py +4 -2
  12. synapse/lib/schemas.py +1 -1
  13. synapse/lib/stormlib/aha.py +385 -20
  14. synapse/lib/stormlib/easyperm.py +8 -0
  15. synapse/lib/stormlib/macro.py +11 -18
  16. synapse/lib/stormlib/stix.py +1 -1
  17. synapse/lib/stormtypes.py +25 -2
  18. synapse/lib/types.py +2 -0
  19. synapse/lib/version.py +2 -2
  20. synapse/lib/view.py +5 -3
  21. synapse/models/base.py +8 -0
  22. synapse/models/files.py +3 -0
  23. synapse/models/planning.py +161 -0
  24. synapse/telepath.py +1 -0
  25. synapse/tests/files/stormpkg/dotstorm/dotstorm.yaml +3 -0
  26. synapse/tests/test_cortex.py +40 -3
  27. synapse/tests/test_lib_aha.py +8 -4
  28. synapse/tests/test_lib_cell.py +6 -2
  29. synapse/tests/test_lib_grammar.py +62 -64
  30. synapse/tests/test_lib_httpapi.py +1 -1
  31. synapse/tests/test_lib_rstorm.py +4 -4
  32. synapse/tests/test_lib_storm.py +3 -3
  33. synapse/tests/test_lib_stormlib_aha.py +196 -0
  34. synapse/tests/test_lib_stormlib_compression.py +12 -12
  35. synapse/tests/test_lib_stormlib_macro.py +94 -0
  36. synapse/tests/test_lib_stormlib_spooled.py +1 -1
  37. synapse/tests/test_lib_stormtypes.py +44 -33
  38. synapse/tests/test_lib_trigger.py +3 -3
  39. synapse/tests/test_lib_view.py +50 -3
  40. synapse/tests/test_model_files.py +3 -0
  41. synapse/tests/test_model_planning.py +126 -0
  42. synapse/tests/test_tools_genpkg.py +26 -0
  43. synapse/tests/test_tools_hiveload.py +1 -0
  44. synapse/tests/test_tools_hivesave.py +1 -0
  45. synapse/tests/utils.py +22 -3
  46. synapse/tools/autodoc.py +1 -1
  47. synapse/tools/hive/load.py +3 -0
  48. synapse/tools/hive/save.py +3 -0
  49. {synapse-2.166.0.dist-info → synapse-2.168.0.dist-info}/METADATA +3 -3
  50. {synapse-2.166.0.dist-info → synapse-2.168.0.dist-info}/RECORD +53 -50
  51. {synapse-2.166.0.dist-info → synapse-2.168.0.dist-info}/LICENSE +0 -0
  52. {synapse-2.166.0.dist-info → synapse-2.168.0.dist-info}/WHEEL +0 -0
  53. {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
- [ graph:node="*" ] +graph:node [ :data=$set.list() ]
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('[graph:node="*" :data=$data]', opts={'vars': {'data': ghstr}})
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('[graph:node="*" :data=$data]', opts={'vars': {'data': mstr}})
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 = '''graph:node=$n1 $gzthing = :data
1353
+ q = '''tel:mob:telem=$n1 $gzthing = :data
1354
1354
  $foo = $lib.base64.decode($gzthing).gunzip()
1355
1355
  $lib.print($foo)
1356
- [( graph:node=$n2 :data=$foo.decode() )]'''
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('graph:node=$valu', opts={'vars': {'valu': n2}})
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'''graph:node=$n2 $bar = :data
1368
- [( graph:node=$n3 :data=$lib.base64.encode($bar.encode().gzip()) )]'''
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('graph:node=$valu', opts={'vars': {'valu': n3}})
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('[graph:node="*" :data=$data]', opts={'vars': {'data': ghstr}})
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('[graph:node="*" :data=$data]', opts={'vars': {'data': mstr}})
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 = '''graph:node=$valu $bzthing = :data $foo = $lib.base64.decode($bzthing).bunzip()
1393
+ q = '''tel:mob:telem=$valu $bzthing = :data $foo = $lib.base64.decode($bzthing).bunzip()
1394
1394
  $lib.print($foo)
1395
- [( graph:node=$n2 :data=$foo.decode() )] -graph:node=$valu'''
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('graph:node=$iden', opts=opts)
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 = '''graph:node=$valu $bar = :data
1409
- [( graph:node=$n3 :data=$lib.base64.encode($bar.encode().bzip()) )] -graph:node=$valu'''
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('[graph:node=$valu :data=$data]', opts={'vars': {'valu': valu, 'data': ghstr}})
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 = '''graph:node=$valu $jzthing=:data $foo=$jzthing.encode().json() [(graph:node=$n2 :data=$foo)]
1429
- -graph:node=$valu'''
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
- [ graph:node="*" ] +graph:node [ :data=$set.list() ]
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
- [ graph:node="*" ] +graph:node [ :data=$set.list() ]
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
- [ graph:node="*" ] +graph:node [ :data=$set.list() ]
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
- [ graph:node="*" ] +graph:node [ :data=$set.list() ]
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
- [ graph:node="*" ] +graph:node [ :data=$idens ]
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="{[graph:node=*]}", hourly=30).pack())')
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 {[graph:node=*]} --name myname --doc mydoc')
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 {[graph:node='*' :type=m1]}"
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('graph:node:type=m1'))
4651
+ self.eq(1, await prox.count('meta:note:type=m1'))
4641
4652
 
4642
- q = "cron.mod $guid { [graph:node='*' :type=m2] }"
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 { [graph:node='*' :type=m2] }"
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('graph:node:type=m1'))
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('graph:node:type=m2'))
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('graph:node:type=m1'))
4671
- self.eq(1, await prox.count('graph:node:type=m2'))
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)
@@ -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 test_view_nomerge(self):
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(nomerge, $lib.true)', opts=opts)
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
- await core.nodes('$lib.view.get().set(nomerge, $lib.false)', opts=opts)
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