synapse 2.195.0__py311-none-any.whl → 2.196.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 (46) hide show
  1. synapse/axon.py +72 -5
  2. synapse/common.py +23 -0
  3. synapse/cortex.py +1 -0
  4. synapse/daemon.py +1 -0
  5. synapse/lib/aha.py +159 -4
  6. synapse/lib/cell.py +133 -8
  7. synapse/lib/jsonstor.py +2 -1
  8. synapse/lib/modelrev.py +5 -1
  9. synapse/lib/nexus.py +13 -6
  10. synapse/lib/reflect.py +4 -5
  11. synapse/lib/snap.py +14 -7
  12. synapse/lib/stormlib/aha.py +351 -1
  13. synapse/lib/stormlib/utils.py +37 -0
  14. synapse/lib/stormtypes.py +124 -6
  15. synapse/lib/version.py +2 -2
  16. synapse/models/base.py +3 -0
  17. synapse/models/infotech.py +55 -16
  18. synapse/models/orgs.py +14 -10
  19. synapse/models/risk.py +23 -10
  20. synapse/models/transport.py +8 -3
  21. synapse/telepath.py +12 -0
  22. synapse/tests/test_axon.py +23 -0
  23. synapse/tests/test_common.py +28 -0
  24. synapse/tests/test_datamodel.py +8 -0
  25. synapse/tests/test_lib_aha.py +241 -0
  26. synapse/tests/test_lib_cell.py +61 -0
  27. synapse/tests/test_lib_jsonstor.py +1 -0
  28. synapse/tests/test_lib_modelrev.py +6 -0
  29. synapse/tests/test_lib_nexus.py +24 -2
  30. synapse/tests/test_lib_stormlib_aha.py +188 -0
  31. synapse/tests/test_lib_stormlib_utils.py +14 -0
  32. synapse/tests/test_lib_stormtypes.py +90 -3
  33. synapse/tests/test_model_base.py +2 -0
  34. synapse/tests/test_model_infotech.py +28 -1
  35. synapse/tests/test_model_orgs.py +2 -0
  36. synapse/tests/test_model_risk.py +2 -0
  37. synapse/tests/test_model_transport.py +1 -0
  38. synapse/tests/test_telepath.py +26 -0
  39. synapse/tests/test_tools_aha.py +192 -0
  40. synapse/tools/aha/mirror.py +193 -0
  41. synapse/tools/changelog.py +32 -27
  42. {synapse-2.195.0.dist-info → synapse-2.196.0.dist-info}/METADATA +1 -1
  43. {synapse-2.195.0.dist-info → synapse-2.196.0.dist-info}/RECORD +46 -43
  44. {synapse-2.195.0.dist-info → synapse-2.196.0.dist-info}/LICENSE +0 -0
  45. {synapse-2.195.0.dist-info → synapse-2.196.0.dist-info}/WHEEL +0 -0
  46. {synapse-2.195.0.dist-info → synapse-2.196.0.dist-info}/top_level.txt +0 -0
synapse/lib/stormtypes.py CHANGED
@@ -2381,6 +2381,50 @@ class LibAxon(Lib):
2381
2381
  {'name': 'sha256', 'type': 'str', 'desc': 'The sha256 value to calculate hashes for.', },
2382
2382
  ),
2383
2383
  'returns': {'type': 'dict', 'desc': 'A dictionary of additional hashes.', }}},
2384
+
2385
+ {'name': 'read', 'desc': '''
2386
+ Read bytes from a file stored in the Axon by its SHA256 hash.
2387
+
2388
+ Examples:
2389
+ Read 100 bytes starting at offset 0::
2390
+
2391
+ $byts = $lib.axon.read($sha256, size=100)
2392
+
2393
+ Read 50 bytes starting at offset 200::
2394
+
2395
+ $byts = $lib.axon.read($sha256, offs=200, size=50)
2396
+ ''',
2397
+ 'type': {'type': 'function', '_funcname': 'read',
2398
+ 'args': (
2399
+ {'name': 'sha256', 'type': 'str', 'desc': 'The SHA256 hash of the file to read.'},
2400
+ {'name': 'offs', 'type': 'int', 'default': 0,
2401
+ 'desc': 'The offset to start reading from.'},
2402
+ {'name': 'size', 'type': 'int', 'default': s_const.mebibyte,
2403
+ 'desc': 'The number of bytes to read. Max is 1 MiB.'},
2404
+ ),
2405
+ 'returns': {'type': 'bytes', 'desc': 'The requested bytes from the file.'}}},
2406
+
2407
+ {'name': 'unpack', 'desc': '''
2408
+ Unpack bytes from a file stored in the Axon into a struct using the specified format.
2409
+
2410
+ Examples:
2411
+ Unpack two 32-bit integers from the start of a file::
2412
+
2413
+ $nums = $lib.axon.unpack($sha256, '<II')
2414
+
2415
+ Unpack a 64-bit float starting at offset 100::
2416
+
2417
+ $float = $lib.axon.unpack($sha256, '<d', offs=100)
2418
+ ''',
2419
+ 'type': {'type': 'function', '_funcname': 'unpack',
2420
+ 'args': (
2421
+ {'name': 'sha256', 'type': 'str', 'desc': 'The SHA256 hash of the file to read.'},
2422
+ {'name': 'fmt', 'type': 'str', 'desc': 'The struct format string.'},
2423
+ {'name': 'offs', 'type': 'int', 'default': 0,
2424
+ 'desc': 'The offset to start reading from.'},
2425
+ ),
2426
+ 'returns': {'type': 'list', 'desc': 'The unpacked values as a tuple.'}}},
2427
+
2384
2428
  {'name': 'upload', 'desc': '''
2385
2429
  Upload a stream of bytes to the Axon as a file.
2386
2430
 
@@ -2426,6 +2470,8 @@ class LibAxon(Lib):
2426
2470
  'size': self.size,
2427
2471
  'upload': self.upload,
2428
2472
  'hashset': self.hashset,
2473
+ 'read': self.read,
2474
+ 'unpack': self.unpack,
2429
2475
  }
2430
2476
 
2431
2477
  @stormfunc(readonly=True)
@@ -2712,6 +2758,48 @@ class LibAxon(Lib):
2712
2758
  await self.runt.snap.core.getAxon()
2713
2759
  return await self.runt.snap.core.axon.hashset(s_common.uhex(sha256))
2714
2760
 
2761
+ @stormfunc(readonly=True)
2762
+ async def read(self, sha256, offs=0, size=s_const.mebibyte):
2763
+ '''
2764
+ Read bytes from a file in the Axon.
2765
+ '''
2766
+ sha256 = await tostr(sha256)
2767
+ size = await toint(size)
2768
+ offs = await toint(offs)
2769
+
2770
+ if size > s_const.mebibyte:
2771
+ mesg = f'Size must be between 1 and {s_const.mebibyte} bytes'
2772
+ raise s_exc.BadArg(mesg=mesg)
2773
+
2774
+ if not self.runt.allowed(('axon', 'get')):
2775
+ self.runt.confirm(('storm', 'lib', 'axon', 'get'))
2776
+
2777
+ await self.runt.snap.core.getAxon()
2778
+
2779
+ byts = b''
2780
+ async for chunk in self.runt.snap.core.axon.get(s_common.uhex(sha256), offs=offs, size=size):
2781
+ byts += chunk
2782
+ return byts
2783
+
2784
+ @stormfunc(readonly=True)
2785
+ async def unpack(self, sha256, fmt, offs=0):
2786
+ '''
2787
+ Unpack bytes from a file in the Axon using struct.
2788
+ '''
2789
+ if self.runt.snap.core.axoninfo.get('features', {}).get('unpack', 0) < 1:
2790
+ mesg = 'The connected Axon does not support the the unpack API. Please update your Axon.'
2791
+ raise s_exc.FeatureNotSupported(mesg=mesg)
2792
+
2793
+ sha256 = await tostr(sha256)
2794
+ fmt = await tostr(fmt)
2795
+ offs = await toint(offs)
2796
+
2797
+ if not self.runt.allowed(('axon', 'get')):
2798
+ self.runt.confirm(('storm', 'lib', 'axon', 'get'))
2799
+
2800
+ await self.runt.snap.core.getAxon()
2801
+ return await self.runt.snap.core.axon.unpack(s_common.uhex(sha256), fmt, offs)
2802
+
2715
2803
  @registry.registerLib
2716
2804
  class LibBytes(Lib):
2717
2805
  '''
@@ -5446,7 +5534,7 @@ class Number(Prim):
5446
5534
  try:
5447
5535
  valu = s_common.hugenum(valu)
5448
5536
  except (TypeError, decimal.DecimalException) as e:
5449
- mesg = f'Failed to make number from {valu!r}'
5537
+ mesg = f'Failed to make number from {s_common.trimText(repr(valu))}'
5450
5538
  raise s_exc.BadCast(mesg=mesg) from e
5451
5539
 
5452
5540
  Prim.__init__(self, valu, path=path)
@@ -6999,6 +7087,22 @@ class Layer(Prim):
6999
7087
  'returns': {'name': 'Yields', 'type': 'node',
7000
7088
  'desc': 'Yields nodes.', }}},
7001
7089
 
7090
+ {'name': 'liftByNodeData', 'desc': '''
7091
+ Lift and yield nodes with the given node data key set within the layer.
7092
+
7093
+ Example:
7094
+ Yield all nodes with the data key zootsuit set in the top layer::
7095
+
7096
+ yield $lib.layer.get().liftByNodeData(zootsuit)
7097
+
7098
+ ''',
7099
+ 'type': {'type': 'function', '_funcname': 'liftByNodeData',
7100
+ 'args': (
7101
+ {'name': 'name', 'type': 'str', 'desc': 'The node data name to lift by.'},
7102
+ ),
7103
+ 'returns': {'name': 'Yields', 'type': 'node',
7104
+ 'desc': 'Yields nodes.', }}},
7105
+
7002
7106
  {'name': 'getEdges', 'desc': '''
7003
7107
  Yield (n1iden, verb, n2iden) tuples for any light edges in the layer.
7004
7108
 
@@ -7110,6 +7214,7 @@ class Layer(Prim):
7110
7214
  'getEdges': self.getEdges,
7111
7215
  'liftByTag': self.liftByTag,
7112
7216
  'liftByProp': self.liftByProp,
7217
+ 'liftByNodeData': self.liftByNodeData,
7113
7218
  'getTagCount': self._methGetTagCount,
7114
7219
  'getPropCount': self._methGetPropCount,
7115
7220
  'getPropValues': self._methGetPropValues,
@@ -7177,6 +7282,19 @@ class Layer(Prim):
7177
7282
  async for _, buid, sode in layr.liftByPropValu(liftform, liftprop, cmprvals):
7178
7283
  yield await self.runt.snap._joinStorNode(buid, {iden: sode})
7179
7284
 
7285
+ @stormfunc(readonly=True)
7286
+ async def liftByNodeData(self, name):
7287
+
7288
+ name = await tostr(name)
7289
+
7290
+ iden = self.valu.get('iden')
7291
+ layr = self.runt.snap.core.getLayer(iden)
7292
+
7293
+ await self.runt.reqUserCanReadLayer(iden)
7294
+
7295
+ async for _, buid, sode in layr.liftByDataName(name):
7296
+ yield await self.runt.snap._joinStorNode(buid, {iden: sode})
7297
+
7180
7298
  @stormfunc(readonly=True)
7181
7299
  async def getMirrorStatus(self):
7182
7300
  iden = self.valu.get('iden')
@@ -9813,7 +9931,7 @@ async def tostr(valu, noneok=False):
9813
9931
 
9814
9932
  return str(valu)
9815
9933
  except Exception as e:
9816
- mesg = f'Failed to make a string from {valu!r}.'
9934
+ mesg = f'Failed to make a string from {s_common.trimText(repr(valu))}.'
9817
9935
  raise s_exc.BadCast(mesg=mesg) from e
9818
9936
 
9819
9937
  async def tobool(valu, noneok=False):
@@ -9827,7 +9945,7 @@ async def tobool(valu, noneok=False):
9827
9945
  try:
9828
9946
  return bool(valu)
9829
9947
  except Exception:
9830
- mesg = f'Failed to make a boolean from {valu!r}.'
9948
+ mesg = f'Failed to make a boolean from {s_common.trimText(repr(valu))}.'
9831
9949
  raise s_exc.BadCast(mesg=mesg)
9832
9950
 
9833
9951
  async def tonumber(valu, noneok=False):
@@ -9852,13 +9970,13 @@ async def toint(valu, noneok=False):
9852
9970
  try:
9853
9971
  return int(valu, 0)
9854
9972
  except ValueError as e:
9855
- mesg = f'Failed to make an integer from {valu!r}.'
9973
+ mesg = f'Failed to make an integer from {s_common.trimText(repr(valu))}.'
9856
9974
  raise s_exc.BadCast(mesg=mesg) from e
9857
9975
 
9858
9976
  try:
9859
9977
  return int(valu)
9860
9978
  except Exception as e:
9861
- mesg = f'Failed to make an integer from {valu!r}.'
9979
+ mesg = f'Failed to make an integer from {s_common.trimText(repr(valu))}.'
9862
9980
  raise s_exc.BadCast(mesg=mesg) from e
9863
9981
 
9864
9982
  async def toiter(valu, noneok=False):
@@ -9877,7 +9995,7 @@ async def toiter(valu, noneok=False):
9877
9995
  async for item in agen:
9878
9996
  yield item
9879
9997
  except TypeError as e:
9880
- mesg = f'Value is not iterable: {valu!r}'
9998
+ mesg = f'Value is not iterable: {s_common.trimText(repr(valu))}'
9881
9999
  raise s_exc.StormRuntimeError(mesg=mesg) from e
9882
10000
 
9883
10001
  async def torepr(valu, usestr=False):
synapse/lib/version.py CHANGED
@@ -223,6 +223,6 @@ def reqVersion(valu, reqver,
223
223
  ##############################################################################
224
224
  # The following are touched during the release process by bumpversion.
225
225
  # Do not modify these directly.
226
- version = (2, 195, 0)
226
+ version = (2, 196, 0)
227
227
  verstring = '.'.join([str(x) for x in version])
228
- commit = 'dc93864afdb2150e6d83ac4ed426c8e99bb3a448'
228
+ commit = '8182360d2ebf8e8bdd00cb72f03812061c819cc2'
synapse/models/base.py CHANGED
@@ -193,6 +193,9 @@ class BaseModule(s_module.CoreModule):
193
193
  ('url', ('inet:url', {}), {
194
194
  'doc': 'A URL which documents the meta source.'}),
195
195
 
196
+ ('ingest:cursor', ('str', {}), {
197
+ 'doc': 'Used by ingest logic to capture the current ingest cursor within a feed.'}),
198
+
196
199
  ('ingest:latest', ('time', {}), {
197
200
  'doc': 'Used by ingest logic to capture the last time a feed ingest ran.'}),
198
201
 
@@ -1417,6 +1417,36 @@ class ItModule(s_module.CoreModule):
1417
1417
  'deprecated': True,
1418
1418
  'doc': 'Deprecated. Please use risk:vuln:cve:references.'}),
1419
1419
 
1420
+ ('nist:nvd:source', ('ou:name', {}), {
1421
+ 'doc': 'The name of the organization which reported the vulnerability to NIST.'}),
1422
+
1423
+ ('nist:nvd:published', ('time', {}), {
1424
+ 'doc': 'The date the vulnerability was first published in the NVD.'}),
1425
+
1426
+ ('nist:nvd:modified', ('time', {"ismax": True}), {
1427
+ 'doc': 'The date the vulnerability was last modified in the NVD.'}),
1428
+
1429
+ ('cisa:kev:name', ('str', {}), {
1430
+ 'doc': 'The name of the vulnerability according to the CISA KEV database.'}),
1431
+
1432
+ ('cisa:kev:desc', ('str', {}), {
1433
+ 'doc': 'The description of the vulnerability according to the CISA KEV database.'}),
1434
+
1435
+ ('cisa:kev:action', ('str', {}), {
1436
+ 'doc': 'The action to mitigate the vulnerability according to the CISA KEV database.'}),
1437
+
1438
+ ('cisa:kev:vendor', ('ou:name', {}), {
1439
+ 'doc': 'The vendor name listed in the CISA KEV database.'}),
1440
+
1441
+ ('cisa:kev:product', ('it:prod:softname', {}), {
1442
+ 'doc': 'The product name listed in the CISA KEV database.'}),
1443
+
1444
+ ('cisa:kev:added', ('time', {}), {
1445
+ 'doc': 'The date the vulnerability was added to the CISA KEV database.'}),
1446
+
1447
+ ('cisa:kev:duedate', ('time', {}), {
1448
+ 'doc': 'The date the action is due according to the CISA KEV database.'}),
1449
+
1420
1450
  )),
1421
1451
  ('it:sec:cpe', {}, (
1422
1452
  ('v2_2', ('it:sec:cpe:v2_2', {}), {
@@ -2248,29 +2278,34 @@ class ItModule(s_module.CoreModule):
2248
2278
  'doc': 'Software architecture.',
2249
2279
  }),
2250
2280
  ('released', ('time', {}), {
2251
- 'doc': 'Timestamp for when this version of the software was released.',
2252
- }),
2281
+ 'doc': 'Timestamp for when this version of the software was released.'}),
2282
+
2253
2283
  ('semver', ('it:semver', {}), {
2254
- 'doc': 'System normalized semantic version number.',
2255
- }),
2284
+ 'doc': 'System normalized semantic version number.'}),
2285
+
2256
2286
  ('semver:major', ('int', {}), {
2257
- 'doc': 'Version major number.',
2258
- }),
2287
+ 'deprecated': True,
2288
+ 'doc': 'Deprecated. Please use semver range queries.'}),
2289
+
2259
2290
  ('semver:minor', ('int', {}), {
2260
- 'doc': 'Version minor number.',
2261
- }),
2291
+ 'deprecated': True,
2292
+ 'doc': 'Deprecated. Please use semver range queries.'}),
2293
+
2262
2294
  ('semver:patch', ('int', {}), {
2263
- 'doc': 'Version patch number.',
2264
- }),
2295
+ 'deprecated': True,
2296
+ 'doc': 'Deprecated. Please use semver range queries.'}),
2297
+
2265
2298
  ('semver:pre', ('str', {}), {
2266
- 'doc': 'Semver prerelease string.',
2267
- }),
2299
+ 'deprecated': True,
2300
+ 'doc': 'Deprecated.'}),
2301
+
2268
2302
  ('semver:build', ('str', {}), {
2269
- 'doc': 'Semver build string.',
2270
- }),
2303
+ 'deprecated': True,
2304
+ 'doc': 'Deprecated.'}),
2305
+
2271
2306
  ('url', ('inet:url', {}), {
2272
- 'doc': 'URL where a specific version of the software is available from.',
2273
- }),
2307
+ 'doc': 'URL where a specific version of the software is available from.'}),
2308
+
2274
2309
  )),
2275
2310
 
2276
2311
  ('it:prod:softlib', {}, (
@@ -2347,6 +2382,10 @@ class ItModule(s_module.CoreModule):
2347
2382
  ('signame', ('it:av:signame', {}), {
2348
2383
  'doc': 'The name of the signature returned by the scanner.'}),
2349
2384
 
2385
+ ('categories', ('array', {'sorted': True, 'uniq': True,
2386
+ 'type': 'str', 'typeopts': {'lower': True, 'onespace': True}}), {
2387
+ 'doc': 'A list of categories for the result returned by the scanner.'}),
2388
+
2350
2389
  ('target:file', ('file:bytes', {}), {
2351
2390
  'doc': 'The file that was scanned to produce the result.'}),
2352
2391
 
synapse/models/orgs.py CHANGED
@@ -1346,23 +1346,27 @@ class OuModule(s_module.CoreModule):
1346
1346
  }),
1347
1347
  )),
1348
1348
  ('ou:contest:result', {}, (
1349
+
1349
1350
  ('contest', ('ou:contest', {}), {
1350
1351
  'ro': True,
1351
- 'doc': 'The contest.',
1352
- }),
1352
+ 'doc': 'The contest that the participant took part in.'}),
1353
+
1353
1354
  ('participant', ('ps:contact', {}), {
1354
1355
  'ro': True,
1355
- 'doc': 'The participant',
1356
- }),
1356
+ 'doc': 'The participant in the contest.'}),
1357
+
1357
1358
  ('rank', ('int', {}), {
1358
- 'doc': 'The rank order of the participant.',
1359
- }),
1359
+ 'doc': "The participant's rank order in the contest."}),
1360
+
1360
1361
  ('score', ('int', {}), {
1361
- 'doc': 'The score of the participant.',
1362
- }),
1362
+ 'doc': "The participant's final score in the contest."}),
1363
+
1364
+ ('period', ('ival', {}), {
1365
+ 'doc': 'The period of time when the participant competed in the contest.'}),
1366
+
1363
1367
  ('url', ('inet:url', {}), {
1364
- 'doc': 'The contest result website URL.',
1365
- }),
1368
+ 'doc': 'The contest result website URL.'}),
1369
+
1366
1370
  )),
1367
1371
  ('ou:enacted:status:taxonomy', {}, ()),
1368
1372
  ('ou:enacted', {}, (
synapse/models/risk.py CHANGED
@@ -492,6 +492,9 @@ class RiskModule(s_module.CoreModule):
492
492
  ('id', ('str', {'strip': True}), {
493
493
  'doc': 'An identifier for the vulnerability.'}),
494
494
 
495
+ ('tag', ('syn:tag', {}), {
496
+ 'doc': 'A tag used to annotate the presence or use of the vulnerability.'}),
497
+
495
498
  ('cve', ('it:sec:cve', {}), {
496
499
  'doc': 'The CVE ID of the vulnerability.'}),
497
500
 
@@ -506,34 +509,44 @@ class RiskModule(s_module.CoreModule):
506
509
  'doc': 'An array of documentation URLs provided by the CVE database.'}),
507
510
 
508
511
  ('nist:nvd:source', ('ou:name', {}), {
509
- 'doc': 'The name of the organization which reported the vulnerability to NIST.'}),
512
+ 'deprecated': True,
513
+ 'doc': 'Deprecated. Please use it:sec:cve:nist:nvd:source.'}),
510
514
 
511
515
  ('nist:nvd:published', ('time', {}), {
512
- 'doc': 'The date the vulnerability was first published in the NVD.'}),
516
+ 'deprecated': True,
517
+ 'doc': 'Deprecated. Please use it:sec:cve:nist:nvd:published.'}),
513
518
 
514
519
  ('nist:nvd:modified', ('time', {"ismax": True}), {
515
- 'doc': 'The date the vulnerability was last modified in the NVD.'}),
520
+ 'deprecated': True,
521
+ 'doc': 'Deprecated. Please use it:sec:cve:nist:nvd:modified.'}),
516
522
 
517
523
  ('cisa:kev:name', ('str', {}), {
518
- 'doc': 'The name of the vulnerability according to the CISA KEV database.'}),
524
+ 'deprecated': True,
525
+ 'doc': 'Deprecated. Please use it:sec:cve:cisa:kev:name.'}),
519
526
 
520
527
  ('cisa:kev:desc', ('str', {}), {
521
- 'doc': 'The description of the vulnerability according to the CISA KEV database.'}),
528
+ 'deprecated': True,
529
+ 'doc': 'Deprecated. Please use it:sec:cve:cisa:kev:desc.'}),
522
530
 
523
531
  ('cisa:kev:action', ('str', {}), {
524
- 'doc': 'The action to mitigate the vulnerability according to the CISA KEV database.'}),
532
+ 'deprecated': True,
533
+ 'doc': 'Deprecated. Please use it:sec:cve:cisa:kev:action.'}),
525
534
 
526
535
  ('cisa:kev:vendor', ('ou:name', {}), {
527
- 'doc': 'The vendor name listed in the CISA KEV database.'}),
536
+ 'deprecated': True,
537
+ 'doc': 'Deprecated. Please use it:sec:cve:cisa:kev:vendor.'}),
528
538
 
529
539
  ('cisa:kev:product', ('it:prod:softname', {}), {
530
- 'doc': 'The product name listed in the CISA KEV database.'}),
540
+ 'deprecated': True,
541
+ 'doc': 'Deprecated. Please use it:sec:cve:cisa:kev:product.'}),
531
542
 
532
543
  ('cisa:kev:added', ('time', {}), {
533
- 'doc': 'The date the vulnerability was added to the CISA KEV database.'}),
544
+ 'deprecated': True,
545
+ 'doc': 'Deprecated. Please use it:sec:cve:cisa:kev:added.'}),
534
546
 
535
547
  ('cisa:kev:duedate', ('time', {}), {
536
- 'doc': 'The date the action is due according to the CISA KEV database.'}),
548
+ 'deprecated': True,
549
+ 'doc': 'Deprecated. Please use it:sec:cve:cisa:kev:duedate.'}),
537
550
 
538
551
  ('cvss:v2', ('cvss:v2', {}), {
539
552
  'doc': 'The CVSS v2 vector for the vulnerability.'}),
@@ -454,21 +454,26 @@ class TransportModule(s_module.CoreModule):
454
454
  ('type', ('transport:sea:vessel:type:taxonomy', {}), {
455
455
  'doc': 'The type of vessel.'}),
456
456
 
457
- # TODO: convert this to an entity:name
458
- ('name', ('str', {'lower': True, 'onespace': True}), {
459
- 'doc': 'The name of the vessel'}),
457
+ ('name', ('entity:name', {}), {
458
+ 'doc': 'The name of the vessel.'}),
459
+
460
460
  ('length', ('geo:dist', {}), {
461
461
  'deprecated': True,
462
462
  'doc': 'Deprecated. Please use :phys:length.'}),
463
+
463
464
  ('beam', ('geo:dist', {}), {
464
465
  'doc': 'The official overall vessel beam'}),
466
+
465
467
  ('flag', ('iso:3166:cc', {}), {
466
468
  'doc': 'The country the vessel is flagged to.'}),
469
+
467
470
  ('mmsi', ('transport:sea:mmsi', {}), {
468
471
  'doc': 'The Maritime Mobile Service Identifier assigned to the vessel.'}),
472
+
469
473
  ('make', ('str', {'lower': True, 'strip': True}), {
470
474
  'deprecated': True,
471
475
  'doc': 'Deprecated. Please use :manufacturer:name.'}),
476
+
472
477
  ('operator', ('ps:contact', {}), {
473
478
  'doc': 'The contact information of the operator.'}),
474
479
  # TODO tonnage / gross tonnage?
synapse/telepath.py CHANGED
@@ -321,6 +321,9 @@ class Aware:
321
321
  '''
322
322
  return self
323
323
 
324
+ async def getTeleFeats(self):
325
+ return {}
326
+
324
327
  def onTeleShare(self, dmon, name):
325
328
  pass
326
329
 
@@ -599,6 +602,8 @@ class Proxy(s_base.Base):
599
602
  self.shares = {}
600
603
 
601
604
  self._ahainfo = {}
605
+ self._features = {}
606
+
602
607
  self.sharinfo = {}
603
608
  self.methinfo = {}
604
609
 
@@ -634,6 +639,12 @@ class Proxy(s_base.Base):
634
639
  self.onfini(fini)
635
640
  self.link.onfini(self.fini)
636
641
 
642
+ def _hasTeleFeat(self, name, vers=1):
643
+ return self._features.get(name, 0) >= vers
644
+
645
+ def _hasTeleMeth(self, name):
646
+ return self.methinfo.get(name) is not None
647
+
637
648
  def _getSynVers(self):
638
649
  '''
639
650
  Helper method to retrieve the remote Synapse version from Proxy.
@@ -906,6 +917,7 @@ class Proxy(s_base.Base):
906
917
 
907
918
  self.sess = self.synack[1].get('sess')
908
919
  self._ahainfo = self.synack[1].get('ahainfo', {})
920
+ self._features = self.synack[1].get('features', {})
909
921
  self.sharinfo = self.synack[1].get('sharinfo', {})
910
922
  self.methinfo = self.sharinfo.get('meths', {})
911
923
 
@@ -4,6 +4,7 @@ import csv
4
4
  import sys
5
5
  import base64
6
6
  import shutil
7
+ import struct
7
8
  import asyncio
8
9
  import hashlib
9
10
  import logging
@@ -489,6 +490,28 @@ bar baz",vv
489
490
  with self.raises(s_exc.BadArg):
490
491
  bytslist = [b async for b in axon.get(sha256, 0, size=0)]
491
492
 
493
+ # test unpack
494
+ intdata = struct.pack('>QQQ', 1, 2, 3)
495
+ size, sha256 = await axon.put(intdata)
496
+ self.eq((1,), await axon.unpack(sha256, '>Q'))
497
+ self.eq((2,), await axon.unpack(sha256, '>Q', offs=8))
498
+ self.eq((3,), await axon.unpack(sha256, '>Q', offs=16))
499
+ self.eq((2, 3), await axon.unpack(sha256, '>QQ', offs=8))
500
+
501
+ fmt = 'Q' * 150_000
502
+ with self.raises(s_exc.BadArg) as cm:
503
+ await axon.unpack(sha256, '>' + fmt)
504
+ self.isin('Struct format would read too much data', cm.exception.get('mesg'))
505
+
506
+ with self.raises(s_exc.BadArg):
507
+ await axon.unpack(sha256, 'not a valid format')
508
+
509
+ with self.raises(s_exc.BadArg):
510
+ await axon.unpack(sha256, 123)
511
+
512
+ with self.raises(s_exc.BadDataValu):
513
+ await axon.unpack(sha256, '>Q', offs=24)
514
+
492
515
  async def test_axon_base(self):
493
516
  async with self.getTestAxon() as axon:
494
517
  self.isin('axon', axon.dmon.shared)
@@ -12,6 +12,34 @@ import synapse.tests.utils as s_t_utils
12
12
  logger = logging.getLogger(__name__)
13
13
 
14
14
  class CommonTest(s_t_utils.SynTest):
15
+
16
+ async def test_waitgenr(self):
17
+
18
+ async def genr():
19
+ yield 10
20
+ raise Exception('omg')
21
+
22
+ rets = [retn async for retn in s_common.waitgenr(genr(), 10)]
23
+
24
+ self.true(rets[0][0])
25
+ self.false(rets[1][0])
26
+
27
+ async def one():
28
+ yield 'item'
29
+
30
+ rets = [retn async for retn in s_common.waitgenr(one(), timeout=1.0)]
31
+ self.eq(rets, [(True, 'item')])
32
+
33
+ async def genr():
34
+ yield 1
35
+ await asyncio.sleep(60)
36
+ yield 2
37
+
38
+ rets = [retn async for retn in s_common.waitgenr(genr(), timeout=0.1)]
39
+ self.eq(rets[0], (True, 1))
40
+ self.false(rets[1][0])
41
+ self.eq(rets[1][1]['err'], 'TimeoutError')
42
+
15
43
  def test_tuplify(self):
16
44
  tv = ['node', [['test:str', 'test'],
17
45
  {'tags': {
@@ -334,3 +334,11 @@ class DataModelTest(s_t_utils.SynTest):
334
334
  self.none(core.model.edge(('meta:rule', 'matches', None)))
335
335
 
336
336
  core.model.delEdge(('meta:rule', 'matches', None))
337
+
338
+ async def test_datamodel_locked_subs(self):
339
+
340
+ async with self.getTestCore() as core:
341
+ await core.setDeprLock('it:prod:softver:semver:major', True)
342
+ nodes = await core.nodes('[ it:prod:softver=* :semver=3.1.0 ]')
343
+ self.none(nodes[0].get('semver:major'))
344
+ self.eq(1, nodes[0].get('semver:minor'))