synapse 2.182.0__py311-none-any.whl → 2.184.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 (37) hide show
  1. synapse/cortex.py +5 -0
  2. synapse/datamodel.py +41 -3
  3. synapse/lib/ast.py +4 -3
  4. synapse/lib/autodoc.py +71 -5
  5. synapse/lib/cell.py +1 -1
  6. synapse/lib/storm.py +23 -0
  7. synapse/lib/stormlib/cortex.py +1 -0
  8. synapse/lib/stormlib/graph.py +17 -0
  9. synapse/lib/stormlib/infosec.py +2 -0
  10. synapse/lib/stormlib/model.py +2 -1
  11. synapse/lib/stormlib/random.py +84 -3
  12. synapse/lib/stormtypes.py +4 -0
  13. synapse/lib/stormwhois.py +3 -0
  14. synapse/lib/version.py +2 -2
  15. synapse/models/infotech.py +3 -15
  16. synapse/models/orgs.py +76 -2
  17. synapse/models/risk.py +22 -0
  18. synapse/tests/files/stormpkg/testpkg.yaml +10 -0
  19. synapse/tests/test_cortex.py +31 -44
  20. synapse/tests/test_lib_ast.py +58 -0
  21. synapse/tests/test_lib_autodoc.py +85 -0
  22. synapse/tests/test_lib_storm.py +18 -0
  23. synapse/tests/test_lib_stormlib_modelext.py +52 -0
  24. synapse/tests/test_lib_stormlib_random.py +93 -0
  25. synapse/tests/test_lib_stormwhois.py +4 -4
  26. synapse/tests/test_model_infotech.py +44 -1
  27. synapse/tests/test_model_orgs.py +37 -0
  28. synapse/tests/test_model_risk.py +3 -0
  29. synapse/tests/test_tools_autodoc.py +6 -0
  30. synapse/tests/utils.py +28 -0
  31. synapse/tools/autodoc.py +2 -1
  32. synapse/tools/changelog.py +53 -10
  33. {synapse-2.182.0.dist-info → synapse-2.184.0.dist-info}/METADATA +1 -1
  34. {synapse-2.182.0.dist-info → synapse-2.184.0.dist-info}/RECORD +37 -37
  35. {synapse-2.182.0.dist-info → synapse-2.184.0.dist-info}/WHEEL +1 -1
  36. {synapse-2.182.0.dist-info → synapse-2.184.0.dist-info}/LICENSE +0 -0
  37. {synapse-2.182.0.dist-info → synapse-2.184.0.dist-info}/top_level.txt +0 -0
@@ -2709,15 +2709,12 @@ class ItModule(s_module.CoreModule):
2709
2709
  'doc': 'The path for the file.',
2710
2710
  }),
2711
2711
  ('path:dir', ('file:path', {}), {
2712
- 'ro': True,
2713
2712
  'doc': 'The parent directory of the file path (parsed from :path).',
2714
2713
  }),
2715
2714
  ('path:ext', ('str', {'lower': True, 'strip': True}), {
2716
- 'ro': True,
2717
2715
  'doc': 'The file extension of the file name (parsed from :path).',
2718
2716
  }),
2719
2717
  ('path:base', ('file:base', {}), {
2720
- 'ro': True,
2721
2718
  'doc': 'The final component of the file path (parsed from :path).',
2722
2719
  }),
2723
2720
  ('file', ('file:bytes', {}), {
@@ -2755,15 +2752,12 @@ class ItModule(s_module.CoreModule):
2755
2752
  'doc': 'The path where the file was created.',
2756
2753
  }),
2757
2754
  ('path:dir', ('file:path', {}), {
2758
- 'ro': True,
2759
2755
  'doc': 'The parent directory of the file path (parsed from :path).',
2760
2756
  }),
2761
2757
  ('path:ext', ('str', {'lower': True, 'strip': True}), {
2762
- 'ro': True,
2763
2758
  'doc': 'The file extension of the file name (parsed from :path).',
2764
2759
  }),
2765
2760
  ('path:base', ('file:base', {}), {
2766
- 'ro': True,
2767
2761
  'doc': 'The final component of the file path (parsed from :path).',
2768
2762
  }),
2769
2763
  ('file', ('file:bytes', {}), {
@@ -2789,15 +2783,12 @@ class ItModule(s_module.CoreModule):
2789
2783
  'doc': 'The path where the file was deleted.',
2790
2784
  }),
2791
2785
  ('path:dir', ('file:path', {}), {
2792
- 'ro': True,
2793
2786
  'doc': 'The parent directory of the file path (parsed from :path).',
2794
2787
  }),
2795
2788
  ('path:ext', ('str', {'lower': True, 'strip': True}), {
2796
- 'ro': True,
2797
2789
  'doc': 'The file extension of the file name (parsed from :path).',
2798
2790
  }),
2799
2791
  ('path:base', ('file:base', {}), {
2800
- 'ro': True,
2801
2792
  'doc': 'The final component of the file path (parsed from :path).',
2802
2793
  }),
2803
2794
  ('file', ('file:bytes', {}), {
@@ -2823,15 +2814,12 @@ class ItModule(s_module.CoreModule):
2823
2814
  'doc': 'The path where the file was read.',
2824
2815
  }),
2825
2816
  ('path:dir', ('file:path', {}), {
2826
- 'ro': True,
2827
2817
  'doc': 'The parent directory of the file path (parsed from :path).',
2828
2818
  }),
2829
2819
  ('path:ext', ('str', {'lower': True, 'strip': True}), {
2830
- 'ro': True,
2831
2820
  'doc': 'The file extension of the file name (parsed from :path).',
2832
2821
  }),
2833
2822
  ('path:base', ('file:base', {}), {
2834
- 'ro': True,
2835
2823
  'doc': 'The final component of the file path (parsed from :path).',
2836
2824
  }),
2837
2825
  ('file', ('file:bytes', {}), {
@@ -2857,15 +2845,12 @@ class ItModule(s_module.CoreModule):
2857
2845
  'doc': 'The path where the file was written to/modified.',
2858
2846
  }),
2859
2847
  ('path:dir', ('file:path', {}), {
2860
- 'ro': True,
2861
2848
  'doc': 'The parent directory of the file path (parsed from :path).',
2862
2849
  }),
2863
2850
  ('path:ext', ('str', {'lower': True, 'strip': True}), {
2864
- 'ro': True,
2865
2851
  'doc': 'The file extension of the file name (parsed from :path).',
2866
2852
  }),
2867
2853
  ('path:base', ('file:base', {}), {
2868
- 'ro': True,
2869
2854
  'doc': 'The final component of the file path (parsed from :path).',
2870
2855
  }),
2871
2856
  ('file', ('file:bytes', {}), {
@@ -3001,6 +2986,9 @@ class ItModule(s_module.CoreModule):
3001
2986
  'doc': 'The sensor host node that produced the hit.'}),
3002
2987
  ('version', ('it:semver', {}), {
3003
2988
  'doc': 'The version of the rule at the time of match.'}),
2989
+
2990
+ ('dropped', ('bool', {}), {
2991
+ 'doc': 'Set to true if the network traffic was dropped due to the match.'}),
3004
2992
  )),
3005
2993
 
3006
2994
  ('it:sec:stix:bundle', {}, (
synapse/models/orgs.py CHANGED
@@ -45,6 +45,24 @@ class OuModule(s_module.CoreModule):
45
45
  ),
46
46
  }}),
47
47
 
48
+ ('ou:asset:type:taxonomy', ('taxonomy', {}), {
49
+ 'interfaces': ('meta:taxonomy',),
50
+ 'doc': 'An asset type taxonomy.'}),
51
+
52
+ ('ou:asset:status:taxonomy', ('taxonomy', {}), {
53
+ 'interfaces': ('meta:taxonomy',),
54
+ 'doc': 'An asset status taxonomy.'}),
55
+
56
+ ('ou:asset', ('guid', {}), {
57
+ 'doc': 'A node for tracking assets which belong to an organization.',
58
+ 'display': {
59
+ 'columns': (
60
+ {'type': 'prop', 'opts': {'name': 'id'}},
61
+ {'type': 'prop', 'opts': {'name': 'name'}},
62
+ {'type': 'prop', 'opts': {'name': 'org::name'}},
63
+ ),
64
+ }}),
65
+
48
66
  ('ou:orgtype', ('taxonomy', {}), {
49
67
  'doc': 'An org type taxonomy.',
50
68
  'interfaces': ('meta:taxonomy',),
@@ -246,6 +264,9 @@ class OuModule(s_module.CoreModule):
246
264
  ('ou:jobtitle', ('str', {'lower': True, 'onespace': True}), {
247
265
  'doc': 'A title for a position within an org.',
248
266
  }),
267
+ ('ou:requirement:type:taxonomy', ('taxonomy', {}), {
268
+ 'interfaces': ('meta:taxonomy',),
269
+ 'doc': 'A taxonomy of requirement types.'}),
249
270
  ('ou:requirement', ('guid', {}), {
250
271
  'doc': 'A specific requirement.'}),
251
272
  ),
@@ -341,8 +362,11 @@ class OuModule(s_module.CoreModule):
341
362
  'doc': 'The currency of the econ:price values.',
342
363
  }),
343
364
  ('costs', ('econ:price', {}), {
344
- 'doc': 'The costs/expenditures over the period.',
345
- }),
365
+ 'doc': 'The costs/expenditures over the period.'}),
366
+
367
+ ('budget', ('econ:price', {}), {
368
+ 'doc': 'The budget allocated for the period.'}),
369
+
346
370
  ('revenue', ('econ:price', {}), {
347
371
  'doc': 'The gross revenue over the period.',
348
372
  }),
@@ -728,6 +752,52 @@ class OuModule(s_module.CoreModule):
728
752
  ('org', ('ou:org', {}), {}),
729
753
  ('name', ('ou:name', {}), {}),
730
754
  )),
755
+
756
+ ('ou:asset:type:taxonomy', {}, ()),
757
+ ('ou:asset:status:taxonomy', {}, ()),
758
+ ('ou:asset', {}, (
759
+ ('org', ('ou:org', {}), {
760
+ 'doc': 'The organization which owns the asset.'}),
761
+
762
+ ('id', ('str', {'strip': True}), {
763
+ 'doc': 'The ID of the asset.'}),
764
+
765
+ ('name', ('str', {'lower': True, 'onespace': True}), {
766
+ 'doc': 'The name of the assset.'}),
767
+
768
+ ('period', ('ival', {}), {
769
+ 'doc': 'The period of time when the asset was being tracked.'}),
770
+
771
+ ('status', ('ou:asset:status:taxonomy', {}), {
772
+ 'doc': 'The current status of the asset.'}),
773
+
774
+ ('type', ('ou:asset:type:taxonomy', {}), {
775
+ 'doc': 'The asset type.'}),
776
+
777
+ ('priority', ('meta:priority', {}), {
778
+ 'doc': 'The overall priority of protecting the asset.'}),
779
+
780
+ ('priority:confidentiality', ('meta:priority', {}), {
781
+ 'doc': 'The priority of protecting the confidentiality of the asset.'}),
782
+
783
+ ('priority:integrity', ('meta:priority', {}), {
784
+ 'doc': 'The priority of protecting the integrity of the asset.'}),
785
+
786
+ ('priority:availability', ('meta:priority', {}), {
787
+ 'doc': 'The priority of protecting the availability of the asset.'}),
788
+
789
+ ('node', ('ndef', {}), {
790
+ 'doc': 'The node which represents the asset.'}),
791
+
792
+ ('place', ('geo:place', {}), {
793
+ 'doc': 'The place where the asset is deployed.'}),
794
+
795
+ ('owner', ('ps:contact', {}), {
796
+ 'doc': 'The contact information of the owner or administrator of the asset.'}),
797
+
798
+ ('operator', ('ps:contact', {}), {
799
+ 'doc': 'The contact information of the user or operator of the asset.'}),
800
+ )),
731
801
  ('ou:position', {}, (
732
802
  ('org', ('ou:org', {}), {
733
803
  'doc': 'The org which has the position.',
@@ -1213,11 +1283,15 @@ class OuModule(s_module.CoreModule):
1213
1283
  }),
1214
1284
  # TODO duration ('duration'
1215
1285
  )),
1286
+ ('ou:requirement:type:taxonomy', {}, ()),
1216
1287
  ('ou:requirement', {}, (
1217
1288
 
1218
1289
  ('name', ('str', {'lower': True, 'onespace': True}), {
1219
1290
  'doc': 'A name for the requirement.'}),
1220
1291
 
1292
+ ('type', ('ou:requirement:type:taxonomy', {}), {
1293
+ 'doc': 'The type of requirement.'}),
1294
+
1221
1295
  ('text', ('str', {}), {
1222
1296
  'disp': {'hint': 'text'},
1223
1297
  'doc': 'The text of the stated requirement.'}),
synapse/models/risk.py CHANGED
@@ -96,12 +96,17 @@ class RiskModule(s_module.CoreModule):
96
96
  ),
97
97
  },
98
98
  }),
99
+ ('risk:mitigation:type:taxonomy', ('taxonomy', {}), {
100
+ 'interaces': ('taxonomy',),
101
+ 'doc': 'A taxonomy of mitigation types.',
102
+ }),
99
103
  ('risk:mitigation', ('guid', {}), {
100
104
  'doc': 'A mitigation for a specific risk:vuln.',
101
105
  'display': {
102
106
  'columns': (
103
107
  {'type': 'prop', 'opts': {'name': 'name'}},
104
108
  {'type': 'prop', 'opts': {'name': 'reporter:name'}},
109
+ {'type': 'prop', 'opts': {'name': 'type'}},
105
110
  {'type': 'prop', 'opts': {'name': 'tag'}},
106
111
  ),
107
112
  },
@@ -198,9 +203,22 @@ class RiskModule(s_module.CoreModule):
198
203
  'doc': 'The tool uses the target node.'}),
199
204
  (('risk:compromise', 'stole', None), {
200
205
  'doc': 'The target node was stolen or copied as a result of the compromise.'}),
206
+
201
207
  (('risk:mitigation', 'addresses', 'ou:technique'), {
202
208
  'doc': 'The mitigation addresses the technique.'}),
203
209
 
210
+ (('risk:mitigation', 'uses', 'meta:rule'), {
211
+ 'doc': 'The mitigation uses the rule.'}),
212
+
213
+ (('risk:mitigation', 'uses', 'it:app:yara:rule'), {
214
+ 'doc': 'The mitigation uses the YARA rule.'}),
215
+
216
+ (('risk:mitigation', 'uses', 'it:app:snort:rule'), {
217
+ 'doc': 'The mitigation uses the Snort rule.'}),
218
+
219
+ (('risk:mitigation', 'uses', 'inet:service:rule'), {
220
+ 'doc': 'The mitigation uses the service rule.'}),
221
+
204
222
  (('risk:leak', 'leaked', None), {
205
223
  'doc': 'The leak included the disclosure of the target node.'}),
206
224
 
@@ -334,6 +352,7 @@ class RiskModule(s_module.CoreModule):
334
352
  'doc': 'A mapping to a MITRE ATT&CK software if applicable.'}),
335
353
 
336
354
  )),
355
+ ('risk:mitigation:type:taxonomy', {}, ()),
337
356
  ('risk:mitigation', {}, (
338
357
 
339
358
  ('vuln', ('risk:vuln', {}), {
@@ -342,6 +361,9 @@ class RiskModule(s_module.CoreModule):
342
361
  ('name', ('str', {'lower': True, 'onespace': True}), {
343
362
  'doc': 'A brief name for this risk mitigation.'}),
344
363
 
364
+ ('type', ('risk:mitigation:type:taxonomy', {}), {
365
+ 'doc': 'A taxonomy type entry for the mitigation.'}),
366
+
345
367
  ('desc', ('str', {}), {
346
368
  'disp': {'hint': 'text'},
347
369
  'doc': 'A description of the mitigation approach for the vulnerability.'}),
@@ -30,6 +30,16 @@ modules:
30
30
  returns:
31
31
  type: dict
32
32
  desc: A status dictionary.
33
+ - name: newp
34
+ desc: Some nonexistent function.
35
+ deprecated:
36
+ eolvers: v2.300.4
37
+ mesg: Newp is no longer maintained. Use bar() instead.
38
+ type:
39
+ type: function
40
+ returns:
41
+ type: 'null'
42
+ desc: '``newp()`` does not return data.'
33
43
 
34
44
  onload: |
35
45
  $lib.time.sleep($lib.globals.get(onload_sleep, 0))
@@ -2985,6 +2985,16 @@ class CortexBasicTest(s_t_utils.SynTest):
2985
2985
  info = await view.pack()
2986
2986
  self.eq(info['name'], 'default')
2987
2987
 
2988
+ depr = [x for x in coreinfo['stormdocs']['libraries'] if x['path'] == ('lib', 'bytes')]
2989
+ self.len(1, depr)
2990
+ deprinfo = depr[0].get('deprecated')
2991
+ self.nn(deprinfo)
2992
+ self.eq(deprinfo.get('eolvers'), 'v3.0.0')
2993
+
2994
+ depr = [x for x in coreinfo['stormdocs']['libraries'] if x['path'] == ('lib', 'infosec', 'cvss')]
2995
+ self.len(1, depr)
2996
+ self.len(2, [x for x in depr[0]['locals'] if x.get('deprecated')])
2997
+
2988
2998
  async def test_cortex_model_dict(self):
2989
2999
 
2990
3000
  async with self.getTestCoreAndProxy() as (core, prox):
@@ -3409,50 +3419,6 @@ class CortexBasicTest(s_t_utils.SynTest):
3409
3419
  self.eq(nodes[0].ndef, ('inet:ipv4', 0x01020304))
3410
3420
  self.nn(nodes[0].getTag('hehe.haha'))
3411
3421
 
3412
- async def test_storm_varlistset(self):
3413
-
3414
- async with self.getTestCore() as core:
3415
-
3416
- opts = {'vars': {'blob': ('vertex.link', '9001')}}
3417
- text = '($fqdn, $crap) = $blob [ inet:fqdn=$fqdn ]'
3418
-
3419
- nodes = await core.nodes(text, opts=opts)
3420
- self.len(1, nodes)
3421
- for node in nodes:
3422
- self.eq(node.ndef, ('inet:fqdn', 'vertex.link'))
3423
-
3424
- now = s_common.now()
3425
- ret = await core.callStorm('($foo, $bar)=$lib.cast(ival, $lib.time.now()) return($foo)')
3426
- self.ge(ret, now)
3427
-
3428
- text = '.created ($foo, $bar, $baz) = $blob'
3429
- with self.raises(s_exc.StormVarListError):
3430
- await core.nodes(text, opts)
3431
-
3432
- text = '($foo, $bar, $baz) = $blob'
3433
- with self.raises(s_exc.StormVarListError):
3434
- await core.nodes(text, opts)
3435
-
3436
- text = 'for ($x, $y) in ((1),) { $lib.print($x) }'
3437
- with self.raises(s_exc.StormVarListError):
3438
- await core.nodes(text)
3439
-
3440
- text = 'for ($x, $y) in ($lib.layer.get(),) { $lib.print($x) }'
3441
- with self.raises(s_exc.StormRuntimeError):
3442
- await core.nodes(text)
3443
-
3444
- text = '[test:str=foo] for ($x, $y) in ((1),) { $lib.print($x) }'
3445
- with self.raises(s_exc.StormVarListError):
3446
- await core.nodes(text)
3447
-
3448
- text = '[test:str=foo] for ($x, $y) in ((1),) { $lib.print($x) }'
3449
- with self.raises(s_exc.StormRuntimeError):
3450
- await core.nodes(text)
3451
-
3452
- text = '($x, $y) = (1)'
3453
- with self.raises(s_exc.StormRuntimeError):
3454
- await core.nodes(text)
3455
-
3456
3422
  async def test_storm_contbreak(self):
3457
3423
 
3458
3424
  async with self.getTestCore() as core:
@@ -3919,6 +3885,15 @@ class CortexBasicTest(s_t_utils.SynTest):
3919
3885
  opts['vars']['useriden'] = visi.iden
3920
3886
 
3921
3887
  await self.asyncraises(s_exc.AuthDeny, core.nodes('$lib.graph.del($iden2)', opts=uopts))
3888
+ await core.nodes('$lib.graph.grant($iden2, users, $useriden, 3)', opts=opts)
3889
+
3890
+ await core.nodes('$lib.graph.mod($iden2, ({"name": "newname"}))', opts=uopts)
3891
+ gdef = await core.callStorm('return($lib.graph.get($iden2))', opts=opts)
3892
+ self.eq(gdef['name'], 'newname')
3893
+
3894
+ await core.nodes('$lib.graph.revoke($iden2, users, $useriden)', opts=opts)
3895
+ await self.asyncraises(s_exc.AuthDeny, core.nodes('$lib.graph.mod($iden2, ({"name": "newp"}))', opts=uopts))
3896
+
3922
3897
  await core.nodes('$lib.graph.grant($iden2, users, $useriden, 3)', opts=opts)
3923
3898
  await core.nodes('$lib.graph.del($iden2)', opts=uopts)
3924
3899
 
@@ -4008,6 +3983,12 @@ class CortexBasicTest(s_t_utils.SynTest):
4008
3983
  async with self.getTestCore(dirn=dirn) as core:
4009
3984
  self.len(3, await core.callStorm('return($lib.graph.list())', opts=opts))
4010
3985
 
3986
+ gdef = await core.callStorm('return($lib.graph.add(({"name": "nodef"})))')
3987
+ self.eq(1, gdef['permissions']['default'])
3988
+
3989
+ gdef = await core.callStorm('return($lib.graph.add(({"name": "def", "permissions": {"default": 0}})))')
3990
+ self.eq(0, gdef['permissions']['default'])
3991
+
4011
3992
  async def test_storm_two_level_assignment(self):
4012
3993
  async with self.getTestCore() as core:
4013
3994
  q = '$foo=baz $bar=$foo [test:str=$bar]'
@@ -7195,6 +7176,12 @@ class CortexBasicTest(s_t_utils.SynTest):
7195
7176
  with self.raises(s_exc.BadTag):
7196
7177
  await core.nodes('[ inet:ipv4=1.2.3.4 +#cno.cve.12345 ]')
7197
7178
 
7179
+ nodes = await core.nodes('[ test:str=beep +?#cno.cve.12345 ]')
7180
+ self.len(1, nodes)
7181
+ self.none(nodes[0].get('#cno'))
7182
+ self.none(nodes[0].get('#cno.cve'))
7183
+ self.none(nodes[0].get('#cno.cve.12345'))
7184
+
7198
7185
  self.eq((None, None, '[0-9]{4}', '[0-9]{5}'), await core.callStorm('''
7199
7186
  return($lib.model.tags.pop(cno.cve, regex))
7200
7187
  '''))
@@ -4331,3 +4331,61 @@ class AstTest(s_test.SynTest):
4331
4331
  _assert_edge(msgs, small, {'type': 'prop', 'prop': 'ndefs', 'reverse': True}, nidx=1)
4332
4332
  _assert_edge(msgs, small, {'type': 'edge', 'verb': 'seen', 'reverse': True}, nidx=2)
4333
4333
  _assert_edge(msgs, small, {'type': 'edge', 'verb': 'someedge', 'reverse': True}, nidx=3)
4334
+
4335
+ async def test_ast_varlistset(self):
4336
+
4337
+ async with self.getTestCore() as core:
4338
+
4339
+ opts = {'vars': {'blob': ('vertex.link', '9001')}}
4340
+ text = '($fqdn, $crap) = $blob [ inet:fqdn=$fqdn ]'
4341
+
4342
+ nodes = await core.nodes(text, opts=opts)
4343
+ self.len(1, nodes)
4344
+ for node in nodes:
4345
+ self.eq(node.ndef, ('inet:fqdn', 'vertex.link'))
4346
+
4347
+ now = s_common.now()
4348
+ ret = await core.callStorm('($foo, $bar)=$lib.cast(ival, $lib.time.now()) return($foo)')
4349
+ self.ge(ret, now)
4350
+
4351
+ # The runtsafe invocation of the VarListSetOper is done per node.
4352
+ q = '''
4353
+ init { $count = ({ 'c': (0) }) }
4354
+ function foo(){
4355
+ $count.c = ( $count.c + (1) )
4356
+ return((a, b))
4357
+ }
4358
+ inet:fqdn=vertex.link
4359
+ ($a, $b) = $foo()
4360
+ fini { return ( $count ) }
4361
+ '''
4362
+ valu = await core.callStorm(q)
4363
+ self.eq(valu, {'c': 1})
4364
+
4365
+ text = '.created ($foo, $bar, $baz) = $blob'
4366
+ with self.raises(s_exc.StormVarListError):
4367
+ await core.nodes(text, opts)
4368
+
4369
+ text = '($foo, $bar, $baz) = $blob'
4370
+ with self.raises(s_exc.StormVarListError):
4371
+ await core.nodes(text, opts)
4372
+
4373
+ text = 'for ($x, $y) in ((1),) { $lib.print($x) }'
4374
+ with self.raises(s_exc.StormVarListError):
4375
+ await core.nodes(text)
4376
+
4377
+ text = 'for ($x, $y) in ($lib.layer.get(),) { $lib.print($x) }'
4378
+ with self.raises(s_exc.StormRuntimeError):
4379
+ await core.nodes(text)
4380
+
4381
+ text = '[test:str=foo] for ($x, $y) in ((1),) { $lib.print($x) }'
4382
+ with self.raises(s_exc.StormVarListError):
4383
+ await core.nodes(text)
4384
+
4385
+ text = '[test:str=foo] for ($x, $y) in ((1),) { $lib.print($x) }'
4386
+ with self.raises(s_exc.StormRuntimeError):
4387
+ await core.nodes(text)
4388
+
4389
+ text = '($x, $y) = (1)'
4390
+ with self.raises(s_exc.StormRuntimeError):
4391
+ await core.nodes(text)
@@ -1,4 +1,6 @@
1
1
  import copy
2
+
3
+ import synapse.exc as s_exc
2
4
  import synapse.lib.autodoc as s_autodoc
3
5
  import synapse.lib.stormtypes as s_stormtypes
4
6
 
@@ -153,6 +155,10 @@ LibTst for testing!
153
155
  beep(valu)
154
156
  ==========
155
157
 
158
+ .. warning::
159
+ ``$lib.test.beep`` has been deprecated and will be removed on or after 8080-08-08.
160
+
161
+
156
162
  Example storm func.
157
163
 
158
164
  Notes:
@@ -173,6 +179,11 @@ Returns:
173
179
  someargs(valu, bar=$lib.true, faz=$lib.null)
174
180
  ============================================
175
181
 
182
+ .. warning::
183
+ ``$lib.test.someargs`` has been deprecated and will be removed in version v3.0.0.
184
+ This is a test library was deprecated from the day it was made.
185
+
186
+
176
187
  Example storm func with args.
177
188
 
178
189
 
@@ -220,6 +231,10 @@ LibTst for testing!
220
231
  $lib.test.beep(valu)
221
232
  ====================
222
233
 
234
+ .. warning::
235
+ ``$lib.test.beep`` has been deprecated and will be removed on or after 8080-08-08.
236
+
237
+
223
238
  Example storm func.
224
239
 
225
240
  Notes:
@@ -240,6 +255,11 @@ Returns:
240
255
  $lib.test.someargs(valu, bar=$lib.true, faz=$lib.null)
241
256
  ======================================================
242
257
 
258
+ .. warning::
259
+ ``$lib.test.someargs`` has been deprecated and will be removed in version v3.0.0.
260
+ This is a test library was deprecated from the day it was made.
261
+
262
+
243
263
  Example storm func with args.
244
264
 
245
265
 
@@ -257,3 +277,68 @@ Args:
257
277
  Returns:
258
278
  The beeped string. The return type is ``str``.'''
259
279
  self.eq(text, expected)
280
+
281
+ badlocls = copy.deepcopy(libtst._storm_locals)
282
+ badlocls[0]['deprecated']['eolvers'] = 'v4.4.4'
283
+ page = s_autodoc.RstHelp()
284
+ doc = {
285
+ 'desc': s_stormtypes.getDoc(libtst, "err"),
286
+ 'path': ('lib',) + libtst._storm_lib_path,
287
+ 'locals': badlocls,
288
+ }
289
+ with self.raises(s_exc.SchemaViolation):
290
+ s_autodoc.docStormTypes(page, (doc,), linkprefix='test')
291
+
292
+ libdepr = s_t_utils.LibDepr
293
+ locls = copy.deepcopy(libdepr._storm_locals)
294
+ [obj.get('type', {}).pop('_funcname', None) for obj in locls]
295
+ doc = {
296
+ 'desc': s_stormtypes.getDoc(libdepr, "err"),
297
+ 'path': ('lib',) + libdepr._storm_lib_path,
298
+ 'locals': locls,
299
+ 'deprecated': libdepr._storm_lib_deprecation
300
+ }
301
+ page = s_autodoc.RstHelp()
302
+ page.addHead('Test')
303
+ page.addLines('I am a line.')
304
+ s_autodoc.docStormTypes(page, (doc,), linkprefix='test', islib=True)
305
+ text = page.getRstText()
306
+ expected = '''
307
+ ####
308
+ Test
309
+ ####
310
+
311
+ I am a line.
312
+
313
+
314
+ .. _test-lib-depr:
315
+
316
+ *********
317
+ $lib.depr
318
+ *********
319
+
320
+ Deprecate me!
321
+
322
+
323
+
324
+ .. _test-lib-depr-boop:
325
+
326
+ $lib.depr.boop(valu)
327
+ ====================
328
+
329
+ .. warning::
330
+ ``$lib.depr.boop`` has been deprecated and will be removed in version v3.0.0.
331
+
332
+
333
+ An example storm function that's not deprecated on its own, but the entire library is.
334
+
335
+
336
+
337
+ Args:
338
+ valu (str): What to boop.
339
+
340
+
341
+
342
+ Returns:
343
+ The booped. The return type is ``str``.'''
344
+ self.eq(text, expected)
@@ -3913,6 +3913,15 @@ class StormTest(s_t_utils.SynTest):
3913
3913
  self.stormIsInPrint('Returns an ou:org by name, adding the node if it does not exist.\n'
3914
3914
  'Args:\n name (str): The name of the org.', msgs)
3915
3915
 
3916
+ msgs = await core.stormlist('help --verbose $lib.infosec.cvss.saveVectToNode')
3917
+ self.stormIsInPrint('Warning', msgs)
3918
+ self.stormIsInPrint('``$lib.infosec.cvss.saveVectToNode`` has been deprecated and will be removed in version v3.0.0.', msgs)
3919
+
3920
+ msgs = await core.stormlist('help --verbose $lib.inet.whois.guid')
3921
+ self.stormIsInPrint('Warning', msgs)
3922
+ self.stormIsInPrint('``$lib.inet.whois.guid`` has been deprecated and will be removed in version v3.0.0.', msgs)
3923
+ self.stormIsInPrint('Please use the GUID constructor syntax.', msgs)
3924
+
3916
3925
  msgs = await core.stormlist('help $lib.inet')
3917
3926
  self.stormIsInPrint('The following libraries are available:\n\n'
3918
3927
  '$lib.inet.http : A Storm Library exposing an HTTP client API.\n'
@@ -3943,6 +3952,15 @@ class StormTest(s_t_utils.SynTest):
3943
3952
  msgs = await core.stormlist('$mod=$lib.import(foosmod) help $mod.f')
3944
3953
  self.stormIsInErr('help does not currently support runtime defined functions.', msgs)
3945
3954
 
3955
+ msgs = await core.stormlist('help --verbose $lib.bytes')
3956
+ self.stormIsInPrint('Warning', msgs)
3957
+ self.stormIsInPrint('$lib.bytes.put`` has been deprecated and will be removed in version v3.0.0', msgs)
3958
+ self.stormIsInPrint('$lib.bytes.has`` has been deprecated and will be removed in version v3.0.0', msgs)
3959
+ self.stormIsInPrint('$lib.bytes.size`` has been deprecated and will be removed in version v3.0.0', msgs)
3960
+ self.stormIsInPrint('$lib.bytes.upload`` has been deprecated and will be removed in version v3.0.0', msgs)
3961
+ self.stormIsInPrint('$lib.bytes.hashset`` has been deprecated and will be removed in version v3.0.0', msgs)
3962
+ self.stormIsInPrint('Use the corresponding ``$lib.axon`` function.', msgs)
3963
+
3946
3964
  async def test_liftby_edge(self):
3947
3965
  async with self.getTestCore() as core:
3948
3966
 
@@ -510,3 +510,55 @@ class StormtypesModelextTest(s_test.SynTest):
510
510
  with self.raises(s_exc.BadArg) as exc:
511
511
  await core.callStorm(query)
512
512
  self.eq(err, exc.exception.get('mesg'))
513
+
514
+ async def test_lib_stormlib_modelext_interfaces(self):
515
+ async with self.getTestCore() as core:
516
+
517
+ await core.callStorm('''
518
+ $forminfo = ({"interfaces": ["test:interface"]})
519
+ $lib.model.ext.addForm(_test:iface, str, ({}), $forminfo)
520
+ $lib.model.ext.addFormProp(_test:iface, tick, (time, ({})), ({}))
521
+ ''')
522
+
523
+ self.nn(core.model.form('_test:iface'))
524
+ self.nn(core.model.prop('_test:iface:flow'))
525
+ self.nn(core.model.prop('_test:iface:proc'))
526
+ self.nn(core.model.prop('_test:iface:tick'))
527
+ self.isin('_test:iface', core.model.formsbyiface['test:interface'])
528
+ self.isin('_test:iface', core.model.formsbyiface['inet:proto:request'])
529
+ self.isin('_test:iface', core.model.formsbyiface['it:host:activity'])
530
+ self.isin('_test:iface:flow', core.model.ifaceprops['inet:proto:request:flow'])
531
+ self.isin('_test:iface:proc', core.model.ifaceprops['test:interface:proc'])
532
+ self.isin('_test:iface:proc', core.model.ifaceprops['inet:proto:request:proc'])
533
+ self.isin('_test:iface:proc', core.model.ifaceprops['it:host:activity:proc'])
534
+
535
+ q = '$lib.model.ext.delForm(_test:iface)'
536
+ with self.raises(s_exc.CantDelForm) as exc:
537
+ await core.callStorm(q)
538
+ self.eq('Form has extended properties: tick', exc.exception.get('mesg'))
539
+
540
+ await core.callStorm('''
541
+ $lib.model.ext.delFormProp(_test:iface, tick)
542
+ $lib.model.ext.delForm(_test:iface)
543
+ ''')
544
+
545
+ self.none(core.model.form('_test:iface'))
546
+ self.none(core.model.prop('_test:iface:flow'))
547
+ self.none(core.model.prop('_test:iface:proc'))
548
+ self.none(core.model.prop('_test:iface:tick'))
549
+ self.notin('_test:iface', core.model.formsbyiface['test:interface'])
550
+ self.notin('_test:iface', core.model.formsbyiface['inet:proto:request'])
551
+ self.notin('_test:iface', core.model.formsbyiface['it:host:activity'])
552
+ self.notin('_test:iface:flow', core.model.ifaceprops['inet:proto:request:flow'])
553
+ self.notin('_test:iface:proc', core.model.ifaceprops['test:interface:proc'])
554
+ self.notin('_test:iface:proc', core.model.ifaceprops['inet:proto:request:proc'])
555
+ self.notin('_test:iface:proc', core.model.ifaceprops['it:host:activity:proc'])
556
+
557
+ await core.stormlist('''
558
+ $forminfo = ({"interfaces": ["newp"]})
559
+ $lib.model.ext.addForm(_test:iface, str, ({}), $forminfo)
560
+ ''')
561
+ self.nn(core.model.form('_test:iface'))
562
+
563
+ await core.callStorm('$lib.model.ext.delForm(_test:iface)')
564
+ self.none(core.model.form('_test:iface'))