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.
- synapse/cortex.py +34 -14
- synapse/data/lark/storm.lark +9 -6
- synapse/lib/ast.py +8 -2
- synapse/lib/layer.py +149 -8
- synapse/lib/parser.py +1 -0
- synapse/lib/rstorm.py +83 -2
- synapse/lib/schemas.py +4 -0
- synapse/lib/snap.py +21 -13
- synapse/lib/stormhttp.py +10 -10
- synapse/lib/stormlib/aha.py +3 -3
- synapse/lib/stormlib/auth.py +11 -11
- synapse/lib/stormlib/cell.py +1 -1
- synapse/lib/stormlib/cortex.py +10 -10
- synapse/lib/stormlib/env.py +4 -5
- synapse/lib/stormlib/ethereum.py +1 -1
- synapse/lib/stormlib/gen.py +3 -3
- synapse/lib/stormlib/hex.py +2 -2
- synapse/lib/stormlib/imap.py +2 -2
- synapse/lib/stormlib/infosec.py +2 -2
- synapse/lib/stormlib/iters.py +2 -2
- synapse/lib/stormlib/model.py +5 -5
- synapse/lib/stormlib/notifications.py +1 -1
- synapse/lib/stormlib/oauth.py +2 -2
- synapse/lib/stormlib/project.py +3 -3
- synapse/lib/stormlib/scrape.py +2 -1
- synapse/lib/stormlib/smtp.py +3 -3
- synapse/lib/stormlib/stats.py +2 -2
- synapse/lib/stormlib/stix.py +2 -2
- synapse/lib/stormlib/utils.py +19 -0
- synapse/lib/stormlib/vault.py +1 -1
- synapse/lib/stormlib/xml.py +2 -2
- synapse/lib/stormlib/yaml.py +1 -1
- synapse/lib/stormtypes.py +182 -64
- synapse/lib/version.py +2 -2
- synapse/models/orgs.py +3 -0
- synapse/tests/test_lib_grammar.py +4 -4
- synapse/tests/test_lib_layer.py +86 -67
- synapse/tests/test_lib_rstorm.py +180 -0
- synapse/tests/test_lib_storm.py +80 -1
- synapse/tests/test_lib_stormlib_auth.py +84 -0
- synapse/tests/test_lib_stormlib_cortex.py +1 -0
- synapse/tests/test_lib_stormlib_env.py +3 -1
- synapse/tests/test_lib_stormlib_utils.py +10 -0
- synapse/tests/test_lib_stormtypes.py +576 -2
- synapse/tests/test_model_orgs.py +6 -1
- synapse/tools/aha/list.py +9 -9
- synapse/tools/aha/provision/service.py +2 -2
- {synapse-2.220.0.dist-info → synapse-2.222.0.dist-info}/METADATA +1 -1
- {synapse-2.220.0.dist-info → synapse-2.222.0.dist-info}/RECORD +52 -52
- {synapse-2.220.0.dist-info → synapse-2.222.0.dist-info}/WHEEL +0 -0
- {synapse-2.220.0.dist-info → synapse-2.222.0.dist-info}/licenses/LICENSE +0 -0
- {synapse-2.220.0.dist-info → synapse-2.222.0.dist-info}/top_level.txt +0 -0
synapse/tests/test_lib_layer.py
CHANGED
|
@@ -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
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
2401
|
-
|
|
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].
|
|
2404
|
-
self.eq(nodes[0].
|
|
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()))
|
synapse/tests/test_lib_rstorm.py
CHANGED
|
@@ -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)
|
synapse/tests/test_lib_storm.py
CHANGED
|
@@ -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:
|