synapse 2.219.0__py311-none-any.whl → 2.221.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 (55) hide show
  1. synapse/data/__init__.py +4 -0
  2. synapse/data/lark/__init__.py +0 -0
  3. synapse/data/lark/imap.lark +8 -0
  4. synapse/exc.py +2 -0
  5. synapse/lib/json.py +6 -5
  6. synapse/lib/layer.py +134 -0
  7. synapse/lib/link.py +49 -50
  8. synapse/lib/parser.py +3 -5
  9. synapse/lib/rstorm.py +65 -2
  10. synapse/lib/snap.py +21 -13
  11. synapse/lib/storm.py +1 -0
  12. synapse/lib/stormhttp.py +10 -10
  13. synapse/lib/stormlib/aha.py +3 -3
  14. synapse/lib/stormlib/auth.py +11 -11
  15. synapse/lib/stormlib/cell.py +1 -1
  16. synapse/lib/stormlib/cortex.py +9 -9
  17. synapse/lib/stormlib/env.py +4 -5
  18. synapse/lib/stormlib/ethereum.py +1 -1
  19. synapse/lib/stormlib/gen.py +3 -3
  20. synapse/lib/stormlib/hex.py +2 -2
  21. synapse/lib/stormlib/imap.py +478 -37
  22. synapse/lib/stormlib/infosec.py +2 -2
  23. synapse/lib/stormlib/iters.py +2 -2
  24. synapse/lib/stormlib/model.py +5 -5
  25. synapse/lib/stormlib/notifications.py +1 -1
  26. synapse/lib/stormlib/oauth.py +2 -2
  27. synapse/lib/stormlib/project.py +3 -3
  28. synapse/lib/stormlib/scrape.py +2 -1
  29. synapse/lib/stormlib/smtp.py +3 -3
  30. synapse/lib/stormlib/stats.py +2 -2
  31. synapse/lib/stormlib/stix.py +2 -2
  32. synapse/lib/stormlib/utils.py +19 -0
  33. synapse/lib/stormlib/vault.py +1 -1
  34. synapse/lib/stormlib/xml.py +2 -2
  35. synapse/lib/stormlib/yaml.py +1 -1
  36. synapse/lib/stormtypes.py +203 -60
  37. synapse/lib/version.py +2 -2
  38. synapse/tests/test_lib_grammar.py +2 -4
  39. synapse/tests/test_lib_json.py +29 -0
  40. synapse/tests/test_lib_layer.py +86 -67
  41. synapse/tests/test_lib_rstorm.py +132 -0
  42. synapse/tests/test_lib_storm.py +11 -1
  43. synapse/tests/test_lib_stormlib_env.py +3 -1
  44. synapse/tests/test_lib_stormlib_imap.py +1307 -230
  45. synapse/tests/test_lib_stormlib_utils.py +10 -0
  46. synapse/tests/test_lib_stormtypes.py +583 -2
  47. synapse/tools/aha/list.py +9 -9
  48. synapse/tools/aha/provision/service.py +2 -2
  49. synapse/utils/stormcov/plugin.py +2 -5
  50. {synapse-2.219.0.dist-info → synapse-2.221.0.dist-info}/METADATA +1 -2
  51. {synapse-2.219.0.dist-info → synapse-2.221.0.dist-info}/RECORD +55 -53
  52. /synapse/{lib → data/lark}/storm.lark +0 -0
  53. {synapse-2.219.0.dist-info → synapse-2.221.0.dist-info}/WHEEL +0 -0
  54. {synapse-2.219.0.dist-info → synapse-2.221.0.dist-info}/licenses/LICENSE +0 -0
  55. {synapse-2.219.0.dist-info → synapse-2.221.0.dist-info}/top_level.txt +0 -0
@@ -2288,11 +2288,9 @@ class LayerTest(s_t_utils.SynTest):
2288
2288
 
2289
2289
  async with self.getTestCore() as core:
2290
2290
 
2291
- iden = (await core.addUser('lowuser')).get('iden')
2292
- lowuser = {'user': iden}
2293
-
2294
2291
  fork00 = await core.view.fork()
2295
2292
  layr00 = core.getLayer(fork00['layers'][0]['iden'])
2293
+ infork = {'view': fork00['iden']}
2296
2294
 
2297
2295
  await core.nodes('''
2298
2296
  for $prop in (_custom:risk:level, _custom:risk:severity) {
@@ -2308,10 +2306,41 @@ class LayerTest(s_t_utils.SynTest):
2308
2306
  self.len(1, await core.nodes('syn:prop=test:guid:_custom:risk:level'))
2309
2307
  self.len(1, await core.nodes('syn:prop=test:guid:_custom:risk:severity'))
2310
2308
 
2311
- await core.nodes('[ test:guid=* :name=test1 :_custom:risk:level=low ]', opts={'view': fork00['iden']})
2309
+ # Full node in the default layer
2310
+ nodes = await core.nodes('[ test:guid=* :name=test0 :_custom:risk:level=high ]')
2311
+ self.len(1, nodes)
2312
+ testnode00 = nodes[0]
2313
+
2314
+ # Make some edits in the fork layer
2315
+ q = '''
2316
+ test:guid
2317
+ [
2318
+ :_custom:risk:level=medium
2319
+ <(seen)+ {[ meta:source=* ]}
2320
+ +(refs)> {[ test:str=foobar ]}
2321
+ ]
2322
+ $node.data.set(foo, foo)
2323
+ $node.data.set(bar, bar)
2324
+ $node.data.set(baz, baz)
2325
+ '''
2326
+ msgs = await core.stormlist(q, opts=infork)
2327
+ self.stormHasNoWarnErr(msgs)
2328
+
2329
+ nodes = await core.nodes('test:str=foobar', opts=infork)
2330
+ self.len(1, nodes)
2331
+ refs = nodes[0]
2332
+
2333
+ # Edit a prop on the node in the default layer
2334
+ await core.nodes('test:guid [ :_custom:risk:level=medium ]', opts=infork)
2335
+
2336
+ # Full node in the fork layer
2337
+ nodes = await core.nodes('[ test:guid=* :name=test1 :_custom:risk:level=low ]', opts=infork)
2338
+ self.len(1, nodes)
2312
2339
 
2313
2340
  await core.getView(fork00['iden']).delete()
2314
2341
 
2342
+ # Can't delete prop because we iterated through the views and there's a _custom:risk:level prop in an
2343
+ # orphaned layer
2315
2344
  with self.raises(s_exc.CantDelProp) as cm:
2316
2345
  await core.callStorm('''
2317
2346
  $fullprop = "test:guid:_custom:risk:level"
@@ -2319,86 +2348,76 @@ class LayerTest(s_t_utils.SynTest):
2319
2348
  view.exec $view.iden {
2320
2349
  yield $lib.layer.get().liftByProp($fullprop)
2321
2350
  $repr = $node.repr("_custom:risk:level")
2322
- [ :severity=$repr -:_custom:risk:level ]
2351
+ [ :_custom:risk:severity=$repr -:_custom:risk:level ]
2323
2352
  }
2324
2353
  }
2325
2354
  $lib.model.ext.delFormProp("test:guid", "_custom:risk:level")
2326
2355
  ''')
2327
- self.isin('Nodes still exist with prop: test:guid:_custom:risk:level', str(cm.exception))
2356
+ self.eq(cm.exception.get('mesg'), f'Nodes still exist with prop: test:guid:_custom:risk:level in layer {layr00.iden}')
2328
2357
  self.len(1, await core.nodes('syn:prop=test:guid:_custom:risk:level'))
2329
2358
 
2330
- with self.raises(s_exc.NoSuchProp) as cm:
2331
- await core.callStorm('''
2332
- $layer = $lib.layer.get()
2333
- $layer.getStorNodesByProp("foo:bar:_custom:risk:level")
2334
- ''')
2335
- self.isin('No property named', str(cm.exception))
2336
-
2337
- with self.raises(s_exc.NoSuchProp):
2338
- await core.callStorm('''
2339
- $fullprop = "test:guid:_custom:risk:level"
2340
- for $layer in $lib.layer.list() {
2341
- for ($buid, $sode) in $layer.getStorNodesByProp($fullprop) {
2342
- $oldv = $sode.props."_custom:risk:level"
2343
- $layer.setStorNodeProp($buid, "foo:bar:severity", $oldv.0)
2344
- }
2345
- }
2346
- ''')
2347
-
2348
- with self.raises(s_exc.BadTypeValu):
2349
- await core.callStorm('''
2350
- $fullprop = "test:guid:_custom:risk:level"
2351
- for $layer in $lib.layer.list() {
2352
- for ($buid, $sode) in $layer.getStorNodesByProp($fullprop) {
2353
- $layer.setStorNodeProp($buid, $fullprop, "newp")
2354
- }
2355
- }
2356
- ''')
2357
-
2358
- with self.raises(s_exc.NoSuchProp):
2359
- await core.callStorm('''
2360
- $fullprop = "test:guid:_custom:risk:level"
2361
- for $layer in $lib.layer.list() {
2362
- for ($buid, $sode) in $layer.getStorNodesByProp($fullprop) {
2363
- $layer.delStorNodeProp($buid, "foo:bar:severity")
2364
- }
2365
- }
2366
- ''')
2367
-
2368
- with self.raises(s_exc.AuthDeny) as cm:
2369
- await core.callStorm('''
2370
- $buid = "8c454b27df9c0ba109c123265b50869759bccac5bbec83b41992b4e91207f4a4"
2371
- $layer = $lib.layer.get()
2372
- $layer.setStorNodeProp($buid, "foo:bar:severity", "newp")
2373
- ''', opts=lowuser)
2374
- self.isin('requires admin privileges', str(cm.exception))
2375
-
2376
- with self.raises(s_exc.AuthDeny) as cm:
2377
- await core.callStorm('''
2378
- $buid = "8c454b27df9c0ba109c123265b50869759bccac5bbec83b41992b4e91207f4a4"
2379
- $layer = $lib.layer.get()
2380
- $layer.delStorNodeProp($buid, "foo:bar:severity")
2381
- ''', opts=lowuser)
2382
- self.isin('requires admin privileges', str(cm.exception))
2383
-
2359
+ # Migrate layer
2384
2360
  await core.callStorm('''
2385
2361
  $fullprop = "test:guid:_custom:risk:level"
2386
2362
  for $layer in $lib.layer.list() {
2387
2363
  if $layer.getPropCount($fullprop, maxsize=1) {
2388
- for ($buid, $sode) in $layer.getStorNodesByProp($fullprop, (10), "=") {
2364
+ for ($buid, $sode) in $layer.getStorNodesByProp($fullprop) {
2389
2365
  $oldv = $sode.props."_custom:risk:level"
2390
2366
  $layer.setStorNodeProp($buid, "test:guid:_custom:risk:severity", $oldv.0)
2391
2367
  $layer.delStorNodeProp($buid, $fullprop)
2392
2368
  }
2369
+
2370
+ $layer.delNodeData($buid, foo)
2371
+ $layer.delNodeData($buid, bar)
2372
+
2373
+ for ($verb, $n2iden) in $layer.getEdgesByN2($buid) {
2374
+ $layer.delEdge($n2iden, $verb, $buid)
2375
+ }
2393
2376
  }
2394
2377
  }
2395
2378
  $lib.model.ext.delFormProp("test:guid", "_custom:risk:level")
2396
2379
  ''')
2397
- self.len(0, await core.nodes('syn:prop=test:guid:_custom:risk:level'))
2398
- self.len(0, await core.nodes('test:guid:_custom:risk:severity'))
2399
2380
 
2400
- view00 = (await core.addView(vdef={'layers': [layr00.iden]}))['iden']
2401
- nodes = await core.nodes('test:guid', opts={'view': view00})
2381
+ nodes = await core.nodes('syn:prop=test:guid:_custom:risk:level')
2382
+ self.len(0, nodes)
2383
+
2384
+ nodes = await core.nodes('test:guid:_custom:risk:severity')
2385
+ self.len(1, nodes)
2386
+ self.eq(nodes[0].iden(), testnode00.iden())
2387
+ self.eq(nodes[0].get('name'), testnode00.get('name'))
2388
+ self.eq(nodes[0].get('_custom:risk:severity'), testnode00.get('_custom:risk:level'))
2389
+
2390
+ nodes = await core.nodes('syn:prop=test:guid:_custom:risk:level')
2391
+ self.len(0, nodes)
2392
+
2393
+ nodes = await core.nodes('test:guid:_custom:risk:severity')
2394
+ self.len(1, nodes)
2395
+ self.eq(nodes[0].iden(), testnode00.iden())
2396
+ self.eq(nodes[0].get('name'), testnode00.get('name'))
2397
+ self.eq(nodes[0].get('_custom:risk:severity'), testnode00.get('_custom:risk:level'))
2398
+
2399
+ view00 = (await core.addView(vdef={'layers': [layr00.iden, core.view.layers[0].iden]}))['iden']
2400
+ inview = {'view': view00}
2401
+
2402
+ nodes = await core.nodes('test:guid:name=test1', opts=inview)
2403
+ self.len(1, nodes)
2404
+ self.none(nodes[0].get('_custom:risk:level'))
2405
+ self.eq(nodes[0].get('_custom:risk:severity'), 10)
2406
+
2407
+ nodes = await core.nodes('test:guid:name=test0', opts=inview)
2408
+ self.len(1, nodes)
2409
+ self.none(nodes[0].get('_custom:risk:level'))
2410
+ self.eq(nodes[0].get('_custom:risk:severity'), 20)
2411
+ self.eq(await s_t_utils.alist(nodes[0].iterData()), [('baz', 'baz')])
2412
+ self.eq(await s_t_utils.alist(nodes[0].iterEdgesN1()), [('refs', refs.iden())])
2413
+ self.len(0, await s_t_utils.alist(nodes[0].iterEdgesN2()))
2414
+
2415
+ msgs = await core.stormlist('test:guid:name=test0 $lib.layer.get().delStorNode($node)', opts=inview)
2416
+
2417
+ nodes = await core.nodes('test:guid:name=test0', opts=inview)
2402
2418
  self.len(1, nodes)
2403
- self.none(nodes[0].props.get('_custom:risk:level'))
2404
- self.eq(nodes[0].props.get('_custom:risk:severity'), 10)
2419
+ self.none(nodes[0].get('_custom:risk:level'))
2420
+ self.eq(nodes[0].get('_custom:risk:severity'), 30)
2421
+ self.len(0, await s_t_utils.alist(nodes[0].iterData()))
2422
+ self.len(0, await s_t_utils.alist(nodes[0].iterEdgesN1()))
2423
+ self.len(0, await s_t_utils.alist(nodes[0].iterEdgesN2()))
@@ -223,6 +223,102 @@ A multiline secondary property.
223
223
  Bye!
224
224
  '''
225
225
 
226
+ shell_input00 = '''
227
+ Shell with environment variable.
228
+
229
+ .. shell-env:: SYN_LOG_LEVEL=DEBUG SYN_FOO=BAR
230
+ .. shell:: python3 -c "import os; print('LEVEL', os.environ.get('SYN_LOG_LEVEL')); print('FOO', os.environ.get('SYN_FOO'))"
231
+ .. shell-env::
232
+ .. shell:: python3 -c "import os; print('LEVEL', os.environ.get('SYN_LOG_LEVEL')); print('FOO', os.environ.get('SYN_FOO'))"
233
+ '''
234
+
235
+ shell_output00 = '''
236
+ Shell with environment variable.
237
+
238
+ ::
239
+
240
+ python3 -c "import os; print('LEVEL', os.environ.get('SYN_LOG_LEVEL')); print('FOO', os.environ.get('SYN_FOO'))"
241
+
242
+ LEVEL DEBUG
243
+ FOO BAR
244
+
245
+
246
+ ::
247
+
248
+ python3 -c "import os; print('LEVEL', os.environ.get('SYN_LOG_LEVEL')); print('FOO', os.environ.get('SYN_FOO'))"
249
+
250
+ LEVEL None
251
+ FOO None
252
+
253
+
254
+ '''
255
+
256
+ shell_input01 = '''
257
+ Shell hide query.
258
+
259
+ .. shell:: --hide-query python3 -c "print('WOOT')"
260
+ '''
261
+
262
+ shell_output01 = '''
263
+ Shell hide query.
264
+
265
+ ::
266
+
267
+ WOOT
268
+
269
+
270
+ '''
271
+
272
+ shell_input02 = '''
273
+ Shell include stderr.
274
+
275
+ .. shell:: --hide-query \
276
+ python3 -c "import sys; print('FOO00'); sys.stdout.flush(); print('BAR00', file=sys.stderr); print('BAZ00')"
277
+ .. shell:: --hide-query --include-stderr \
278
+ python3 -c "import sys; print('FOO01'); sys.stdout.flush(); print('BAR01', file=sys.stderr); print('BAZ01')"
279
+ '''
280
+
281
+ shell_output02 = '''
282
+ Shell include stderr.
283
+
284
+ ::
285
+
286
+ FOO00
287
+ BAZ00
288
+
289
+
290
+ ::
291
+
292
+ FOO01
293
+ BAR01
294
+ BAZ01
295
+
296
+
297
+ '''
298
+
299
+ shell_text03 = '''--hide-query python3 -c "import sys; print('WOOT'); sys.exit(1)"'''
300
+ shell_input03 = f'''
301
+ Shell non-zero exit.
302
+
303
+ .. shell:: {shell_text03}
304
+ '''
305
+
306
+ shell_text04 = '''--hide-query --fail-ok python3 -c "import sys; print('WOOT'); sys.exit(1)"'''
307
+ shell_input04 = f'''
308
+ Shell non-zero exit.
309
+
310
+ .. shell:: {shell_text04}
311
+ '''
312
+ shell_output04 = '''
313
+ Shell non-zero exit.
314
+
315
+ ::
316
+
317
+ WOOT
318
+
319
+
320
+ '''
321
+
226
322
  fail00 = '''
227
323
 
228
324
  .. storm-cortex:: default
@@ -342,6 +438,42 @@ class RStormLibTest(s_test.SynTest):
342
438
  text_nocrt = '\n'.join(line for line in text.split('\n') if '.created =' not in line)
343
439
  self.eq(text_nocrt, multiline_storm_output)
344
440
 
441
+ # shell and shell-env
442
+ path = s_common.genpath(dirn, 'shell00.rst')
443
+ with s_common.genfile(path) as fd:
444
+ fd.write(shell_input00.encode())
445
+ text = await get_rst_text(path)
446
+ self.eq(text, shell_output00)
447
+
448
+ # shell --hide-query
449
+ path = s_common.genpath(dirn, 'shell01.rst')
450
+ with s_common.genfile(path) as fd:
451
+ fd.write(shell_input01.encode())
452
+ text = await get_rst_text(path)
453
+ self.eq(text, shell_output01)
454
+
455
+ # shell --include-stderr
456
+ path = s_common.genpath(dirn, 'shell02.rst')
457
+ with s_common.genfile(path) as fd:
458
+ fd.write(shell_input02.encode())
459
+ text = await get_rst_text(path)
460
+ self.eq(text, shell_output02)
461
+
462
+ # shell non-zero exit
463
+ path = s_common.genpath(dirn, 'shell03.rst')
464
+ with s_common.genfile(path) as fd:
465
+ fd.write(shell_input03.encode())
466
+ with self.raises(s_exc.SynErr) as exc:
467
+ await get_rst_text(path)
468
+ self.eq(exc.exception.get('mesg'), f'Error when executing shell directive: {shell_text03} (rv: 1)')
469
+
470
+ # shell non-zero exit --fail-ok
471
+ path = s_common.genpath(dirn, 'shell04.rst')
472
+ with s_common.genfile(path) as fd:
473
+ fd.write(shell_input04.encode())
474
+ text = await get_rst_text(path)
475
+ self.eq(text, shell_output04)
476
+
345
477
  # http
346
478
  path = s_common.genpath(dirn, 'http.rst')
347
479
  with s_common.genfile(path) as fd:
@@ -148,6 +148,12 @@ class StormTest(s_t_utils.SynTest):
148
148
  orgn = nodes[0].ndef
149
149
  self.eq(orgn, nodes11[0].ndef)
150
150
 
151
+ self.len(1, await core.nodes('ou:org?=({"name": "the vertex project", "type": "lulz"})'))
152
+
153
+ with self.raises(s_exc.BadTypeValu):
154
+ await core.nodes('ou:org=({"logo": "newp"})')
155
+ self.len(0, await core.nodes('ou:org?=({"logo": "newp"})'))
156
+
151
157
  q = '[ ps:contact=* :org={ ou:org=({"name": "the vertex project", "type": "lulz"}) } ]'
152
158
  nodes = await core.nodes(q)
153
159
  self.len(1, nodes)
@@ -732,13 +738,17 @@ class StormTest(s_t_utils.SynTest):
732
738
  [(ou:org=* :names=(foo, baz))]
733
739
  [(ou:org=* :names=(foo, hehe))]
734
740
  ''')
735
- nodes = await core.nodes('ou:org | intersect { -> ou:name }')
741
+ nodes = await core.nodes('ou:org | intersect { -> ou:name }', opts={'readonly': True})
736
742
  self.len(1, nodes)
737
743
  self.eq(nodes[0].ndef[1], 'foo')
738
744
 
739
745
  msgs = await core.stormlist('ou:org $foo=$node.value() | intersect $foo')
740
746
  self.stormIsInErr('intersect arguments must be runtsafe', msgs)
741
747
 
748
+ with self.raises(s_exc.IsReadOnly) as exc:
749
+ await core.nodes('ou:org | intersect { [ou:org=*] }', opts={'readonly': True})
750
+ self.eq(exc.exception.get('mesg'), 'Storm runtime is in readonly mode, cannot create or edit nodes and other graph data.')
751
+
742
752
  async def test_lib_storm_trycatch(self):
743
753
 
744
754
  async with self.getTestCore() as core:
@@ -1,4 +1,3 @@
1
- import os
2
1
  import synapse.exc as s_exc
3
2
  import synapse.tests.utils as s_test
4
3
 
@@ -15,6 +14,9 @@ class StormLibEnvTest(s_test.SynTest):
15
14
 
16
15
  self.none(await core.callStorm('return($lib.env.get(SYN_STORM_ENV_HEHE))'))
17
16
 
17
+ valu = await core.callStorm('return($lib.env.get(SYN_STORM_ENV_NOPE, default=({"foo": "bar"})))')
18
+ self.eq(valu, "{'foo': 'bar'}")
19
+
18
20
  visi = await core.auth.addUser('visi')
19
21
 
20
22
  with self.raises(s_exc.AuthDeny):