synapse 2.176.0__py311-none-any.whl → 2.178.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/axon.py +24 -9
- synapse/cortex.py +337 -172
- synapse/cryotank.py +46 -37
- synapse/datamodel.py +17 -4
- synapse/exc.py +19 -0
- synapse/lib/agenda.py +7 -13
- synapse/lib/aha.py +361 -88
- synapse/lib/auth.py +1520 -0
- synapse/lib/base.py +27 -9
- synapse/lib/cell.py +422 -163
- synapse/lib/config.py +15 -11
- synapse/lib/coro.py +13 -0
- synapse/lib/grammar.py +5 -0
- synapse/lib/hive.py +24 -3
- synapse/lib/hiveauth.py +6 -32
- synapse/lib/layer.py +7 -9
- synapse/lib/link.py +22 -18
- synapse/lib/lmdbslab.py +152 -3
- synapse/lib/modelrev.py +1 -1
- synapse/lib/nexus.py +24 -12
- synapse/lib/schemas.py +136 -0
- synapse/lib/storm.py +61 -29
- synapse/lib/stormlib/aha.py +1 -1
- synapse/lib/stormlib/auth.py +185 -10
- synapse/lib/stormlib/cortex.py +16 -5
- synapse/lib/stormlib/gen.py +80 -0
- synapse/lib/stormlib/imap.py +6 -2
- synapse/lib/stormlib/model.py +55 -0
- synapse/lib/stormlib/modelext.py +60 -0
- synapse/lib/stormlib/smtp.py +12 -2
- synapse/lib/stormlib/tabular.py +212 -0
- synapse/lib/stormtypes.py +14 -1
- synapse/lib/trigger.py +1 -1
- synapse/lib/version.py +2 -2
- synapse/lib/view.py +55 -28
- synapse/models/base.py +7 -0
- synapse/models/biz.py +4 -0
- synapse/models/files.py +8 -1
- synapse/models/inet.py +8 -0
- synapse/telepath.py +32 -17
- synapse/tests/files/aha/certs/cas/synapse.crt +28 -0
- synapse/tests/files/aha/certs/cas/synapse.key +51 -0
- synapse/tests/files/aha/certs/hosts/00.aha.loop.vertex.link.crt +30 -0
- synapse/tests/files/aha/certs/hosts/00.aha.loop.vertex.link.key +51 -0
- synapse/tests/files/aha/certs/users/root@synapse.crt +29 -0
- synapse/tests/files/aha/certs/users/root@synapse.key +51 -0
- synapse/tests/files/changelog/model_2.176.0_16ee721a6b7221344eaf946c3ab4602dda546b1a.yaml.gz +0 -0
- synapse/tests/files/changelog/model_2.176.0_2a25c58bbd344716cd7cbc3f4304d8925b0f4ef2.yaml.gz +0 -0
- synapse/tests/files/rstorm/testsvc.py +1 -1
- synapse/tests/test_axon.py +8 -5
- synapse/tests/test_cortex.py +149 -141
- synapse/tests/test_cryotank.py +4 -4
- synapse/tests/test_datamodel.py +7 -0
- synapse/tests/test_lib_agenda.py +10 -3
- synapse/tests/test_lib_aha.py +336 -490
- synapse/tests/{test_lib_hiveauth.py → test_lib_auth.py} +314 -11
- synapse/tests/test_lib_base.py +20 -0
- synapse/tests/test_lib_cell.py +210 -30
- synapse/tests/test_lib_config.py +4 -3
- synapse/tests/test_lib_httpapi.py +18 -14
- synapse/tests/test_lib_layer.py +33 -33
- synapse/tests/test_lib_link.py +42 -1
- synapse/tests/test_lib_lmdbslab.py +68 -0
- synapse/tests/test_lib_nexus.py +12 -4
- synapse/tests/test_lib_node.py +0 -7
- synapse/tests/test_lib_storm.py +45 -0
- synapse/tests/test_lib_stormlib_aha.py +35 -36
- synapse/tests/test_lib_stormlib_auth.py +21 -0
- synapse/tests/test_lib_stormlib_cell.py +4 -15
- synapse/tests/test_lib_stormlib_cortex.py +12 -12
- synapse/tests/test_lib_stormlib_gen.py +99 -0
- synapse/tests/test_lib_stormlib_imap.py +14 -3
- synapse/tests/test_lib_stormlib_model.py +108 -0
- synapse/tests/test_lib_stormlib_modelext.py +64 -0
- synapse/tests/test_lib_stormlib_smtp.py +51 -0
- synapse/tests/test_lib_stormlib_tabular.py +226 -0
- synapse/tests/test_lib_stormsvc.py +4 -1
- synapse/tests/test_lib_stormtypes.py +10 -0
- synapse/tests/test_model_base.py +3 -0
- synapse/tests/test_model_biz.py +3 -0
- synapse/tests/test_model_files.py +12 -2
- synapse/tests/test_model_inet.py +24 -0
- synapse/tests/test_tools_aha.py +78 -101
- synapse/tests/test_tools_changelog.py +196 -0
- synapse/tests/test_tools_healthcheck.py +4 -3
- synapse/tests/utils.py +87 -121
- synapse/tools/aha/clone.py +50 -0
- synapse/tools/aha/enroll.py +2 -1
- synapse/tools/backup.py +2 -2
- synapse/tools/changelog.py +776 -15
- {synapse-2.176.0.dist-info → synapse-2.178.0.dist-info}/METADATA +48 -48
- {synapse-2.176.0.dist-info → synapse-2.178.0.dist-info}/RECORD +95 -82
- {synapse-2.176.0.dist-info → synapse-2.178.0.dist-info}/WHEEL +1 -1
- {synapse-2.176.0.dist-info → synapse-2.178.0.dist-info}/LICENSE +0 -0
- {synapse-2.176.0.dist-info → synapse-2.178.0.dist-info}/top_level.txt +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import synapse.exc as s_exc
|
|
2
|
+
import synapse.common as s_common
|
|
2
3
|
|
|
3
4
|
import synapse.tests.utils as s_test
|
|
4
5
|
|
|
@@ -245,3 +246,101 @@ class StormLibGenTest(s_test.SynTest):
|
|
|
245
246
|
names = nodes[0].get('names')
|
|
246
247
|
self.len(1, names)
|
|
247
248
|
self.isin('rhodesia', names)
|
|
249
|
+
|
|
250
|
+
async def test_stormlib_gen_fileBytes(self):
|
|
251
|
+
|
|
252
|
+
async with self.getTestCore() as core:
|
|
253
|
+
sha256 = s_common.buid().hex()
|
|
254
|
+
opts = {'vars': {'sha256': sha256}}
|
|
255
|
+
|
|
256
|
+
nodes = await core.nodes('yield $lib.gen.fileBytesBySha256($sha256)', opts=opts)
|
|
257
|
+
self.len(1, nodes)
|
|
258
|
+
self.eq(nodes[0].get('sha256'), sha256)
|
|
259
|
+
|
|
260
|
+
sha256 = s_common.buid().hex()
|
|
261
|
+
opts = {'vars': {'sha256': sha256}}
|
|
262
|
+
|
|
263
|
+
q = '''
|
|
264
|
+
[ file:bytes=(file1,) :sha256=$sha256 ]
|
|
265
|
+
spin |
|
|
266
|
+
yield $lib.gen.fileBytesBySha256($sha256)
|
|
267
|
+
'''
|
|
268
|
+
nodes = await core.nodes(q, opts=opts)
|
|
269
|
+
self.len(1, nodes)
|
|
270
|
+
self.eq(nodes[0].repr(), 'guid:' + s_common.guid(('file1',)))
|
|
271
|
+
|
|
272
|
+
with self.raises(s_exc.BadTypeValu):
|
|
273
|
+
await core.callStorm('$lib.gen.fileBytesBySha256(newp)', opts=opts)
|
|
274
|
+
|
|
275
|
+
q = 'return($lib.gen.fileBytesBySha256(newp, try=$lib.true))'
|
|
276
|
+
self.none(await core.callStorm(q, opts=opts))
|
|
277
|
+
|
|
278
|
+
async def test_stormlib_gen_inetTlsServerCert(self):
|
|
279
|
+
|
|
280
|
+
async with self.getTestCore() as core:
|
|
281
|
+
sha256 = s_common.buid().hex()
|
|
282
|
+
opts = {'vars': {'sha256': sha256}}
|
|
283
|
+
|
|
284
|
+
q = '''
|
|
285
|
+
$server = {[ inet:server="1.2.3.4:443" ]}
|
|
286
|
+
yield $lib.gen.inetTlsServerCertByServerAndSha256($server, $sha256)
|
|
287
|
+
'''
|
|
288
|
+
nodes = await core.nodes(q, opts=opts)
|
|
289
|
+
self.len(1, nodes)
|
|
290
|
+
self.eq(nodes[0].get('server'), 'tcp://1.2.3.4:443')
|
|
291
|
+
cert = nodes[0].get('cert')
|
|
292
|
+
self.nn(cert)
|
|
293
|
+
|
|
294
|
+
nodes = await core.nodes('crypto:x509:cert:sha256=$sha256', opts=opts)
|
|
295
|
+
self.len(1, nodes)
|
|
296
|
+
self.eq(nodes[0].repr(), cert)
|
|
297
|
+
|
|
298
|
+
with self.raises(s_exc.BadTypeValu):
|
|
299
|
+
await core.callStorm('$lib.gen.inetTlsServerCertByServerAndSha256(newp, $sha256)', opts=opts)
|
|
300
|
+
|
|
301
|
+
q = 'return($lib.gen.inetTlsServerCertByServerAndSha256(newp, $sha256, try=$lib.true))'
|
|
302
|
+
self.none(await core.callStorm(q, opts=opts))
|
|
303
|
+
|
|
304
|
+
async def test_stormlib_gen_cryptoX509Cert(self):
|
|
305
|
+
|
|
306
|
+
async with self.getTestCore() as core:
|
|
307
|
+
|
|
308
|
+
# Check guid generation
|
|
309
|
+
sha256 = s_common.buid().hex()
|
|
310
|
+
opts = {'vars': {'sha256': sha256}}
|
|
311
|
+
nodes = await core.nodes('yield $lib.gen.cryptoX509CertBySha256($sha256)', opts=opts)
|
|
312
|
+
self.len(1, nodes)
|
|
313
|
+
self.eq(nodes[0].get('sha256'), sha256)
|
|
314
|
+
self.eq(nodes[0].repr(), s_common.guid(sha256))
|
|
315
|
+
|
|
316
|
+
# Check invalid values, no try
|
|
317
|
+
with self.raises(s_exc.BadTypeValu):
|
|
318
|
+
await core.callStorm('$lib.gen.cryptoX509CertBySha256(newp)')
|
|
319
|
+
|
|
320
|
+
# Check invalid values, with try
|
|
321
|
+
self.none(await core.callStorm('return($lib.gen.cryptoX509CertBySha256(newp, try=$lib.true))'))
|
|
322
|
+
|
|
323
|
+
# Check node matching with same sha256 values
|
|
324
|
+
sha256 = s_common.buid().hex()
|
|
325
|
+
opts = {'vars': {'sha256': sha256}}
|
|
326
|
+
nodes = await core.nodes('[crypto:x509:cert=* :sha256=$sha256]', opts=opts)
|
|
327
|
+
self.len(1, nodes)
|
|
328
|
+
self.eq(nodes[0].get('sha256'), sha256)
|
|
329
|
+
self.ne(nodes[0].repr(), s_common.guid(sha256))
|
|
330
|
+
crypto = nodes[0].repr()
|
|
331
|
+
|
|
332
|
+
nodes = await core.nodes('yield $lib.gen.cryptoX509CertBySha256($sha256)', opts=opts)
|
|
333
|
+
self.len(1, nodes)
|
|
334
|
+
self.eq(nodes[0].repr(), crypto)
|
|
335
|
+
|
|
336
|
+
# Check node matching, crypto:x509:cert -> file with matching sha256
|
|
337
|
+
sha256 = s_common.buid().hex()
|
|
338
|
+
opts = {'vars': {'sha256': sha256}}
|
|
339
|
+
nodes = await core.nodes('[crypto:x509:cert=* :file={[ file:bytes=$sha256 ]} ]', opts=opts)
|
|
340
|
+
self.len(1, nodes)
|
|
341
|
+
self.none(nodes[0].get('sha256'))
|
|
342
|
+
crypto = nodes[0].repr()
|
|
343
|
+
|
|
344
|
+
nodes = await core.nodes('yield $lib.gen.cryptoX509CertBySha256($sha256)', opts=opts)
|
|
345
|
+
self.len(1, nodes)
|
|
346
|
+
self.eq(nodes[0].repr(), crypto)
|
|
@@ -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
|
-
|
|
128
|
-
|
|
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 = '''
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import synapse.exc as s_exc
|
|
2
|
+
import synapse.common as s_common
|
|
3
|
+
|
|
2
4
|
import synapse.lib.time as s_time
|
|
3
5
|
import synapse.lib.layer as s_layer
|
|
4
6
|
|
|
@@ -827,3 +829,109 @@ class StormlibModelTest(s_test.SynTest):
|
|
|
827
829
|
with self.raises(s_exc.BadArg) as ectx:
|
|
828
830
|
await core.nodes('$lib.model.migration.s.riskHasVulnToVulnerable(newp)')
|
|
829
831
|
self.isin('must be a node', ectx.exception.errinfo['mesg'])
|
|
832
|
+
|
|
833
|
+
async def test_stormlib_model_migration_s_inet_ssl_to_tls_servercert(self):
|
|
834
|
+
async with self.getRegrCore('inet_ssl_to_tls_servercert') as core:
|
|
835
|
+
nodes = await core.nodes('meta:source')
|
|
836
|
+
self.len(1, nodes)
|
|
837
|
+
|
|
838
|
+
nodes = await core.nodes('meta:source -(seen)> *')
|
|
839
|
+
self.len(3, nodes)
|
|
840
|
+
for node in nodes:
|
|
841
|
+
self.eq(node.ndef[0], 'inet:ssl:cert')
|
|
842
|
+
|
|
843
|
+
nodes = await core.nodes('inet:ssl:cert')
|
|
844
|
+
self.len(3, nodes)
|
|
845
|
+
|
|
846
|
+
nodes = await core.nodes('file:bytes')
|
|
847
|
+
self.len(3, nodes)
|
|
848
|
+
|
|
849
|
+
nodes = await core.nodes('crypto:x509:cert')
|
|
850
|
+
self.len(2, nodes)
|
|
851
|
+
|
|
852
|
+
nodes = await core.nodes('inet:tls:servercert')
|
|
853
|
+
self.len(0, nodes)
|
|
854
|
+
|
|
855
|
+
q = 'inet:ssl:cert | $lib.model.migration.s.inetSslCertToTlsServerCert($node)'
|
|
856
|
+
await core.nodes(q)
|
|
857
|
+
|
|
858
|
+
nodes = await core.nodes('file:bytes')
|
|
859
|
+
self.len(3, nodes)
|
|
860
|
+
|
|
861
|
+
nodes = await core.nodes('crypto:x509:cert')
|
|
862
|
+
self.len(3, nodes)
|
|
863
|
+
|
|
864
|
+
nodes = await core.nodes('inet:tls:servercert')
|
|
865
|
+
self.len(3, nodes)
|
|
866
|
+
|
|
867
|
+
nodes = await core.nodes('crypto:x509:cert=(cert1,)')
|
|
868
|
+
self.len(1, nodes)
|
|
869
|
+
cert1 = nodes[0]
|
|
870
|
+
|
|
871
|
+
nodes = await core.nodes('inet:tls:servercert:server="tcp://1.2.3.4:443"')
|
|
872
|
+
self.len(1, nodes)
|
|
873
|
+
self.eq(nodes[0].get('.seen'), (1688947200000, 1688947200001))
|
|
874
|
+
self.eq(nodes[0].get('server'), 'tcp://1.2.3.4:443')
|
|
875
|
+
self.eq(nodes[0].get('cert'), cert1.ndef[1])
|
|
876
|
+
self.isin('ssl.migration.one', nodes[0].tags)
|
|
877
|
+
|
|
878
|
+
nodes = await core.nodes('crypto:x509:cert=(cert2,)')
|
|
879
|
+
self.len(1, nodes)
|
|
880
|
+
cert2 = nodes[0]
|
|
881
|
+
|
|
882
|
+
nodes = await core.nodes('inet:tls:servercert:server="tcp://[fe80::1]:8080"')
|
|
883
|
+
self.len(1, nodes)
|
|
884
|
+
self.none(nodes[0].get('.seen'))
|
|
885
|
+
self.eq(nodes[0].get('server'), 'tcp://[fe80::1]:8080')
|
|
886
|
+
self.eq(nodes[0].get('cert'), cert2.ndef[1])
|
|
887
|
+
self.isin('ssl.migration.two', nodes[0].tags)
|
|
888
|
+
|
|
889
|
+
sha256 = 'aa0366ffb013ba2053e45cd7e4bcc8acd6a6c1bafc82eddb4e155876734c5e25'
|
|
890
|
+
opts = {'vars': {'sha256': sha256}}
|
|
891
|
+
|
|
892
|
+
nodes = await core.nodes('file:bytes=$sha256', opts=opts)
|
|
893
|
+
self.len(1, nodes)
|
|
894
|
+
file = nodes[0]
|
|
895
|
+
|
|
896
|
+
# This cert was created by the migration code so do a little extra
|
|
897
|
+
# checking
|
|
898
|
+
nodes = await core.nodes('crypto:x509:cert:file=$sha256', opts=opts)
|
|
899
|
+
self.len(1, nodes)
|
|
900
|
+
self.eq(nodes[0].get('file'), file.ndef[1])
|
|
901
|
+
self.eq(nodes[0].ndef, ('crypto:x509:cert', s_common.guid(sha256)))
|
|
902
|
+
cert3 = nodes[0]
|
|
903
|
+
|
|
904
|
+
nodes = await core.nodes('inet:tls:servercert:server="tcp://8.8.8.8:53" $node.data.load(foo)')
|
|
905
|
+
self.len(1, nodes)
|
|
906
|
+
self.none(nodes[0].get('.seen'))
|
|
907
|
+
self.eq(nodes[0].get('server'), 'tcp://8.8.8.8:53')
|
|
908
|
+
self.eq(nodes[0].get('cert'), cert3.ndef[1])
|
|
909
|
+
self.isin('ssl.migration.three', nodes[0].tags)
|
|
910
|
+
self.eq(nodes[0].nodedata, {'foo': 'bar'})
|
|
911
|
+
|
|
912
|
+
# Check that edges were migrated
|
|
913
|
+
nodes = await core.nodes('meta:source -(seen)> *')
|
|
914
|
+
self.len(6, nodes)
|
|
915
|
+
self.sorteq(
|
|
916
|
+
[k.ndef[0] for k in nodes],
|
|
917
|
+
(
|
|
918
|
+
'inet:ssl:cert', 'inet:ssl:cert', 'inet:ssl:cert',
|
|
919
|
+
'inet:tls:servercert', 'inet:tls:servercert', 'inet:tls:servercert',
|
|
920
|
+
)
|
|
921
|
+
)
|
|
922
|
+
|
|
923
|
+
with self.raises(s_exc.BadArg) as exc:
|
|
924
|
+
await core.callStorm('inet:server | $lib.model.migration.s.inetSslCertToTlsServerCert($node)')
|
|
925
|
+
self.isin(', not inet:server', exc.exception.get('mesg'))
|
|
926
|
+
|
|
927
|
+
async with self.getRegrCore('inet_ssl_to_tls_servercert') as core:
|
|
928
|
+
q = 'inet:ssl:cert | $lib.model.migration.s.inetSslCertToTlsServerCert($node, nodata=$lib.true)'
|
|
929
|
+
await core.nodes(q)
|
|
930
|
+
|
|
931
|
+
nodes = await core.nodes('inet:tls:servercert:server="tcp://8.8.8.8:53" $node.data.load(foo)')
|
|
932
|
+
self.len(1, nodes)
|
|
933
|
+
self.none(nodes[0].get('.seen'))
|
|
934
|
+
self.eq(nodes[0].get('server'), 'tcp://8.8.8.8:53')
|
|
935
|
+
self.eq(nodes[0].get('cert'), cert3.ndef[1])
|
|
936
|
+
self.isin('ssl.migration.three', nodes[0].tags)
|
|
937
|
+
self.eq(nodes[0].nodedata, {'foo': None})
|
|
@@ -22,6 +22,9 @@ class StormtypesModelextTest(s_test.SynTest):
|
|
|
22
22
|
|
|
23
23
|
$pinfo = ({"doc": "Extended a core model."})
|
|
24
24
|
$lib.model.ext.addFormProp(test:int, _tick, (time, ({})), $propinfo)
|
|
25
|
+
|
|
26
|
+
$edgeinfo = ({"doc": "A test edge."})
|
|
27
|
+
$lib.model.ext.addEdge(inet:user, _copies, *, $edgeinfo)
|
|
25
28
|
''')
|
|
26
29
|
|
|
27
30
|
nodes = await core.nodes('[ _visi:int=10 :tick=20210101 ._woot=30 +#lol:score=99 ]')
|
|
@@ -44,6 +47,12 @@ class StormtypesModelextTest(s_test.SynTest):
|
|
|
44
47
|
q = '''$lib.model.ext.addUnivProp(_woot, (time, ({})), ({}))'''
|
|
45
48
|
await core.callStorm(q)
|
|
46
49
|
|
|
50
|
+
with self.raises(s_exc.DupEdgeType):
|
|
51
|
+
q = '''$lib.model.ext.addEdge(inet:user, _copies, *, ({}))'''
|
|
52
|
+
await core.callStorm(q)
|
|
53
|
+
|
|
54
|
+
self.nn(core.model.edge(('inet:user', '_copies', None)))
|
|
55
|
+
|
|
47
56
|
# Grab the extended model definitions
|
|
48
57
|
model_defs = await core.callStorm('return ( $lib.model.ext.getExtModel() )')
|
|
49
58
|
self.isinstance(model_defs, dict)
|
|
@@ -55,6 +64,7 @@ class StormtypesModelextTest(s_test.SynTest):
|
|
|
55
64
|
$lib.model.ext.delFormProp(_visi:int, tick)
|
|
56
65
|
$lib.model.ext.delFormProp(test:int, _tick)
|
|
57
66
|
$lib.model.ext.delForm(_visi:int)
|
|
67
|
+
$lib.model.ext.delEdge(inet:user, _copies, *)
|
|
58
68
|
''')
|
|
59
69
|
|
|
60
70
|
self.none(core.model.form('_visi:int'))
|
|
@@ -62,6 +72,7 @@ class StormtypesModelextTest(s_test.SynTest):
|
|
|
62
72
|
self.none(core.model.prop('_visi:int:tick'))
|
|
63
73
|
self.none(core.model.prop('test:int:_tick'))
|
|
64
74
|
self.none(core.model.tagprop('score'))
|
|
75
|
+
self.none(core.model.edge(('inet:user', '_copies', None)))
|
|
65
76
|
|
|
66
77
|
# Underscores can exist in extended names but only at specific locations
|
|
67
78
|
q = '''$l =$lib.list('str', ({})) $d=({"doc": "Foo"})
|
|
@@ -105,6 +116,26 @@ class StormtypesModelextTest(s_test.SynTest):
|
|
|
105
116
|
q = '''$lib.model.ext.addTagProp(_someones:_score^value, (int, ({})), ({}))'''
|
|
106
117
|
await core.callStorm(q)
|
|
107
118
|
|
|
119
|
+
with self.raises(s_exc.BadEdgeDef):
|
|
120
|
+
q = '''$lib.model.ext.addEdge(*, does, *, ({}))'''
|
|
121
|
+
await core.callStorm(q)
|
|
122
|
+
|
|
123
|
+
with self.raises(s_exc.BadEdgeDef):
|
|
124
|
+
q = '''$lib.model.ext.addEdge(*, _NEWP, *, ({}))'''
|
|
125
|
+
await core.callStorm(q)
|
|
126
|
+
|
|
127
|
+
with self.raises(s_exc.BadEdgeDef):
|
|
128
|
+
q = '''$lib.model.ext.addEdge(*, "_ne wp", *, ({}))'''
|
|
129
|
+
await core.callStorm(q)
|
|
130
|
+
|
|
131
|
+
with self.raises(s_exc.BadEdgeDef):
|
|
132
|
+
q = f'''$lib.model.ext.addEdge(*, "_{'a'*201}", *, ({{}}))'''
|
|
133
|
+
await core.callStorm(q)
|
|
134
|
+
|
|
135
|
+
with self.raises(s_exc.BadEdgeDef):
|
|
136
|
+
q = '''$lib.model.ext.delEdge(*, "_ne wp", *)'''
|
|
137
|
+
await core.callStorm(q)
|
|
138
|
+
|
|
108
139
|
# Permission errors
|
|
109
140
|
visi = await core.auth.addUser('visi')
|
|
110
141
|
opts = {'user': visi.iden}
|
|
@@ -133,6 +164,10 @@ class StormtypesModelextTest(s_test.SynTest):
|
|
|
133
164
|
$lib.model.ext.addTagProp(score, (int, ({})), $tagpropinfo)
|
|
134
165
|
''', opts=opts)
|
|
135
166
|
|
|
167
|
+
with self.raises(s_exc.AuthDeny):
|
|
168
|
+
q = '''$lib.model.ext.addEdge(*, _does, *, ({}))'''
|
|
169
|
+
await core.callStorm(q, opts=opts)
|
|
170
|
+
|
|
136
171
|
# Reload the model extensions automatically
|
|
137
172
|
async with self.getTestCore() as core:
|
|
138
173
|
opts = {'vars': {'model_defs': model_defs}}
|
|
@@ -174,6 +209,9 @@ class StormtypesModelextTest(s_test.SynTest):
|
|
|
174
209
|
|
|
175
210
|
$pinfo = ({"doc": "NEWP"})
|
|
176
211
|
$lib.model.ext.addFormProp(test:int, _tick, (time, ({})), $propinfo)
|
|
212
|
+
|
|
213
|
+
$edgeinfo = ({"doc": "NEWP"})
|
|
214
|
+
$lib.model.ext.addEdge(inet:user, _copies, *, $edgeinfo)
|
|
177
215
|
''')
|
|
178
216
|
|
|
179
217
|
q = '''return ($lib.model.ext.addExtModel($model_defs))'''
|
|
@@ -196,6 +234,11 @@ class StormtypesModelextTest(s_test.SynTest):
|
|
|
196
234
|
opts = {'vars': {'model_defs': {'univs': model_defs['univs']}}}
|
|
197
235
|
await core.callStorm(q, opts)
|
|
198
236
|
|
|
237
|
+
q = '''return ($lib.model.ext.addExtModel($model_defs))'''
|
|
238
|
+
with self.raises(s_exc.BadEdgeDef) as cm:
|
|
239
|
+
opts = {'vars': {'model_defs': {'edges': model_defs['edges']}}}
|
|
240
|
+
await core.callStorm(q, opts)
|
|
241
|
+
|
|
199
242
|
# Reload the model extensions from the dump by hand
|
|
200
243
|
async with self.getTestCore() as core:
|
|
201
244
|
opts = {'vars': {'model_defs': model_defs}}
|
|
@@ -212,6 +255,10 @@ class StormtypesModelextTest(s_test.SynTest):
|
|
|
212
255
|
for ($prop, $def, $info) in $model_defs.univs {
|
|
213
256
|
$lib.model.ext.addUnivProp($prop, $def, $info)
|
|
214
257
|
}
|
|
258
|
+
for ($edge, $info) in $model_defs.edges {
|
|
259
|
+
($n1form, $verb, $n2form) = $edge
|
|
260
|
+
$lib.model.ext.addEdge($n1form, $verb, $n2form, $info)
|
|
261
|
+
}
|
|
215
262
|
'''
|
|
216
263
|
await core.nodes(q, opts)
|
|
217
264
|
|
|
@@ -227,6 +274,8 @@ class StormtypesModelextTest(s_test.SynTest):
|
|
|
227
274
|
self.eq(nodes[0].ndef, ('test:int', 1234))
|
|
228
275
|
self.eq(nodes[0].get('_tick'), 1609459200000)
|
|
229
276
|
|
|
277
|
+
self.nn(core.model.edge(('inet:user', '_copies', None)))
|
|
278
|
+
|
|
230
279
|
async def test_lib_stormlib_behold_modelext(self):
|
|
231
280
|
self.skipIfNexusReplay()
|
|
232
281
|
async with self.getTestCore() as core:
|
|
@@ -252,6 +301,7 @@ class StormtypesModelextTest(s_test.SynTest):
|
|
|
252
301
|
$lib.model.ext.addFormProp(_behold:score, rank, (int, ({})), ({"doc": "second string"}))
|
|
253
302
|
$lib.model.ext.addUnivProp(_beep, (int, ({})), ({"doc": "third string"}))
|
|
254
303
|
$lib.model.ext.addTagProp(thingy, (int, ({})), ({"doc": "fourth string"}))
|
|
304
|
+
$lib.model.ext.addEdge(*, _goes, geo:place, ({"doc": "fifth string"}))
|
|
255
305
|
''')
|
|
256
306
|
|
|
257
307
|
formmesg = await sock.receive_json()
|
|
@@ -279,11 +329,17 @@ class StormtypesModelextTest(s_test.SynTest):
|
|
|
279
329
|
self.eq(tagpmesg['data']['info']['name'], 'thingy')
|
|
280
330
|
self.eq(tagpmesg['data']['info']['info'], {'doc': 'fourth string'})
|
|
281
331
|
|
|
332
|
+
edgemesg = await sock.receive_json()
|
|
333
|
+
self.eq(edgemesg['data']['event'], 'model:edge:add')
|
|
334
|
+
self.eq(edgemesg['data']['info']['edge'], (None, '_goes', 'geo:place'))
|
|
335
|
+
self.eq(edgemesg['data']['info']['info'], {'doc': 'fifth string'})
|
|
336
|
+
|
|
282
337
|
await core.callStorm('''
|
|
283
338
|
$lib.model.ext.delTagProp(thingy)
|
|
284
339
|
$lib.model.ext.delUnivProp(_beep)
|
|
285
340
|
$lib.model.ext.delFormProp(_behold:score, rank)
|
|
286
341
|
$lib.model.ext.delForm(_behold:score)
|
|
342
|
+
$lib.model.ext.delEdge(*, _goes, geo:place)
|
|
287
343
|
''')
|
|
288
344
|
deltagp = await sock.receive_json()
|
|
289
345
|
self.eq(deltagp['data']['event'], 'model:tagprop:del')
|
|
@@ -302,6 +358,10 @@ class StormtypesModelextTest(s_test.SynTest):
|
|
|
302
358
|
self.eq(delform['data']['event'], 'model:form:del')
|
|
303
359
|
self.eq(delform['data']['info']['form'], '_behold:score')
|
|
304
360
|
|
|
361
|
+
deledge = await sock.receive_json()
|
|
362
|
+
self.eq(deledge['data']['event'], 'model:edge:del')
|
|
363
|
+
self.eq(deledge['data']['info']['edge'], (None, '_goes', 'geo:place'))
|
|
364
|
+
|
|
305
365
|
async def test_lib_stormlib_modelext_delform(self):
|
|
306
366
|
'''
|
|
307
367
|
Verify extended forms can't be deleted if they have associated extended props
|
|
@@ -385,6 +445,10 @@ class StormtypesModelextTest(s_test.SynTest):
|
|
|
385
445
|
'$lib.model.ext.addTagProp(_foo:bar, (), ())',
|
|
386
446
|
'Tag property definitions should be a dict.'
|
|
387
447
|
),
|
|
448
|
+
(
|
|
449
|
+
'$lib.model.ext.addEdge(*, _foo, *, ())',
|
|
450
|
+
'Edge info should be a dict.'
|
|
451
|
+
),
|
|
388
452
|
)
|
|
389
453
|
|
|
390
454
|
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()
|