synapse 2.190.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.

Files changed (38) hide show
  1. synapse/common.py +9 -0
  2. synapse/cortex.py +1 -0
  3. synapse/datamodel.py +8 -1
  4. synapse/lib/cell.py +7 -7
  5. synapse/lib/msgpack.py +10 -3
  6. synapse/lib/stormlib/model.py +37 -0
  7. synapse/lib/version.py +2 -2
  8. synapse/models/auth.py +2 -1
  9. synapse/models/base.py +20 -0
  10. synapse/models/crypto.py +5 -2
  11. synapse/models/economic.py +45 -11
  12. synapse/models/inet.py +78 -21
  13. synapse/models/person.py +11 -4
  14. synapse/models/risk.py +6 -0
  15. synapse/models/syn.py +22 -12
  16. synapse/models/telco.py +3 -1
  17. synapse/tests/test_cortex.py +8 -17
  18. synapse/tests/test_lib_agenda.py +1 -6
  19. synapse/tests/test_lib_cell.py +28 -4
  20. synapse/tests/test_lib_httpapi.py +2 -4
  21. synapse/tests/test_lib_lmdbslab.py +1 -4
  22. synapse/tests/test_lib_stormlib_cortex.py +1 -3
  23. synapse/tests/test_lib_stormlib_log.py +1 -6
  24. synapse/tests/test_lib_stormlib_model.py +28 -0
  25. synapse/tests/test_lib_stormtypes.py +1 -2
  26. synapse/tests/test_lib_trigger.py +2 -3
  27. synapse/tests/test_model_base.py +12 -2
  28. synapse/tests/test_model_inet.py +23 -0
  29. synapse/tests/test_model_person.py +2 -0
  30. synapse/tests/test_model_risk.py +5 -0
  31. synapse/tests/test_model_syn.py +198 -0
  32. synapse/tests/test_utils.py +23 -4
  33. synapse/tests/utils.py +39 -5
  34. {synapse-2.190.0.dist-info → synapse-2.191.0.dist-info}/METADATA +4 -4
  35. {synapse-2.190.0.dist-info → synapse-2.191.0.dist-info}/RECORD +38 -38
  36. {synapse-2.190.0.dist-info → synapse-2.191.0.dist-info}/LICENSE +0 -0
  37. {synapse-2.190.0.dist-info → synapse-2.191.0.dist-info}/WHEEL +0 -0
  38. {synapse-2.190.0.dist-info → synapse-2.191.0.dist-info}/top_level.txt +0 -0
synapse/models/person.py CHANGED
@@ -377,10 +377,12 @@ class PsModule(s_module.CoreModule):
377
377
  'doc': 'The service accounts associated with this contact.'}),
378
378
 
379
379
  ('web:acct', ('inet:web:acct', {}), {
380
- 'doc': 'The social media account for this contact.',
380
+ 'deprecated': True,
381
+ 'doc': 'Deprecated. Use :service:accounts.',
381
382
  }),
382
383
  ('web:group', ('inet:web:group', {}), {
383
- 'doc': 'A web group representing this contact.',
384
+ 'deprecated': True,
385
+ 'doc': 'Deprecated. Use inet:service:group:profile to link to a group.',
384
386
  }),
385
387
  ('birth:place', ('geo:place', {}), {
386
388
  'doc': 'A fully resolved place of birth for this contact.',
@@ -463,7 +465,8 @@ class PsModule(s_module.CoreModule):
463
465
  'doc': 'An array of secondary/associated email addresses.',
464
466
  }),
465
467
  ('web:accts', ('array', {'type': 'inet:web:acct', 'uniq': True, 'sorted': True}), {
466
- 'doc': 'An array of secondary/associated web accounts.',
468
+ 'deprecated': True,
469
+ 'doc': 'Deprecated. Use :service:accounts.',
467
470
  }),
468
471
  ('id:numbers', ('array', {'type': 'ou:id:number', 'uniq': True, 'sorted': True}), {
469
472
  'doc': 'An array of secondary/associated IDs.',
@@ -511,7 +514,11 @@ class PsModule(s_module.CoreModule):
511
514
  'doc': 'The file from which the contact list was extracted.',
512
515
  }),
513
516
  ('source:acct', ('inet:web:acct', {}), {
514
- 'doc': 'The web account from which the contact list was extracted.',
517
+ 'deprecated': True,
518
+ 'doc': 'Deprecated. Use :source:account.',
519
+ }),
520
+ ('source:account', ('inet:service:account', {}), {
521
+ 'doc': 'The service account from which the contact list was extracted.',
515
522
  }),
516
523
  )),
517
524
 
synapse/models/risk.py CHANGED
@@ -279,6 +279,9 @@ class RiskModule(s_module.CoreModule):
279
279
  ('active', ('ival', {}), {
280
280
  'doc': 'An interval for when the threat cluster is assessed to have been active.'}),
281
281
 
282
+ ('activity', ('meta:activity', {}), {
283
+ 'doc': 'The most recently assessed activity level of the threat cluster.'}),
284
+
282
285
  ('reporter', ('ou:org', {}), {
283
286
  'doc': 'The organization reporting on the threat cluster.'}),
284
287
 
@@ -1078,6 +1081,9 @@ class RiskModule(s_module.CoreModule):
1078
1081
  'ex': 'nature.earthquake',
1079
1082
  'doc': 'The outage cause type.'}),
1080
1083
 
1084
+ ('attack', ('risk:attack', {}), {
1085
+ 'doc': 'An attack which caused the outage.'}),
1086
+
1081
1087
  ('provider', ('ou:org', {}), {
1082
1088
  'doc': 'The organization which experienced the outage event.'}),
1083
1089
 
synapse/models/syn.py CHANGED
@@ -83,23 +83,28 @@ class SynModule(s_module.CoreModule):
83
83
 
84
84
  async def _liftRuntSynCmd(self, full, valu=None, cmpr=None, view=None):
85
85
 
86
- genr = self.core.stormcmds.values
86
+ def iterStormCmds():
87
+ for item in self.core.getStormCmds():
88
+ yield item[1]
87
89
 
88
- async for node in self._doRuntLift(genr, full, valu, cmpr):
90
+ async for node in self._doRuntLift(iterStormCmds, full, valu, cmpr):
89
91
  yield node
90
92
 
91
93
  async def _liftRuntSynCron(self, full, valu=None, cmpr=None, view=None):
92
94
 
93
- genr = self.core.agenda.appts.values
95
+ def iterAppts():
96
+ for item in self.core.agenda.list():
97
+ yield item[1]
94
98
 
95
- async for node in self._doRuntLift(genr, full, valu, cmpr):
99
+ async for node in self._doRuntLift(iterAppts, full, valu, cmpr):
96
100
  yield node
97
101
 
98
102
  async def _liftRuntSynForm(self, full, valu=None, cmpr=None, view=None):
99
103
 
100
- genr = self.model.forms.values
104
+ def getForms():
105
+ return list(self.model.forms.values())
101
106
 
102
- async for node in self._doRuntLift(genr, full, valu, cmpr):
107
+ async for node in self._doRuntLift(getForms, full, valu, cmpr):
103
108
  yield node
104
109
 
105
110
  async def _liftRuntSynProp(self, full, valu=None, cmpr=None, view=None):
@@ -111,24 +116,29 @@ class SynModule(s_module.CoreModule):
111
116
 
112
117
  async def _liftRuntSynType(self, full, valu=None, cmpr=None, view=None):
113
118
 
114
- genr = self.model.types.values
119
+ def getTypes():
120
+ return list(self.model.types.values())
115
121
 
116
- async for node in self._doRuntLift(genr, full, valu, cmpr):
122
+ async for node in self._doRuntLift(getTypes, full, valu, cmpr):
117
123
  yield node
118
124
 
119
125
  async def _liftRuntSynTagProp(self, full, valu=None, cmpr=None, view=None):
120
126
 
121
- genr = self.model.tagprops.values
127
+ def getTagProps():
128
+ return list(self.model.tagprops.values())
122
129
 
123
- async for node in self._doRuntLift(genr, full, valu, cmpr):
130
+ async for node in self._doRuntLift(getTagProps, full, valu, cmpr):
124
131
  yield node
125
132
 
126
133
  async def _liftRuntSynTrigger(self, full, valu=None, cmpr=None, view=None):
127
134
 
128
135
  view = self.core.getView(iden=view)
129
- genr = view.triggers.triggers.values
130
136
 
131
- async for node in self._doRuntLift(genr, full, valu, cmpr):
137
+ def iterTriggers():
138
+ for item in view.triggers.list():
139
+ yield item[1]
140
+
141
+ async for node in self._doRuntLift(iterTriggers, full, valu, cmpr):
132
142
  yield node
133
143
 
134
144
  async def _doRuntLift(self, genr, full, valu=None, cmpr=None):
synapse/models/telco.py CHANGED
@@ -376,7 +376,9 @@ class TelcoModule(s_module.CoreModule):
376
376
  # User related data
377
377
  ('name', ('ps:name', {}), {}),
378
378
  ('email', ('inet:email', {}), {}),
379
- ('acct', ('inet:web:acct', {}), {}),
379
+ ('acct', ('inet:web:acct', {}), {
380
+ 'doc': 'Deprecated, use :account.',
381
+ 'deprecated': True}),
380
382
 
381
383
  ('account', ('inet:service:account', {}), {
382
384
  'doc': 'The service account which is associated with the tracked device.'}),
@@ -1,6 +1,5 @@
1
1
  import os
2
2
  import copy
3
- import json
4
3
  import time
5
4
  import asyncio
6
5
  import hashlib
@@ -36,10 +35,6 @@ from synapse.tests.utils import alist
36
35
 
37
36
  logger = logging.getLogger(__name__)
38
37
 
39
- def jsonlines(text):
40
- lines = [k for k in text.split('\n') if k]
41
- return [json.loads(line) for line in lines]
42
-
43
38
  class CortexTest(s_t_utils.SynTest):
44
39
  '''
45
40
  The tests that should be run with different types of layers
@@ -1117,8 +1112,7 @@ class CortexTest(s_t_utils.SynTest):
1117
1112
  ''')
1118
1113
  self.true(await stream.wait(6))
1119
1114
 
1120
- buf = stream.getvalue()
1121
- mesg = json.loads(buf.split('\n')[0])
1115
+ mesg = stream.jsonlines()[0]
1122
1116
  self.eq(mesg.get('message'), f'Running dmon {iden}')
1123
1117
  self.eq(mesg.get('iden'), iden)
1124
1118
 
@@ -3368,8 +3362,7 @@ class CortexBasicTest(s_t_utils.SynTest):
3368
3362
  await alist(core.storm('help foo', opts={'show': ('init', 'fini', 'print',)}))
3369
3363
  self.true(await stream.wait(4))
3370
3364
 
3371
- buf = stream.getvalue()
3372
- mesg = json.loads(buf.split('\n')[0])
3365
+ mesg = stream.jsonlines()[0]
3373
3366
  self.eq(mesg.get('view'), view)
3374
3367
 
3375
3368
  async def test_strict(self):
@@ -7904,8 +7897,7 @@ class CortexBasicTest(s_t_utils.SynTest):
7904
7897
  self.eq('admin', whoami)
7905
7898
  self.eq('lowuser', udef.get('name'))
7906
7899
 
7907
- raw_mesgs = [m for m in stream.getvalue().split('\n') if m]
7908
- msgs = [json.loads(m) for m in raw_mesgs]
7900
+ msgs = stream.jsonlines()
7909
7901
  mesg = [m for m in msgs if 'Added user' in m.get('message')][0]
7910
7902
  self.eq('Added user=lowuser', mesg.get('message'))
7911
7903
  self.eq('admin', mesg.get('username'))
@@ -7919,8 +7911,7 @@ class CortexBasicTest(s_t_utils.SynTest):
7919
7911
  msgs.append(mesg)
7920
7912
  self.stormHasNoWarnErr(msgs)
7921
7913
 
7922
- raw_mesgs = [m for m in stream.getvalue().split('\n') if m]
7923
- msgs = [json.loads(m) for m in raw_mesgs]
7914
+ msgs = stream.jsonlines()
7924
7915
  mesg = [m for m in msgs if 'Set admin' in m.get('message')][0]
7925
7916
  self.isin('Set admin=True for lowuser', mesg.get('message'))
7926
7917
  self.eq('admin', mesg.get('username'))
@@ -8128,7 +8119,7 @@ class CortexBasicTest(s_t_utils.SynTest):
8128
8119
 
8129
8120
  data = stream.getvalue()
8130
8121
  self.notin('Timeout', data)
8131
- msgs = jsonlines(data)
8122
+ msgs = stream.jsonlines()
8132
8123
  self.len(2, msgs)
8133
8124
 
8134
8125
  self.eq(msgs[0].get('message'), f'Offloading Storm query to mirror 01.core.{ahanet}.')
@@ -8147,7 +8138,7 @@ class CortexBasicTest(s_t_utils.SynTest):
8147
8138
 
8148
8139
  data = stream.getvalue()
8149
8140
  self.notin('Timeout', data)
8150
- msgs = jsonlines(data)
8141
+ msgs = stream.jsonlines()
8151
8142
  self.len(2, msgs)
8152
8143
 
8153
8144
  self.eq(msgs[0].get('message'), f'Offloading Storm query to mirror 01.core.{ahanet}.')
@@ -8166,7 +8157,7 @@ class CortexBasicTest(s_t_utils.SynTest):
8166
8157
 
8167
8158
  data = stream.getvalue()
8168
8159
  self.notin('Timeout', data)
8169
- msgs = jsonlines(data)
8160
+ msgs = stream.jsonlines()
8170
8161
  self.len(2, msgs)
8171
8162
 
8172
8163
  self.eq(msgs[0].get('message'), f'Offloading Storm query to mirror 01.core.{ahanet}.')
@@ -8185,7 +8176,7 @@ class CortexBasicTest(s_t_utils.SynTest):
8185
8176
 
8186
8177
  data = stream.getvalue()
8187
8178
  self.notin('Timeout', data)
8188
- msgs = jsonlines(data)
8179
+ msgs = stream.jsonlines()
8189
8180
  self.len(2, msgs)
8190
8181
 
8191
8182
  self.eq(msgs[0].get('message'), f'Offloading Storm query to mirror 01.core.{ahanet}.')
@@ -1,4 +1,3 @@
1
- import json
2
1
  import asyncio
3
2
  import hashlib
4
3
  import datetime
@@ -9,8 +8,6 @@ import synapse.exc as s_exc
9
8
  import synapse.common as s_common
10
9
  import synapse.tests.utils as s_t_utils
11
10
 
12
- import synapse.lib.hive as s_hive
13
- import synapse.lib.lmdbslab as s_lmdbslab
14
11
  import synapse.tools.backup as s_tools_backup
15
12
 
16
13
  import synapse.lib.agenda as s_agenda
@@ -401,9 +398,7 @@ class AgendaTest(s_t_utils.SynTest):
401
398
  self.eq((12, 'bar'), await asyncio.wait_for(core.callStorm('return($lib.queue.gen(visi).pop(wait=$lib.true))'), timeout=5))
402
399
  core.stormlog = False
403
400
 
404
- data = stream.getvalue()
405
- raw_mesgs = [m for m in data.split('\n') if m]
406
- msgs = [json.loads(m) for m in raw_mesgs]
401
+ msgs = stream.jsonlines()
407
402
  msgs = [m for m in msgs if m['text'] == '$lib.queue.gen(visi).put(bar)']
408
403
  self.gt(len(msgs), 0)
409
404
  for m in msgs:
@@ -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.seek(0)
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
- data = stream.getvalue()
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
- data = stream.getvalue()
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'))
@@ -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
- data = stream.getvalue()
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')
@@ -4920,8 +4920,7 @@ class StormTypesTest(s_test.SynTest):
4920
4920
  unixtime += 7 * MINSECS
4921
4921
  self.eq('m3', await getNextFoo())
4922
4922
  self.true(await stream.wait(6))
4923
- buf = stream.getvalue()
4924
- mesg = json.loads(buf.split('\n')[0])
4923
+ mesg = stream.jsonlines()[0]
4925
4924
  self.eq(mesg['message'], f'm3 cron {guid}')
4926
4925
  self.eq(mesg['iden'], guid)
4927
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
- buf = stream.getvalue()
257
- mesg = json.loads(buf.split('\n')[-2])
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
 
@@ -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('[meta:source="*" :name="FOO Bar" :type=osint :url="https://foo.bar/index.html"]')
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:acct', 'tel:mob:telem:app', 'tel:mob:telem:data',
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',
@@ -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 = *
@@ -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"'))