synapse 2.168.0__py311-none-any.whl → 2.170.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 (42) hide show
  1. synapse/cortex.py +99 -10
  2. synapse/datamodel.py +5 -0
  3. synapse/lib/agenda.py +3 -0
  4. synapse/lib/ast.py +70 -12
  5. synapse/lib/cell.py +83 -21
  6. synapse/lib/httpapi.py +3 -0
  7. synapse/lib/layer.py +75 -6
  8. synapse/lib/node.py +7 -0
  9. synapse/lib/snap.py +25 -5
  10. synapse/lib/storm.py +1 -1
  11. synapse/lib/stormlib/cortex.py +1 -1
  12. synapse/lib/stormlib/model.py +420 -1
  13. synapse/lib/stormtypes.py +68 -3
  14. synapse/lib/types.py +35 -0
  15. synapse/lib/version.py +2 -2
  16. synapse/lib/view.py +94 -24
  17. synapse/models/files.py +40 -0
  18. synapse/models/inet.py +8 -4
  19. synapse/models/infotech.py +355 -17
  20. synapse/tests/files/cpedata.json +525034 -0
  21. synapse/tests/test_cortex.py +99 -0
  22. synapse/tests/test_lib_agenda.py +17 -3
  23. synapse/tests/test_lib_ast.py +66 -0
  24. synapse/tests/test_lib_cell.py +133 -52
  25. synapse/tests/test_lib_layer.py +52 -1
  26. synapse/tests/test_lib_scrape.py +72 -71
  27. synapse/tests/test_lib_snap.py +16 -1
  28. synapse/tests/test_lib_storm.py +118 -0
  29. synapse/tests/test_lib_stormlib_cortex.py +27 -0
  30. synapse/tests/test_lib_stormlib_model.py +532 -0
  31. synapse/tests/test_lib_stormtypes.py +161 -14
  32. synapse/tests/test_lib_types.py +20 -0
  33. synapse/tests/test_lib_view.py +77 -0
  34. synapse/tests/test_model_files.py +51 -0
  35. synapse/tests/test_model_inet.py +63 -1
  36. synapse/tests/test_model_infotech.py +187 -26
  37. synapse/tests/utils.py +12 -0
  38. {synapse-2.168.0.dist-info → synapse-2.170.0.dist-info}/METADATA +1 -1
  39. {synapse-2.168.0.dist-info → synapse-2.170.0.dist-info}/RECORD +42 -41
  40. {synapse-2.168.0.dist-info → synapse-2.170.0.dist-info}/LICENSE +0 -0
  41. {synapse-2.168.0.dist-info → synapse-2.170.0.dist-info}/WHEEL +0 -0
  42. {synapse-2.168.0.dist-info → synapse-2.170.0.dist-info}/top_level.txt +0 -0
synapse/lib/view.py CHANGED
@@ -196,10 +196,6 @@ class View(s_nexus.Pusher): # type: ignore
196
196
  async def _setMergeRequest(self, mergeinfo):
197
197
  self.reqParentQuorum()
198
198
 
199
- if self.hasKids():
200
- mesg = 'Cannot add a merge request to a view with children.'
201
- raise s_exc.BadState(mesg=mesg)
202
-
203
199
  s_schemas.reqValidMerge(mergeinfo)
204
200
  lkey = self.bidn + b'merge:req'
205
201
  self.core.slab.put(lkey, s_msgpack.en(mergeinfo), db='view:meta')
@@ -450,8 +446,7 @@ class View(s_nexus.Pusher): # type: ignore
450
446
  await self.core.feedBeholder('view:merge:fini', {'view': self.iden, 'merge': merge, 'merge': merge, 'votes': votes})
451
447
 
452
448
  # remove the view and top layer
453
- await self.core.delView(self.iden)
454
- await self.core.delLayer(self.layers[0].iden)
449
+ await self.core.delViewWithLayer(self.iden)
455
450
 
456
451
  except Exception as e: # pragma: no cover
457
452
  logger.exception(f'Error while merging view: {self.iden}')
@@ -868,20 +863,16 @@ class View(s_nexus.Pusher): # type: ignore
868
863
 
869
864
  self.layers.append(layr)
870
865
 
871
- async def eval(self, text, opts=None, log_info=None):
866
+ async def eval(self, text, opts=None):
872
867
  '''
873
868
  Evaluate a storm query and yield Nodes only.
874
869
  '''
875
870
  opts = self.core._initStormOpts(opts)
876
871
  user = self.core._userFromOpts(opts)
877
872
 
878
- if log_info is None:
879
- log_info = {}
880
-
881
- log_info['mode'] = opts.get('mode', 'storm')
882
- log_info['view'] = self.iden
883
-
884
- self.core._logStormQuery(text, user, info=log_info)
873
+ info = opts.get('_loginfo', {})
874
+ info.update({'mode': opts.get('mode', 'storm'), 'view': self.iden})
875
+ self.core._logStormQuery(text, user, info=info)
885
876
 
886
877
  taskiden = opts.get('task')
887
878
  taskinfo = {'query': text, 'view': self.iden}
@@ -997,8 +988,9 @@ class View(s_nexus.Pusher): # type: ignore
997
988
  count += 1
998
989
 
999
990
  else:
1000
- self.core._logStormQuery(text, user,
1001
- info={'mode': opts.get('mode', 'storm'), 'view': self.iden})
991
+ info = opts.get('_loginfo', {})
992
+ info.update({'mode': opts.get('mode', 'storm'), 'view': self.iden})
993
+ self.core._logStormQuery(text, user, info=info)
1002
994
  async for item in snap.storm(text, opts=opts, user=user):
1003
995
  count += 1
1004
996
 
@@ -1115,10 +1107,6 @@ class View(s_nexus.Pusher): # type: ignore
1115
1107
  mesg = 'Circular dependency of view parents is not supported.'
1116
1108
  raise s_exc.BadArg(mesg=mesg)
1117
1109
 
1118
- if parent.getMergeRequest() is not None:
1119
- mesg = 'You may not set the parent to a view with a pending merge request.'
1120
- raise s_exc.BadState(mesg=mesg)
1121
-
1122
1110
  if self.parent is not None:
1123
1111
  if self.parent.iden == parent.iden:
1124
1112
  return valu
@@ -1257,6 +1245,92 @@ class View(s_nexus.Pusher): # type: ignore
1257
1245
 
1258
1246
  todo.append(child)
1259
1247
 
1248
+ async def insertParentFork(self, useriden, name=None):
1249
+ '''
1250
+ Insert a new View between a forked View and its parent.
1251
+
1252
+ Returns:
1253
+ New view definition with the same perms as the current fork.
1254
+ '''
1255
+ if not self.isafork():
1256
+ mesg = f'View ({self.iden}) is not a fork, cannot insert a new fork between it and parent.'
1257
+ raise s_exc.BadState(mesg=mesg)
1258
+
1259
+ ctime = s_common.now()
1260
+ layriden = s_common.guid()
1261
+
1262
+ ldef = {
1263
+ 'iden': layriden,
1264
+ 'created': ctime,
1265
+ 'creator': useriden,
1266
+ 'lockmemory': self.core.conf.get('layers:lockmemory'),
1267
+ 'logedits': self.core.conf.get('layers:logedits'),
1268
+ 'readonly': False
1269
+ }
1270
+
1271
+ vdef = {
1272
+ 'iden': s_common.guid(),
1273
+ 'created': ctime,
1274
+ 'creator': useriden,
1275
+ 'parent': self.parent.iden,
1276
+ 'layers': [layriden] + [lyr.iden for lyr in self.parent.layers]
1277
+ }
1278
+
1279
+ if name is not None:
1280
+ vdef['name'] = name
1281
+
1282
+ s_layer.reqValidLdef(ldef)
1283
+ s_schemas.reqValidView(vdef)
1284
+
1285
+ return await self._push('view:forkparent', ldef, vdef)
1286
+
1287
+ @s_nexus.Pusher.onPush('view:forkparent', passitem=True)
1288
+ async def _insertParentFork(self, ldef, vdef, nexsitem):
1289
+
1290
+ s_layer.reqValidLdef(ldef)
1291
+ s_schemas.reqValidView(vdef)
1292
+
1293
+ if self.getMergeRequest() is not None:
1294
+ await self._delMergeRequest()
1295
+
1296
+ await self.core._addLayer(ldef, nexsitem)
1297
+ await self.core._addView(vdef)
1298
+
1299
+ forkiden = vdef.get('iden')
1300
+ self.parent = self.core.reqView(forkiden)
1301
+ await self.info.set('parent', forkiden)
1302
+
1303
+ await self._calcForkLayers()
1304
+
1305
+ for view in self.core.views.values():
1306
+ if view.isForkOf(self.iden):
1307
+ await view._calcForkLayers()
1308
+
1309
+ self.core._calcViewsByLayer()
1310
+
1311
+ authgate = await self.core.getAuthGate(self.iden)
1312
+ if authgate is None: # pragma: no cover
1313
+ return await self.parent.pack()
1314
+
1315
+ for userinfo in authgate.get('users'):
1316
+ useriden = userinfo.get('iden')
1317
+ if (user := self.core.auth.user(useriden)) is None: # pragma: no cover
1318
+ logger.warning(f'View {self.iden} AuthGate refers to unknown user {useriden}')
1319
+ continue
1320
+
1321
+ await user.setRules(userinfo.get('rules'), gateiden=forkiden, nexs=False)
1322
+ await user.setAdmin(userinfo.get('admin'), gateiden=forkiden, logged=False)
1323
+
1324
+ for roleinfo in authgate.get('roles'):
1325
+ roleiden = roleinfo.get('iden')
1326
+ if (role := self.core.auth.role(roleiden)) is None: # pragma: no cover
1327
+ logger.warning(f'View {self.iden} AuthGate refers to unknown role {roleiden}')
1328
+ continue
1329
+
1330
+ await role.setRules(roleinfo.get('rules'), gateiden=forkiden, nexs=False)
1331
+
1332
+ return await self.parent.pack()
1333
+
1260
1334
  async def fork(self, ldef=None, vdef=None):
1261
1335
  '''
1262
1336
  Make a new view inheriting from this view with the same layers and a new write layer on top
@@ -1275,10 +1349,6 @@ class View(s_nexus.Pusher): # type: ignore
1275
1349
  if vdef is None:
1276
1350
  vdef = {}
1277
1351
 
1278
- if self.getMergeRequest() is not None:
1279
- mesg = 'Cannot fork a view which has a merge request.'
1280
- raise s_exc.BadState(mesg=mesg)
1281
-
1282
1352
  ldef = await self.core.addLayer(ldef)
1283
1353
  layriden = ldef.get('iden')
1284
1354
 
synapse/models/files.py CHANGED
@@ -408,6 +408,9 @@ class FileModule(s_module.CoreModule):
408
408
  'doc': 'A section inside a Mach-O binary denoting a named region of bytes inside a segment.',
409
409
  }),
410
410
 
411
+ ('file:mime:lnk', ('guid', {}), {
412
+ 'doc': 'The GUID of the metadata pulled from a Windows shortcut or LNK file.',
413
+ }),
411
414
  ),
412
415
 
413
416
  'forms': (
@@ -699,6 +702,43 @@ class FileModule(s_module.CoreModule):
699
702
  'doc': 'The file offset to the beginning of the section'}),
700
703
  )),
701
704
 
705
+ ('file:mime:lnk', {}, (
706
+ ('flags', ('int', {}), {
707
+ 'doc': 'The flags specified by the LNK header that control the structure of the LNK file.'}),
708
+ ('entry:primary', ('file:path', {}), {
709
+ 'doc': 'The primary file path contained within the FileEntry structure of the LNK file.'}),
710
+ ('entry:secondary', ('file:path', {}), {
711
+ 'doc': 'The secondary file path contained within the FileEntry structure of the LNK file.'}),
712
+ ('entry:extended', ('file:path', {}), {
713
+ 'doc': 'The extended file path contained within the extended FileEntry structure of the LNK file.'}),
714
+ ('entry:localized', ('file:path', {}), {
715
+ 'doc': 'The localized file path contained within the extended FileEntry structure of the LNK file.'}),
716
+ ('entry:icon', ('file:path', {}), {
717
+ 'doc': 'The icon file path contained within the StringData structure of the LNK file.'}),
718
+ ('environment:path', ('file:path', {}), {
719
+ 'doc': 'The target file path contained within the EnvironmentVariableDataBlock structure of the LNK file.'}),
720
+ ('environment:icon', ('file:path', {}), {
721
+ 'doc': 'The icon file path contained within the IconEnvironmentDataBlock structure of the LNK file.'}),
722
+ ('working', ('file:path', {}), {
723
+ 'doc': 'The working directory used when activating the link target.'}),
724
+ ('relative', ('str', {'strip': True}), {
725
+ 'doc': 'The relative target path string contained within the StringData structure of the LNK file.'}),
726
+ ('arguments', ('it:cmd', {}), {
727
+ 'doc': 'The command line arguments passed to the target file when the LNK file is activated.'}),
728
+ ('desc', ('str', {}), {
729
+ 'disp': {'hint': 'text'},
730
+ 'doc': 'The description of the LNK file contained within the StringData section of the LNK file.'}),
731
+ ('target:attrs', ('int', {}), {
732
+ 'doc': 'The attributes of the target file according to the LNK header.'}),
733
+ ('target:size', ('int', {}), {
734
+ 'doc': 'The size of the target file according to the LNK header. The LNK format specifies that this is only the lower 32 bits of the target file size.'}),
735
+ ('target:created', ('time', {}), {
736
+ 'doc': 'The creation time of the target file according to the LNK header.'}),
737
+ ('target:accessed', ('time', {}), {
738
+ 'doc': 'The access time of the target file according to the LNK header.'}),
739
+ ('target:written', ('time', {}), {
740
+ 'doc': 'The write time of the target file according to the LNK header.'}),
741
+ )),
702
742
  ),
703
743
 
704
744
  }
synapse/models/inet.py CHANGED
@@ -23,7 +23,7 @@ import synapse.lookup.iana as s_l_iana
23
23
  logger = logging.getLogger(__name__)
24
24
  drivre = regex.compile(r'^\w[:|]')
25
25
  fqdnre = regex.compile(r'^[\w._-]+$', regex.U)
26
- srv6re = regex.compile(r'^\[([a-f0-9\.:]+)\]:(\d+)$')
26
+ srv6re = regex.compile(r'^\[([a-f0-9\.:]+)\](?::(\d+))?$', regex.IGNORECASE)
27
27
 
28
28
  udots = regex.compile(r'[\u3002\uff0e\uff61]')
29
29
 
@@ -142,11 +142,15 @@ class Addr(s_types.Str):
142
142
  if v6v4addr is not None:
143
143
  subs['ipv4'] = v6v4addr
144
144
 
145
- port = self.modl.type('inet:port').norm(port)[0]
146
145
  subs['ipv6'] = ipv6
147
- subs['port'] = port
148
146
 
149
- return f'{proto}://[{ipv6}]:{port}', {'subs': subs}
147
+ portstr = ''
148
+ if port is not None:
149
+ port = self.modl.type('inet:port').norm(port)[0]
150
+ subs['port'] = port
151
+ portstr = f':{port}'
152
+
153
+ return f'{proto}://[{ipv6}]{portstr}', {'subs': subs}
150
154
 
151
155
  mesg = f'Invalid IPv6 w/port ({orig})'
152
156
  raise s_exc.BadTypeValu(valu=orig, name=self.name, mesg=mesg)