synapse 2.177.0__py311-none-any.whl → 2.179.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 (73) hide show
  1. synapse/cortex.py +170 -31
  2. synapse/datamodel.py +47 -1
  3. synapse/exc.py +1 -0
  4. synapse/lib/aha.py +362 -88
  5. synapse/lib/ast.py +26 -22
  6. synapse/lib/base.py +39 -12
  7. synapse/lib/cell.py +315 -119
  8. synapse/lib/config.py +15 -11
  9. synapse/lib/coro.py +27 -0
  10. synapse/lib/drive.py +551 -0
  11. synapse/lib/layer.py +0 -5
  12. synapse/lib/link.py +1 -1
  13. synapse/lib/lmdbslab.py +3 -3
  14. synapse/lib/nexus.py +24 -12
  15. synapse/lib/schemas.py +39 -0
  16. synapse/lib/snap.py +17 -7
  17. synapse/lib/storm.py +3 -1
  18. synapse/lib/stormhttp.py +1 -0
  19. synapse/lib/stormlib/imap.py +6 -2
  20. synapse/lib/stormlib/modelext.py +29 -3
  21. synapse/lib/stormlib/smtp.py +12 -2
  22. synapse/lib/stormlib/stix.py +40 -17
  23. synapse/lib/stormlib/vault.py +2 -2
  24. synapse/lib/stormtypes.py +1 -1
  25. synapse/lib/types.py +9 -0
  26. synapse/lib/version.py +2 -2
  27. synapse/lookup/pe.py +303 -38
  28. synapse/models/dns.py +24 -1
  29. synapse/models/geospace.py +4 -1
  30. synapse/models/infotech.py +26 -1
  31. synapse/telepath.py +32 -17
  32. synapse/tests/files/aha/certs/cas/synapse.crt +28 -0
  33. synapse/tests/files/aha/certs/cas/synapse.key +51 -0
  34. synapse/tests/files/aha/certs/hosts/00.aha.loop.vertex.link.crt +30 -0
  35. synapse/tests/files/aha/certs/hosts/00.aha.loop.vertex.link.key +51 -0
  36. synapse/tests/files/aha/certs/users/root@synapse.crt +29 -0
  37. synapse/tests/files/aha/certs/users/root@synapse.key +51 -0
  38. synapse/tests/files/rstorm/testsvc.py +1 -1
  39. synapse/tests/test_axon.py +1 -1
  40. synapse/tests/test_cortex.py +67 -60
  41. synapse/tests/test_lib_agenda.py +3 -3
  42. synapse/tests/test_lib_aha.py +353 -490
  43. synapse/tests/test_lib_base.py +20 -0
  44. synapse/tests/test_lib_cell.py +273 -22
  45. synapse/tests/test_lib_config.py +4 -3
  46. synapse/tests/test_lib_coro.py +12 -0
  47. synapse/tests/test_lib_nexus.py +8 -0
  48. synapse/tests/test_lib_stormhttp.py +40 -0
  49. synapse/tests/test_lib_stormlib_aha.py +35 -35
  50. synapse/tests/test_lib_stormlib_cell.py +4 -15
  51. synapse/tests/test_lib_stormlib_imap.py +14 -3
  52. synapse/tests/test_lib_stormlib_modelext.py +55 -3
  53. synapse/tests/test_lib_stormlib_smtp.py +51 -0
  54. synapse/tests/test_lib_stormlib_stix.py +15 -0
  55. synapse/tests/test_lib_stormlib_vault.py +11 -1
  56. synapse/tests/test_lib_stormtypes.py +5 -0
  57. synapse/tests/test_lib_types.py +9 -0
  58. synapse/tests/test_model_dns.py +8 -0
  59. synapse/tests/test_model_geospace.py +3 -1
  60. synapse/tests/test_model_infotech.py +47 -0
  61. synapse/tests/test_model_syn.py +11 -0
  62. synapse/tests/test_tools_aha.py +78 -101
  63. synapse/tests/test_utils_stormcov.py +1 -1
  64. synapse/tests/utils.py +86 -120
  65. synapse/tools/aha/clone.py +50 -0
  66. synapse/tools/aha/enroll.py +2 -1
  67. synapse/tools/backup.py +2 -2
  68. synapse/tools/changelog.py +31 -1
  69. {synapse-2.177.0.dist-info → synapse-2.179.0.dist-info}/METADATA +48 -48
  70. {synapse-2.177.0.dist-info → synapse-2.179.0.dist-info}/RECORD +73 -65
  71. {synapse-2.177.0.dist-info → synapse-2.179.0.dist-info}/WHEEL +1 -1
  72. {synapse-2.177.0.dist-info → synapse-2.179.0.dist-info}/LICENSE +0 -0
  73. {synapse-2.177.0.dist-info → synapse-2.179.0.dist-info}/top_level.txt +0 -0
@@ -10,7 +10,7 @@ class AhaLibTest(s_test.SynTest):
10
10
 
11
11
  async def test_stormlib_aha_basics(self):
12
12
 
13
- async with self.getTestAhaProv() as aha:
13
+ async with self.getTestAha() as aha:
14
14
 
15
15
  with self.getTestDir() as dirn:
16
16
 
@@ -36,24 +36,24 @@ class AhaLibTest(s_test.SynTest):
36
36
  self.len(5, svcs)
37
37
 
38
38
  svc = await core00.callStorm('return( $lib.aha.get(core...) )')
39
- self.eq('core.loop.vertex.link', svc.get('name'))
40
- svc = await core00.callStorm('return( $lib.aha.get(core.loop.vertex.link))')
41
- self.eq('core.loop.vertex.link', svc.get('name'))
39
+ self.eq('core.synapse', svc.get('name'))
40
+ svc = await core00.callStorm('return( $lib.aha.get(core.synapse))')
41
+ self.eq('core.synapse', svc.get('name'))
42
42
  svc = await core00.callStorm('return( $lib.aha.get(00.cell...))')
43
- self.eq('00.cell.loop.vertex.link', svc.get('name'))
43
+ self.eq('00.cell.synapse', svc.get('name'))
44
44
  svc = await core00.callStorm('return( $lib.aha.get(cell...))')
45
- self.eq('cell.loop.vertex.link', svc.get('name'))
45
+ self.eq('cell.synapse', svc.get('name'))
46
46
  svc = await core00.callStorm('$f=({"mirror": (true)}) return( $lib.aha.get(cell..., filters=$f))')
47
- self.eq('01.cell.loop.vertex.link', svc.get('name'))
47
+ self.eq('01.cell.synapse', svc.get('name'))
48
48
 
49
49
  # List the aha services available
50
50
  msgs = await core00.stormlist('aha.svc.list --nexus')
51
51
  self.stormIsInPrint('Nexus', msgs)
52
- self.stormIsInPrint('00.cell.loop.vertex.link true true true', msgs)
53
- self.stormIsInPrint('01.cell.loop.vertex.link false true true', msgs)
54
- self.stormIsInPrint('cell.loop.vertex.link true true true', msgs)
55
- self.stormIsInPrint('core.loop.vertex.link null true true', msgs)
56
- self.stormIsInPrint('mysvc.loop.vertex.link null true true', msgs)
52
+ self.stormIsInPrint('00.cell.synapse true true true', msgs, whitespace=False)
53
+ self.stormIsInPrint('01.cell.synapse false true true', msgs, whitespace=False)
54
+ self.stormIsInPrint('cell.synapse true true true', msgs, whitespace=False)
55
+ self.stormIsInPrint('core.synapse null true true', msgs, whitespace=False)
56
+ self.stormIsInPrint('mysvc.synapse null true true', msgs, whitespace=False)
57
57
 
58
58
  msgs = await core00.stormlist('aha.svc.list')
59
59
  self.stormNotInPrint('Nexus', msgs)
@@ -63,24 +63,24 @@ class AhaLibTest(s_test.SynTest):
63
63
  # Omit checking part of that.
64
64
  emsg = '''Resolved cell... to an AHA Service.
65
65
 
66
- Name: cell.loop.vertex.link
66
+ Name: cell.synapse
67
67
  Online: true
68
68
  Ready: true
69
69
  Run iden: ********************************
70
70
  Cell iden: ********************************
71
71
  Leader: cell
72
72
  Connection information:
73
- ca: loop.vertex.link
73
+ ca: synapse
74
74
  '''
75
75
  self.stormIsInPrint(emsg, msgs, deguid=True)
76
- self.stormIsInPrint(' hostname: 00.cell.loop.vertex.link', msgs)
76
+ self.stormIsInPrint(' hostname: 00.cell.synapse', msgs)
77
77
  self.stormIsInPrint(' scheme: ssl', msgs)
78
78
  self.stormIsInPrint(' user: root', msgs)
79
79
 
80
80
  msgs = await core00.stormlist('aha.svc.stat --nexus cell...')
81
81
  emsg = '''Resolved cell... to an AHA Service.
82
82
 
83
- Name: cell.loop.vertex.link
83
+ Name: cell.synapse
84
84
  Online: true
85
85
  Ready: true
86
86
  Run iden: ********************************
@@ -88,14 +88,14 @@ Cell iden: ********************************
88
88
  Leader: cell
89
89
  Nexus: 1
90
90
  Connection information:
91
- ca: loop.vertex.link
91
+ ca: synapse
92
92
  '''
93
93
  self.stormIsInPrint(emsg, msgs, deguid=True)
94
94
 
95
95
  msgs = await core00.stormlist('aha.svc.stat --nexus 01.cell...')
96
96
  emsg = '''Resolved 01.cell... to an AHA Service.
97
97
 
98
- Name: 01.cell.loop.vertex.link
98
+ Name: 01.cell.synapse
99
99
  Online: true
100
100
  Ready: true
101
101
  Run iden: ********************************
@@ -103,15 +103,15 @@ Cell iden: ********************************
103
103
  Leader: cell
104
104
  Nexus: 1
105
105
  Connection information:
106
- ca: loop.vertex.link
106
+ ca: synapse
107
107
  '''
108
108
  self.stormIsInPrint(emsg, msgs, deguid=True)
109
109
 
110
110
  # Full name works
111
- msgs = await core00.stormlist('aha.svc.stat 01.cell.loop.vertex.link')
112
- emsg = '''Resolved 01.cell.loop.vertex.link to an AHA Service.
111
+ msgs = await core00.stormlist('aha.svc.stat 01.cell.synapse')
112
+ emsg = '''Resolved 01.cell.synapse to an AHA Service.
113
113
 
114
- Name: 01.cell.loop.vertex.link
114
+ Name: 01.cell.synapse
115
115
  '''
116
116
  self.stormIsInPrint(emsg, msgs, deguid=True)
117
117
 
@@ -128,8 +128,8 @@ Name: 01.cell.loop.vertex.link
128
128
  emsg = '''Resolved pool00... to an AHA Pool.
129
129
 
130
130
  The pool currently has 1 members.
131
- AHA Pool: pool00.loop.vertex.link
132
- Member: 00.cell.loop.vertex.link'''
131
+ AHA Pool: pool00.synapse
132
+ Member: 00.cell.synapse'''
133
133
  self.stormIsInPrint(emsg, msgs)
134
134
 
135
135
  # Shut down a service
@@ -139,15 +139,15 @@ Member: 00.cell.loop.vertex.link'''
139
139
  self.len(nevents, await waiter.wait(timeout=12))
140
140
 
141
141
  msgs = await core00.stormlist('aha.svc.list')
142
- self.stormIsInPrint('01.cell.loop.vertex.link false false false', msgs)
142
+ self.stormIsInPrint('01.cell.synapse false false false', msgs, whitespace=False)
143
143
 
144
144
  # Fake a record
145
145
  await aha.addAhaSvc('00.newp', info={'urlinfo': {'scheme': 'tcp', 'host': '0.0.0.0', 'port': '3030'}},
146
- network='loop.vertex.link')
146
+ network='synapse')
147
147
 
148
148
  msgs = await core00.stormlist('aha.svc.list --nexus')
149
- emsg = '00.newp.loop.vertex.link null false null 0.0.0.0 3030 <offline>'
150
- self.stormIsInPrint(emsg, msgs)
149
+ emsg = '00.newp.synapse null false null 0.0.0.0 3030 <offline>'
150
+ self.stormIsInPrint(emsg, msgs, whitespace=False)
151
151
 
152
152
  self.none(await core00.callStorm('return($lib.aha.del(00.newp...))'))
153
153
  msgs = await core00.stormlist('aha.svc.list')
@@ -160,22 +160,22 @@ Member: 00.cell.loop.vertex.link'''
160
160
  'port': '3030'},
161
161
  'online': guid,
162
162
  },
163
- network='loop.vertex.link')
163
+ network='synapse')
164
164
  msgs = await core00.stormlist('aha.svc.list --nexus')
165
- emsg = '00.newp.loop.vertex.link null true null 0.0.0.0 3030 ' \
166
- 'Failed to connect to Telepath service: "aha://00.newp.loop.vertex.link/" error:'
167
- self.stormIsInPrint(emsg, msgs)
165
+ emsg = '00.newp.synapse null true null 0.0.0.0 3030 ' \
166
+ 'Failed to connect to Telepath service: "aha://00.newp.synapse/" error:'
167
+ self.stormIsInPrint(emsg, msgs, whitespace=False)
168
168
 
169
169
  msgs = await core00.stormlist('aha.svc.stat --nexus 00.newp...')
170
170
  emsg = '''Resolved 00.newp... to an AHA Service.
171
171
 
172
- Name: 00.newp.loop.vertex.link
172
+ Name: 00.newp.synapse
173
173
  Online: true
174
174
  Ready: null
175
175
  Run iden: $lib.null
176
176
  Cell iden: $lib.null
177
177
  Leader: Service did not register itself with a leader name.
178
- Nexus: Failed to connect to Telepath service: "aha://00.newp.loop.vertex.link/" error: [Errno 111] Connect call failed ('0.0.0.0', 3030)
178
+ Nexus: Failed to connect to Telepath service: "aha://00.newp.synapse/" error: [Errno 111] Connect call failed ('0.0.0.0', 3030)
179
179
  Connection information:
180
180
  host: 0.0.0.0
181
181
  port: 3030
@@ -184,7 +184,7 @@ Connection information:
184
184
  self.stormIsInPrint(emsg, msgs)
185
185
 
186
186
  # Delete the fake service with its full service name
187
- self.none(await core00.callStorm('return($lib.aha.del(00.newp.loop.vertex.link))'))
187
+ self.none(await core00.callStorm('return($lib.aha.del(00.newp.synapse))'))
188
188
  self.none(await core00.callStorm('return($lib.aha.get(00.newp...))'))
189
189
 
190
190
  # Coverage for sad paths
@@ -76,18 +76,7 @@ class StormCellTest(s_test.SynTest):
76
76
 
77
77
  async def test_stormlib_cell_getmirrors(self):
78
78
 
79
- conf = {
80
- 'aha:name': 'aha',
81
- 'aha:network': 'mynet',
82
- 'provision:listen': 'tcp://127.0.0.1:0',
83
- }
84
- async with self.getTestCell(s_aha.AhaCell, conf=conf) as aha:
85
-
86
- provaddr, provport = aha.provdmon.addr
87
- aha.conf['provision:listen'] = f'tcp://127.0.0.1:{provport}'
88
-
89
- ahahost, ahaport = await aha.dmon.listen('ssl://127.0.0.1:0?hostname=aha.mynet&ca=mynet')
90
- aha.conf['aha:urls'] = (f'ssl://127.0.0.1:{ahaport}?hostname=aha.mynet',)
79
+ async with self.getTestAha() as aha:
91
80
 
92
81
  provurl = await aha.addAhaSvcProv('00.cortex')
93
82
  coreconf = {'aha:provision': provurl}
@@ -116,7 +105,7 @@ class StormCellTest(s_test.SynTest):
116
105
  await core01.nodes('[ inet:ipv4=1.2.3.4 ]')
117
106
  self.len(1, await core00.nodes('inet:ipv4=1.2.3.4'))
118
107
 
119
- expurls = ['aha://01.cortex.mynet']
108
+ expurls = ['aha://01.cortex.synapse']
120
109
 
121
110
  self.eq(expurls, await core00.callStorm('return($lib.cell.getMirrorUrls())'))
122
111
  self.eq(expurls, await core01.callStorm('return($lib.cell.getMirrorUrls())'))
@@ -148,11 +137,11 @@ class StormCellTest(s_test.SynTest):
148
137
 
149
138
  await svc01.sync()
150
139
 
151
- expurls = ('aha://01.testsvc.mynet',)
140
+ expurls = ('aha://01.testsvc.synapse',)
152
141
 
153
142
  self.eq(expurls, await core00.callStorm('return($lib.cell.getMirrorUrls(name=testsvc))'))
154
143
 
155
- await aha.delAhaSvc('00.testsvc.mynet')
144
+ await aha.delAhaSvc('00.testsvc.synapse')
156
145
 
157
146
  with self.raises(s_exc.NoSuchName):
158
147
  await core00.callStorm('return($lib.cell.getMirrorUrls(name=testsvc))')
@@ -1,3 +1,4 @@
1
+ import ssl
1
2
  import asyncio
2
3
 
3
4
  from unittest import mock
@@ -124,8 +125,13 @@ class ImapTest(s_test.SynTest):
124
125
 
125
126
  async def test_storm_imap(self):
126
127
 
127
- with mock.patch('aioimaplib.IMAP4.create_client', mock_create_client), \
128
- mock.patch('aioimaplib.IMAP4_SSL.create_client', mock_create_client):
128
+ client_args = []
129
+ def client_mock(*args, **kwargs):
130
+ client_args.append((args, kwargs))
131
+ return mock_create_client(*args, **kwargs)
132
+
133
+ with mock.patch('aioimaplib.IMAP4.create_client', client_mock), \
134
+ mock.patch('aioimaplib.IMAP4_SSL.create_client', client_mock):
129
135
 
130
136
  async with self.getTestCore() as core:
131
137
 
@@ -137,16 +143,20 @@ class ImapTest(s_test.SynTest):
137
143
  '''
138
144
  retn = await core.callStorm(scmd)
139
145
  self.eq((True, ('INBOX',)), retn)
146
+ ctx = self.nn(client_args[-1][0][5]) # type: ssl.SSLContext
147
+ self.eq(ctx.verify_mode, ssl.CERT_REQUIRED)
140
148
 
141
149
  # search for UIDs
142
150
  scmd = '''
143
- $server = $lib.inet.imap.connect(hello)
151
+ $server = $lib.inet.imap.connect(hello, ssl_verify=(false))
144
152
  $server.login("vtx@email.com", "secret")
145
153
  $server.select("INBOX")
146
154
  return($server.search("FROM", "foo@mail.com"))
147
155
  '''
148
156
  retn = await core.callStorm(scmd)
149
157
  self.eq((True, ('8181', '8192', '8194')), retn)
158
+ ctx = self.nn(client_args[-1][0][5]) # type: ssl.SSLContext
159
+ self.eq(ctx.verify_mode, ssl.CERT_NONE)
150
160
 
151
161
  # search for UIDs with specific charset
152
162
  scmd = '''
@@ -186,6 +196,7 @@ class ImapTest(s_test.SynTest):
186
196
  '''
187
197
  retn = await core.callStorm(scmd)
188
198
  self.eq((True, None), retn)
199
+ self.none(client_args[-1][0][5])
189
200
 
190
201
  # delete
191
202
  scmd = '''
@@ -57,12 +57,24 @@ class StormtypesModelextTest(s_test.SynTest):
57
57
  model_defs = await core.callStorm('return ( $lib.model.ext.getExtModel() )')
58
58
  self.isinstance(model_defs, dict)
59
59
 
60
+ self.len(1, await core.nodes('_visi:int:tick'))
61
+ await core._delAllFormProp('_visi:int', 'tick', {})
62
+ self.len(0, await core.nodes('_visi:int:tick'))
63
+
64
+ self.len(1, await core.nodes('._woot'))
65
+ await core._delAllUnivProp('_woot', {})
66
+ self.len(0, await core.nodes('._woot'))
67
+
68
+ self.len(1, await core.nodes('#lol:score'))
69
+ await core._delAllTagProp('score', {})
70
+ self.len(0, await core.nodes('#lol:score'))
71
+
60
72
  await core.callStorm('_visi:int=10 test:int=1234 | delnode')
61
73
  await core.callStorm('''
62
- $lib.model.ext.delTagProp(score)
63
- $lib.model.ext.delUnivProp(_woot)
74
+ $lib.model.ext.delTagProp(score, force=(true))
75
+ $lib.model.ext.delUnivProp(_woot, force=(true))
64
76
  $lib.model.ext.delFormProp(_visi:int, tick)
65
- $lib.model.ext.delFormProp(test:int, _tick)
77
+ $lib.model.ext.delFormProp(test:int, _tick, force=(true))
66
78
  $lib.model.ext.delForm(_visi:int)
67
79
  $lib.model.ext.delEdge(inet:user, _copies, *)
68
80
  ''')
@@ -276,6 +288,46 @@ class StormtypesModelextTest(s_test.SynTest):
276
288
 
277
289
  self.nn(core.model.edge(('inet:user', '_copies', None)))
278
290
 
291
+ # Property values left behind in layers are cleanly removed
292
+ async with self.getTestCore() as core:
293
+ await core.callStorm('''
294
+ $typeinfo = ({})
295
+ $docinfo = ({"doc": "NEWP"})
296
+ $lib.model.ext.addUnivProp(_woot, (int, ({})), $docinfo)
297
+ $lib.model.ext.addTagProp(score, (int, ({})), $docinfo)
298
+ $lib.model.ext.addFormProp(test:int, _tick, (time, ({})), $docinfo)
299
+ ''')
300
+ fork = await core.callStorm('return ( $lib.view.get().fork().iden ) ')
301
+ nodes = await core.nodes('[test:int=1234 :_tick=2024 ._woot=1 +#hehe:score=10]')
302
+ self.len(1, nodes)
303
+ self.eq(nodes[0].get('._woot'), 1)
304
+
305
+ nodes = await core.nodes('test:int=1234 [:_tick=2023 ._woot=2 +#hehe:score=9]',
306
+ opts={'view': fork})
307
+ self.len(1, nodes)
308
+ self.eq(nodes[0].get('._woot'), 2)
309
+
310
+ self.len(0, await core.nodes('test:int | delnode'))
311
+
312
+ with self.raises(s_exc.CantDelUniv):
313
+ await core.callStorm('$lib.model.ext.delUnivProp(_woot)')
314
+ with self.raises(s_exc.CantDelProp):
315
+ await core.callStorm('$lib.model.ext.delFormProp(test:int, _tick)')
316
+ with self.raises(s_exc.CantDelProp):
317
+ await core.callStorm('$lib.model.ext.delTagProp(score)')
318
+
319
+ await core.callStorm('$lib.model.ext.delUnivProp(_woot, force=(true))')
320
+ await core.callStorm('$lib.model.ext.delFormProp(test:int, _tick, force=(true))')
321
+ await core.callStorm('$lib.model.ext.delTagProp(score, force=(true))')
322
+
323
+ nodes = await core.nodes('[test:int=1234]')
324
+ self.len(1, nodes)
325
+ self.none(nodes[0].get('._woot'))
326
+ self.none(nodes[0].get('_tick'))
327
+ nodes = await core.nodes('test:int=1234', opts={'view': fork})
328
+ self.none(nodes[0].get('._woot'))
329
+ self.none(nodes[0].get('_tick'))
330
+
279
331
  async def test_lib_stormlib_behold_modelext(self):
280
332
  self.skipIfNexusReplay()
281
333
  async with self.getTestCore() as core:
@@ -1,3 +1,6 @@
1
+ import ssl
2
+ import email.mime.multipart as e_muiltipart
3
+
1
4
  from unittest import mock
2
5
  import synapse.tests.utils as s_test
3
6
 
@@ -5,7 +8,9 @@ class SmtpTest(s_test.SynTest):
5
8
 
6
9
  async def test_storm_smtp(self):
7
10
 
11
+ called_args = []
8
12
  async def send(*args, **kwargs):
13
+ called_args.append((args, kwargs))
9
14
  return
10
15
 
11
16
  with mock.patch('aiosmtplib.send', send):
@@ -14,6 +19,9 @@ class SmtpTest(s_test.SynTest):
14
19
 
15
20
  retn = await core.callStorm('return($lib.inet.smtp.message().send(127.0.0.1))')
16
21
  self.false(retn[0])
22
+ self.eq(retn[1].get('err'), 'StormRuntimeError')
23
+ self.isin('The inet:smtp:message has no HTML or text body.', retn[1].get('errmsg'))
24
+ self.len(0, called_args)
17
25
 
18
26
  retn = await core.callStorm('''
19
27
  $message = $lib.inet.smtp.message()
@@ -31,6 +39,49 @@ class SmtpTest(s_test.SynTest):
31
39
  return($message.send('smtp.gmail.com', port=465, usetls=true))
32
40
  ''')
33
41
  self.eq(retn, (True, {}))
42
+ mesg = called_args[-1][0][0] # type: e_muiltipart.MIMEMultipart
43
+ self.eq(mesg.get_all('subject'), ['woot'])
44
+ payload = mesg.get_payload()
45
+ self.len(2, payload)
46
+ self.eq([pl.get_content_type() for pl in payload],
47
+ ['text/plain', 'text/html'])
48
+ ctx = self.nn(called_args[-1][1].get('tls_context')) # type: ssl.SSLContext
49
+ self.eq(ctx.verify_mode, ssl.CERT_REQUIRED)
50
+ self.eq(called_args[-1][1].get('port'), 465)
51
+ self.true(called_args[-1][1].get('use_tls'))
52
+ self.false(called_args[-1][1].get('start_tls'))
53
+
54
+ retn = await core.callStorm('''
55
+ $message = $lib.inet.smtp.message()
56
+ $message.text = "HELLO WORLD"
57
+ $message.sender = visi@vertex.link
58
+ $message.headers.Subject = woot
59
+ $message.recipients.append(visi@vertex.link)
60
+ return($message.send('smtp.gmail.com', port=465, starttls=true, ssl_verify=(false)))
61
+ ''')
62
+ self.eq(retn, (True, {}))
63
+ mesg = called_args[-1][0][0] # type: e_muiltipart.MIMEMultipart
64
+ payload = mesg.get_payload()
65
+ self.len(1, payload)
66
+ self.eq([pl.get_content_type() for pl in payload], ['text/plain'])
67
+ ctx = self.nn(called_args[-1][1].get('tls_context')) # type: ssl.SSLContext
68
+ self.eq(ctx.verify_mode, ssl.CERT_NONE)
69
+ self.false(called_args[-1][1].get('use_tls'))
70
+ self.true(called_args[-1][1].get('start_tls'))
71
+
72
+ retn = await core.callStorm('''
73
+ $message = $lib.inet.smtp.message()
74
+ $message.text = "HELLO WORLD"
75
+ $message.sender = visi@vertex.link
76
+ $message.headers.Subject = woot
77
+ $message.recipients.append(visi@vertex.link)
78
+ return($message.send('smtp.gmail.com', port=25))
79
+ ''')
80
+ self.eq(retn, (True, {}))
81
+ self.none(called_args[-1][1].get('tls_context')) # type: ssl.SSLContext
82
+ self.eq(called_args[-1][1].get('port'), 25)
83
+ self.false(called_args[-1][1].get('use_tls'))
84
+ self.false(called_args[-1][1].get('start_tls'))
34
85
 
35
86
  isok, info = await core.callStorm('''
36
87
  $message = $lib.inet.smtp.message()
@@ -410,6 +410,21 @@ class StormLibStixTest(s_test.SynTest):
410
410
  self.len(1, [n for n in nodes if n[0][0] == 'it:cmd'])
411
411
  self.stormIsInWarn("STIX bundle ingest has no relationship definition for: ('threat-actor', 'gronks', 'threat-actor')", msgs)
412
412
 
413
+ msgs = await core.stormlist('yield $lib.stix.import.ingest(({}), newp)')
414
+ self.stormIsInErr('config must be a dictionary', msgs)
415
+
416
+ msgs = await core.stormlist('yield $lib.stix.import.ingest(({}), ({"relationships": 5}))')
417
+ self.stormIsInErr('Error processing relationships', msgs)
418
+
419
+ msgs = await core.stormlist('yield $lib.stix.import.ingest(({}), ({"bundle": 3}))')
420
+ self.stormIsInErr('bundle value must be a dictionary', msgs)
421
+
422
+ msgs = await core.stormlist('yield $lib.stix.import.ingest(({}), ({"bundle": {"storm": 3}}))')
423
+ self.stormIsInErr('storm query must be a string', msgs)
424
+
425
+ msgs = await core.stormlist('yield $lib.stix.import.ingest(({"objects": 3}), ({}))')
426
+ self.stormIsInErr('Error processing objects', msgs)
427
+
413
428
  async def test_stix_export_custom(self):
414
429
 
415
430
  async with self.getTestCore() as core:
@@ -159,10 +159,13 @@ class StormlibVaultTest(s_test.SynTest):
159
159
 
160
160
  # Rename vault
161
161
  opts = {'vars': {'giden': giden}}
162
+ self.eq('gvault', await core.callStorm('return($lib.vault.get($giden).name)', opts=opts))
162
163
  q = '$lib.vault.get($giden).name = foobar'
163
164
  await core.callStorm(q, opts=opts)
164
165
  vault = core.getVault(giden)
165
166
  self.eq(vault.get('name'), 'foobar')
167
+ self.nn(await core.callStorm('return($lib.vault.byname(foobar))'))
168
+ await self.asyncraises(s_exc.NoSuchName, core.callStorm('return($lib.vault.byname(gvault))'))
166
169
 
167
170
  # Get secrets without EDIT perms
168
171
  opts = {'vars': {'giden': giden}, 'user': visi1.iden}
@@ -222,10 +225,17 @@ class StormlibVaultTest(s_test.SynTest):
222
225
  q = '$vault = $lib.vault.get($giden) return($vault.setPerm($iden, $lib.auth.easyperm.level.deny))'
223
226
  self.true(await core.callStorm(q, opts=opts))
224
227
 
225
- # List vaults again
226
228
  opts = {'user': visi1.iden}
227
229
  self.eq(0, await core.callStorm('return($lib.len($lib.vault.list()))', opts=opts))
228
230
 
231
+ # Remove permission on global vault
232
+ opts = {'vars': {'iden': visi1.iden, 'giden': giden}}
233
+ q = '$vault = $lib.vault.get($giden) return($vault.setPerm($iden, $lib.null))'
234
+ self.true(await core.callStorm(q, opts=opts))
235
+
236
+ opts = {'user': visi1.iden}
237
+ self.eq(1, await core.callStorm('return($lib.len($lib.vault.list()))', opts=opts))
238
+
229
239
  # Runtime asroot
230
240
 
231
241
  await core.addStormPkg({
@@ -6388,6 +6388,11 @@ words\tword\twrd'''
6388
6388
  self.eq(1, await core.callStorm('return($lib.math.number(1.23).toint())'))
6389
6389
  self.eq(2, await core.callStorm('return($lib.math.number(1.23).toint(rounding=ROUND_UP))'))
6390
6390
 
6391
+ with self.raises(s_exc.BadCast):
6392
+ await core.callStorm('return($lib.math.number((null)))')
6393
+ with self.raises(s_exc.BadCast):
6394
+ await core.callStorm('return($lib.math.number(newp))')
6395
+
6391
6396
  with self.raises(s_exc.StormRuntimeError):
6392
6397
  await core.callStorm('return($lib.math.number(1.23).toint(rounding=NEWP))')
6393
6398
 
@@ -1606,3 +1606,12 @@ class TypesTest(s_t_utils.SynTest):
1606
1606
 
1607
1607
  core.getLayer()._testAddPropArrayIndx(buid, 'test:int', '_hehe', ('newp' * 100,))
1608
1608
  self.len(0, await core.nodes('test:int:_hehe*[~=newp]'))
1609
+
1610
+ async def test_types_typehash(self):
1611
+ async with self.getTestCore() as core:
1612
+ self.true(core.model.form('inet:fqdn').type.typehash is core.model.prop('inet:dns:a:fqdn').type.typehash)
1613
+ self.true(core.model.form('it:prod:softname').type.typehash is core.model.prop('it:network:name').type.typehash)
1614
+ self.true(core.model.form('inet:asn').type.typehash is not core.model.prop('inet:proto:port').type.typehash)
1615
+
1616
+ self.true(s_common.isguid(core.model.form('inet:fqdn').type.typehash))
1617
+ self.true(s_common.isguid(core.model.form('inet:fqdn').typehash))
@@ -108,6 +108,14 @@ class DnsModelTest(s_t_utils.SynTest):
108
108
  self.eq(node.get('name:fqdn'), 'vertex.link')
109
109
  self.eq(node.get('type'), 255)
110
110
 
111
+ nodes = await core.nodes('[inet:dns:request=* :reply:code=NXDOMAIN]')
112
+ self.eq(nodes[0].get('reply:code'), 3)
113
+ self.eq(nodes[0].repr('reply:code'), 'NXDOMAIN')
114
+
115
+ nodes = await core.nodes('[inet:dns:request=* :reply:code=1138]')
116
+ self.eq(nodes[0].get('reply:code'), 1138)
117
+ self.eq(nodes[0].repr('reply:code'), '1138')
118
+
111
119
  nodes = await core.nodes('[inet:dns:query=("tcp://1.2.3.4", 4.3.2.1.in-addr.arpa, 255)]')
112
120
  self.len(1, nodes)
113
121
  node = nodes[0]
@@ -2,7 +2,6 @@ import synapse.exc as s_exc
2
2
  import synapse.common as s_common
3
3
 
4
4
  import synapse.tests.utils as s_t_utils
5
- from synapse.tests.utils import alist
6
5
 
7
6
  import synapse.lib.module as s_module
8
7
 
@@ -499,6 +498,7 @@ class GeoTest(s_t_utils.SynTest):
499
498
  :place:name=woot
500
499
  :place={[geo:place=* :name=woot]}
501
500
  :accuracy=10m
501
+ :node=(test:int, 1234)
502
502
  ]
503
503
  ''')
504
504
  self.eq(1655510400000, nodes[0].get('time'))
@@ -507,6 +507,8 @@ class GeoTest(s_t_utils.SynTest):
507
507
  self.eq('woot', nodes[0].get('place:name'))
508
508
  self.eq(10000, nodes[0].get('accuracy'))
509
509
  self.len(1, await core.nodes('geo:telem -> geo:place +:name=woot'))
510
+ self.eq(('test:int', 1234), nodes[0].get('node'))
511
+ self.len(1, await core.nodes('test:int=1234'))
510
512
 
511
513
  async def test_model_geospace_area(self):
512
514
 
@@ -407,6 +407,35 @@ class InfotechModelTest(s_t_utils.SynTest):
407
407
  self.eq(nodes[0].get('net6'), ('fe80::', 'fe80::ffff:ffff:ffff:ffff'))
408
408
  self.eq(nodes[0].get('type'), 'virtual.sdn.')
409
409
 
410
+ nodes = await core.nodes('''[
411
+ it:sec:stix:indicator=*
412
+ :id=zoinks
413
+ :name=woot
414
+ :confidence=90
415
+ :revoked=(false)
416
+ :description="my neato indicator"
417
+ :pattern="some rule text"
418
+ :pattern_type=yara
419
+ :created=20240815
420
+ :updated=20240815
421
+ :labels=(hehe, haha)
422
+ :valid_from=20240815
423
+ :valid_until=20240815
424
+ ]''')
425
+ self.len(1, nodes)
426
+ self.eq('zoinks', nodes[0].get('id'))
427
+ self.eq('woot', nodes[0].get('name'))
428
+ self.eq(90, nodes[0].get('confidence'))
429
+ self.eq(False, nodes[0].get('revoked'))
430
+ self.eq('my neato indicator', nodes[0].get('description'))
431
+ self.eq('some rule text', nodes[0].get('pattern'))
432
+ self.eq('yara', nodes[0].get('pattern_type'))
433
+ self.eq(('haha', 'hehe'), nodes[0].get('labels'))
434
+ self.eq(1723680000000, nodes[0].get('created'))
435
+ self.eq(1723680000000, nodes[0].get('updated'))
436
+ self.eq(1723680000000, nodes[0].get('valid_from'))
437
+ self.eq(1723680000000, nodes[0].get('valid_until'))
438
+
410
439
  async def test_infotech_ios(self):
411
440
 
412
441
  async with self.getTestCore() as core:
@@ -1553,6 +1582,24 @@ class InfotechModelTest(s_t_utils.SynTest):
1553
1582
  self.eq(rule, nodes[0].get('rule'))
1554
1583
  self.eq(0x10000200003, nodes[0].get('version'))
1555
1584
 
1585
+ nodes = await core.nodes('''[
1586
+ (it:app:yara:netmatch=* :node=(inet:fqdn, foo.com))
1587
+ (it:app:yara:netmatch=* :node=(inet:ipv4, 1.2.3.4))
1588
+ (it:app:yara:netmatch=* :node=(inet:ipv6, "::ffff"))
1589
+ (it:app:yara:netmatch=* :node=(inet:url, "http://foo.com"))
1590
+ :rule=$rule
1591
+ :version=1.2.3
1592
+ ]''', opts=opts)
1593
+ self.len(4, nodes)
1594
+ for node in nodes:
1595
+ self.nn(node.get('node'))
1596
+ self.nn(node.get('version'))
1597
+
1598
+ self.len(4, await core.nodes('it:app:yara:rule=$rule -> it:app:yara:netmatch', opts=opts))
1599
+
1600
+ with self.raises(s_exc.BadTypeValu):
1601
+ await core.nodes('[it:app:yara:netmatch=* :node=(it:dev:str, foo)]')
1602
+
1556
1603
  async def test_it_app_snort(self):
1557
1604
 
1558
1605
  async with self.getTestCore() as core:
@@ -340,11 +340,22 @@ class SynModelTest(s_t_utils.SynTest):
340
340
  nodes = await core.nodes(f'syn:trigger={iden}')
341
341
  self.len(1, nodes)
342
342
 
343
+ indx = await core.getNexsIndx()
344
+
343
345
  # set the trigger doc
344
346
  nodes = await core.nodes(f'syn:trigger={iden} [ :doc=hehe ]')
345
347
  self.len(1, nodes)
346
348
  self.eq('hehe', nodes[0].get('doc'))
347
349
 
350
+ self.eq(await core.getNexsIndx(), indx + 1)
351
+
352
+ # set the trigger name
353
+ nodes = await core.nodes(f'syn:trigger={iden} [ :name=trigname ]')
354
+ self.len(1, nodes)
355
+ self.eq('trigname', nodes[0].get('name'))
356
+
357
+ self.eq(await core.getNexsIndx(), indx + 2)
358
+
348
359
  # Trigger reloads and make some more triggers to play with
349
360
  tdef = {'cond': 'prop:set', 'prop': 'inet:ipv4:asn', 'storm': '[inet:user=1] | testcmd'}
350
361
  await core.view.addTrigger(tdef)