synapse 2.178.0__py311-none-any.whl → 2.180.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 (62) hide show
  1. synapse/cortex.py +166 -31
  2. synapse/datamodel.py +47 -1
  3. synapse/exc.py +1 -0
  4. synapse/lib/aha.py +2 -1
  5. synapse/lib/ast.py +110 -76
  6. synapse/lib/base.py +12 -3
  7. synapse/lib/cell.py +150 -11
  8. synapse/lib/coro.py +14 -0
  9. synapse/lib/drive.py +551 -0
  10. synapse/lib/layer.py +1 -1
  11. synapse/lib/lmdbslab.py +2 -0
  12. synapse/lib/modelrev.py +5 -1
  13. synapse/lib/node.py +14 -4
  14. synapse/lib/schemas.py +97 -0
  15. synapse/lib/snap.py +36 -11
  16. synapse/lib/storm.py +9 -5
  17. synapse/lib/stormhttp.py +1 -0
  18. synapse/lib/stormlib/modelext.py +29 -3
  19. synapse/lib/stormlib/stix.py +44 -17
  20. synapse/lib/stormlib/vault.py +2 -2
  21. synapse/lib/stormtypes.py +1 -1
  22. synapse/lib/types.py +9 -0
  23. synapse/lib/version.py +2 -2
  24. synapse/lookup/pe.py +303 -38
  25. synapse/models/auth.py +2 -0
  26. synapse/models/dns.py +24 -1
  27. synapse/models/geopol.py +3 -0
  28. synapse/models/geospace.py +4 -1
  29. synapse/models/inet.py +1 -0
  30. synapse/models/infotech.py +135 -92
  31. synapse/models/person.py +5 -2
  32. synapse/models/telco.py +3 -0
  33. synapse/tests/test_cortex.py +45 -1
  34. synapse/tests/test_lib_aha.py +17 -0
  35. synapse/tests/test_lib_ast.py +231 -0
  36. synapse/tests/test_lib_cell.py +225 -0
  37. synapse/tests/test_lib_coro.py +12 -0
  38. synapse/tests/test_lib_layer.py +22 -0
  39. synapse/tests/test_lib_modelrev.py +7 -0
  40. synapse/tests/test_lib_node.py +12 -1
  41. synapse/tests/test_lib_storm.py +32 -7
  42. synapse/tests/test_lib_stormhttp.py +40 -0
  43. synapse/tests/test_lib_stormlib_modelext.py +55 -3
  44. synapse/tests/test_lib_stormlib_stix.py +15 -0
  45. synapse/tests/test_lib_stormlib_vault.py +11 -1
  46. synapse/tests/test_lib_stormtypes.py +5 -0
  47. synapse/tests/test_lib_types.py +9 -0
  48. synapse/tests/test_model_dns.py +8 -0
  49. synapse/tests/test_model_geopol.py +2 -0
  50. synapse/tests/test_model_geospace.py +3 -1
  51. synapse/tests/test_model_inet.py +10 -1
  52. synapse/tests/test_model_infotech.py +47 -0
  53. synapse/tests/test_model_person.py +2 -0
  54. synapse/tests/test_model_syn.py +11 -0
  55. synapse/tests/test_model_telco.py +2 -1
  56. synapse/tests/test_utils_stormcov.py +1 -1
  57. synapse/tools/changelog.py +28 -0
  58. {synapse-2.178.0.dist-info → synapse-2.180.0.dist-info}/METADATA +1 -1
  59. {synapse-2.178.0.dist-info → synapse-2.180.0.dist-info}/RECORD +62 -61
  60. {synapse-2.178.0.dist-info → synapse-2.180.0.dist-info}/WHEEL +1 -1
  61. {synapse-2.178.0.dist-info → synapse-2.180.0.dist-info}/LICENSE +0 -0
  62. {synapse-2.178.0.dist-info → synapse-2.180.0.dist-info}/top_level.txt +0 -0
synapse/lib/schemas.py CHANGED
@@ -274,6 +274,7 @@ reqValidSslCtxOpts = s_config.getJsValidator({
274
274
  'verify': {'type': 'boolean', 'default': True},
275
275
  'client_cert': {'type': ['string', 'null'], 'default': None},
276
276
  'client_key': {'type': ['string', 'null'], 'default': None},
277
+ 'ca_cert': {'type': ['string', 'null'], 'default': None},
277
278
  },
278
279
  'additionalProperties': False,
279
280
  })
@@ -454,3 +455,99 @@ tabularConfSchema = {
454
455
  }
455
456
 
456
457
  reqValidTabularConf = s_config.getJsValidator(tabularConfSchema)
458
+
459
+ emptySchema = {'object': {}, 'additionalProperties': False}
460
+ re_drivename = r'^[\w_.-]{1,128}$'
461
+
462
+ driveInfoSchema = {
463
+ 'type': 'object',
464
+ 'properties': {
465
+ 'iden': {'type': 'string', 'pattern': s_config.re_iden},
466
+ 'parent': {'type': 'string', 'pattern': s_config.re_iden},
467
+ 'type': {'type': 'string', 'pattern': re_drivename},
468
+ 'name': {'type': 'string', 'pattern': re_drivename},
469
+ 'perm': s_msgpack.deepcopy(easyPermSchema),
470
+ 'kids': {'type': 'number', 'minimum': 0},
471
+ 'created': {'type': 'number'},
472
+ 'creator': {'type': 'string', 'pattern': s_config.re_iden},
473
+ # these are also data version info...
474
+ 'size': {'type': 'number', 'minimum': 0},
475
+ 'updated': {'type': 'number'},
476
+ 'updater': {'type': 'string', 'pattern': s_config.re_iden},
477
+ 'version': {'type': 'array', 'items': {'type': 'number', 'minItems': 3, 'maxItems': 3}},
478
+ },
479
+ 'required': ('iden', 'parent', 'name', 'created', 'creator', 'kids'),
480
+ 'additionalProperties': False,
481
+ }
482
+ reqValidDriveInfo = s_config.getJsValidator(driveInfoSchema)
483
+
484
+ driveDataVersSchema = {
485
+ 'type': 'object',
486
+ 'properties': {
487
+ 'size': {'type': 'number', 'minimum': 0},
488
+ 'updated': {'type': 'number'},
489
+ 'updater': {'type': 'string', 'pattern': s_config.re_iden},
490
+ 'version': {'type': 'array', 'items': {'type': 'number', 'minItems': 3, 'maxItems': 3}},
491
+ },
492
+ 'required': ('size', 'version', 'updated', 'updater'),
493
+ 'additionalProperties': False,
494
+ }
495
+ reqValidDriveDataVers = s_config.getJsValidator(driveDataVersSchema)
496
+
497
+ stixIngestConfigSchema = {
498
+ 'type': 'object',
499
+ 'properties': {
500
+ 'bundle': {
501
+ 'type': ['object', 'null'],
502
+ 'properties': {'storm': {'type': 'string'}},
503
+ },
504
+ 'objects': {
505
+ 'type': 'object',
506
+ 'properties': {'storm': {'type': 'string'}},
507
+ },
508
+ 'relationships': {
509
+ 'type': 'array',
510
+ 'items': {
511
+ 'type': 'object',
512
+ 'properties': {
513
+ 'type': {
514
+ 'type': 'array',
515
+ 'items': {
516
+ 'type': ['string', 'null'],
517
+ 'minItems': 3,
518
+ 'maxItems': 3,
519
+ },
520
+ },
521
+ 'storm': {'type': 'string'},
522
+ },
523
+ 'required': ['type'],
524
+ },
525
+ },
526
+ },
527
+ 'required': ['bundle', 'objects'],
528
+ }
529
+ reqValidStixIngestConfig = s_config.getJsValidator(stixIngestConfigSchema)
530
+
531
+ stixIngestBundleSchema = {
532
+ 'type': 'object',
533
+ 'properties': {
534
+ 'objects': {
535
+ 'type': 'array',
536
+ 'items': {
537
+ 'type': 'object',
538
+ 'properties': {
539
+ 'id': {'type': 'string'},
540
+ 'type': {'type': 'string'},
541
+ 'object_refs': {'type': 'array', 'items': {'type': 'string'}},
542
+ 'relationship_type': {'type': 'string'},
543
+ 'source_ref': {'type': 'string'},
544
+ 'target_ref': {'type': 'string'},
545
+ },
546
+ 'required': ['id', 'type'],
547
+ 'if': {'properties': {'type': {'const': 'relationship'}}},
548
+ 'then': {'required': ['source_ref', 'target_ref']},
549
+ }
550
+ },
551
+ },
552
+ }
553
+ reqValidStixIngestBundle = s_config.getJsValidator(stixIngestBundleSchema)
synapse/lib/snap.py CHANGED
@@ -316,6 +316,10 @@ class ProtoNode:
316
316
  mesg = f'Tagprop {name} does not exist in this Cortex.'
317
317
  return await self.ctx.snap._raiseOnStrict(s_exc.NoSuchTagProp, mesg)
318
318
 
319
+ if prop.locked:
320
+ mesg = f'Tagprop {name} is locked.'
321
+ return await self.ctx.snap._raiseOnStrict(s_exc.IsDeprLocked, mesg)
322
+
319
323
  try:
320
324
  norm, info = prop.type.norm(valu)
321
325
  except s_exc.BadTypeValu as e:
@@ -732,6 +736,7 @@ class Snap(s_base.Base):
732
736
 
733
737
  dorepr = False
734
738
  dopath = False
739
+ dolink = False
735
740
 
736
741
  show_storage = False
737
742
 
@@ -750,6 +755,7 @@ class Snap(s_base.Base):
750
755
  if opts is not None:
751
756
  dorepr = opts.get('repr', False)
752
757
  dopath = opts.get('path', False)
758
+ dolink = opts.get('links', False)
753
759
  show_storage = opts.get('show:storage', False)
754
760
 
755
761
  async for node, path in self.storm(text, opts=opts, user=user):
@@ -757,6 +763,9 @@ class Snap(s_base.Base):
757
763
  pode = node.pack(dorepr=dorepr)
758
764
  pode[1]['path'] = await path.pack(path=dopath)
759
765
 
766
+ if dolink:
767
+ pode[1]['links'] = path.links
768
+
760
769
  if show_storage:
761
770
  pode[1]['storage'] = await node.getStorNodes()
762
771
 
@@ -1029,7 +1038,7 @@ class Snap(s_base.Base):
1029
1038
  if node is not None:
1030
1039
  yield node
1031
1040
 
1032
- async def nodesByPropValu(self, full, cmpr, valu, reverse=False):
1041
+ async def nodesByPropValu(self, full, cmpr, valu, reverse=False, norm=True):
1033
1042
  if cmpr == 'type=':
1034
1043
  if reverse:
1035
1044
  async for node in self.nodesByPropTypeValu(full, valu, reverse=reverse):
@@ -1050,10 +1059,13 @@ class Snap(s_base.Base):
1050
1059
  mesg = f'No property named "{full}".'
1051
1060
  raise s_exc.NoSuchProp(mesg=mesg)
1052
1061
 
1053
- cmprvals = prop.type.getStorCmprs(cmpr, valu)
1054
- # an empty return probably means ?= with invalid value
1055
- if not cmprvals:
1056
- return
1062
+ if norm:
1063
+ cmprvals = prop.type.getStorCmprs(cmpr, valu)
1064
+ # an empty return probably means ?= with invalid value
1065
+ if not cmprvals:
1066
+ return
1067
+ else:
1068
+ cmprvals = ((cmpr, valu, prop.type.stortype),)
1057
1069
 
1058
1070
  if prop.isrunt:
1059
1071
  for storcmpr, storvalu, _ in cmprvals:
@@ -1108,7 +1120,7 @@ class Snap(s_base.Base):
1108
1120
  async for node in self.nodesByPropArray(prop.full, '=', valu, reverse=reverse):
1109
1121
  yield node
1110
1122
 
1111
- async def nodesByPropArray(self, full, cmpr, valu, reverse=False):
1123
+ async def nodesByPropArray(self, full, cmpr, valu, reverse=False, norm=True):
1112
1124
 
1113
1125
  prop = self.core.model.prop(full)
1114
1126
  if prop is None:
@@ -1119,7 +1131,10 @@ class Snap(s_base.Base):
1119
1131
  mesg = f'Array syntax is invalid on non array type: {prop.type.name}.'
1120
1132
  raise s_exc.BadTypeValu(mesg=mesg)
1121
1133
 
1122
- cmprvals = prop.type.arraytype.getStorCmprs(cmpr, valu)
1134
+ if norm:
1135
+ cmprvals = prop.type.arraytype.getStorCmprs(cmpr, valu)
1136
+ else:
1137
+ cmprvals = ((cmpr, valu, prop.type.arraytype.stortype),)
1123
1138
 
1124
1139
  if prop.isform:
1125
1140
  async for (buid, sodes) in self.core._liftByPropArray(prop.name, None, cmprvals, self.layers, reverse=reverse):
@@ -1602,18 +1617,28 @@ class Snap(s_base.Base):
1602
1617
  last = verb
1603
1618
  yield verb
1604
1619
 
1605
- async def getNdefRefs(self, buid):
1620
+ async def _getLayrNdefProp(self, layr, buid):
1621
+ async for refsbuid, refsabrv in layr.getNdefRefs(buid):
1622
+ yield refsbuid, layr.getAbrvProp(refsabrv)
1623
+
1624
+ async def getNdefRefs(self, buid, props=False):
1606
1625
  last = None
1607
- gens = [layr.getNdefRefs(buid) for layr in self.layers]
1626
+ if props:
1627
+ gens = [self._getLayrNdefProp(layr, buid) for layr in self.layers]
1628
+ else:
1629
+ gens = [layr.getNdefRefs(buid) for layr in self.layers]
1608
1630
 
1609
- async for refsbuid, _ in s_common.merggenr2(gens):
1631
+ async for refsbuid, xtra in s_common.merggenr2(gens):
1610
1632
  if refsbuid == last:
1611
1633
  continue
1612
1634
 
1613
1635
  await asyncio.sleep(0)
1614
1636
  last = refsbuid
1615
1637
 
1616
- yield refsbuid
1638
+ if props:
1639
+ yield refsbuid, xtra[1]
1640
+ else:
1641
+ yield refsbuid
1617
1642
 
1618
1643
  async def hasNodeData(self, buid, name):
1619
1644
  '''
synapse/lib/storm.py CHANGED
@@ -53,7 +53,9 @@ When condition is tag:add or tag:del, you may optionally provide a form name
53
53
  to restrict the trigger to fire only on tags added or deleted from nodes of
54
54
  those forms.
55
55
 
56
- The added tag is provided to the query as an embedded variable '$tag'.
56
+ The added tag is provided to the query in the ``$auto`` dictionary variable under
57
+ ``$auto.opts.tag``. Usage of the ``$tag`` variable is deprecated and it will no longer
58
+ be populated in Synapse v3.0.0.
57
59
 
58
60
  Simple one level tag globbing is supported, only at the end after a period,
59
61
  that is aka.* matches aka.foo and aka.bar but not aka.foo.bar. aka* is not
@@ -5375,7 +5377,7 @@ class TeeCmd(Cmd):
5375
5377
 
5376
5378
  outq = asyncio.Queue(maxsize=outq_size)
5377
5379
  for subr in runts:
5378
- subg = s_common.agen((node, path.fork(node)))
5380
+ subg = s_common.agen((node, path.fork(node, None)))
5379
5381
  self.runt.snap.schedCoro(self.pipeline(subr, outq, genr=subg))
5380
5382
 
5381
5383
  exited = 0
@@ -5397,7 +5399,7 @@ class TeeCmd(Cmd):
5397
5399
  else:
5398
5400
 
5399
5401
  for subr in runts:
5400
- subg = s_common.agen((node, path.fork(node)))
5402
+ subg = s_common.agen((node, path.fork(node, None)))
5401
5403
  async for subitem in subr.execute(genr=subg):
5402
5404
  yield subitem
5403
5405
 
@@ -5551,6 +5553,7 @@ class ScrapeCmd(Cmd):
5551
5553
  if not todo:
5552
5554
  todo = list(node.props.values())
5553
5555
 
5556
+ link = {'type': 'scrape'}
5554
5557
  for text in todo:
5555
5558
 
5556
5559
  text = str(text)
@@ -5560,7 +5563,7 @@ class ScrapeCmd(Cmd):
5560
5563
  continue
5561
5564
 
5562
5565
  nnode = await node.snap.addNode(form, valu)
5563
- npath = path.fork(nnode)
5566
+ npath = path.fork(nnode, link)
5564
5567
 
5565
5568
  if refs:
5566
5569
  if node.form.isrunt:
@@ -5664,8 +5667,9 @@ class LiftByVerb(Cmd):
5664
5667
 
5665
5668
  yield _node, _path
5666
5669
 
5670
+ link = {'type': 'runtime'}
5667
5671
  async for node in self.iterEdgeNodes(verb, idenset, n2):
5668
- yield node, _path.fork(node)
5672
+ yield node, _path.fork(node, link)
5669
5673
 
5670
5674
  class EdgesDelCmd(Cmd):
5671
5675
  '''
synapse/lib/stormhttp.py CHANGED
@@ -95,6 +95,7 @@ class LibHttp(s_stormtypes.Lib):
95
95
  'verify': <bool> - Perform SSL/TLS verification. Is overridden by the ssl_verify argument.
96
96
  'client_cert': <str> - PEM encoded full chain certificate for use in mTLS.
97
97
  'client_key': <str> - PEM encoded key for use in mTLS. Alternatively, can be included in client_cert.
98
+ 'ca_cert': <str> - A PEM encoded full chain CA certificate for use when verifying the request.
98
99
  }
99
100
  '''
100
101
  _storm_locals = (
@@ -1,4 +1,5 @@
1
1
  import synapse.exc as s_exc
2
+ import synapse.common as s_common
2
3
  import synapse.lib.grammar as s_grammar
3
4
 
4
5
  import synapse.lib.stormtypes as s_stormtypes
@@ -54,6 +55,8 @@ class LibModelExt(s_stormtypes.Lib):
54
55
  'args': (
55
56
  {'name': 'formname', 'type': 'str', 'desc': 'The form with the extended property.', },
56
57
  {'name': 'propname', 'type': 'str', 'desc': 'The extended property to remove.', },
58
+ {'name': 'force', 'type': 'boolean', 'default': False,
59
+ 'desc': 'Delete the property from all nodes before removing the definition.', },
57
60
  ),
58
61
  'returns': {'type': 'null', }}},
59
62
  {'name': 'delUnivProp',
@@ -61,12 +64,16 @@ class LibModelExt(s_stormtypes.Lib):
61
64
  'type': {'type': 'function', '_funcname': 'delUnivProp',
62
65
  'args': (
63
66
  {'name': 'propname', 'type': 'str', 'desc': 'Name of the universal property to remove.', },
67
+ {'name': 'force', 'type': 'boolean', 'default': False,
68
+ 'desc': 'Delete the property from all nodes before removing the definition.', },
64
69
  ),
65
70
  'returns': {'type': 'null', }}},
66
71
  {'name': 'delTagProp', 'desc': 'Remove an extended tag property definition from the model.',
67
72
  'type': {'type': 'function', '_funcname': 'delTagProp',
68
73
  'args': (
69
74
  {'name': 'propname', 'type': 'str', 'desc': 'Name of the tag property to remove.', },
75
+ {'name': 'force', 'type': 'boolean', 'default': False,
76
+ 'desc': 'Delete the tag property from all nodes before removing the definition.', },
70
77
  ),
71
78
  'returns': {'type': 'null', }}},
72
79
  {'name': 'getExtModel', 'desc': 'Get all extended model elements.',
@@ -163,20 +170,39 @@ class LibModelExt(s_stormtypes.Lib):
163
170
  s_stormtypes.confirm(('model', 'form', 'del', formname))
164
171
  await self.runt.snap.core.delForm(formname)
165
172
 
166
- async def delFormProp(self, formname, propname):
173
+ async def delFormProp(self, formname, propname, force=False):
167
174
  formname = await s_stormtypes.tostr(formname)
168
175
  propname = await s_stormtypes.tostr(propname)
176
+ force = await s_stormtypes.tobool(force)
169
177
  s_stormtypes.confirm(('model', 'prop', 'del', formname))
178
+
179
+ if force is True:
180
+ meta = {'user': self.runt.snap.user.iden, 'time': s_common.now()}
181
+ await self.runt.snap.core._delAllFormProp(formname, propname, meta)
182
+
170
183
  await self.runt.snap.core.delFormProp(formname, propname)
171
184
 
172
- async def delUnivProp(self, propname):
185
+ async def delUnivProp(self, propname, force=False):
173
186
  propname = await s_stormtypes.tostr(propname)
187
+ force = await s_stormtypes.tobool(force)
174
188
  s_stormtypes.confirm(('model', 'univ', 'del'))
189
+
190
+ if force:
191
+ meta = {'user': self.runt.snap.user.iden, 'time': s_common.now()}
192
+ await self.runt.snap.core._delAllUnivProp(propname, meta)
193
+
175
194
  await self.runt.snap.core.delUnivProp(propname)
176
195
 
177
- async def delTagProp(self, propname):
196
+ async def delTagProp(self, propname, force=False):
178
197
  propname = await s_stormtypes.tostr(propname)
198
+ force = await s_stormtypes.tobool(force)
199
+
179
200
  s_stormtypes.confirm(('model', 'tagprop', 'del'))
201
+
202
+ if force:
203
+ meta = {'user': self.runt.snap.user.iden, 'time': s_common.now()}
204
+ await self.runt.snap.core._delAllTagProp(propname, meta)
205
+
180
206
  await self.runt.snap.core.delTagProp(propname)
181
207
 
182
208
  @s_stormtypes.stormfunc(readonly=True)
@@ -11,6 +11,7 @@ import synapse.common as s_common
11
11
  import synapse.lib.coro as s_coro
12
12
  import synapse.lib.node as s_node
13
13
  import synapse.lib.msgpack as s_msgpack
14
+ import synapse.lib.schemas as s_schemas
14
15
  import synapse.lib.stormctrl as s_stormctrl
15
16
  import synapse.lib.stormtypes as s_stormtypes
16
17
 
@@ -875,14 +876,19 @@ class LibStixImport(s_stormtypes.Lib):
875
876
  bundle = await s_stormtypes.toprim(bundle)
876
877
  config = await s_stormtypes.toprim(config)
877
878
 
879
+ if not isinstance(config, dict):
880
+ mesg = 'STIX ingest config must be a dictionary.'
881
+ raise s_exc.BadArg(mesg=mesg)
882
+
878
883
  config.setdefault('bundle', {})
879
884
  config.setdefault('objects', {})
880
885
  config.setdefault('relationships', [])
881
886
 
882
- rellook = {r['type']: r for r in config.get('relationships', ())}
883
-
884
- nodesbyid = {}
885
- relationships = []
887
+ try:
888
+ rellook = {r['type']: r for r in config.get('relationships', ())}
889
+ except Exception as e:
890
+ mesg = f'Error processing relationships in STIX bundle ingest config: {e}.'
891
+ raise s_exc.BadArg(mesg=mesg)
886
892
 
887
893
  bundlenode = None
888
894
 
@@ -890,13 +896,44 @@ class LibStixImport(s_stormtypes.Lib):
890
896
  if bundleconf is None:
891
897
  bundleconf = {}
892
898
 
899
+ if not isinstance(bundleconf, dict):
900
+ mesg = 'STIX ingest config bundle value must be a dictionary.'
901
+ raise s_exc.BadArg(mesg=mesg)
902
+
893
903
  bundlestorm = bundleconf.get('storm')
894
904
  if bundlestorm:
905
+ if not isinstance(bundlestorm, str):
906
+ mesg = 'STIX ingest config storm query must be a string.'
907
+ raise s_exc.BadArg(mesg=mesg)
908
+
895
909
  bundlenode = await self._callStorm(bundlestorm, {'bundle': bundle})
896
910
 
897
911
  self.runt.layerConfirm(('node', 'edge', 'add', 'refs'))
898
912
 
899
- for obj in bundle.get('objects'):
913
+ config = s_schemas.reqValidStixIngestConfig(config)
914
+ bundle = s_schemas.reqValidStixIngestBundle(bundle)
915
+
916
+ try:
917
+ nodesbyid = await self._ingestObjects(bundle, config, rellook)
918
+ except Exception as e:
919
+ mesg = f'Error processing objects in STIX bundle ingest: {e}.'
920
+ raise s_exc.BadArg(mesg=mesg)
921
+
922
+ if bundlenode is not None:
923
+ for node in nodesbyid.values():
924
+ await bundlenode.addEdge('refs', node.iden())
925
+ await asyncio.sleep(0)
926
+ yield bundlenode
927
+
928
+ for node in nodesbyid.values():
929
+ yield node
930
+
931
+ async def _ingestObjects(self, bundle, config, rellook):
932
+
933
+ nodesbyid = {}
934
+ relationships = []
935
+
936
+ for obj in bundle.get('objects', ()):
900
937
 
901
938
  objtype = obj.get('type')
902
939
 
@@ -971,7 +1008,7 @@ class LibStixImport(s_stormtypes.Lib):
971
1008
  await self.runt.snap.warnonce(f'STIX bundle ingest has no relationship definition for: {reltype}.')
972
1009
 
973
1010
  # attempt to resolve object_refs
974
- for obj in bundle.get('objects'):
1011
+ for obj in bundle.get('objects', ()):
975
1012
 
976
1013
  node = nodesbyid.get(obj.get('id'))
977
1014
  if node is None:
@@ -984,17 +1021,7 @@ class LibStixImport(s_stormtypes.Lib):
984
1021
 
985
1022
  await node.addEdge('refs', refsnode.iden())
986
1023
 
987
- if bundlenode is not None:
988
- for node in nodesbyid.values():
989
- await bundlenode.addEdge('refs', node.iden())
990
- await asyncio.sleep(0)
991
- yield bundlenode
992
-
993
- for node in nodesbyid.values():
994
- yield node
995
-
996
- if bundlenode:
997
- yield bundlenode
1024
+ return nodesbyid
998
1025
 
999
1026
  async def _callStorm(self, text, varz):
1000
1027
 
@@ -649,7 +649,7 @@ class Vault(s_stormtypes.Prim):
649
649
  'type': {'type': 'function', '_funcname': '_methSetPerm',
650
650
  'args': (
651
651
  {'name': 'iden', 'type': 'str', 'desc': 'The user or role to modify.'},
652
- {'name': 'level', 'type': 'str', 'desc': 'The easyperm level for the iden. $lib.undef to remove an existing permission.'},
652
+ {'name': 'level', 'type': 'str', 'desc': 'The easyperm level for the iden. $lib.null to remove an existing permission.'},
653
653
  ),
654
654
  'returns': {'type': 'boolean', 'desc': '$lib.true if the permission was set, $lib.false otherwise.', }}},
655
655
 
@@ -744,7 +744,7 @@ class Vault(s_stormtypes.Prim):
744
744
  s_stormtypes.confirmEasyPerm(vault, s_cell.PERM_ADMIN, mesg=mesg)
745
745
 
746
746
  iden = await s_stormtypes.tostr(iden)
747
- level = await s_stormtypes.toint(level)
747
+ level = await s_stormtypes.toint(level, noneok=True)
748
748
 
749
749
  return await self.runt.snap.core.setVaultPerm(self.valu, iden, level)
750
750
 
synapse/lib/stormtypes.py CHANGED
@@ -5277,7 +5277,7 @@ class Number(Prim):
5277
5277
  def __init__(self, valu, path=None):
5278
5278
  try:
5279
5279
  valu = s_common.hugenum(valu)
5280
- except decimal.DecimalException as e:
5280
+ except (TypeError, decimal.DecimalException) as e:
5281
5281
  mesg = f'Failed to make number from {valu!r}'
5282
5282
  raise s_exc.BadCast(mesg=mesg) from e
5283
5283
 
synapse/lib/types.py CHANGED
@@ -1,3 +1,4 @@
1
+ import sys
1
2
  import asyncio
2
3
  import decimal
3
4
  import logging
@@ -78,6 +79,14 @@ class Type:
78
79
 
79
80
  self.postTypeInit()
80
81
 
82
+ normopts = dict(self.opts)
83
+ for optn, valu in normopts.items():
84
+ if isinstance(valu, float):
85
+ normopts[optn] = str(valu)
86
+
87
+ ctor = '.'.join([self.__class__.__module__, self.__class__.__qualname__])
88
+ self.typehash = sys.intern(s_common.guid((ctor, s_common.flatten(normopts))))
89
+
81
90
  def _storLiftSafe(self, cmpr, valu):
82
91
  try:
83
92
  return self.storlifts['=']('=', valu)
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, 178, 0)
226
+ version = (2, 180, 0)
227
227
  verstring = '.'.join([str(x) for x in version])
228
- commit = '56bad29e241893b702ea437d500a0229e8e1956b'
228
+ commit = 'aecbb8c0839f3ad763076dd7acae968fae6ba8b7'