synapse 2.211.0__py311-none-any.whl → 2.213.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/lib/cell.py CHANGED
@@ -3495,13 +3495,16 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
3495
3495
  await user.addRule(rule)
3496
3496
 
3497
3497
  @contextlib.asynccontextmanager
3498
- async def getLocalProxy(self, share='*', user='root'):
3498
+ async def getLocalProxy(self, share=None, user='root'):
3499
3499
  url = self.getLocalUrl(share=share, user=user)
3500
3500
  prox = await s_telepath.openurl(url)
3501
3501
  yield prox
3502
3502
 
3503
- def getLocalUrl(self, share='*', user='root'):
3504
- return f'cell://{user}@{self.dirn}:{share}'
3503
+ def getLocalUrl(self, share=None, user='root'):
3504
+ url = f'cell://{user}@{self.dirn}'
3505
+ if share is not None:
3506
+ url = f'{url}:{share}'
3507
+ return url
3505
3508
 
3506
3509
  def _initCellConf(self, conf):
3507
3510
  '''
synapse/lib/node.py CHANGED
@@ -207,8 +207,13 @@ class Node:
207
207
 
208
208
  embdnode = retn.get(nodepath)
209
209
  if embdnode is None:
210
- embdnode = retn[nodepath] = {}
211
- embdnode['*'] = s_common.ehex(node.buid)
210
+ iden = node.iden()
211
+ # TODO deprecate / remove use of * once we can minver optic
212
+ embdnode = retn[nodepath] = {
213
+ '*': iden,
214
+ '$iden': iden,
215
+ '$form': node.form.name,
216
+ }
212
217
 
213
218
  for relp in relprops:
214
219
  embdnode[relp] = node.props.get(relp)
synapse/lib/scrape.py CHANGED
@@ -65,6 +65,8 @@ inverse_prefixs = {
65
65
  '<': '>',
66
66
  '{': '}',
67
67
  '(': ')',
68
+ '\u2018': '\u2019', # Unicode Left Single Quotation Mark and Right Single Quotation Mark
69
+ '\u201c': '\u201d', # Unicode Left Double Quotation Mark and Right Double Quotation Mark
68
70
  }
69
71
 
70
72
  cve_dashes = ''.join(('-',) + s_chop.unicode_dashes)
@@ -287,7 +289,7 @@ def url_scheme_check(match: regex.Match):
287
289
  scrape_types = [ # type: ignore
288
290
  ('file:path', linux_path_regex, {'callback': linux_path_check, 'flags': regex.VERBOSE}),
289
291
  ('file:path', windows_path_regex, {'callback': windows_path_check, 'flags': regex.VERBOSE}),
290
- ('inet:url', r'(?P<prefix>[\\{<\(\[]?)(?P<valu>[a-zA-Z][a-zA-Z0-9]*://(?(?=[,.]+[ \'\"\t\n\r\f\v])|[^ \'\"\t\n\r\f\v])+)',
292
+ ('inet:url', r'(?P<prefix>[‘“\\{<\(\[]?)(?P<valu>[a-zA-Z][a-zA-Z0-9]*://(?(?=[,.]+[ \'\"\t\n\r\f\v])|[^ \'\"\t\n\r\f\v])+)',
291
293
  {'callback': url_scheme_check}),
292
294
  ('inet:url', r'(["\'])?(?P<valu>\\[^\n]+?)(?(1)\1|\s)', {'callback': unc_path_check}),
293
295
  ('inet:email', r'(?=(?:[^a-z0-9_.+-]|^)(?P<valu>[a-z0-9_\.\-+]{1,256}@(?:[a-z0-9_-]{1,63}\.){1,10}(?:%s))(?:[^a-z0-9_.-]|[.\s]|$))' % tldcat, {}),
synapse/lib/snap.py CHANGED
@@ -746,19 +746,25 @@ class Snap(s_base.Base):
746
746
 
747
747
  async def _joinEmbedStor(self, storage, embeds):
748
748
  for nodePath, relProps in embeds.items():
749
+
749
750
  await asyncio.sleep(0)
750
- iden = relProps.get('*')
751
+
752
+ iden = relProps.get('$iden')
751
753
  if not iden:
752
754
  continue
753
755
 
754
756
  stor = await self.view.getStorNodes(s_common.uhex(iden))
755
757
  for relProp in relProps.keys():
758
+
756
759
  await asyncio.sleep(0)
757
- if relProp == '*':
760
+
761
+ if relProp[0] in ('*', '$'):
758
762
  continue
759
763
 
760
764
  for idx, layrstor in enumerate(stor):
765
+
761
766
  await asyncio.sleep(0)
767
+
762
768
  props = layrstor.get('props')
763
769
  if not props:
764
770
  continue
@@ -1319,13 +1325,13 @@ class Snap(s_base.Base):
1319
1325
 
1320
1326
  if etyp == s_layer.EDIT_NODE_ADD:
1321
1327
  node.bylayer['ndef'] = wlyr.iden
1322
- callbacks.append((node.form.wasAdded, (node,), {}))
1323
- callbacks.append((self.view.runNodeAdd, (node,), {}))
1328
+ callbacks.append((node.form.wasAdded, (node,)))
1329
+ callbacks.append((self.view.runNodeAdd, (node,)))
1324
1330
  continue
1325
1331
 
1326
1332
  if etyp == s_layer.EDIT_NODE_DEL:
1327
- callbacks.append((node.form.wasDeleted, (node,), {}))
1328
- callbacks.append((self.view.runNodeDel, (node,), {}))
1333
+ callbacks.append((node.form.wasDeleted, (node,)))
1334
+ callbacks.append((self.view.runNodeDel, (node,)))
1329
1335
  continue
1330
1336
 
1331
1337
  if etyp == s_layer.EDIT_PROP_SET:
@@ -1340,8 +1346,8 @@ class Snap(s_base.Base):
1340
1346
  node.props[name] = valu
1341
1347
  node.bylayer['props'][name] = wlyr.iden
1342
1348
 
1343
- callbacks.append((prop.wasSet, (node, oldv), {}))
1344
- callbacks.append((self.view.runPropSet, (node, prop, oldv), {}))
1349
+ callbacks.append((prop.wasSet, (node, oldv)))
1350
+ callbacks.append((self.view.runPropSet, (node, prop, oldv)))
1345
1351
  continue
1346
1352
 
1347
1353
  if etyp == s_layer.EDIT_PROP_DEL:
@@ -1356,8 +1362,8 @@ class Snap(s_base.Base):
1356
1362
  node.props.pop(name, None)
1357
1363
  node.bylayer['props'].pop(name, None)
1358
1364
 
1359
- callbacks.append((prop.wasDel, (node, oldv), {}))
1360
- callbacks.append((self.view.runPropSet, (node, prop, oldv), {}))
1365
+ callbacks.append((prop.wasDel, (node, oldv)))
1366
+ callbacks.append((self.view.runPropSet, (node, prop, oldv)))
1361
1367
  continue
1362
1368
 
1363
1369
  if etyp == s_layer.EDIT_TAG_SET:
@@ -1367,8 +1373,7 @@ class Snap(s_base.Base):
1367
1373
  node.tags[tag] = valu
1368
1374
  node.bylayer['tags'][tag] = wlyr.iden
1369
1375
 
1370
- callbacks.append((self.view.runTagAdd, (node, tag, valu), {}))
1371
- callbacks.append((self.wlyr.fire, ('tag:add', ), {'tag': tag, 'node': node.iden()}))
1376
+ callbacks.append((self.view.runTagAdd, (node, tag, valu)))
1372
1377
  continue
1373
1378
 
1374
1379
  if etyp == s_layer.EDIT_TAG_DEL:
@@ -1378,8 +1383,7 @@ class Snap(s_base.Base):
1378
1383
  node.tags.pop(tag, None)
1379
1384
  node.bylayer['tags'].pop(tag, None)
1380
1385
 
1381
- callbacks.append((self.view.runTagDel, (node, tag, oldv), {}))
1382
- callbacks.append((self.wlyr.fire, ('tag:del', ), {'tag': tag, 'node': node.iden()}))
1386
+ callbacks.append((self.view.runTagDel, (node, tag, oldv)))
1383
1387
  continue
1384
1388
 
1385
1389
  if etyp == s_layer.EDIT_TAGPROP_SET:
@@ -1414,14 +1418,14 @@ class Snap(s_base.Base):
1414
1418
  if etyp == s_layer.EDIT_EDGE_ADD:
1415
1419
  verb, n2iden = parms
1416
1420
  n2 = await self.getNodeByBuid(s_common.uhex(n2iden))
1417
- callbacks.append((self.view.runEdgeAdd, (node, verb, n2), {}))
1421
+ callbacks.append((self.view.runEdgeAdd, (node, verb, n2)))
1418
1422
 
1419
1423
  if etyp == s_layer.EDIT_EDGE_DEL:
1420
1424
  verb, n2iden = parms
1421
1425
  n2 = await self.getNodeByBuid(s_common.uhex(n2iden))
1422
- callbacks.append((self.view.runEdgeDel, (node, verb, n2), {}))
1426
+ callbacks.append((self.view.runEdgeDel, (node, verb, n2)))
1423
1427
 
1424
- [await func(*args, **kwargs) for (func, args, kwargs) in callbacks]
1428
+ [await func(*args) for (func, args) in callbacks]
1425
1429
 
1426
1430
  if actualedits:
1427
1431
  await self.fire('node:edits', edits=actualedits)
@@ -134,7 +134,7 @@ class JsonLib(s_stormtypes.Lib):
134
134
 
135
135
  @s_stormtypes.stormfunc(readonly=True)
136
136
  async def _jsonSchema(self, schema, use_default=True):
137
- schema = await s_stormtypes.toprim(schema)
137
+ schema = await s_stormtypes.toprim(schema, use_list=True)
138
138
  use_default = await s_stormtypes.tobool(use_default)
139
139
  # We have to ensure that we have a valid schema for making the object.
140
140
  try:
@@ -107,3 +107,6 @@ class SpooledSet(s_stormtypes.Set):
107
107
 
108
108
  async def value(self):
109
109
  return set([x async for x in self.valu])
110
+
111
+ async def bool(self):
112
+ return bool(len(self.valu))
synapse/lib/stormtypes.py CHANGED
@@ -4731,6 +4731,9 @@ class Str(Prim):
4731
4731
  return str(self) == str(othr)
4732
4732
  return False
4733
4733
 
4734
+ async def bool(self):
4735
+ return bool(self.valu)
4736
+
4734
4737
  @stormfunc(readonly=True)
4735
4738
  async def _methStrFind(self, valu):
4736
4739
  text = await tostr(valu)
@@ -4970,6 +4973,9 @@ class Bytes(Prim):
4970
4973
  return self.valu == othr.valu
4971
4974
  return False
4972
4975
 
4976
+ async def bool(self):
4977
+ return bool(self.valu)
4978
+
4973
4979
  async def _storm_copy(self):
4974
4980
  item = await s_coro.ornot(self.value)
4975
4981
  return s_msgpack.deepcopy(item, use_list=True)
@@ -5042,6 +5048,9 @@ class Dict(Prim):
5042
5048
  def __len__(self):
5043
5049
  return len(self.valu)
5044
5050
 
5051
+ async def bool(self):
5052
+ return bool(self.valu)
5053
+
5045
5054
  async def _storm_copy(self):
5046
5055
  item = await s_coro.ornot(self.value)
5047
5056
  return s_msgpack.deepcopy(item, use_list=True)
@@ -5194,6 +5203,9 @@ class Set(Prim):
5194
5203
  def __len__(self):
5195
5204
  return len(self.valu)
5196
5205
 
5206
+ async def bool(self):
5207
+ return bool(self.valu)
5208
+
5197
5209
  async def _methSetSize(self):
5198
5210
  return len(self)
5199
5211
 
@@ -5384,6 +5396,9 @@ class List(Prim):
5384
5396
  def __len__(self):
5385
5397
  return len(self.valu)
5386
5398
 
5399
+ async def bool(self):
5400
+ return bool(self.valu)
5401
+
5387
5402
  @stormfunc(readonly=True)
5388
5403
  async def _methListHas(self, valu):
5389
5404
  if valu in self.valu:
@@ -5519,6 +5534,9 @@ class Bool(Prim):
5519
5534
  def __hash__(self):
5520
5535
  return hash((self._storm_typename, self.value()))
5521
5536
 
5537
+ async def bool(self):
5538
+ return bool(self.valu)
5539
+
5522
5540
  @registry.registerType
5523
5541
  class Number(Prim):
5524
5542
  '''
synapse/lib/types.py CHANGED
@@ -651,9 +651,10 @@ class Hex(Type):
651
651
 
652
652
  def postTypeInit(self):
653
653
  self._size = self.opts.get('size')
654
+ self._zeropad = self.opts.get('zeropad')
654
655
 
655
656
  # This is for backward compat with v2.142.x where zeropad was a bool
656
- self._zeropad = self.opts.get('zeropad')
657
+ # TODO: Remove this compat check in 3xx
657
658
  if isinstance(self._zeropad, bool):
658
659
  if self._zeropad:
659
660
  self._zeropad = self._size
@@ -678,6 +679,7 @@ class Hex(Type):
678
679
  if self._size:
679
680
  self._zeropad = min(self._zeropad, self._size)
680
681
 
682
+ self.setNormFunc(int, self._normPyInt)
681
683
  self.setNormFunc(str, self._normPyStr)
682
684
  self.setNormFunc(bytes, self._normPyBytes)
683
685
  self.storlifts.update({
@@ -703,21 +705,47 @@ class Hex(Type):
703
705
  return self._storLiftNorm(cmpr, valu)
704
706
 
705
707
  def _storLiftPref(self, cmpr, valu):
708
+ if not isinstance(valu, str):
709
+ vtyp = type(valu).__name__
710
+ mesg = f'Hex prefix lift values must be str, not {vtyp}.'
711
+ raise s_exc.BadTypeValu(mesg=mesg, type=vtyp, name=self.name)
712
+
706
713
  valu = self._preNormHex(valu)
707
714
  return (
708
715
  ('^=', valu, self.stortype),
709
716
  )
710
717
 
718
+ def _normPyInt(self, valu):
719
+ extra = 7
720
+ if valu < 0:
721
+ # Negative values need a little more space to store the sign
722
+ extra = 8
723
+
724
+ bytelen = max((valu.bit_length() + extra) // 8, self._zeropad // 2)
725
+
726
+ try:
727
+ byts = valu.to_bytes(bytelen, 'big', signed=(valu < 0))
728
+ hexval = s_common.ehex(byts)
729
+
730
+ except OverflowError as e: # pragma: no cover
731
+ mesg = f'Invalid width for {valu}.'
732
+ raise s_exc.BadTypeValu(mesg=mesg, name=self.name)
733
+
734
+ if self._size and len(hexval) != self._size:
735
+ raise s_exc.BadTypeValu(valu=valu, reqwidth=self._size, name=self.name,
736
+ mesg='Invalid width.')
737
+
738
+ return hexval, {}
739
+
711
740
  def _normPyStr(self, valu):
712
- valu = valu.strip().lower()
713
- if valu.startswith('0x'):
714
- valu = valu[2:]
741
+ valu = self._preNormHex(valu)
715
742
 
716
- valu = valu.replace(' ', '').replace(':', '')
743
+ if len(valu) % 2 != 0:
744
+ valu = f'0{valu}'
717
745
 
718
746
  if not valu:
719
- raise s_exc.BadTypeValu(valu=valu, name='hex',
720
- mesg='No string left after stripping')
747
+ raise s_exc.BadTypeValu(valu=valu, name=self.name,
748
+ mesg='No string left after stripping.')
721
749
 
722
750
  if self._zeropad and len(valu) < self._zeropad:
723
751
  padlen = self._zeropad - len(valu)
@@ -732,7 +760,7 @@ class Hex(Type):
732
760
 
733
761
  if self._size and len(valu) != self._size:
734
762
  raise s_exc.BadTypeValu(valu=valu, reqwidth=self._size, name=self.name,
735
- mesg='invalid width')
763
+ mesg='Invalid width.')
736
764
  return valu, {}
737
765
 
738
766
  def _normPyBytes(self, 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, 211, 0)
226
+ version = (2, 213, 0)
227
227
  verstring = '.'.join([str(x) for x in version])
228
- commit = '99beab651131ab996a967c6d0345c80b89de4a74'
228
+ commit = 'e3d843a470b137e9d2094b69a7878101afb4f8b1'
synapse/models/inet.py CHANGED
@@ -35,6 +35,10 @@ ipv4max = 2 ** 32 - 1
35
35
 
36
36
  rfc6598 = ipaddress.IPv4Network('100.64.0.0/10')
37
37
 
38
+ # defined from https://x.com/4A4133/status/1887269972545839559
39
+ ja4_regex = r'^([tqd])([sd\d]\d)([di])(\d{2})(\d{2})([a-zA-Z0-9]{2})_([0-9a-f]{12})_([0-9a-f]{12})$'
40
+ ja4s_regex = r'^([tq])([sd\d]\d)(\d{2})([a-zA-Z0-9]{2})_([0-9a-f]{4})_([0-9a-f]{12})$'
41
+
38
42
  def getAddrType(ip):
39
43
 
40
44
  if ip.is_multicast:
@@ -1678,6 +1682,18 @@ class InetModule(s_module.CoreModule):
1678
1682
  ('inet:tls:handshake', ('guid', {}), {
1679
1683
  'doc': 'An instance of a TLS handshake between a server and client.'}),
1680
1684
 
1685
+ ('inet:tls:ja4', ('str', {'strip': True, 'regex': ja4_regex}), {
1686
+ 'doc': 'A JA4 TLS client fingerprint.'}),
1687
+
1688
+ ('inet:tls:ja4s', ('str', {'strip': True, 'regex': ja4s_regex}), {
1689
+ 'doc': 'A JA4S TLS server fingerprint.'}),
1690
+
1691
+ ('inet:tls:ja4:sample', ('comp', {'fields': (('client', 'inet:client'), ('ja4', 'inet:tls:ja4'))}), {
1692
+ 'doc': 'A JA4 TLS client fingerprint used by a client.'}),
1693
+
1694
+ ('inet:tls:ja4s:sample', ('comp', {'fields': (('server', 'inet:server'), ('ja4s', 'inet:tls:ja4s'))}), {
1695
+ 'doc': 'A JA4S TLS server fingerprint used by a server.'}),
1696
+
1681
1697
  ('inet:tls:ja3s:sample', ('comp', {'fields': (('server', 'inet:server'), ('ja3s', 'hash:md5'))}), {
1682
1698
  'doc': 'A JA3 sample taken from a server.'}),
1683
1699
 
@@ -3565,23 +3581,70 @@ class InetModule(s_module.CoreModule):
3565
3581
  'doc': 'The server that was sampled to compute the JARM hash.'}),
3566
3582
  )),
3567
3583
 
3584
+ ('inet:tls:ja4', {}, ()),
3585
+ ('inet:tls:ja4s', {}, ()),
3586
+
3587
+ ('inet:tls:ja4:sample', {}, (
3588
+
3589
+ ('ja4', ('inet:tls:ja4', {}), {
3590
+ 'ro': True,
3591
+ 'doc': 'The JA4 TLS client fingerprint.'}),
3592
+
3593
+ ('client', ('inet:client', {}), {
3594
+ 'ro': True,
3595
+ 'doc': 'The client which initiated the TLS handshake with a JA4 fingerprint.'}),
3596
+ )),
3597
+
3598
+ ('inet:tls:ja4s:sample', {}, (
3599
+
3600
+ ('ja4s', ('inet:tls:ja4s', {}), {
3601
+ 'ro': True,
3602
+ 'doc': 'The JA4S TLS server fingerprint.'}),
3603
+
3604
+ ('server', ('inet:server', {}), {
3605
+ 'ro': True,
3606
+ 'doc': 'The server which responded to the TLS handshake with a JA4S fingerprint.'}),
3607
+ )),
3608
+
3568
3609
  ('inet:tls:handshake', {}, (
3610
+
3569
3611
  ('time', ('time', {}), {
3570
3612
  'doc': 'The time the handshake was initiated.'}),
3613
+
3571
3614
  ('flow', ('inet:flow', {}), {
3572
3615
  'doc': 'The raw inet:flow associated with the handshake.'}),
3616
+
3573
3617
  ('server', ('inet:server', {}), {
3574
3618
  'doc': 'The TLS server during the handshake.'}),
3619
+
3575
3620
  ('server:cert', ('crypto:x509:cert', {}), {
3576
3621
  'doc': 'The x509 certificate sent by the server during the handshake.'}),
3577
- ('server:fingerprint:ja3', ('hash:md5', {}), {
3578
- 'doc': 'The JA3S finger of the server.'}),
3622
+
3623
+ ('server:ja3s', ('hash:md5', {}), {
3624
+ 'doc': 'The JA3S fingerprint of the server response.'}),
3625
+
3626
+ ('server:ja4s', ('inet:tls:ja4s', {}), {
3627
+ 'doc': 'The JA4S fingerprint of the server response.'}),
3628
+
3579
3629
  ('client', ('inet:client', {}), {
3580
3630
  'doc': 'The TLS client during the handshake.'}),
3631
+
3581
3632
  ('client:cert', ('crypto:x509:cert', {}), {
3582
3633
  'doc': 'The x509 certificate sent by the client during the handshake.'}),
3634
+
3635
+ ('client:ja3', ('hash:md5', {}), {
3636
+ 'doc': 'The JA3 fingerprint of the client request.'}),
3637
+
3638
+ ('client:ja4', ('inet:tls:ja4', {}), {
3639
+ 'doc': 'The JA4 fingerprint of the client request.'}),
3640
+
3583
3641
  ('client:fingerprint:ja3', ('hash:md5', {}), {
3584
- 'doc': 'The JA3 fingerprint of the client.'}),
3642
+ 'deprecated': True,
3643
+ 'doc': 'Deprecated. Please use :client:ja3.'}),
3644
+
3645
+ ('server:fingerprint:ja3', ('hash:md5', {}), {
3646
+ 'deprecated': True,
3647
+ 'doc': 'Deprecated. Please use :server:ja3s.'}),
3585
3648
  )),
3586
3649
 
3587
3650
  ('inet:tls:ja3s:sample', {}, (
synapse/telepath.py CHANGED
@@ -1605,8 +1605,6 @@ async def openinfo(info):
1605
1605
  # cell://rel/path/to/celldir:share
1606
1606
  path = info.get('path')
1607
1607
 
1608
- name = info.get('name', '*')
1609
-
1610
1608
  # support cell://<relpath>/<to>/<cell>
1611
1609
  # by detecting host...
1612
1610
  host = info.get('host')
@@ -1614,9 +1612,12 @@ async def openinfo(info):
1614
1612
  path = path.strip('/')
1615
1613
  path = os.path.join(host, path)
1616
1614
 
1615
+ name = '*'
1617
1616
  if ':' in path:
1618
1617
  path, name = path.split(':')
1619
1618
 
1619
+ name = info.get('name', name)
1620
+
1620
1621
  full = os.path.join(path, 'sock')
1621
1622
  link = await s_link.unixconnect(full)
1622
1623
 
@@ -1626,6 +1627,7 @@ async def openinfo(info):
1626
1627
  path = info.get('path')
1627
1628
  if ':' in path:
1628
1629
  path, name = path.split(':')
1630
+ name = info.get('name', name)
1629
1631
  link = await s_link.unixconnect(path)
1630
1632
 
1631
1633
  elif scheme in ('tcp', 'ssl'):
@@ -194,6 +194,18 @@ testDataSchema_v1 = {
194
194
 
195
195
  class CellTest(s_t_utils.SynTest):
196
196
 
197
+ async def test_cell_getLocalUrl(self):
198
+ with self.getTestDir() as dirn:
199
+ async with self.getTestCell(dirn=dirn) as cell:
200
+ url = cell.getLocalUrl()
201
+ self.eq(url, f'cell://root@{dirn}')
202
+
203
+ url = cell.getLocalUrl(share='*/layer')
204
+ self.eq(url, f'cell://root@{dirn}:*/layer')
205
+
206
+ url = cell.getLocalUrl(user='lowuser', share='*/view')
207
+ self.eq(url, f'cell://lowuser@{dirn}:*/view')
208
+
197
209
  async def test_cell_drive(self):
198
210
 
199
211
  with self.getTestDir() as dirn:
@@ -2580,10 +2592,10 @@ class CellTest(s_t_utils.SynTest):
2580
2592
  viewiden = view.get('iden')
2581
2593
 
2582
2594
  opts = {'view': viewiden}
2583
- with self.getLoggerStream('synapse.lib.lmdbslab',
2595
+ with self.getAsyncLoggerStream('synapse.lib.lmdbslab',
2584
2596
  'Error during slab resize callback - foo') as stream:
2585
- nodes = await core.stormlist('for $x in $lib.range(200) {[inet:ipv4=$x]}', opts=opts)
2586
- self.true(stream.wait(1))
2597
+ msgs = await core.stormlist('for $x in $lib.range(200) {[test:int=$x]}', opts=opts)
2598
+ self.true(await stream.wait(timeout=30))
2587
2599
 
2588
2600
  async with self.getTestCore() as core:
2589
2601
 
@@ -164,8 +164,8 @@ class ConfTest(s_test.SynTest):
164
164
  # We can ensure that certain vars are loaded
165
165
  self.eq('Funky string time!', conf.req('key:string'))
166
166
  # And throw if they are not, or if the requested key isn't even schema valid
167
- self.raises(s_exc.NeedConfValu, conf.reqConfValu, 'key:bool:nodefval')
168
- self.raises(s_exc.BadArg, conf.reqConfValu, 'key:newp')
167
+ self.raises(s_exc.NeedConfValu, conf.req, 'key:bool:nodefval')
168
+ self.raises(s_exc.BadArg, conf.req, 'key:newp')
169
169
 
170
170
  # Since we're an Mutable mapping, we have some dict methods available to us
171
171
  self.len(8, conf) # __len__
@@ -380,6 +380,12 @@ class ConfTest(s_test.SynTest):
380
380
  self.eq(item['key:number'], 123)
381
381
  self.notin('key:string', item)
382
382
 
383
+ item = validator({'key:multi': 123})
384
+ self.eq(item['key:multi'], 123)
385
+
386
+ item = validator({'key:multi': '123'})
387
+ self.eq(item['key:multi'], '123')
388
+
383
389
  async def test_config_ref_handler(self):
384
390
 
385
391
  filename = pathlib.Path(s_data.path(
@@ -1399,8 +1399,8 @@ class LayerTest(s_t_utils.SynTest):
1399
1399
  self.len(1, nodes)
1400
1400
  self.eq(nodes[0].ndef, ('inet:ipv4', 0x01020304))
1401
1401
  self.eq(nodes[0].get('asn'), 33)
1402
- self.true(nodes[0].getTag('foo.bar'), (None, None))
1403
- self.true(nodes[0].getTagProp('foo.bar', 'confidence'), 22)
1402
+ self.eq(nodes[0].getTag('foo.bar'), (None, None))
1403
+ self.eq(nodes[0].getTagProp('foo.bar', 'confidence'), 100)
1404
1404
 
1405
1405
  self.eq(10004, await core.count('.created'))
1406
1406
  self.len(2, await core.nodes('syn:tag~=foo'))
@@ -203,6 +203,10 @@ A bunch of prefixed urls
203
203
 
204
204
  https://c2server.com/evil/malware/doesnot[care+]aboutstandards{at-all}
205
205
 
206
+ beep “https://unicode.doublequote.org/test.php” boop
207
+
208
+ x ‘https://unicode.singlequote.org/test.php’ z
209
+
206
210
  '''
207
211
 
208
212
  data3 = '''
@@ -725,6 +729,8 @@ class ScrapeTest(s_t_utils.SynTest):
725
729
  nodes.remove(('inet:url', 'https://www.thingspace.com/blog/giggles.html'))
726
730
  nodes.remove(('inet:url', 'https://testme.org/test.php'))
727
731
  nodes.remove(('inet:url', 'https://c2server.com/evil/malware/doesnot[care+]aboutstandards{at-all}'))
732
+ nodes.remove(('inet:url', 'https://unicode.doublequote.org/test.php'))
733
+ nodes.remove(('inet:url', 'https://unicode.singlequote.org/test.php'))
728
734
 
729
735
  nodes = list(s_scrape.scrape(btc_addresses))
730
736
  self.len(11, nodes)
@@ -1736,6 +1736,8 @@ class StormTest(s_t_utils.SynTest):
1736
1736
  self.stormHasNoErr(await core.stormlist('merge --diff', opts=altview))
1737
1737
 
1738
1738
  oldn = await core.nodes('[ ou:name=readonly ]', opts=altview)
1739
+ # need to pause a moment so the created times differ
1740
+ await asyncio.sleep(0.01)
1739
1741
  newn = await core.nodes('[ ou:name=readonly ]')
1740
1742
  self.ne(oldn[0].props['.created'], newn[0].props['.created'])
1741
1743
 
@@ -2251,16 +2253,18 @@ class StormTest(s_t_utils.SynTest):
2251
2253
  nodes = [m[1] for m in msgs if m[0] == 'node']
2252
2254
 
2253
2255
  node = nodes[0]
2256
+ self.eq('inet:asn', node[1]['embeds']['asn']['$form'])
2254
2257
  self.eq('hehe', node[1]['embeds']['asn']['name'])
2255
- self.eq('796d67b92a6ffe9b88fa19d115b46ab6712d673a06ae602d41de84b1464782f2', node[1]['embeds']['asn']['*'])
2258
+ self.eq('796d67b92a6ffe9b88fa19d115b46ab6712d673a06ae602d41de84b1464782f2', node[1]['embeds']['asn']['$iden'])
2256
2259
 
2257
2260
  opts = {'embeds': {'ou:org': {'hq::email': ('user',)}}}
2258
2261
  msgs = await core.stormlist('[ ou:org=* :country=* :hq=* ] { -> ps:contact [ :email=visi@vertex.link ] }', opts=opts)
2259
2262
  nodes = [m[1] for m in msgs if m[0] == 'node']
2260
2263
  node = nodes[0]
2261
2264
 
2265
+ self.eq('inet:email', node[1]['embeds']['hq::email']['$form'])
2262
2266
  self.eq('visi', node[1]['embeds']['hq::email']['user'])
2263
- self.eq('2346d7bed4b0fae05e00a413bbf8716c9e08857eb71a1ecf303b8972823f2899', node[1]['embeds']['hq::email']['*'])
2267
+ self.eq('2346d7bed4b0fae05e00a413bbf8716c9e08857eb71a1ecf303b8972823f2899', node[1]['embeds']['hq::email']['$iden'])
2264
2268
 
2265
2269
  fork = await core.callStorm('return($lib.view.get().fork().iden)')
2266
2270
 
@@ -2373,10 +2377,17 @@ class StormTest(s_t_utils.SynTest):
2373
2377
  self.eq(['inet:service:rule', 'risk:vulnerable'], [n[0][0] for n in nodes])
2374
2378
 
2375
2379
  embeds = nodes[0][1]['embeds']
2380
+
2381
+ self.nn(embeds['object']['$iden'])
2382
+ self.eq('risk:vulnerable', embeds['object']['$form'])
2376
2383
  self.eq(1, embeds['object']['mitigated'])
2377
2384
  self.eq(None, embeds['object']['newp'])
2385
+
2386
+ self.nn(embeds['object::node']['$iden'])
2387
+ self.eq('it:prod:hardware', embeds['object::node']['$form'])
2378
2388
  self.eq('foohw', embeds['object::node']['name'])
2379
2389
  self.eq(None, embeds['object::node']['newp'])
2390
+ self.eq('inet:service:account', embeds['grantee']['$form'])
2380
2391
  self.eq('foocon', embeds['grantee']['id'])
2381
2392
  self.eq(None, embeds['grantee']['newp'])
2382
2393
 
@@ -642,9 +642,9 @@ class StormHttpTest(s_test.SynTest):
642
642
  self.isin('connect to proxy 127.0.0.1:1', resp['mesg'])
643
643
 
644
644
  q = '$resp=$lib.inet.http.get("http://vertex.link") return(($resp.code, $resp.err))'
645
- code, (errname, _) = await core.callStorm(q)
645
+ code, (errname, errinfo) = await core.callStorm(q)
646
646
  self.eq(code, -1)
647
- self.eq('ProxyConnectionError', errname)
647
+ self.isin("connect to proxy 127.0.0.1:1", errinfo.get('mesg'))
648
648
 
649
649
  msgs = await core.stormlist('$resp=$lib.inet.http.get("http://vertex.link", proxy=(null)) $lib.print($resp.err)')
650
650
  self.stormIsInWarn('HTTP proxy argument to $lib.null is deprecated', msgs)
@@ -669,7 +669,7 @@ class StormHttpTest(s_test.SynTest):
669
669
  self.stormIsInErr(errmsg.format(perm='storm.lib.inet.http.proxy'), msgs)
670
670
 
671
671
  resp = await core.callStorm('return($lib.inet.http.get(http://vertex.link, proxy=socks5://user:pass@127.0.0.1:1))')
672
- self.eq('ProxyConnectionError', resp['err'][0])
672
+ self.isin("connect to proxy 127.0.0.1:1", resp['err'][1].get('mesg'))
673
673
 
674
674
  # test $lib.axon proxy API
675
675
  asvisi = {'user': visi.iden}
@@ -748,13 +748,13 @@ class StormHttpTest(s_test.SynTest):
748
748
  opts = {'vars': {'proxy': 'socks5://user:pass@127.0.0.1:1'}, 'user': visi.iden}
749
749
 
750
750
  resp = await core.callStorm(q1, opts=opts)
751
- self.eq('ProxyConnectionError', resp['err'][0])
751
+ self.isin("connect to proxy 127.0.0.1:1", resp['err'][1].get('mesg'))
752
752
 
753
753
  resp = await core.callStorm(q2, opts=opts)
754
- self.eq('ProxyConnectionError', resp['err'][0])
754
+ self.isin("connect to proxy 127.0.0.1:1", resp['err'][1].get('mesg'))
755
755
 
756
756
  resp = await core.callStorm(q3, opts=opts)
757
- self.eq('ProxyConnectionError', resp['err'][0])
757
+ self.isin("connect to proxy 127.0.0.1:1", resp['err'][1].get('mesg'))
758
758
 
759
759
  opts = {'vars': {'proxy': False}, 'user': visi.iden}
760
760