synapse 2.220.0__py311-none-any.whl → 2.222.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 (52) hide show
  1. synapse/cortex.py +34 -14
  2. synapse/data/lark/storm.lark +9 -6
  3. synapse/lib/ast.py +8 -2
  4. synapse/lib/layer.py +149 -8
  5. synapse/lib/parser.py +1 -0
  6. synapse/lib/rstorm.py +83 -2
  7. synapse/lib/schemas.py +4 -0
  8. synapse/lib/snap.py +21 -13
  9. synapse/lib/stormhttp.py +10 -10
  10. synapse/lib/stormlib/aha.py +3 -3
  11. synapse/lib/stormlib/auth.py +11 -11
  12. synapse/lib/stormlib/cell.py +1 -1
  13. synapse/lib/stormlib/cortex.py +10 -10
  14. synapse/lib/stormlib/env.py +4 -5
  15. synapse/lib/stormlib/ethereum.py +1 -1
  16. synapse/lib/stormlib/gen.py +3 -3
  17. synapse/lib/stormlib/hex.py +2 -2
  18. synapse/lib/stormlib/imap.py +2 -2
  19. synapse/lib/stormlib/infosec.py +2 -2
  20. synapse/lib/stormlib/iters.py +2 -2
  21. synapse/lib/stormlib/model.py +5 -5
  22. synapse/lib/stormlib/notifications.py +1 -1
  23. synapse/lib/stormlib/oauth.py +2 -2
  24. synapse/lib/stormlib/project.py +3 -3
  25. synapse/lib/stormlib/scrape.py +2 -1
  26. synapse/lib/stormlib/smtp.py +3 -3
  27. synapse/lib/stormlib/stats.py +2 -2
  28. synapse/lib/stormlib/stix.py +2 -2
  29. synapse/lib/stormlib/utils.py +19 -0
  30. synapse/lib/stormlib/vault.py +1 -1
  31. synapse/lib/stormlib/xml.py +2 -2
  32. synapse/lib/stormlib/yaml.py +1 -1
  33. synapse/lib/stormtypes.py +182 -64
  34. synapse/lib/version.py +2 -2
  35. synapse/models/orgs.py +3 -0
  36. synapse/tests/test_lib_grammar.py +4 -4
  37. synapse/tests/test_lib_layer.py +86 -67
  38. synapse/tests/test_lib_rstorm.py +180 -0
  39. synapse/tests/test_lib_storm.py +80 -1
  40. synapse/tests/test_lib_stormlib_auth.py +84 -0
  41. synapse/tests/test_lib_stormlib_cortex.py +1 -0
  42. synapse/tests/test_lib_stormlib_env.py +3 -1
  43. synapse/tests/test_lib_stormlib_utils.py +10 -0
  44. synapse/tests/test_lib_stormtypes.py +576 -2
  45. synapse/tests/test_model_orgs.py +6 -1
  46. synapse/tools/aha/list.py +9 -9
  47. synapse/tools/aha/provision/service.py +2 -2
  48. {synapse-2.220.0.dist-info → synapse-2.222.0.dist-info}/METADATA +1 -1
  49. {synapse-2.220.0.dist-info → synapse-2.222.0.dist-info}/RECORD +52 -52
  50. {synapse-2.220.0.dist-info → synapse-2.222.0.dist-info}/WHEEL +0 -0
  51. {synapse-2.220.0.dist-info → synapse-2.222.0.dist-info}/licenses/LICENSE +0 -0
  52. {synapse-2.220.0.dist-info → synapse-2.222.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()))
@@ -1,4 +1,5 @@
1
1
  import os
2
+ import sys
2
3
 
3
4
  import vcr
4
5
 
@@ -223,6 +224,102 @@ A multiline secondary property.
223
224
  Bye!
224
225
  '''
225
226
 
227
+ shell_input00 = '''
228
+ Shell with environment variable.
229
+
230
+ .. shell-env:: SYN_HEHE_HAHA=BEEP SYN_FOO=BAR
231
+ .. shell:: python3 -c "import os; print('HEHE_HAHA', os.environ.get('SYN_HEHE_HAHA')); print('FOO', os.environ.get('SYN_FOO'))"
232
+ .. shell-env::
233
+ .. shell:: python3 -c "import os; print('HEHE_HAHA', os.environ.get('SYN_HEHE_HAHA')); print('FOO', os.environ.get('SYN_FOO'))"
234
+ '''
235
+
236
+ shell_output00 = '''
237
+ Shell with environment variable.
238
+
239
+ ::
240
+
241
+ python3 -c "import os; print('HEHE_HAHA', os.environ.get('SYN_HEHE_HAHA')); print('FOO', os.environ.get('SYN_FOO'))"
242
+
243
+ HEHE_HAHA BEEP
244
+ FOO BAR
245
+
246
+
247
+ ::
248
+
249
+ python3 -c "import os; print('HEHE_HAHA', os.environ.get('SYN_HEHE_HAHA')); print('FOO', os.environ.get('SYN_FOO'))"
250
+
251
+ HEHE_HAHA None
252
+ FOO None
253
+
254
+
255
+ '''
256
+
257
+ shell_input01 = '''
258
+ Shell hide query.
259
+
260
+ .. shell:: --hide-query python3 -c "print('WOOT')"
261
+ '''
262
+
263
+ shell_output01 = '''
264
+ Shell hide query.
265
+
266
+ ::
267
+
268
+ WOOT
269
+
270
+
271
+ '''
272
+
273
+ shell_input02 = '''
274
+ Shell include stderr.
275
+
276
+ .. shell:: --hide-query \
277
+ python3 -c "import sys; print('FOO00'); sys.stdout.flush(); print('BAR00', file=sys.stderr); print('BAZ00')"
278
+ .. shell:: --hide-query --include-stderr \
279
+ python3 -c "import sys; print('FOO01'); sys.stdout.flush(); print('BAR01', file=sys.stderr); print('BAZ01')"
280
+ '''
281
+
282
+ shell_output02 = '''
283
+ Shell include stderr.
284
+
285
+ ::
286
+
287
+ FOO00
288
+ BAZ00
289
+
290
+
291
+ ::
292
+
293
+ FOO01
294
+ BAR01
295
+ BAZ01
296
+
297
+
298
+ '''
299
+
300
+ shell_text03 = '''--hide-query python3 -c "import sys; print('WOOT'); sys.exit(1)"'''
301
+ shell_input03 = f'''
302
+ Shell non-zero exit.
303
+
304
+ .. shell:: {shell_text03}
305
+ '''
306
+
307
+ shell_text04 = '''--hide-query --fail-ok python3 -c "import sys; print('WOOT'); sys.exit(1)"'''
308
+ shell_input04 = f'''
309
+ Shell non-zero exit.
310
+
311
+ .. shell:: {shell_text04}
312
+ '''
313
+ shell_output04 = '''
314
+ Shell non-zero exit.
315
+
316
+ ::
317
+
318
+ WOOT
319
+
320
+
321
+ '''
322
+
226
323
  fail00 = '''
227
324
 
228
325
  .. storm-cortex:: default
@@ -342,6 +439,42 @@ class RStormLibTest(s_test.SynTest):
342
439
  text_nocrt = '\n'.join(line for line in text.split('\n') if '.created =' not in line)
343
440
  self.eq(text_nocrt, multiline_storm_output)
344
441
 
442
+ # shell and shell-env
443
+ path = s_common.genpath(dirn, 'shell00.rst')
444
+ with s_common.genfile(path) as fd:
445
+ fd.write(shell_input00.encode())
446
+ text = await get_rst_text(path)
447
+ self.eq(text, shell_output00)
448
+
449
+ # shell --hide-query
450
+ path = s_common.genpath(dirn, 'shell01.rst')
451
+ with s_common.genfile(path) as fd:
452
+ fd.write(shell_input01.encode())
453
+ text = await get_rst_text(path)
454
+ self.eq(text, shell_output01)
455
+
456
+ # shell --include-stderr
457
+ path = s_common.genpath(dirn, 'shell02.rst')
458
+ with s_common.genfile(path) as fd:
459
+ fd.write(shell_input02.encode())
460
+ text = await get_rst_text(path)
461
+ self.eq(text, shell_output02)
462
+
463
+ # shell non-zero exit
464
+ path = s_common.genpath(dirn, 'shell03.rst')
465
+ with s_common.genfile(path) as fd:
466
+ fd.write(shell_input03.encode())
467
+ with self.raises(s_exc.SynErr) as exc:
468
+ await get_rst_text(path)
469
+ self.eq(exc.exception.get('mesg'), f'Error when executing shell directive: {shell_text03} (rv: 1)')
470
+
471
+ # shell non-zero exit --fail-ok
472
+ path = s_common.genpath(dirn, 'shell04.rst')
473
+ with s_common.genfile(path) as fd:
474
+ fd.write(shell_input04.encode())
475
+ text = await get_rst_text(path)
476
+ self.eq(text, shell_output04)
477
+
345
478
  # http
346
479
  path = s_common.genpath(dirn, 'http.rst')
347
480
  with s_common.genfile(path) as fd:
@@ -644,3 +777,50 @@ class RStormLibTest(s_test.SynTest):
644
777
  fd.write(fix_input_for_cli(fail02).encode())
645
778
  with self.raises(s_exc.StormRuntimeError):
646
779
  await get_rst_text(path)
780
+
781
+ async def test_rstorm_python_path(self):
782
+ content = '''#comment
783
+ import synapse.lib.cell as s_cell
784
+ import synapse.lib.stormsvc as s_stormsvc
785
+
786
+ class SomeApi(s_stormsvc.StormSvc, s_cell.CellApi):
787
+ _storm_svc_name = 'someservice'
788
+ _storm_svc_vers = '0.1.0',
789
+ _storm_svc_pkgs = ()
790
+
791
+ class SomeService(s_cell.Cell):
792
+ cellapi = SomeApi
793
+ '''
794
+ with self.getTestDir() as dirn:
795
+ with s_common.genfile(dirn, 'somefile.py') as fd:
796
+ fd.write(content.encode())
797
+ pythonpath_rst_in = f'''
798
+ .. storm-cortex:: default
799
+ .. storm-python-path:: {dirn}
800
+ .. storm-svc:: somefile.SomeService fooservice {{"https:port": 0}}
801
+ .. storm:: service.list
802
+
803
+ hello world
804
+ '''
805
+ rst_path = s_common.genpath(dirn, 'test.rst')
806
+
807
+ with s_common.genfile(rst_path) as fd:
808
+ fd.write(pythonpath_rst_in.encode())
809
+
810
+ pythonpath_rst_out = await get_rst_text(rst_path)
811
+ self.notin('storm-python-path', pythonpath_rst_out)
812
+ self.isin('(fooservice) (someservice @ 0.1.0)', pythonpath_rst_out)
813
+ self.isin('hello world', pythonpath_rst_out)
814
+ # Fini handler cleaned up the path manipulation
815
+ self.notin(dirn, sys.path)
816
+
817
+ # Sad path
818
+ pythonpath_rst_in = f'''
819
+ .. storm-python-path:: {dirn}/{s_common.guid()}
820
+ hello world
821
+ '''
822
+ rst_path = s_common.genpath(dirn, 'test.rst')
823
+ with s_common.genfile(rst_path) as fd:
824
+ fd.write(pythonpath_rst_in.encode())
825
+ with self.raises(s_exc.NoSuchDir):
826
+ await get_rst_text(rst_path)
@@ -1,6 +1,5 @@
1
1
  import copy
2
2
  import asyncio
3
- import datetime
4
3
  import itertools
5
4
  import urllib.parse as u_parse
6
5
  import unittest.mock as mock
@@ -17,6 +16,7 @@ import synapse.lib.storm as s_storm
17
16
  import synapse.lib.httpapi as s_httpapi
18
17
  import synapse.lib.msgpack as s_msgpack
19
18
  import synapse.lib.version as s_version
19
+ import synapse.lib.stormtypes as s_stormtypes
20
20
 
21
21
  import synapse.tests.utils as s_t_utils
22
22
  from synapse.tests.utils import alist
@@ -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)
@@ -4868,6 +4874,79 @@ class StormTest(s_t_utils.SynTest):
4868
4874
  self.len(1, links)
4869
4875
  self.eq({'type': 'runtime'}, links[0][1])
4870
4876
 
4877
+ async def test_storm_derefprops(self):
4878
+ async with self.getTestCore() as core:
4879
+ await core.addTagProp('score', ('int', {}), {})
4880
+
4881
+ mesg = "Expected value of type 'str', got '"
4882
+
4883
+ # editnodeadd
4884
+ msgs = await core.stormlist('$form = inet:fqdn [ *$form=foobar.com ]')
4885
+ self.stormHasNoWarnErr(msgs)
4886
+
4887
+ invals = [10, None, False, [], {}]
4888
+
4889
+ for inval in invals:
4890
+ opts = {'vars': {'form': inval}}
4891
+ with self.raises(s_exc.StormRuntimeError) as exc:
4892
+ await core.nodes('[ *$form=valu ]', opts=opts)
4893
+ self.true(exc.exception.get('mesg').startswith(mesg))
4894
+
4895
+ # liftprop
4896
+ msgs = await core.stormlist('$form = inet:fqdn *$form')
4897
+ self.stormHasNoWarnErr(msgs)
4898
+
4899
+ for inval in invals:
4900
+ opts = {'vars': {'form': inval}}
4901
+ with self.raises(s_exc.StormRuntimeError) as exc:
4902
+ await core.nodes('*$form', opts=opts)
4903
+ self.true(exc.exception.get('mesg').startswith(mesg))
4904
+
4905
+ # liftpropby
4906
+ msgs = await core.stormlist('$form = inet:fqdn *$form=foobar.com')
4907
+ self.stormHasNoWarnErr(msgs)
4908
+
4909
+ for inval in invals:
4910
+ opts = {'vars': {'form': inval}}
4911
+ with self.raises(s_exc.StormRuntimeError) as exc:
4912
+ await core.nodes('*$form=newp', opts=opts)
4913
+ self.true(exc.exception.get('mesg').startswith(mesg))
4914
+
4915
+ # liftformtag
4916
+ msgs = await core.stormlist('$form = inet:fqdn *$form#foo')
4917
+ self.stormHasNoWarnErr(msgs)
4918
+
4919
+ for inval in invals:
4920
+ opts = {'vars': {'form': inval}}
4921
+ with self.raises(s_exc.StormRuntimeError) as exc:
4922
+ await core.nodes('*$form#newp', opts=opts)
4923
+ self.true(exc.exception.get('mesg').startswith(mesg))
4924
+
4925
+ # liftbyarray
4926
+ msgs = await core.stormlist('$form = test:arrayform *$form*[=(10)]')
4927
+ self.stormHasNoWarnErr(msgs)
4928
+
4929
+ for inval in invals:
4930
+ opts = {'vars': {'form': inval}}
4931
+ with self.raises(s_exc.StormRuntimeError) as exc:
4932
+ await core.nodes('*$form*[="newp"]', opts=opts)
4933
+ self.true(exc.exception.get('mesg').startswith(mesg))
4934
+
4935
+ # formtagprop
4936
+ msgs = await core.stormlist('$form = inet:fqdn *$form#foo:score')
4937
+ self.stormHasNoWarnErr(msgs)
4938
+
4939
+ for inval in invals:
4940
+ opts = {'vars': {'form': inval}}
4941
+ with self.raises(s_exc.StormRuntimeError) as exc:
4942
+ await core.nodes('*$form#newp:score', opts=opts)
4943
+ self.true(exc.exception.get('mesg').startswith(mesg))
4944
+
4945
+ # Check Storm Str types
4946
+ name = s_stormtypes.Str('inet:fqdn')
4947
+ msgs = await core.stormlist('*$form', opts={'vars': {'form': name}})
4948
+ self.stormHasNoWarnErr(msgs)
4949
+
4871
4950
  async def test_storm_nested_root(self):
4872
4951
  async with self.getTestCore() as core:
4873
4952
  self.eq(20, await core.callStorm('''
@@ -427,6 +427,90 @@ class StormLibAuthTest(s_test.SynTest):
427
427
  opts=asuser
428
428
  )
429
429
 
430
+ async def test_stormlib_auth_asroot_ondeny(self):
431
+ async with self.getTestCore() as core:
432
+
433
+ stormpkg = {
434
+ 'name': 'authtest',
435
+ 'version': '0.0.1',
436
+ 'perms': (
437
+ {'perm': ('authtest', 'perm'), 'desc': 'Elevate mod', 'gate': 'cortex'},
438
+ ),
439
+ 'modules': (
440
+ {
441
+ 'name': 'authtest.mod.default',
442
+ 'asroot:perms': (
443
+ ('authtest', 'perm'),
444
+ ),
445
+ 'storm': 'function func() { [ test:guid=* ] return($node) }',
446
+ },
447
+ {
448
+ 'name': 'authtest.mod.allow',
449
+ 'asroot:perms': (
450
+ ('authtest', 'perm'),
451
+ ),
452
+ 'asroot:ondeny:import': 'allow',
453
+ 'storm': '''
454
+ function func() { [ test:guid=* ] return($node) }
455
+ function func2() { [ test:str=newp ] return($node) }
456
+ ''',
457
+ },
458
+ {
459
+ 'name': 'authtest.mod.warn',
460
+ 'asroot:perms': (
461
+ ('authtest', 'perm'),
462
+ ),
463
+ 'asroot:ondeny:import': 'warn',
464
+ 'storm': '''
465
+ function func() { [ test:guid=* ] return($node) }
466
+ function func2() { [ test:str=newp ] return($node) }
467
+ ''',
468
+ },
469
+ {
470
+ 'name': 'authtest.mod.deny',
471
+ 'asroot:perms': (
472
+ ('authtest', 'perm'),
473
+ ),
474
+ 'asroot:ondeny:import': 'deny',
475
+ 'storm': 'function func() { [ test:guid=* ] return($node) }',
476
+ },
477
+ ),
478
+ }
479
+
480
+ await core.stormlist('auth.user.add user')
481
+ await core.stormlist('auth.user.add lowuser')
482
+
483
+ await core.addStormPkg(stormpkg)
484
+
485
+ user = await core.auth.getUserByName('user')
486
+ asuser = {'user': user.iden}
487
+
488
+ lowuser = await core.auth.getUserByName('lowuser')
489
+ aslowuser = {'user': lowuser.iden}
490
+
491
+ await core.stormlist('auth.user.addrule user authtest.perm')
492
+ await core.stormlist('auth.user.addrule lowuser node.add.test:guid')
493
+
494
+ # user has no node perms, but has asroot so perms are elevated
495
+ self.len(1, await core.nodes('yield $lib.import(authtest.mod.default).func()', opts=asuser))
496
+ self.len(1, await core.nodes('yield $lib.import(authtest.mod.allow).func()', opts=asuser))
497
+ self.len(1, await core.nodes('yield $lib.import(authtest.mod.deny).func()', opts=asuser))
498
+ msgs = await core.stormlist('yield $lib.import(authtest.mod.warn).func()', opts=asuser)
499
+ self.stormHasNoWarnErr(msgs)
500
+ self.len(1, [m for m in msgs if m[0] == 'node'])
501
+
502
+ # lowuser does not have asroot perms and gets denied importing certain modules
503
+ await self.asyncraises(s_exc.AuthDeny, core.nodes('yield $lib.import(authtest.mod.deny).func()', opts=aslowuser))
504
+ await self.asyncraises(s_exc.AuthDeny, core.nodes('yield $lib.import(authtest.mod.default).func()', opts=aslowuser))
505
+ # ...and for modules they can import perms are not elevated so they can only add test:guid nodes
506
+ self.len(1, await core.nodes('yield $lib.import(authtest.mod.allow).func()', opts=aslowuser))
507
+ msgs = await core.stormlist('yield $lib.import(authtest.mod.warn).func()', opts=aslowuser)
508
+ self.stormIsInWarn('permissions will not be elevated.', msgs)
509
+ self.len(1, [m for m in msgs if m[0] == 'node'])
510
+ # ...and gets denied on adding test:str nodes
511
+ await self.asyncraises(s_exc.AuthDeny, core.nodes('yield $lib.import(authtest.mod.allow).func2()', opts=aslowuser))
512
+ await self.asyncraises(s_exc.AuthDeny, core.nodes('yield $lib.import(authtest.mod.warn).func2()', opts=aslowuser))
513
+
430
514
  async def test_stormlib_auth_userjson(self):
431
515
 
432
516
  async with self.getTestCore() as core:
@@ -110,6 +110,7 @@ $request.reply(206, headers=$headers, body=({"no":"body"}))
110
110
  self.eq(resp.status, http.HTTPStatus.OK)
111
111
  data = await resp.json()
112
112
  self.eq(data.get('method'), 'get')
113
+ self.eq(resp.headers.get('Content-Type'), 'application/json; charset=utf8')
113
114
 
114
115
  resp = await sess.post(f'https://localhost:{hport}/api/ext/testpath00')
115
116
  self.eq(resp.status, http.HTTPStatus.CREATED)
@@ -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):
@@ -1,8 +1,18 @@
1
1
  import synapse.exc as s_exc
2
+ import synapse.common as s_common
3
+
2
4
  import synapse.tests.utils as s_test
3
5
 
4
6
  class UtilsTest(s_test.SynTest):
5
7
 
8
+ async def test_lib_stormlib_utils_buid(self):
9
+ async with self.getTestCore() as core:
10
+ obj = ('meta:source', '0123456789abcdef0123456789abcdef')
11
+ self.eq(
12
+ await core.callStorm('return($lib.utils.buid($obj))', opts={'vars': {'obj': obj}}),
13
+ s_common.buid(obj)
14
+ )
15
+
6
16
  async def test_lib_stormlib_utils_todo(self):
7
17
 
8
18
  async with self.getTestCore() as core: