synapse 2.178.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.
- synapse/cortex.py +162 -27
- synapse/datamodel.py +47 -1
- synapse/exc.py +1 -0
- synapse/lib/aha.py +2 -1
- synapse/lib/ast.py +26 -22
- synapse/lib/base.py +12 -3
- synapse/lib/cell.py +150 -11
- synapse/lib/coro.py +14 -0
- synapse/lib/drive.py +551 -0
- synapse/lib/schemas.py +39 -0
- synapse/lib/snap.py +17 -7
- synapse/lib/storm.py +3 -1
- synapse/lib/stormhttp.py +1 -0
- synapse/lib/stormlib/modelext.py +29 -3
- synapse/lib/stormlib/stix.py +40 -17
- synapse/lib/stormlib/vault.py +2 -2
- synapse/lib/stormtypes.py +1 -1
- synapse/lib/types.py +9 -0
- synapse/lib/version.py +2 -2
- synapse/lookup/pe.py +303 -38
- synapse/models/dns.py +24 -1
- synapse/models/geospace.py +4 -1
- synapse/models/infotech.py +26 -1
- synapse/tests/test_cortex.py +45 -1
- synapse/tests/test_lib_aha.py +17 -0
- synapse/tests/test_lib_cell.py +224 -0
- synapse/tests/test_lib_coro.py +12 -0
- synapse/tests/test_lib_stormhttp.py +40 -0
- synapse/tests/test_lib_stormlib_modelext.py +55 -3
- synapse/tests/test_lib_stormlib_stix.py +15 -0
- synapse/tests/test_lib_stormlib_vault.py +11 -1
- synapse/tests/test_lib_stormtypes.py +5 -0
- synapse/tests/test_lib_types.py +9 -0
- synapse/tests/test_model_dns.py +8 -0
- synapse/tests/test_model_geospace.py +3 -1
- synapse/tests/test_model_infotech.py +47 -0
- synapse/tests/test_model_syn.py +11 -0
- synapse/tests/test_utils_stormcov.py +1 -1
- synapse/tools/changelog.py +28 -0
- {synapse-2.178.0.dist-info → synapse-2.179.0.dist-info}/METADATA +1 -1
- {synapse-2.178.0.dist-info → synapse-2.179.0.dist-info}/RECORD +44 -43
- {synapse-2.178.0.dist-info → synapse-2.179.0.dist-info}/WHEEL +1 -1
- {synapse-2.178.0.dist-info → synapse-2.179.0.dist-info}/LICENSE +0 -0
- {synapse-2.178.0.dist-info → synapse-2.179.0.dist-info}/top_level.txt +0 -0
synapse/tests/test_cortex.py
CHANGED
|
@@ -41,6 +41,50 @@ class CortexTest(s_t_utils.SynTest):
|
|
|
41
41
|
'''
|
|
42
42
|
The tests that should be run with different types of layers
|
|
43
43
|
'''
|
|
44
|
+
async def test_cortex_basics(self):
|
|
45
|
+
|
|
46
|
+
with self.getTestDir() as dirn:
|
|
47
|
+
|
|
48
|
+
async with self.getTestCore(dirn=dirn) as core:
|
|
49
|
+
|
|
50
|
+
with self.raises(s_exc.NoSuchProp):
|
|
51
|
+
await core.setPropLocked('newp', True)
|
|
52
|
+
|
|
53
|
+
with self.raises(s_exc.NoSuchUniv):
|
|
54
|
+
await core.setUnivLocked('newp', True)
|
|
55
|
+
|
|
56
|
+
with self.raises(s_exc.NoSuchTagProp):
|
|
57
|
+
await core.setTagPropLocked('newp', True)
|
|
58
|
+
|
|
59
|
+
await core.addTagProp('score', ('int', {}), {})
|
|
60
|
+
|
|
61
|
+
await core.setPropLocked('inet:ipv4:asn', True)
|
|
62
|
+
await core.setUnivLocked('.seen', True)
|
|
63
|
+
await core.setTagPropLocked('score', True)
|
|
64
|
+
|
|
65
|
+
with self.raises(s_exc.IsDeprLocked):
|
|
66
|
+
await core.nodes('[ inet:ipv4=1.2.3.4 :asn=99 ]')
|
|
67
|
+
with self.raises(s_exc.IsDeprLocked):
|
|
68
|
+
await core.nodes('[ inet:ipv4=1.2.3.4 .seen=now ]')
|
|
69
|
+
with self.raises(s_exc.IsDeprLocked):
|
|
70
|
+
await core.nodes('[ inet:ipv4=1.2.3.4 +#foo:score=10 ]')
|
|
71
|
+
|
|
72
|
+
# test persistence...
|
|
73
|
+
async with self.getTestCore(dirn=dirn) as core:
|
|
74
|
+
|
|
75
|
+
with self.raises(s_exc.IsDeprLocked):
|
|
76
|
+
await core.nodes('[ inet:ipv4=1.2.3.4 :asn=99 ]')
|
|
77
|
+
with self.raises(s_exc.IsDeprLocked):
|
|
78
|
+
await core.nodes('[ inet:ipv4=1.2.3.4 .seen=now ]')
|
|
79
|
+
with self.raises(s_exc.IsDeprLocked):
|
|
80
|
+
await core.nodes('[ inet:ipv4=1.2.3.4 +#foo:score=10 ]')
|
|
81
|
+
|
|
82
|
+
await core.setPropLocked('inet:ipv4:asn', False)
|
|
83
|
+
await core.setUnivLocked('.seen', False)
|
|
84
|
+
await core.setTagPropLocked('score', False)
|
|
85
|
+
|
|
86
|
+
await core.nodes('[ inet:ipv4=1.2.3.4 :asn=99 .seen=now +#foo:score=10 ]')
|
|
87
|
+
|
|
44
88
|
async def test_cortex_cellguid(self):
|
|
45
89
|
iden = s_common.guid()
|
|
46
90
|
conf = {'cell:guid': iden}
|
|
@@ -1302,7 +1346,7 @@ class CortexTest(s_t_utils.SynTest):
|
|
|
1302
1346
|
|
|
1303
1347
|
await core.delTagProp('score')
|
|
1304
1348
|
|
|
1305
|
-
with self.raises(s_exc.
|
|
1349
|
+
with self.raises(s_exc.NoSuchTagProp):
|
|
1306
1350
|
await core.delTagProp('score')
|
|
1307
1351
|
|
|
1308
1352
|
modl = await core.getModelDict()
|
synapse/tests/test_lib_aha.py
CHANGED
|
@@ -1292,3 +1292,20 @@ class AhaTest(s_test.SynTest):
|
|
|
1292
1292
|
async with await s_cell.Cell.anit(dirn=clldir, conf=cllconf) as cell:
|
|
1293
1293
|
self.none(await cell.ahaclient.waitready(timeout=12))
|
|
1294
1294
|
self.eq(cell.conf.get('aha:registry'), ahaurl)
|
|
1295
|
+
|
|
1296
|
+
async def test_aha_provision_listen_dns_name(self):
|
|
1297
|
+
# Ensure that we use the dns:name for the provisioning listener when
|
|
1298
|
+
# the provision:listen value is not provided.
|
|
1299
|
+
conf = {
|
|
1300
|
+
'aha:network': 'synapse',
|
|
1301
|
+
'dns:name': 'here.loop.vertex.link',
|
|
1302
|
+
}
|
|
1303
|
+
mesg = 'provision listening: ssl://0.0.0.0:27272?hostname=here.loop.vertex.link'
|
|
1304
|
+
with self.getAsyncLoggerStream('synapse.lib.aha', mesg) as stream:
|
|
1305
|
+
async with self.getTestCell(s_aha.AhaCell, conf=conf) as aha:
|
|
1306
|
+
self.true(await stream.wait(timeout=6))
|
|
1307
|
+
# And the URL works with our listener :)
|
|
1308
|
+
provurl = await aha.addAhaUserEnroll('bob.grey')
|
|
1309
|
+
async with await s_telepath.openurl(provurl) as prox:
|
|
1310
|
+
info = await prox.getUserInfo()
|
|
1311
|
+
self.eq(info.get('aha:user'), 'bob.grey')
|
synapse/tests/test_lib_cell.py
CHANGED
|
@@ -28,6 +28,7 @@ import synapse.lib.base as s_base
|
|
|
28
28
|
import synapse.lib.cell as s_cell
|
|
29
29
|
import synapse.lib.coro as s_coro
|
|
30
30
|
import synapse.lib.link as s_link
|
|
31
|
+
import synapse.lib.drive as s_drive
|
|
31
32
|
import synapse.lib.nexus as s_nexus
|
|
32
33
|
import synapse.lib.certdir as s_certdir
|
|
33
34
|
import synapse.lib.msgpack as s_msgpack
|
|
@@ -155,8 +156,217 @@ async def altAuthCtor(cell):
|
|
|
155
156
|
cell.onfini(auth.fini)
|
|
156
157
|
return auth
|
|
157
158
|
|
|
159
|
+
testDataSchema_v0 = {
|
|
160
|
+
'type': 'object',
|
|
161
|
+
'properties': {
|
|
162
|
+
'type': {'type': 'string'},
|
|
163
|
+
'size': {'type': 'number'},
|
|
164
|
+
},
|
|
165
|
+
'required': ['type', 'size'],
|
|
166
|
+
'additionalProperties': False,
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
testDataSchema_v1 = {
|
|
170
|
+
'type': 'object',
|
|
171
|
+
'properties': {
|
|
172
|
+
'type': {'type': 'string'},
|
|
173
|
+
'size': {'type': 'number'},
|
|
174
|
+
'woot': {'type': 'string'},
|
|
175
|
+
},
|
|
176
|
+
'required': ['type', 'size', 'woot'],
|
|
177
|
+
'additionalProperties': False,
|
|
178
|
+
}
|
|
179
|
+
|
|
158
180
|
class CellTest(s_t_utils.SynTest):
|
|
159
181
|
|
|
182
|
+
async def test_cell_drive(self):
|
|
183
|
+
|
|
184
|
+
async with self.getTestCell() as cell:
|
|
185
|
+
|
|
186
|
+
with self.raises(s_exc.BadName):
|
|
187
|
+
s_drive.reqValidName('A' * 512)
|
|
188
|
+
|
|
189
|
+
info = {'name': 'users'}
|
|
190
|
+
pathinfo = await cell.addDriveItem(info)
|
|
191
|
+
|
|
192
|
+
info = {'name': 'root'}
|
|
193
|
+
pathinfo = await cell.addDriveItem(info, path='users')
|
|
194
|
+
|
|
195
|
+
with self.raises(s_exc.DupIden):
|
|
196
|
+
await cell.drive.addItemInfo(pathinfo[-1], path='users')
|
|
197
|
+
|
|
198
|
+
rootdir = pathinfo[-1].get('iden')
|
|
199
|
+
self.eq(0, pathinfo[-1].get('kids'))
|
|
200
|
+
|
|
201
|
+
info = {'name': 'win32k.sys', 'type': 'hehe'}
|
|
202
|
+
with self.raises(s_exc.NoSuchType):
|
|
203
|
+
info = await cell.addDriveItem(info, reldir=rootdir)
|
|
204
|
+
|
|
205
|
+
infos = [i async for i in cell.getDriveKids(s_drive.rootdir)]
|
|
206
|
+
self.len(1, infos)
|
|
207
|
+
self.eq(1, infos[0].get('kids'))
|
|
208
|
+
self.eq('users', infos[0].get('name'))
|
|
209
|
+
|
|
210
|
+
# TODO how to handle iden match with additional property mismatch
|
|
211
|
+
|
|
212
|
+
await cell.drive.setTypeSchema('woot', testDataSchema_v0)
|
|
213
|
+
|
|
214
|
+
info = {'name': 'win32k.sys', 'type': 'woot'}
|
|
215
|
+
info = await cell.addDriveItem(info, reldir=rootdir)
|
|
216
|
+
|
|
217
|
+
iden = info[-1].get('iden')
|
|
218
|
+
|
|
219
|
+
tick = s_common.now()
|
|
220
|
+
rootuser = cell.auth.rootuser.iden
|
|
221
|
+
|
|
222
|
+
with self.raises(s_exc.SchemaViolation):
|
|
223
|
+
versinfo = {'version': (1, 0, 0), 'updated': tick, 'updater': rootuser}
|
|
224
|
+
await cell.setDriveData(iden, versinfo, {'newp': 'newp'})
|
|
225
|
+
|
|
226
|
+
versinfo = {'version': (1, 1, 0), 'updated': tick + 10, 'updater': rootuser}
|
|
227
|
+
info, versinfo = await cell.setDriveData(iden, versinfo, {'type': 'haha', 'size': 20})
|
|
228
|
+
self.eq(info.get('version'), (1, 1, 0))
|
|
229
|
+
self.eq(versinfo.get('version'), (1, 1, 0))
|
|
230
|
+
|
|
231
|
+
versinfo = {'version': (1, 0, 0), 'updated': tick, 'updater': rootuser}
|
|
232
|
+
info, versinfo = await cell.setDriveData(iden, versinfo, {'type': 'hehe', 'size': 0})
|
|
233
|
+
self.eq(info.get('version'), (1, 1, 0))
|
|
234
|
+
self.eq(versinfo.get('version'), (1, 0, 0))
|
|
235
|
+
|
|
236
|
+
versinfo10, data10 = await cell.getDriveData(iden, vers=(1, 0, 0))
|
|
237
|
+
self.eq(versinfo10.get('updated'), tick)
|
|
238
|
+
self.eq(versinfo10.get('updater'), rootuser)
|
|
239
|
+
self.eq(versinfo10.get('version'), (1, 0, 0))
|
|
240
|
+
|
|
241
|
+
versinfo11, data11 = await cell.getDriveData(iden, vers=(1, 1, 0))
|
|
242
|
+
self.eq(versinfo11.get('updated'), tick + 10)
|
|
243
|
+
self.eq(versinfo11.get('updater'), rootuser)
|
|
244
|
+
self.eq(versinfo11.get('version'), (1, 1, 0))
|
|
245
|
+
|
|
246
|
+
versions = [vers async for vers in cell.getDriveDataVersions(iden)]
|
|
247
|
+
self.len(2, versions)
|
|
248
|
+
self.eq(versions[0], versinfo11)
|
|
249
|
+
self.eq(versions[1], versinfo10)
|
|
250
|
+
|
|
251
|
+
info = await cell.delDriveData(iden, vers=(0, 0, 0))
|
|
252
|
+
|
|
253
|
+
versions = [vers async for vers in cell.getDriveDataVersions(iden)]
|
|
254
|
+
self.len(2, versions)
|
|
255
|
+
self.eq(versions[0], versinfo11)
|
|
256
|
+
self.eq(versions[1], versinfo10)
|
|
257
|
+
|
|
258
|
+
info = await cell.delDriveData(iden, vers=(1, 1, 0))
|
|
259
|
+
self.eq(info.get('updated'), tick)
|
|
260
|
+
self.eq(info.get('version'), (1, 0, 0))
|
|
261
|
+
|
|
262
|
+
info = await cell.delDriveData(iden, vers=(1, 0, 0))
|
|
263
|
+
self.eq(info.get('size'), 0)
|
|
264
|
+
self.eq(info.get('version'), (0, 0, 0))
|
|
265
|
+
self.none(info.get('updated'))
|
|
266
|
+
self.none(info.get('updater'))
|
|
267
|
+
|
|
268
|
+
# repopulate a couple data versions to test migration and delete
|
|
269
|
+
versinfo = {'version': (1, 0, 0), 'updated': tick, 'updater': rootuser}
|
|
270
|
+
info, versinfo = await cell.setDriveData(iden, versinfo, {'type': 'hehe', 'size': 0})
|
|
271
|
+
versinfo = {'version': (1, 1, 0), 'updated': tick + 10, 'updater': rootuser}
|
|
272
|
+
info, versinfo = await cell.setDriveData(iden, versinfo, {'type': 'haha', 'size': 17})
|
|
273
|
+
self.eq(versinfo, (await cell.getDriveData(iden))[0])
|
|
274
|
+
|
|
275
|
+
# This will be done by the cell in a cell storage version migration...
|
|
276
|
+
async def migrate_v1(info, versinfo, data):
|
|
277
|
+
data['woot'] = 'woot'
|
|
278
|
+
return data
|
|
279
|
+
|
|
280
|
+
await cell.drive.setTypeSchema('woot', testDataSchema_v1, migrate_v1)
|
|
281
|
+
|
|
282
|
+
versinfo, data = await cell.getDriveData(iden, vers=(1, 0, 0))
|
|
283
|
+
self.eq('woot', data.get('woot'))
|
|
284
|
+
|
|
285
|
+
versinfo, data = await cell.getDriveData(iden, vers=(1, 1, 0))
|
|
286
|
+
self.eq('woot', data.get('woot'))
|
|
287
|
+
|
|
288
|
+
self.nn(await cell.getDriveInfo(iden))
|
|
289
|
+
self.len(2, [vers async for vers in cell.getDriveDataVersions(iden)])
|
|
290
|
+
|
|
291
|
+
await cell.delDriveData(iden)
|
|
292
|
+
self.len(1, [vers async for vers in cell.getDriveDataVersions(iden)])
|
|
293
|
+
|
|
294
|
+
await cell.delDriveInfo(iden)
|
|
295
|
+
|
|
296
|
+
self.none(await cell.getDriveInfo(iden))
|
|
297
|
+
self.len(0, [vers async for vers in cell.getDriveDataVersions(iden)])
|
|
298
|
+
|
|
299
|
+
with self.raises(s_exc.NoSuchPath):
|
|
300
|
+
await cell.getDrivePath('users/root/win32k.sys')
|
|
301
|
+
|
|
302
|
+
pathinfo = await cell.addDrivePath('foo/bar/baz')
|
|
303
|
+
self.len(3, pathinfo)
|
|
304
|
+
self.eq('foo', pathinfo[0].get('name'))
|
|
305
|
+
self.eq(1, pathinfo[0].get('kids'))
|
|
306
|
+
self.eq('bar', pathinfo[1].get('name'))
|
|
307
|
+
self.eq(1, pathinfo[1].get('kids'))
|
|
308
|
+
self.eq('baz', pathinfo[2].get('name'))
|
|
309
|
+
self.eq(0, pathinfo[2].get('kids'))
|
|
310
|
+
|
|
311
|
+
self.eq(pathinfo, await cell.addDrivePath('foo/bar/baz'))
|
|
312
|
+
|
|
313
|
+
baziden = pathinfo[2].get('iden')
|
|
314
|
+
self.eq(pathinfo, await cell.drive.getItemPath(baziden))
|
|
315
|
+
|
|
316
|
+
info = await cell.setDriveInfoPerm(baziden, {'users': {rootuser: 3}, 'roles': {}})
|
|
317
|
+
self.eq(3, info['perm']['users'][rootuser])
|
|
318
|
+
|
|
319
|
+
with self.raises(s_exc.NoSuchIden):
|
|
320
|
+
# s_drive.rootdir is all 00s... ;)
|
|
321
|
+
await cell.setDriveInfoPerm(s_drive.rootdir, {'users': {}, 'roles': {}})
|
|
322
|
+
|
|
323
|
+
await cell.addDrivePath('hehe/haha')
|
|
324
|
+
pathinfo = await cell.setDriveInfoPath(baziden, 'hehe/haha/hoho')
|
|
325
|
+
|
|
326
|
+
self.eq('hoho', pathinfo[-1].get('name'))
|
|
327
|
+
self.eq(baziden, pathinfo[-1].get('iden'))
|
|
328
|
+
|
|
329
|
+
self.true(await cell.drive.hasPathInfo('hehe/haha/hoho'))
|
|
330
|
+
self.false(await cell.drive.hasPathInfo('foo/bar/baz'))
|
|
331
|
+
|
|
332
|
+
pathinfo = await cell.getDrivePath('foo/bar')
|
|
333
|
+
self.eq(0, pathinfo[-1].get('kids'))
|
|
334
|
+
|
|
335
|
+
pathinfo = await cell.getDrivePath('hehe/haha')
|
|
336
|
+
self.eq(1, pathinfo[-1].get('kids'))
|
|
337
|
+
|
|
338
|
+
with self.raises(s_exc.DupName):
|
|
339
|
+
iden = pathinfo[-2].get('iden')
|
|
340
|
+
name = pathinfo[-1].get('name')
|
|
341
|
+
cell.drive.reqFreeStep(iden, name)
|
|
342
|
+
|
|
343
|
+
walks = [item async for item in cell.drive.walkPathInfo('hehe')]
|
|
344
|
+
self.len(3, walks)
|
|
345
|
+
# confirm walked paths are yielded depth first...
|
|
346
|
+
self.eq('hoho', walks[0].get('name'))
|
|
347
|
+
self.eq('haha', walks[1].get('name'))
|
|
348
|
+
self.eq('hehe', walks[2].get('name'))
|
|
349
|
+
|
|
350
|
+
iden = walks[2].get('iden')
|
|
351
|
+
walks = [item async for item in cell.drive.walkItemInfo(iden)]
|
|
352
|
+
self.len(3, walks)
|
|
353
|
+
self.eq('hoho', walks[0].get('name'))
|
|
354
|
+
self.eq('haha', walks[1].get('name'))
|
|
355
|
+
self.eq('hehe', walks[2].get('name'))
|
|
356
|
+
|
|
357
|
+
self.none(cell.drive.getTypeSchema('newp'))
|
|
358
|
+
|
|
359
|
+
cell.drive.validators.pop('woot')
|
|
360
|
+
self.nn(cell.drive.getTypeValidator('woot'))
|
|
361
|
+
|
|
362
|
+
# move to root dir
|
|
363
|
+
pathinfo = await cell.setDriveInfoPath(baziden, 'zipzop')
|
|
364
|
+
self.len(1, pathinfo)
|
|
365
|
+
self.eq(s_drive.rootdir, pathinfo[-1].get('parent'))
|
|
366
|
+
|
|
367
|
+
pathinfo = await cell.setDriveInfoPath(baziden, 'hehe/haha/hoho')
|
|
368
|
+
self.len(3, pathinfo)
|
|
369
|
+
|
|
160
370
|
async def test_cell_auth(self):
|
|
161
371
|
|
|
162
372
|
with self.getTestDir() as dirn:
|
|
@@ -2914,3 +3124,17 @@ class CellTest(s_t_utils.SynTest):
|
|
|
2914
3124
|
|
|
2915
3125
|
async with self.getTestCell(s_cell.Cell, dirn=dirn):
|
|
2916
3126
|
pass
|
|
3127
|
+
|
|
3128
|
+
async def test_cell_initslab_fini(self):
|
|
3129
|
+
class SlabCell(s_cell.Cell):
|
|
3130
|
+
async def initServiceStorage(self):
|
|
3131
|
+
self.long_lived_slab = await self._initSlabFile(os.path.join(self.dirn, 'slabs', 'long.lmdb'))
|
|
3132
|
+
short_slab = await self._initSlabFile(os.path.join(self.dirn, 'slabs', 'short.lmdb'), ephemeral=True)
|
|
3133
|
+
self.short_slab_path = short_slab.lenv.path()
|
|
3134
|
+
await short_slab.fini()
|
|
3135
|
+
|
|
3136
|
+
async with self.getTestCell(SlabCell) as cell:
|
|
3137
|
+
self.true(os.path.isdir(cell.short_slab_path))
|
|
3138
|
+
self.isin(cell.long_lived_slab.fini, cell._fini_funcs)
|
|
3139
|
+
slabs = [s for s in cell.tofini if isinstance(s, s_lmdbslab.Slab) and s.lenv.path() == cell.short_slab_path]
|
|
3140
|
+
self.len(0, slabs)
|
synapse/tests/test_lib_coro.py
CHANGED
|
@@ -41,6 +41,18 @@ def nopickle():
|
|
|
41
41
|
|
|
42
42
|
class CoroTest(s_t_utils.SynTest):
|
|
43
43
|
|
|
44
|
+
async def test_coro_chunks(self):
|
|
45
|
+
async def agen():
|
|
46
|
+
for i in range(101):
|
|
47
|
+
yield i
|
|
48
|
+
|
|
49
|
+
chunks = []
|
|
50
|
+
async for chunk in s_coro.chunks(agen()):
|
|
51
|
+
chunks.append(chunk)
|
|
52
|
+
|
|
53
|
+
self.len(1, chunks[1])
|
|
54
|
+
self.len(100, chunks[0])
|
|
55
|
+
|
|
44
56
|
async def test_coro_event(self):
|
|
45
57
|
|
|
46
58
|
evnt = s_coro.Event()
|
|
@@ -692,6 +692,9 @@ class StormHttpTest(s_test.SynTest):
|
|
|
692
692
|
tlscadir = s_common.gendir(dirn, 'cadir')
|
|
693
693
|
cacertpath = shutil.copyfile(os.path.join(cadir, 'somelocalca.crt'), os.path.join(tlscadir, 'somelocalca.crt'))
|
|
694
694
|
|
|
695
|
+
with s_common.genfile(cacertpath) as fd:
|
|
696
|
+
ca_cert = fd.read().decode()
|
|
697
|
+
|
|
695
698
|
pkey, cert = tdir.genUserCert('someuser', signas='somelocalca')
|
|
696
699
|
user_pkey = tdir._pkeyToByts(pkey).decode()
|
|
697
700
|
user_cert = tdir._certToByts(cert).decode()
|
|
@@ -835,3 +838,40 @@ class StormHttpTest(s_test.SynTest):
|
|
|
835
838
|
## bad cert
|
|
836
839
|
sslopts['client_cert'] = 'not-gonna-work'
|
|
837
840
|
await self.asyncraises(s_exc.BadArg, core.callStorm(q, opts=opts))
|
|
841
|
+
|
|
842
|
+
# Provide a CA certificate directly
|
|
843
|
+
async with self.getTestCore(dirn=dirn) as core:
|
|
844
|
+
|
|
845
|
+
sslctx = core.initSslCtx(certpath, pkeypath)
|
|
846
|
+
sslctx.load_verify_locations(cafile=cacertpath)
|
|
847
|
+
|
|
848
|
+
addr, port = await core.addHttpsPort(0, sslctx=sslctx)
|
|
849
|
+
root = await core.auth.getUserByName('root')
|
|
850
|
+
await root.setPasswd('root')
|
|
851
|
+
|
|
852
|
+
core.addHttpApi('/api/v0/test', s_test.HttpReflector, {'cell': core})
|
|
853
|
+
|
|
854
|
+
sslopts = {}
|
|
855
|
+
|
|
856
|
+
opts = {
|
|
857
|
+
'vars': {
|
|
858
|
+
'url': f'https://root:root@localhost:{port}/api/v0/test',
|
|
859
|
+
'verify': True,
|
|
860
|
+
'sslopts': sslopts,
|
|
861
|
+
},
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
q = 'return($lib.inet.http.get($url, ssl_verify=$verify, ssl_opts=$sslopts))'
|
|
865
|
+
|
|
866
|
+
size, sha256 = await core.callStorm('return($lib.bytes.put($lib.base64.decode(Zm9v)))')
|
|
867
|
+
opts['vars']['sha256'] = sha256
|
|
868
|
+
|
|
869
|
+
## no cert provided
|
|
870
|
+
resp = await core.callStorm(q, opts=opts)
|
|
871
|
+
self.eq(-1, resp['code'])
|
|
872
|
+
self.isin('certificate verify failed', resp['reason'])
|
|
873
|
+
|
|
874
|
+
## provide just the CA Certificate
|
|
875
|
+
sslopts['ca_cert'] = ca_cert
|
|
876
|
+
resp = await core.callStorm(q, opts=opts)
|
|
877
|
+
self.eq(200, resp['code'])
|
|
@@ -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:
|
|
@@ -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
|
|
synapse/tests/test_lib_types.py
CHANGED
|
@@ -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))
|
synapse/tests/test_model_dns.py
CHANGED
|
@@ -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:
|