synapse 2.189.0__py311-none-any.whl → 2.191.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/common.py +9 -0
- synapse/cortex.py +26 -5
- synapse/datamodel.py +8 -1
- synapse/lib/cell.py +7 -7
- synapse/lib/msgpack.py +10 -3
- synapse/lib/storm.py +5 -1
- synapse/lib/stormhttp.py +3 -10
- synapse/lib/stormlib/model.py +37 -0
- synapse/lib/stormtypes.py +27 -17
- synapse/lib/version.py +2 -2
- synapse/lib/view.py +2 -5
- synapse/models/auth.py +2 -1
- synapse/models/base.py +20 -0
- synapse/models/crypto.py +5 -2
- synapse/models/economic.py +45 -11
- synapse/models/inet.py +78 -21
- synapse/models/person.py +11 -4
- synapse/models/risk.py +6 -0
- synapse/models/syn.py +22 -12
- synapse/models/telco.py +3 -1
- synapse/tests/test_cortex.py +73 -31
- synapse/tests/test_lib_agenda.py +1 -6
- synapse/tests/test_lib_cell.py +28 -4
- synapse/tests/test_lib_httpapi.py +2 -4
- synapse/tests/test_lib_lmdbslab.py +1 -4
- synapse/tests/test_lib_stormhttp.py +9 -0
- synapse/tests/test_lib_stormlib_cortex.py +1 -3
- synapse/tests/test_lib_stormlib_log.py +1 -6
- synapse/tests/test_lib_stormlib_model.py +28 -0
- synapse/tests/test_lib_stormtypes.py +17 -3
- synapse/tests/test_lib_trigger.py +2 -3
- synapse/tests/test_model_base.py +12 -2
- synapse/tests/test_model_inet.py +23 -0
- synapse/tests/test_model_person.py +2 -0
- synapse/tests/test_model_risk.py +5 -0
- synapse/tests/test_model_syn.py +198 -0
- synapse/tests/test_utils.py +23 -4
- synapse/tests/utils.py +39 -5
- {synapse-2.189.0.dist-info → synapse-2.191.0.dist-info}/METADATA +5 -5
- {synapse-2.189.0.dist-info → synapse-2.191.0.dist-info}/RECORD +43 -43
- {synapse-2.189.0.dist-info → synapse-2.191.0.dist-info}/LICENSE +0 -0
- {synapse-2.189.0.dist-info → synapse-2.191.0.dist-info}/WHEEL +0 -0
- {synapse-2.189.0.dist-info → synapse-2.191.0.dist-info}/top_level.txt +0 -0
synapse/tests/test_lib_cell.py
CHANGED
|
@@ -115,6 +115,14 @@ class EchoAuthApi(s_cell.CellApi):
|
|
|
115
115
|
await self._reqUserAllowed(path)
|
|
116
116
|
return True
|
|
117
117
|
|
|
118
|
+
@s_cell.adminapi()
|
|
119
|
+
async def adminOnly(self):
|
|
120
|
+
return True
|
|
121
|
+
|
|
122
|
+
@s_cell.adminapi(log=True)
|
|
123
|
+
async def adminOnlyLog(self, arg1, arg2, **kwargs):
|
|
124
|
+
return arg1, arg2, kwargs
|
|
125
|
+
|
|
118
126
|
class EchoAuth(s_cell.Cell):
|
|
119
127
|
cellapi = EchoAuthApi
|
|
120
128
|
|
|
@@ -428,6 +436,16 @@ class CellTest(s_t_utils.SynTest):
|
|
|
428
436
|
self.eq(info.get('user').get('name'), 'root')
|
|
429
437
|
self.eq(info.get('user').get('iden'), root.iden)
|
|
430
438
|
|
|
439
|
+
# @adminApi methods are allowed
|
|
440
|
+
self.true(await proxy.adminOnly())
|
|
441
|
+
mesg = "Executing [EchoAuthApi.adminOnlyLog] as [root] with args [(1, 2)[{'three': 4}]"
|
|
442
|
+
with self.getStructuredAsyncLoggerStream('synapse.lib.cell', mesg) as stream:
|
|
443
|
+
self.eq(await proxy.adminOnlyLog(1, 2, three=4), (1, 2, {'three': 4}))
|
|
444
|
+
self.true(await stream.wait(timeout=10))
|
|
445
|
+
msgs = stream.jsonlines()
|
|
446
|
+
self.len(1, msgs)
|
|
447
|
+
self.eq('EchoAuthApi.adminOnlyLog', msgs[0].get('wrapped_func'))
|
|
448
|
+
|
|
431
449
|
visi = await echo.auth.addUser('visi')
|
|
432
450
|
await visi.setPasswd('foo')
|
|
433
451
|
await visi.addRule((True, ('foo', 'bar')))
|
|
@@ -454,6 +472,15 @@ class CellTest(s_t_utils.SynTest):
|
|
|
454
472
|
with self.raises(s_exc.NoSuchUser):
|
|
455
473
|
await proxy.getUserInfo('newp')
|
|
456
474
|
|
|
475
|
+
# @adminApi methods are not allowed
|
|
476
|
+
with self.raises(s_exc.AuthDeny) as cm:
|
|
477
|
+
await proxy.adminOnly()
|
|
478
|
+
self.eq(cm.exception.get('mesg'), 'User is not an admin [visi]')
|
|
479
|
+
self.eq(cm.exception.get('user'), visi.iden)
|
|
480
|
+
self.eq(cm.exception.get('username'), visi.name)
|
|
481
|
+
with self.raises(s_exc.AuthDeny) as cm:
|
|
482
|
+
await proxy.adminOnlyLog(1, 2, three=4)
|
|
483
|
+
|
|
457
484
|
# User cannot get authinfo for other items since they are
|
|
458
485
|
# not an admin or do not have those roles.
|
|
459
486
|
await self.asyncraises(s_exc.AuthDeny, proxy.getUserInfo('root'))
|
|
@@ -3064,10 +3091,7 @@ class CellTest(s_t_utils.SynTest):
|
|
|
3064
3091
|
async with self.getTestCore(conf={'health:sysctl:checks': True}):
|
|
3065
3092
|
pass
|
|
3066
3093
|
|
|
3067
|
-
stream.
|
|
3068
|
-
data = stream.getvalue()
|
|
3069
|
-
raw_mesgs = [m for m in data.split('\n') if m]
|
|
3070
|
-
msgs = [json.loads(m) for m in raw_mesgs]
|
|
3094
|
+
msgs = stream.jsonlines()
|
|
3071
3095
|
|
|
3072
3096
|
self.len(1, msgs)
|
|
3073
3097
|
|
|
@@ -1722,10 +1722,8 @@ class HttpApiTest(s_tests.SynTest):
|
|
|
1722
1722
|
|
|
1723
1723
|
async def test_request_logging(self):
|
|
1724
1724
|
|
|
1725
|
-
def get_mesg(stream):
|
|
1726
|
-
|
|
1727
|
-
raw_mesgs = [m for m in data.split('\n') if m]
|
|
1728
|
-
msgs = [json.loads(m) for m in raw_mesgs]
|
|
1725
|
+
def get_mesg(stream: s_tests.AsyncStreamEvent) -> dict:
|
|
1726
|
+
msgs = stream.jsonlines()
|
|
1729
1727
|
self.len(1, msgs)
|
|
1730
1728
|
return msgs[0]
|
|
1731
1729
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import os
|
|
2
|
-
import json
|
|
3
2
|
import asyncio
|
|
4
3
|
import pathlib
|
|
5
4
|
import multiprocessing
|
|
@@ -15,7 +14,6 @@ import synapse.lib.lmdbslab as s_lmdbslab
|
|
|
15
14
|
import synapse.lib.thisplat as s_thisplat
|
|
16
15
|
|
|
17
16
|
import synapse.tests.utils as s_t_utils
|
|
18
|
-
from synapse.tests.utils import alist
|
|
19
17
|
|
|
20
18
|
def getFileMapCount(filename):
|
|
21
19
|
filename = str(filename)
|
|
@@ -360,8 +358,7 @@ class LmdbSlabTest(s_t_utils.SynTest):
|
|
|
360
358
|
slab.put(b'\xff\xff\xff\xff' + s_common.guid(i).encode('utf8'), byts, db=foo)
|
|
361
359
|
self.true(await stream.wait(timeout=1))
|
|
362
360
|
|
|
363
|
-
|
|
364
|
-
msgs = [json.loads(m) for m in data.split('\\n') if m]
|
|
361
|
+
msgs = stream.jsonlines()
|
|
365
362
|
self.gt(len(msgs), 0)
|
|
366
363
|
self.nn(msgs[0].get('delta'))
|
|
367
364
|
self.nn(msgs[0].get('path'))
|
|
@@ -464,6 +464,15 @@ class StormHttpTest(s_test.SynTest):
|
|
|
464
464
|
self.isin('mesg', errinfo)
|
|
465
465
|
self.eq('', errinfo.get('mesg')) # timeouterror has no mesg
|
|
466
466
|
|
|
467
|
+
q = '''
|
|
468
|
+
$params=({"foo": ["bar", "baz"], "key": [["valu"]]})
|
|
469
|
+
$resp = $lib.inet.http.request(GET, $url, params=$params, ssl_verify=$lib.false)
|
|
470
|
+
return ( $resp.json() )
|
|
471
|
+
'''
|
|
472
|
+
resp = await core.callStorm(q, opts=opts)
|
|
473
|
+
data = resp.get('result')
|
|
474
|
+
self.eq(data.get('params'), {'foo': ['bar', 'baz'], 'key': ["('valu',)"]})
|
|
475
|
+
|
|
467
476
|
async def test_storm_http_post(self):
|
|
468
477
|
|
|
469
478
|
async with self.getTestCore() as core:
|
|
@@ -304,9 +304,7 @@ $request.reply(206, headers=$headers, body=({"no":"body"}))
|
|
|
304
304
|
resp = await sess.get(url)
|
|
305
305
|
self.eq(resp.status, 200)
|
|
306
306
|
self.true(await stream.wait(timeout=12))
|
|
307
|
-
|
|
308
|
-
raw_mesgs = [m for m in data.split('\n') if m]
|
|
309
|
-
msgs = [json.loads(m) for m in raw_mesgs]
|
|
307
|
+
msgs = stream.jsonlines()
|
|
310
308
|
self.eq(msgs[0].get('httpapi'), echoiden)
|
|
311
309
|
core.stormlog = False
|
|
312
310
|
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import json
|
|
2
|
-
|
|
3
1
|
import synapse.exc as s_exc
|
|
4
2
|
|
|
5
3
|
import synapse.tests.utils as s_test
|
|
@@ -49,10 +47,7 @@ class LogTest(s_test.SynTest):
|
|
|
49
47
|
await core.callStorm('$lib.log.debug("struct1 message")')
|
|
50
48
|
await core.callStorm('$lib.log.debug("struct2 message", extra=({"key": "valu"}))')
|
|
51
49
|
self.true(await stream.wait(6))
|
|
52
|
-
|
|
53
|
-
data = stream.getvalue()
|
|
54
|
-
raw_mesgs = [m for m in data.split('\n') if m]
|
|
55
|
-
msgs = [json.loads(m) for m in raw_mesgs]
|
|
50
|
+
msgs = stream.jsonlines()
|
|
56
51
|
self.len(2, msgs)
|
|
57
52
|
mesg = msgs[0]
|
|
58
53
|
self.eq(mesg.get('logger').get('name'), 'synapse.storm.log')
|
|
@@ -704,3 +704,31 @@ class StormlibModelTest(s_test.SynTest):
|
|
|
704
704
|
self.eq(nodes[0].get('cert'), cert3.ndef[1])
|
|
705
705
|
self.isin('ssl.migration.three', nodes[0].tags)
|
|
706
706
|
self.eq(nodes[0].nodedata, {'foo': None})
|
|
707
|
+
|
|
708
|
+
async def test_stormlib_model_migrations_inet_service_message_client(self):
|
|
709
|
+
|
|
710
|
+
async with self.getTestCore() as core:
|
|
711
|
+
|
|
712
|
+
await core.nodes('''[
|
|
713
|
+
(inet:service:message=* :client:address=1.2.3.4 :client=2.3.4.5)
|
|
714
|
+
(inet:service:message=* :client:address=3.4.5.6)
|
|
715
|
+
(inet:service:message=* :client=4.5.6.7)
|
|
716
|
+
]''')
|
|
717
|
+
|
|
718
|
+
nodes = await core.nodes('''
|
|
719
|
+
inet:service:message
|
|
720
|
+
$lib.model.migration.s.inetServiceMessageClientAddress($node)
|
|
721
|
+
''')
|
|
722
|
+
|
|
723
|
+
self.len(3, nodes)
|
|
724
|
+
|
|
725
|
+
for node in nodes:
|
|
726
|
+
self.none(node.get('client:address'))
|
|
727
|
+
|
|
728
|
+
exp = ['tcp://2.3.4.5', 'tcp://3.4.5.6', 'tcp://4.5.6.7']
|
|
729
|
+
self.sorteq(exp, [n.get('client') for n in nodes])
|
|
730
|
+
|
|
731
|
+
ndata = [n for n in nodes if await n.getData('migration:inet:service:message:client:address')]
|
|
732
|
+
self.len(1, ndata)
|
|
733
|
+
self.eq(ndata[0].get('client'), 'tcp://2.3.4.5')
|
|
734
|
+
self.eq(await ndata[0].getData('migration:inet:service:message:client:address'), 'tcp://1.2.3.4')
|
|
@@ -1665,8 +1665,23 @@ class StormTypesTest(s_test.SynTest):
|
|
|
1665
1665
|
self.eq('bar', await core.callStorm('$foo = (foo, bar) return($foo.1)'))
|
|
1666
1666
|
self.eq('foo', await core.callStorm('$foo = (foo, bar) return($foo."-2")'))
|
|
1667
1667
|
self.eq('bar', await core.callStorm('$foo = (foo, bar) return($foo.pop())'))
|
|
1668
|
-
|
|
1668
|
+
|
|
1669
|
+
self.eq(3, await core.callStorm('$list = ([1, 2, 3, 4]) return($list.pop(2))'))
|
|
1670
|
+
self.eq(2, await core.callStorm('$list = ([1, 2, 3, 4]) return($list.pop(-3))'))
|
|
1671
|
+
self.eq(4, await core.callStorm('$list = ([1, 2, 3, 4]) $list.pop(2) return($list.pop(2))'))
|
|
1672
|
+
self.eq([1, 3, 4], await core.callStorm('$list = ([1, 2, 3, 4]) $list.pop(1) return($list)'))
|
|
1673
|
+
|
|
1674
|
+
with self.raises(s_exc.StormRuntimeError) as exc:
|
|
1669
1675
|
await core.callStorm('$lib.list().pop()')
|
|
1676
|
+
self.eq(exc.exception.get('mesg'), 'pop from empty list')
|
|
1677
|
+
|
|
1678
|
+
with self.raises(s_exc.StormRuntimeError) as exc:
|
|
1679
|
+
await core.callStorm('$list = ([1, 2, 3, 4]) return($list.pop(13))')
|
|
1680
|
+
self.eq(exc.exception.get('mesg'), 'pop index out of range')
|
|
1681
|
+
|
|
1682
|
+
with self.raises(s_exc.StormRuntimeError) as exc:
|
|
1683
|
+
await core.callStorm('$list = ([1, 2, 3, 4]) return($list.pop(-5))')
|
|
1684
|
+
self.eq(exc.exception.get('mesg'), 'pop index out of range')
|
|
1670
1685
|
|
|
1671
1686
|
somelist = ["foo", "bar", "baz", "bar"]
|
|
1672
1687
|
q = '''
|
|
@@ -4905,8 +4920,7 @@ class StormTypesTest(s_test.SynTest):
|
|
|
4905
4920
|
unixtime += 7 * MINSECS
|
|
4906
4921
|
self.eq('m3', await getNextFoo())
|
|
4907
4922
|
self.true(await stream.wait(6))
|
|
4908
|
-
|
|
4909
|
-
mesg = json.loads(buf.split('\n')[0])
|
|
4923
|
+
mesg = stream.jsonlines()[0]
|
|
4910
4924
|
self.eq(mesg['message'], f'm3 cron {guid}')
|
|
4911
4925
|
self.eq(mesg['iden'], guid)
|
|
4912
4926
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import os
|
|
2
|
-
import json
|
|
3
2
|
import synapse.exc as s_exc
|
|
4
3
|
import synapse.common as s_common
|
|
5
4
|
|
|
@@ -253,8 +252,8 @@ class TrigTest(s_t_utils.SynTest):
|
|
|
253
252
|
with self.getStructuredAsyncLoggerStream('synapse.storm.log', 'test trigger') as stream:
|
|
254
253
|
await core.nodes('[ test:str=logit ]')
|
|
255
254
|
self.true(await stream.wait(6))
|
|
256
|
-
|
|
257
|
-
mesg =
|
|
255
|
+
msgs = stream.jsonlines()
|
|
256
|
+
mesg = [m for m in msgs if m.get('iden') == tdef.get('iden')][0]
|
|
258
257
|
self.eq(mesg['message'], f'test trigger {tdef.get("iden")}')
|
|
259
258
|
self.eq(mesg['iden'], tdef.get('iden'))
|
|
260
259
|
|
synapse/tests/test_model_base.py
CHANGED
|
@@ -222,13 +222,23 @@ class BaseTest(s_t_utils.SynTest):
|
|
|
222
222
|
|
|
223
223
|
async with self.getTestCore() as core:
|
|
224
224
|
|
|
225
|
-
nodes = await core.nodes('
|
|
225
|
+
nodes = await core.nodes('''
|
|
226
|
+
[meta:source="*"
|
|
227
|
+
:name="FOO Bar"
|
|
228
|
+
:type=osint
|
|
229
|
+
:url="https://foo.bar/index.html"
|
|
230
|
+
:ingest:latest=20241205
|
|
231
|
+
:ingest:offset=17
|
|
232
|
+
]
|
|
233
|
+
''')
|
|
226
234
|
self.len(1, nodes)
|
|
227
235
|
sorc = nodes[0]
|
|
228
236
|
|
|
229
237
|
self.eq(sorc.get('type'), 'osint')
|
|
230
238
|
self.eq(sorc.get('name'), 'foo bar')
|
|
231
239
|
self.eq(sorc.get('url'), 'https://foo.bar/index.html')
|
|
240
|
+
self.eq(sorc.get('ingest:offset'), 17)
|
|
241
|
+
self.eq(sorc.get('ingest:latest'), 1733356800000)
|
|
232
242
|
|
|
233
243
|
valu = (sorc.ndef[1], ('inet:fqdn', 'woot.com'))
|
|
234
244
|
nodes = await core.nodes('[meta:seen=$valu]', opts={'vars': {'valu': valu}})
|
|
@@ -330,7 +340,7 @@ class BaseTest(s_t_utils.SynTest):
|
|
|
330
340
|
'tel:mob:telem:ipv6', 'tel:mob:telem:wifi', 'tel:mob:telem:wifi:ssid',
|
|
331
341
|
'tel:mob:telem:wifi:bssid', 'tel:mob:telem:adid', 'tel:mob:telem:aaid',
|
|
332
342
|
'tel:mob:telem:idfa', 'tel:mob:telem:name', 'tel:mob:telem:email',
|
|
333
|
-
'tel:mob:telem:
|
|
343
|
+
'tel:mob:telem:app', 'tel:mob:telem:data',
|
|
334
344
|
'inet:http:request:response:time', 'inet:http:request:response:code',
|
|
335
345
|
'inet:http:request:response:reason', 'inet:http:request:response:body',
|
|
336
346
|
'gov:us:cage:street', 'gov:us:cage:city', 'gov:us:cage:state', 'gov:us:cage:zip',
|
synapse/tests/test_model_inet.py
CHANGED
|
@@ -2958,10 +2958,12 @@ class InetModelTest(s_t_utils.SynTest):
|
|
|
2958
2958
|
:platform={ inet:service:platform=(slack,) }
|
|
2959
2959
|
:url="https://v.vtx.lk/slack"
|
|
2960
2960
|
:name="Synapse users slack"
|
|
2961
|
+
:tenant={[ inet:service:tenant=({"id": "VS-31337"}) ]}
|
|
2961
2962
|
]
|
|
2962
2963
|
'''
|
|
2963
2964
|
nodes = await core.nodes(q)
|
|
2964
2965
|
self.len(1, nodes)
|
|
2966
|
+
self.nn(nodes[0].get('tenant'))
|
|
2965
2967
|
self.eq(nodes[0].ndef, ('inet:service:instance', s_common.guid(('vertex', 'slack'))))
|
|
2966
2968
|
self.eq(nodes[0].get('id'), 'T2XK1223Y')
|
|
2967
2969
|
self.eq(nodes[0].get('platform'), platform.ndef[1])
|
|
@@ -2976,6 +2978,7 @@ class InetModelTest(s_t_utils.SynTest):
|
|
|
2976
2978
|
:user=blackout
|
|
2977
2979
|
:email=blackout@vertex.link
|
|
2978
2980
|
:profile={ gen.ps.contact.email vertex.employee blackout@vertex.link }
|
|
2981
|
+
:tenant={[ inet:service:tenant=({"id": "VS-31337"}) ]}
|
|
2979
2982
|
)
|
|
2980
2983
|
|
|
2981
2984
|
(inet:service:account=(visi, account, vertex, slack)
|
|
@@ -2989,6 +2992,8 @@ class InetModelTest(s_t_utils.SynTest):
|
|
|
2989
2992
|
accounts = await core.nodes(q)
|
|
2990
2993
|
self.len(2, accounts)
|
|
2991
2994
|
|
|
2995
|
+
self.nn(accounts[0].get('tenant'))
|
|
2996
|
+
|
|
2992
2997
|
profiles = await core.nodes('ps:contact')
|
|
2993
2998
|
self.len(2, profiles)
|
|
2994
2999
|
self.eq(profiles[0].get('email'), 'blackout@vertex.link')
|
|
@@ -3068,14 +3073,17 @@ class InetModelTest(s_t_utils.SynTest):
|
|
|
3068
3073
|
[ inet:service:session=*
|
|
3069
3074
|
:creator=$blckiden
|
|
3070
3075
|
:period=(202405160900, 202405161055)
|
|
3076
|
+
:http:session=*
|
|
3071
3077
|
]
|
|
3072
3078
|
'''
|
|
3073
3079
|
opts = {'vars': {'blckiden': blckacct.ndef[1]}}
|
|
3074
3080
|
nodes = await core.nodes(q, opts=opts)
|
|
3075
3081
|
self.len(1, nodes)
|
|
3082
|
+
self.nn(nodes[0].get('http:session'))
|
|
3076
3083
|
self.eq(nodes[0].get('creator'), blckacct.ndef[1])
|
|
3077
3084
|
self.eq(nodes[0].get('period'), (1715850000000, 1715856900000))
|
|
3078
3085
|
blcksess = nodes[0]
|
|
3086
|
+
self.len(1, await core.nodes('inet:service:session -> inet:http:session'))
|
|
3079
3087
|
|
|
3080
3088
|
q = '''
|
|
3081
3089
|
[ inet:service:login=*
|
|
@@ -3407,3 +3415,18 @@ class InetModelTest(s_t_utils.SynTest):
|
|
|
3407
3415
|
|
|
3408
3416
|
with self.raises(s_exc.BadTypeValu):
|
|
3409
3417
|
await core.nodes('[ inet:service:relationship=* :source={[it:dev:str=foo]} ]')
|
|
3418
|
+
|
|
3419
|
+
nodes = await core.nodes('''
|
|
3420
|
+
[ inet:service:subscription=*
|
|
3421
|
+
:level=vertex.synapse.enterprise
|
|
3422
|
+
:pay:instrument={[ econ:bank:account=* :contact={[ ps:contact=* :name=visi]} ]}
|
|
3423
|
+
:subscriber={[ inet:service:tenant=({"id": "VS-31337"}) ]}
|
|
3424
|
+
]
|
|
3425
|
+
''')
|
|
3426
|
+
self.len(1, nodes)
|
|
3427
|
+
self.eq('vertex.synapse.enterprise.', nodes[0].get('level'))
|
|
3428
|
+
self.eq('econ:bank:account', nodes[0].get('pay:instrument')[0])
|
|
3429
|
+
self.eq('inet:service:tenant', nodes[0].get('subscriber')[0])
|
|
3430
|
+
self.len(1, await core.nodes('inet:service:subscription -> inet:service:subscription:level:taxonomy'))
|
|
3431
|
+
self.len(1, await core.nodes('inet:service:subscription :pay:instrument -> econ:bank:account'))
|
|
3432
|
+
self.len(1, await core.nodes('inet:service:subscription :subscriber -> inet:service:tenant'))
|
|
@@ -278,12 +278,14 @@ class PsModelTest(s_t_utils.SynTest):
|
|
|
278
278
|
:source:host=*
|
|
279
279
|
:source:file=*
|
|
280
280
|
:source:acct=(twitter.com, invisig0th)
|
|
281
|
+
:source:account=(twitter.com, invisig0th)
|
|
281
282
|
]''')
|
|
282
283
|
self.len(1, nodes)
|
|
283
284
|
self.len(1, await core.nodes('ps:contactlist -> it:host'))
|
|
284
285
|
self.len(1, await core.nodes('ps:contactlist -> file:bytes'))
|
|
285
286
|
self.len(2, await core.nodes('ps:contactlist -> ps:contact'))
|
|
286
287
|
self.len(1, await core.nodes('ps:contactlist -> inet:web:acct'))
|
|
288
|
+
self.len(1, await core.nodes('ps:contactlist -> inet:service:account'))
|
|
287
289
|
|
|
288
290
|
nodes = await core.nodes('''[
|
|
289
291
|
ps:workhist = *
|
synapse/tests/test_model_risk.py
CHANGED
|
@@ -379,6 +379,7 @@ class RiskModelTest(s_t_utils.SynTest):
|
|
|
379
379
|
:desc=VTX-APT1
|
|
380
380
|
:tag=cno.threat.apt1
|
|
381
381
|
:active=(2012,2023)
|
|
382
|
+
:activity=high
|
|
382
383
|
:reporter=*
|
|
383
384
|
:reporter:name=mandiant
|
|
384
385
|
:reporter:discovered=202202
|
|
@@ -400,6 +401,7 @@ class RiskModelTest(s_t_utils.SynTest):
|
|
|
400
401
|
self.len(1, nodes)
|
|
401
402
|
self.eq('vtx-apt1', nodes[0].get('name'))
|
|
402
403
|
self.eq('VTX-APT1', nodes[0].get('desc'))
|
|
404
|
+
self.eq(40, nodes[0].get('activity'))
|
|
403
405
|
self.eq('apt1', nodes[0].get('org:name'))
|
|
404
406
|
self.eq('ua', nodes[0].get('country:code'))
|
|
405
407
|
self.eq('cn.shanghai', nodes[0].get('org:loc'))
|
|
@@ -546,11 +548,13 @@ class RiskModelTest(s_t_utils.SynTest):
|
|
|
546
548
|
:cause=nature.earthquake
|
|
547
549
|
:provider={[ ou:org=* :name="desert power" ]}
|
|
548
550
|
:provider:name="desert power"
|
|
551
|
+
:attack={[ risk:attack=* ]}
|
|
549
552
|
:reporter={ ou:org:name=vertex }
|
|
550
553
|
:reporter:name=vertex
|
|
551
554
|
]
|
|
552
555
|
''')
|
|
553
556
|
self.len(1, nodes)
|
|
557
|
+
self.nn(nodes[0].get('attack'))
|
|
554
558
|
self.nn(nodes[0].get('reporter'))
|
|
555
559
|
self.eq('the big one', nodes[0].get('name'))
|
|
556
560
|
self.eq('vertex', nodes[0].get('reporter:name'))
|
|
@@ -559,6 +563,7 @@ class RiskModelTest(s_t_utils.SynTest):
|
|
|
559
563
|
self.eq('nature.earthquake.', nodes[0].get('cause'))
|
|
560
564
|
self.eq((1672531200000, 1704067200000), nodes[0].get('period'))
|
|
561
565
|
|
|
566
|
+
self.len(1, await core.nodes('risk:outage -> risk:attack'))
|
|
562
567
|
self.len(1, await core.nodes('risk:outage -> risk:outage:cause:taxonomy'))
|
|
563
568
|
self.len(1, await core.nodes('risk:outage :reporter -> ou:org +:name=vertex'))
|
|
564
569
|
self.len(1, await core.nodes('risk:outage :provider -> ou:org +:name="desert power"'))
|
synapse/tests/test_model_syn.py
CHANGED
|
@@ -362,6 +362,93 @@ class SynModelTest(s_t_utils.SynTest):
|
|
|
362
362
|
nodes = await core.nodes('syn:tagprop')
|
|
363
363
|
self.len(0, nodes)
|
|
364
364
|
|
|
365
|
+
async with self.getTestCore() as core:
|
|
366
|
+
# Check we can iterate runt nodes while changing the underlying dictionary
|
|
367
|
+
|
|
368
|
+
numforms = len(core.model.forms)
|
|
369
|
+
|
|
370
|
+
q = '''
|
|
371
|
+
init {
|
|
372
|
+
$forms = ()
|
|
373
|
+
$count = (0)
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
syn:form
|
|
377
|
+
|
|
378
|
+
$forms.append(({'name': $node.repr(), 'doc': :doc }))
|
|
379
|
+
|
|
380
|
+
$count = ($count + 1)
|
|
381
|
+
|
|
382
|
+
if ($count = (2)) {
|
|
383
|
+
$info = ({"doc": "test taxonomy", "interfaces": ["meta:taxonomy"]})
|
|
384
|
+
$lib.model.ext.addForm(_test:taxonomy, taxonomy, ({}), $info)
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
spin |
|
|
388
|
+
|
|
389
|
+
fini { return($forms) }
|
|
390
|
+
'''
|
|
391
|
+
|
|
392
|
+
forms = await core.callStorm(q)
|
|
393
|
+
self.len(numforms, forms)
|
|
394
|
+
self.len(numforms + 1, core.model.forms)
|
|
395
|
+
|
|
396
|
+
numtypes = len(core.model.types)
|
|
397
|
+
q = '''
|
|
398
|
+
init {
|
|
399
|
+
$types = ()
|
|
400
|
+
$count = (0)
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
syn:type
|
|
404
|
+
|
|
405
|
+
$types.append(({'name': $node.repr(), 'doc': :doc }))
|
|
406
|
+
|
|
407
|
+
$count = ($count + 1)
|
|
408
|
+
|
|
409
|
+
if ($count = (2)) {
|
|
410
|
+
$typeopts = ({"lower": true, "onespace": true})
|
|
411
|
+
$typeinfo = ({"doc": "A test type doc."})
|
|
412
|
+
$lib.model.ext.addType(_test:type, str, $typeopts, $typeinfo)
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
spin |
|
|
416
|
+
|
|
417
|
+
fini { return($types) }
|
|
418
|
+
'''
|
|
419
|
+
|
|
420
|
+
types = await core.callStorm(q)
|
|
421
|
+
self.len(numtypes, types)
|
|
422
|
+
self.len(numtypes + 1, core.model.types)
|
|
423
|
+
|
|
424
|
+
q = '''
|
|
425
|
+
init {
|
|
426
|
+
$tagprops = ()
|
|
427
|
+
$count = (0)
|
|
428
|
+
$lib.model.ext.addTagProp(cypher, (str, ({})), ({}))
|
|
429
|
+
$lib.model.ext.addTagProp(trinity, (str, ({})), ({}))
|
|
430
|
+
$lib.model.ext.addTagProp(morpheus, (str, ({})), ({}))
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
syn:tagprop
|
|
434
|
+
|
|
435
|
+
$tagprops.append(({'name': $node.repr(), 'doc': :doc }))
|
|
436
|
+
|
|
437
|
+
$count = ($count + 1)
|
|
438
|
+
|
|
439
|
+
if ($count = (2)) {
|
|
440
|
+
$lib.model.ext.addTagProp(neo, (str, ({})), ({}))
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
spin |
|
|
444
|
+
|
|
445
|
+
fini { return($tagprops) }
|
|
446
|
+
'''
|
|
447
|
+
|
|
448
|
+
tagprops = await core.callStorm(q)
|
|
449
|
+
self.len(3, tagprops)
|
|
450
|
+
self.len(4, core.model.tagprops)
|
|
451
|
+
|
|
365
452
|
async def test_syn_trigger_runts(self):
|
|
366
453
|
async with self.getTestCore() as core:
|
|
367
454
|
nodes = await core.nodes('syn:trigger')
|
|
@@ -465,6 +552,42 @@ class SynModelTest(s_t_utils.SynTest):
|
|
|
465
552
|
pode = nodes[0].pack()
|
|
466
553
|
self.eq(pode[0][1], iden)
|
|
467
554
|
|
|
555
|
+
async with self.getTestCore() as core:
|
|
556
|
+
# Check we can iterate runt nodes while changing the underlying dictionary
|
|
557
|
+
|
|
558
|
+
tdef = {'cond': 'node:add', 'form': 'it:dev:str', 'storm': '[inet:user=1] | testcmd'}
|
|
559
|
+
await core.view.addTrigger(tdef)
|
|
560
|
+
|
|
561
|
+
tdef = {'cond': 'node:add', 'form': 'it:dev:str', 'storm': '[inet:user=2] | testcmd'}
|
|
562
|
+
await core.view.addTrigger(tdef)
|
|
563
|
+
|
|
564
|
+
q = '''
|
|
565
|
+
init {
|
|
566
|
+
$trigs = ()
|
|
567
|
+
$count = (0)
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
syn:trigger
|
|
571
|
+
|
|
572
|
+
$trigs.append(({'name': $node.repr(), 'doc': :doc }))
|
|
573
|
+
|
|
574
|
+
$count = ($count + 1)
|
|
575
|
+
|
|
576
|
+
if ($count = (2)) {
|
|
577
|
+
$lib.trigger.add($tdef)
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
spin |
|
|
581
|
+
|
|
582
|
+
fini { return($trigs) }
|
|
583
|
+
'''
|
|
584
|
+
|
|
585
|
+
tdef = {'cond': 'node:add', 'form': 'it:dev:str', 'storm': '[inet:user=3] | testcmd'}
|
|
586
|
+
opts = {'vars': {'tdef': tdef}}
|
|
587
|
+
triggers = await core.callStorm(q, opts=opts)
|
|
588
|
+
self.len(2, triggers)
|
|
589
|
+
self.len(3, core.view.triggers.triggers)
|
|
590
|
+
|
|
468
591
|
async def test_syn_cmd_runts(self):
|
|
469
592
|
|
|
470
593
|
async with self.getTestDmon() as dmon:
|
|
@@ -554,6 +677,49 @@ class SynModelTest(s_t_utils.SynTest):
|
|
|
554
677
|
self.eq(nodes[0].get('output'), ('inet:fqdn',))
|
|
555
678
|
self.eq(nodes[0].get('nodedata'), (('foo', 'inet:ipv4'), ('bar', 'inet:fqdn')))
|
|
556
679
|
|
|
680
|
+
async with self.getTestCore() as core:
|
|
681
|
+
# Check we can iterate runt nodes while changing the underlying dictionary
|
|
682
|
+
|
|
683
|
+
numcmds = len(core.stormcmds)
|
|
684
|
+
|
|
685
|
+
stormpkg = {
|
|
686
|
+
'name': 'stormpkg',
|
|
687
|
+
'version': '1.2.3',
|
|
688
|
+
'synapse_version': '>=2.8.0,<3.0.0',
|
|
689
|
+
'commands': (
|
|
690
|
+
{
|
|
691
|
+
'name': 'pkgcmd.old',
|
|
692
|
+
'storm': '$lib.print(hi)',
|
|
693
|
+
},
|
|
694
|
+
),
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
q = '''
|
|
698
|
+
init {
|
|
699
|
+
$cmds = ()
|
|
700
|
+
$count = (0)
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
syn:cmd
|
|
704
|
+
|
|
705
|
+
$cmds.append(({'name': $node.repr(), 'doc': :doc }))
|
|
706
|
+
|
|
707
|
+
$count = ($count + 1)
|
|
708
|
+
|
|
709
|
+
if ($count = (2)) {
|
|
710
|
+
$lib.pkg.add($pkgdef)
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
spin |
|
|
714
|
+
|
|
715
|
+
fini { return($cmds) }
|
|
716
|
+
'''
|
|
717
|
+
|
|
718
|
+
opts = {'vars': {'pkgdef': stormpkg}}
|
|
719
|
+
cmds = await core.callStorm(q, opts=opts)
|
|
720
|
+
self.len(numcmds, cmds)
|
|
721
|
+
self.len(numcmds + 1, core.stormcmds)
|
|
722
|
+
|
|
557
723
|
async def test_syn_cron_runts(self):
|
|
558
724
|
|
|
559
725
|
async with self.getTestCore() as core:
|
|
@@ -582,3 +748,35 @@ class SynModelTest(s_t_utils.SynTest):
|
|
|
582
748
|
self.eq(nodes[0].ndef, ('syn:cron', iden))
|
|
583
749
|
self.eq(nodes[0].get('doc'), 'hehe')
|
|
584
750
|
self.eq(nodes[0].get('name'), 'haha')
|
|
751
|
+
|
|
752
|
+
async with self.getTestCore() as core:
|
|
753
|
+
# Check we can iterate runt nodes while changing the underlying dictionary
|
|
754
|
+
|
|
755
|
+
q = '''
|
|
756
|
+
init {
|
|
757
|
+
$appts = ()
|
|
758
|
+
$count = (0)
|
|
759
|
+
|
|
760
|
+
cron.add --hour 1 --day 1 {#foo} |
|
|
761
|
+
cron.add --hour 2 --day 1 {#foo} |
|
|
762
|
+
cron.add --hour 3 --day 1 {#foo}
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
syn:cron
|
|
766
|
+
|
|
767
|
+
$appts.append(({'name': $node.repr(), 'doc': :doc }))
|
|
768
|
+
|
|
769
|
+
$count = ($count + 1)
|
|
770
|
+
|
|
771
|
+
if ($count = (2)) {
|
|
772
|
+
cron.add --hour 4 --day 1 {#foo}
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
spin |
|
|
776
|
+
|
|
777
|
+
fini { return($appts) }
|
|
778
|
+
'''
|
|
779
|
+
|
|
780
|
+
appts = await core.callStorm(q)
|
|
781
|
+
self.len(3, appts)
|
|
782
|
+
self.len(4, core.agenda.appts)
|
synapse/tests/test_utils.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import time
|
|
3
|
+
import json
|
|
3
4
|
import logging
|
|
4
5
|
import unittest
|
|
5
6
|
|
|
@@ -109,13 +110,13 @@ class TestUtils(s_t_utils.SynTest):
|
|
|
109
110
|
def test_syntest_logstream_event(self):
|
|
110
111
|
|
|
111
112
|
@s_common.firethread
|
|
112
|
-
def logathing():
|
|
113
|
+
def logathing(mesg):
|
|
113
114
|
time.sleep(0.01)
|
|
114
|
-
logger.error(
|
|
115
|
+
logger.error(mesg)
|
|
115
116
|
|
|
116
117
|
logger.error('notthere')
|
|
117
118
|
with self.getLoggerStream('synapse.tests.test_utils', 'Test Message') as stream:
|
|
118
|
-
thr = logathing()
|
|
119
|
+
thr = logathing('StreamEvent Test Message')
|
|
119
120
|
self.true(stream.wait(10))
|
|
120
121
|
thr.join()
|
|
121
122
|
|
|
@@ -124,16 +125,34 @@ class TestUtils(s_t_utils.SynTest):
|
|
|
124
125
|
self.isin('StreamEvent Test Message', mesgs)
|
|
125
126
|
self.notin('notthere', mesgs)
|
|
126
127
|
|
|
128
|
+
with self.getLoggerStream('synapse.tests.test_utils', 'Test Message') as stream:
|
|
129
|
+
thr = logathing(json.dumps({'mesg': 'Test Message'}))
|
|
130
|
+
self.true(stream.wait(10))
|
|
131
|
+
thr.join()
|
|
132
|
+
|
|
133
|
+
msgs = stream.jsonlines()
|
|
134
|
+
self.len(1, msgs)
|
|
135
|
+
self.eq(msgs[0], {'mesg': 'Test Message'})
|
|
136
|
+
|
|
127
137
|
def test_syntest_envars(self):
|
|
128
138
|
os.environ['foo'] = '1'
|
|
129
139
|
os.environ['bar'] = '2'
|
|
130
140
|
|
|
131
|
-
with self.setTstEnvars(foo=1, bar='joke', baz=1234) as cm:
|
|
141
|
+
with self.setTstEnvars(foo=1, bar='joke', baz=1234, FOO_THING=1, BAR_THING=0) as cm:
|
|
132
142
|
self.none(cm)
|
|
133
143
|
self.eq(os.environ.get('foo'), '1')
|
|
134
144
|
self.eq(os.environ.get('bar'), 'joke')
|
|
135
145
|
self.eq(os.environ.get('baz'), '1234')
|
|
136
146
|
|
|
147
|
+
self.thisEnvMust('FOO_THING', 'baz')
|
|
148
|
+
self.thisEnvMustNot('BAR_THING', 'NEWP_THING')
|
|
149
|
+
with self.raises(unittest.SkipTest):
|
|
150
|
+
self.thisEnvMust('MEWP_THING')
|
|
151
|
+
with self.raises(unittest.SkipTest):
|
|
152
|
+
self.thisEnvMust('BAR_THING')
|
|
153
|
+
with self.raises(unittest.SkipTest):
|
|
154
|
+
self.thisEnvMustNot('FOO_THING')
|
|
155
|
+
|
|
137
156
|
self.eq(os.environ.get('foo'), '1')
|
|
138
157
|
self.eq(os.environ.get('bar'), '2')
|
|
139
158
|
self.none(os.environ.get('baz'))
|