synapse 2.201.0__py311-none-any.whl → 2.203.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/axon.py +4 -4
- synapse/cmds/cortex.py +4 -6
- synapse/cmds/hive.py +10 -10
- synapse/common.py +17 -58
- synapse/cortex.py +36 -29
- synapse/data/__init__.py +3 -2
- synapse/data/iana.uris.mpk +1 -0
- synapse/lib/autodoc.py +3 -3
- synapse/lib/base.py +2 -12
- synapse/lib/cell.py +9 -13
- synapse/lib/cli.py +2 -2
- synapse/lib/config.py +2 -2
- synapse/lib/encoding.py +4 -3
- synapse/lib/httpapi.py +7 -11
- synapse/lib/json.py +224 -0
- synapse/lib/lmdbslab.py +1 -1
- synapse/lib/oauth.py +176 -54
- synapse/lib/parser.py +2 -1
- synapse/lib/rstorm.py +18 -14
- synapse/lib/schemas.py +87 -1
- synapse/lib/scrape.py +35 -13
- synapse/lib/snap.py +2 -1
- synapse/lib/storm.lark +5 -4
- synapse/lib/storm.py +2 -2
- synapse/lib/storm_format.py +2 -1
- synapse/lib/stormhttp.py +11 -13
- synapse/lib/stormlib/aha.py +4 -4
- synapse/lib/stormlib/auth.py +1 -1
- synapse/lib/stormlib/cache.py +2 -2
- synapse/lib/stormlib/cortex.py +5 -5
- synapse/lib/stormlib/graph.py +1 -1
- synapse/lib/stormlib/imap.py +1 -1
- synapse/lib/stormlib/json.py +8 -11
- synapse/lib/stormlib/model.py +1 -1
- synapse/lib/stormlib/notifications.py +2 -2
- synapse/lib/stormlib/oauth.py +105 -2
- synapse/lib/stormlib/stats.py +4 -0
- synapse/lib/stormlib/stix.py +3 -4
- synapse/lib/stormlib/vault.py +6 -6
- synapse/lib/stormlib/xml.py +2 -2
- synapse/lib/stormtypes.py +19 -28
- synapse/lib/structlog.py +3 -3
- synapse/lib/types.py +2 -1
- synapse/lib/version.py +2 -2
- synapse/lib/view.py +7 -3
- synapse/models/base.py +51 -2
- synapse/telepath.py +79 -18
- synapse/tests/files/__init__.py +0 -1
- synapse/tests/test_axon.py +1 -1
- synapse/tests/test_cmds_cortex.py +3 -2
- synapse/tests/test_cmds_hive.py +4 -4
- synapse/tests/test_common.py +29 -19
- synapse/tests/test_cortex.py +28 -8
- synapse/tests/test_lib_ast.py +3 -3
- synapse/tests/test_lib_autodoc.py +5 -5
- synapse/tests/test_lib_base.py +1 -1
- synapse/tests/test_lib_cell.py +24 -7
- synapse/tests/test_lib_config.py +2 -2
- synapse/tests/test_lib_encoding.py +2 -2
- synapse/tests/test_lib_grammar.py +68 -64
- synapse/tests/test_lib_httpapi.py +13 -13
- synapse/tests/test_lib_json.py +219 -0
- synapse/tests/test_lib_multislabseqn.py +2 -1
- synapse/tests/test_lib_node.py +2 -2
- synapse/tests/test_lib_scrape.py +50 -0
- synapse/tests/test_lib_storm.py +12 -6
- synapse/tests/test_lib_stormhttp.py +4 -4
- synapse/tests/test_lib_stormlib_auth.py +3 -2
- synapse/tests/test_lib_stormlib_cortex.py +10 -12
- synapse/tests/test_lib_stormlib_infosec.py +2 -3
- synapse/tests/test_lib_stormlib_json.py +18 -21
- synapse/tests/test_lib_stormlib_log.py +1 -1
- synapse/tests/test_lib_stormlib_oauth.py +603 -1
- synapse/tests/test_lib_stormlib_stats.py +13 -3
- synapse/tests/test_lib_stormlib_stix.py +5 -5
- synapse/tests/test_lib_stormtypes.py +4 -4
- synapse/tests/test_lib_structlog.py +5 -6
- synapse/tests/test_lib_view.py +8 -0
- synapse/tests/test_model_base.py +32 -0
- synapse/tests/test_model_infotech.py +2 -2
- synapse/tests/test_telepath.py +56 -35
- synapse/tests/test_tools_cryo_cat.py +4 -3
- synapse/tests/test_tools_docker_validate.py +4 -2
- synapse/tests/test_tools_feed.py +30 -2
- synapse/tests/test_tools_genpkg.py +1 -1
- synapse/tests/test_tools_healthcheck.py +8 -7
- synapse/tests/test_utils.py +2 -2
- synapse/tests/test_utils_getrefs.py +35 -28
- synapse/tests/utils.py +3 -3
- synapse/tools/autodoc.py +3 -3
- synapse/tools/changelog.py +2 -2
- synapse/tools/cryo/cat.py +3 -3
- synapse/tools/csvtool.py +2 -3
- synapse/tools/docker/validate.py +5 -5
- synapse/tools/feed.py +2 -1
- synapse/tools/genpkg.py +3 -2
- synapse/tools/healthcheck.py +2 -3
- synapse/tools/json2mpk.py +2 -2
- synapse/utils/getrefs.py +10 -8
- synapse/vendor/cpython/lib/json.py +35 -0
- synapse/vendor/cpython/lib/test/test_json.py +22 -0
- {synapse-2.201.0.dist-info → synapse-2.203.0.dist-info}/METADATA +2 -1
- {synapse-2.201.0.dist-info → synapse-2.203.0.dist-info}/RECORD +106 -101
- {synapse-2.201.0.dist-info → synapse-2.203.0.dist-info}/WHEEL +1 -1
- {synapse-2.201.0.dist-info → synapse-2.203.0.dist-info}/LICENSE +0 -0
- {synapse-2.201.0.dist-info → synapse-2.203.0.dist-info}/top_level.txt +0 -0
synapse/axon.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import csv
|
|
2
|
-
import json
|
|
3
2
|
import struct
|
|
4
3
|
import asyncio
|
|
5
4
|
import hashlib
|
|
@@ -16,6 +15,7 @@ import synapse.common as s_common
|
|
|
16
15
|
import synapse.lib.cell as s_cell
|
|
17
16
|
import synapse.lib.coro as s_coro
|
|
18
17
|
import synapse.lib.base as s_base
|
|
18
|
+
import synapse.lib.json as s_json
|
|
19
19
|
import synapse.lib.link as s_link
|
|
20
20
|
import synapse.lib.const as s_const
|
|
21
21
|
import synapse.lib.nexus as s_nexus
|
|
@@ -1509,8 +1509,8 @@ class Axon(s_cell.Cell):
|
|
|
1509
1509
|
continue
|
|
1510
1510
|
|
|
1511
1511
|
try:
|
|
1512
|
-
yield
|
|
1513
|
-
except
|
|
1512
|
+
yield s_json.loads(line)
|
|
1513
|
+
except s_exc.BadJsonText as e:
|
|
1514
1514
|
logger.exception(f'Bad json line encountered for {sha256}')
|
|
1515
1515
|
raise s_exc.BadJsonText(mesg=f'Bad json line encountered while processing {sha256}, ({e})',
|
|
1516
1516
|
sha256=sha256) from None
|
|
@@ -1643,7 +1643,7 @@ class Axon(s_cell.Cell):
|
|
|
1643
1643
|
else:
|
|
1644
1644
|
valu = field.get('value')
|
|
1645
1645
|
if not isinstance(valu, (bytes, str)):
|
|
1646
|
-
valu =
|
|
1646
|
+
valu = s_json.dumps(valu).decode()
|
|
1647
1647
|
|
|
1648
1648
|
data.add_field(name,
|
|
1649
1649
|
valu,
|
synapse/cmds/cortex.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import os
|
|
2
|
-
import json
|
|
3
2
|
import queue
|
|
4
3
|
import shlex
|
|
5
4
|
import pprint
|
|
@@ -10,6 +9,7 @@ import synapse.common as s_common
|
|
|
10
9
|
|
|
11
10
|
import synapse.lib.cli as s_cli
|
|
12
11
|
import synapse.lib.cmd as s_cmd
|
|
12
|
+
import synapse.lib.json as s_json
|
|
13
13
|
import synapse.lib.node as s_node
|
|
14
14
|
import synapse.lib.time as s_time
|
|
15
15
|
import synapse.lib.msgpack as s_msgpack
|
|
@@ -118,9 +118,7 @@ Examples:
|
|
|
118
118
|
|
|
119
119
|
fmt = self.locs.get('log:fmt')
|
|
120
120
|
if fmt == 'jsonl':
|
|
121
|
-
|
|
122
|
-
buf = s.encode()
|
|
123
|
-
return buf
|
|
121
|
+
return s_json.dumps(mesg, sort_keys=True, newline=True)
|
|
124
122
|
|
|
125
123
|
elif fmt == 'mpk':
|
|
126
124
|
buf = s_msgpack.en(mesg)
|
|
@@ -430,8 +428,8 @@ class StormCmd(s_cli.Cmd):
|
|
|
430
428
|
if mesg[0] == 'node':
|
|
431
429
|
|
|
432
430
|
if nodesfd is not None:
|
|
433
|
-
byts =
|
|
434
|
-
nodesfd.write(byts
|
|
431
|
+
byts = s_json.dumps(mesg[1], newline=True)
|
|
432
|
+
nodesfd.write(byts)
|
|
435
433
|
|
|
436
434
|
try:
|
|
437
435
|
func = self.cmdmeths[mesg[0]]
|
synapse/cmds/hive.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import os
|
|
2
|
-
import json
|
|
3
2
|
import shlex
|
|
4
3
|
import pprint
|
|
5
4
|
import asyncio
|
|
@@ -12,6 +11,7 @@ import synapse.common as s_common
|
|
|
12
11
|
|
|
13
12
|
import synapse.lib.cmd as s_cmd
|
|
14
13
|
import synapse.lib.cli as s_cli
|
|
14
|
+
import synapse.lib.json as s_json
|
|
15
15
|
|
|
16
16
|
ListHelp = '''
|
|
17
17
|
Lists all the keys underneath a particular key in the hive.
|
|
@@ -140,8 +140,8 @@ A Hive is a hierarchy persistent storage mechanism typically used for configurat
|
|
|
140
140
|
return
|
|
141
141
|
|
|
142
142
|
if opts.json:
|
|
143
|
-
|
|
144
|
-
|
|
143
|
+
rend = s_json.dumps(valu, indent=True, sort_keys=True)
|
|
144
|
+
prend = rend.decode()
|
|
145
145
|
elif isinstance(valu, str):
|
|
146
146
|
rend = valu.encode()
|
|
147
147
|
prend = valu
|
|
@@ -149,7 +149,7 @@ A Hive is a hierarchy persistent storage mechanism typically used for configurat
|
|
|
149
149
|
rend = valu
|
|
150
150
|
prend = pprint.pformat(valu)
|
|
151
151
|
else:
|
|
152
|
-
rend =
|
|
152
|
+
rend = s_json.dumps(valu, indent=True, sort_keys=True)
|
|
153
153
|
prend = pprint.pformat(valu)
|
|
154
154
|
|
|
155
155
|
if opts.file:
|
|
@@ -172,7 +172,7 @@ A Hive is a hierarchy persistent storage mechanism typically used for configurat
|
|
|
172
172
|
if opts.value[0] not in '([{"':
|
|
173
173
|
data = opts.value
|
|
174
174
|
else:
|
|
175
|
-
data =
|
|
175
|
+
data = s_json.loads(opts.value)
|
|
176
176
|
await core.setHiveKey(path, data)
|
|
177
177
|
return
|
|
178
178
|
elif opts.file is not None:
|
|
@@ -181,7 +181,7 @@ A Hive is a hierarchy persistent storage mechanism typically used for configurat
|
|
|
181
181
|
if len(s) == 0:
|
|
182
182
|
self.printf('Empty file. Not writing key.')
|
|
183
183
|
return
|
|
184
|
-
data = s if opts.string else
|
|
184
|
+
data = s if opts.string else s_json.loads(s)
|
|
185
185
|
await core.setHiveKey(path, data)
|
|
186
186
|
return
|
|
187
187
|
|
|
@@ -201,8 +201,8 @@ A Hive is a hierarchy persistent storage mechanism typically used for configurat
|
|
|
201
201
|
data = old_valu
|
|
202
202
|
else:
|
|
203
203
|
try:
|
|
204
|
-
data =
|
|
205
|
-
except
|
|
204
|
+
data = s_json.dumps(old_valu, indent=True, sort_keys=True).decode()
|
|
205
|
+
except s_exc.MustBeJsonSafe:
|
|
206
206
|
self.printf('Value is not JSON-encodable, therefore not editable.')
|
|
207
207
|
return
|
|
208
208
|
fh.write(data)
|
|
@@ -218,8 +218,8 @@ A Hive is a hierarchy persistent storage mechanism typically used for configurat
|
|
|
218
218
|
self.printf('Empty file. Not writing key.')
|
|
219
219
|
return
|
|
220
220
|
try:
|
|
221
|
-
valu = rawval if opts.string else
|
|
222
|
-
except
|
|
221
|
+
valu = rawval if opts.string else s_json.loads(rawval)
|
|
222
|
+
except s_exc.BadJsonText as e: # pragma: no cover
|
|
223
223
|
self.printf(f'JSON decode failure: [{e}]. Reopening.')
|
|
224
224
|
await asyncio.sleep(1)
|
|
225
225
|
continue
|
synapse/common.py
CHANGED
|
@@ -3,7 +3,6 @@ import os
|
|
|
3
3
|
import ssl
|
|
4
4
|
import sys
|
|
5
5
|
import enum
|
|
6
|
-
import json
|
|
7
6
|
import http
|
|
8
7
|
import stat
|
|
9
8
|
import time
|
|
@@ -30,6 +29,7 @@ import contextlib
|
|
|
30
29
|
import collections
|
|
31
30
|
|
|
32
31
|
import http.cookies
|
|
32
|
+
import tornado.escape
|
|
33
33
|
|
|
34
34
|
import yaml
|
|
35
35
|
import regex
|
|
@@ -511,24 +511,6 @@ def getDirSize(*paths):
|
|
|
511
511
|
|
|
512
512
|
return realsum, apprsum
|
|
513
513
|
|
|
514
|
-
def jsload(*paths):
|
|
515
|
-
with genfile(*paths) as fd:
|
|
516
|
-
byts = fd.read()
|
|
517
|
-
if not byts:
|
|
518
|
-
return None
|
|
519
|
-
|
|
520
|
-
return json.loads(byts.decode('utf8'))
|
|
521
|
-
|
|
522
|
-
def jslines(*paths):
|
|
523
|
-
with genfile(*paths) as fd:
|
|
524
|
-
for line in fd:
|
|
525
|
-
yield json.loads(line)
|
|
526
|
-
|
|
527
|
-
def jssave(js, *paths):
|
|
528
|
-
path = genpath(*paths)
|
|
529
|
-
with io.open(path, 'wb') as fd:
|
|
530
|
-
fd.write(json.dumps(js, sort_keys=True, indent=2).encode('utf8'))
|
|
531
|
-
|
|
532
514
|
def yamlloads(data):
|
|
533
515
|
return yaml.load(data, Loader)
|
|
534
516
|
|
|
@@ -959,16 +941,6 @@ def deprdate(name, date): # pragma: no cover
|
|
|
959
941
|
mesg = f'{name} is deprecated and will be removed on {date}.'
|
|
960
942
|
warnings.warn(mesg, DeprecationWarning)
|
|
961
943
|
|
|
962
|
-
def reqjsonsafe(item):
|
|
963
|
-
'''
|
|
964
|
-
Returns None if item is json serializable, otherwise raises an exception.
|
|
965
|
-
Uses default type coercion from built-in json.dumps.
|
|
966
|
-
'''
|
|
967
|
-
try:
|
|
968
|
-
json.dumps(item)
|
|
969
|
-
except TypeError as e:
|
|
970
|
-
raise s_exc.MustBeJsonSafe(mesg=str(e)) from None
|
|
971
|
-
|
|
972
944
|
def jsonsafe_nodeedits(nodeedits):
|
|
973
945
|
'''
|
|
974
946
|
Hexlify the buid of each node:edits
|
|
@@ -998,35 +970,6 @@ def reprauthrule(rule):
|
|
|
998
970
|
text = '!' + text
|
|
999
971
|
return text
|
|
1000
972
|
|
|
1001
|
-
def reqJsonSafeStrict(item):
|
|
1002
|
-
'''
|
|
1003
|
-
Require the item to be safe to serialize to JSON without type coercion issues.
|
|
1004
|
-
|
|
1005
|
-
Args:
|
|
1006
|
-
item: The python primitive to check.
|
|
1007
|
-
|
|
1008
|
-
Returns:
|
|
1009
|
-
None
|
|
1010
|
-
|
|
1011
|
-
Raise:
|
|
1012
|
-
s_exc.BadArg: If the item contains invalid data.
|
|
1013
|
-
'''
|
|
1014
|
-
if item is None:
|
|
1015
|
-
return
|
|
1016
|
-
if isinstance(item, (str, int,)):
|
|
1017
|
-
return
|
|
1018
|
-
if isinstance(item, (list, tuple)):
|
|
1019
|
-
for valu in item:
|
|
1020
|
-
reqJsonSafeStrict(valu)
|
|
1021
|
-
return
|
|
1022
|
-
if isinstance(item, dict):
|
|
1023
|
-
for key, valu in item.items():
|
|
1024
|
-
if not isinstance(key, str):
|
|
1025
|
-
raise s_exc.BadArg(mesg='Non-string keys are not valid json', key=key)
|
|
1026
|
-
reqJsonSafeStrict(valu)
|
|
1027
|
-
return
|
|
1028
|
-
raise s_exc.BadArg(mesg=f'Invalid item type encountered: {item.__class__.__name__}')
|
|
1029
|
-
|
|
1030
973
|
async def merggenr(genrs, cmprkey):
|
|
1031
974
|
'''
|
|
1032
975
|
Iterate multiple sorted async generators and yield their results in order.
|
|
@@ -1234,7 +1177,23 @@ def _patch_http_cookies():
|
|
|
1234
1177
|
return
|
|
1235
1178
|
http.cookies._unquote = v_cookies._unquote
|
|
1236
1179
|
|
|
1180
|
+
def _patch_tornado_json():
|
|
1181
|
+
import synapse.lib.json as s_json
|
|
1182
|
+
|
|
1183
|
+
if hasattr(tornado.escape, 'json_encode'):
|
|
1184
|
+
# This exists for a specific reason. See the following URL for explanation:
|
|
1185
|
+
# https://github.com/tornadoweb/tornado/blob/d5ac65c1f1453c2aeddd089d8e68c159645c13e1/tornado/escape.py#L83-L96
|
|
1186
|
+
# https://github.com/tornadoweb/tornado/pull/706
|
|
1187
|
+
def _tornado_json_encode(value):
|
|
1188
|
+
return s_json.dumps(value).replace(b'</', br'<\/').decode()
|
|
1189
|
+
|
|
1190
|
+
tornado.escape.json_encode = _tornado_json_encode
|
|
1191
|
+
|
|
1192
|
+
if hasattr(tornado.escape, 'json_decode'):
|
|
1193
|
+
tornado.escape.json_decode = s_json.loads
|
|
1194
|
+
|
|
1237
1195
|
_patch_http_cookies()
|
|
1196
|
+
_patch_tornado_json()
|
|
1238
1197
|
|
|
1239
1198
|
# TODO: Switch back to using asyncio.wait_for when we are using py 3.12+
|
|
1240
1199
|
# This is a workaround for a race where asyncio.wait_for can end up
|
synapse/cortex.py
CHANGED
|
@@ -1265,7 +1265,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
1265
1265
|
|
|
1266
1266
|
byts = self.slab.get(newname.encode(), db=self.macrodb)
|
|
1267
1267
|
if byts is not None:
|
|
1268
|
-
raise s_exc.DupName('A macro named {newname} already exists!')
|
|
1268
|
+
raise s_exc.DupName(mesg=f'A macro named {newname} already exists!', name=newname)
|
|
1269
1269
|
|
|
1270
1270
|
self.slab.put(newname.encode(), s_msgpack.en(mdef), db=self.macrodb)
|
|
1271
1271
|
self.slab.pop(name.encode(), db=self.macrodb)
|
|
@@ -5874,38 +5874,45 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
5874
5874
|
if self.stormpool is None: # pragma: no cover
|
|
5875
5875
|
return None
|
|
5876
5876
|
|
|
5877
|
-
|
|
5877
|
+
size = self.stormpool.size()
|
|
5878
|
+
if size == 0:
|
|
5878
5879
|
logger.warning('Storm query mirror pool is empty, running query locally.')
|
|
5879
5880
|
return None
|
|
5880
5881
|
|
|
5881
|
-
|
|
5882
|
+
for _ in range(size):
|
|
5882
5883
|
|
|
5883
|
-
|
|
5884
|
-
|
|
5885
|
-
|
|
5886
|
-
|
|
5887
|
-
|
|
5888
|
-
|
|
5889
|
-
|
|
5884
|
+
try:
|
|
5885
|
+
timeout = self.stormpoolopts.get('timeout:connection')
|
|
5886
|
+
proxy = await self.stormpool.proxy(timeout=timeout)
|
|
5887
|
+
proxyname = proxy._ahainfo.get('name')
|
|
5888
|
+
if proxyname is not None and proxyname == self.ahasvcname:
|
|
5889
|
+
# we are part of the pool and were selected. Convert to local use.
|
|
5890
|
+
return None
|
|
5891
|
+
|
|
5892
|
+
except TimeoutError:
|
|
5893
|
+
logger.warning('Timeout waiting for pool mirror proxy.')
|
|
5894
|
+
continue
|
|
5895
|
+
|
|
5896
|
+
try:
|
|
5897
|
+
|
|
5898
|
+
curoffs = opts.setdefault('nexsoffs', await self.getNexsIndx() - 1)
|
|
5899
|
+
miroffs = await s_common.wait_for(proxy.getNexsIndx(), timeout) - 1
|
|
5900
|
+
if (delta := curoffs - miroffs) <= MAX_NEXUS_DELTA:
|
|
5901
|
+
return proxy
|
|
5890
5902
|
|
|
5891
|
-
|
|
5892
|
-
miroffs = await s_common.wait_for(proxy.getNexsIndx(), timeout) - 1
|
|
5893
|
-
if (delta := curoffs - miroffs) > MAX_NEXUS_DELTA:
|
|
5894
|
-
mesg = (f'Pool mirror [{proxyname}] Nexus offset delta too large '
|
|
5895
|
-
f'({delta} > {MAX_NEXUS_DELTA}), running query locally.')
|
|
5903
|
+
mesg = f'Pool mirror [{proxyname}] is too far out of sync. Skipping.'
|
|
5896
5904
|
logger.warning(mesg, extra=await self.getLogExtra(delta=delta, mirror=proxyname, mirror_offset=miroffs))
|
|
5897
|
-
return None
|
|
5898
5905
|
|
|
5899
|
-
|
|
5906
|
+
except s_exc.IsFini:
|
|
5907
|
+
mesg = f'Proxy for pool mirror [{proxyname}] was shutdown. Skipping.'
|
|
5908
|
+
logger.warning(mesg, extra=await self.getLogExtra(mirror=proxyname))
|
|
5900
5909
|
|
|
5901
|
-
|
|
5902
|
-
|
|
5903
|
-
logger.warning('Timeout waiting for pool mirror, running query locally.')
|
|
5904
|
-
else:
|
|
5905
|
-
mesg = f'Timeout waiting for pool mirror [{proxyname}] Nexus offset, running query locally.'
|
|
5910
|
+
except TimeoutError:
|
|
5911
|
+
mesg = f'Timeout waiting for pool mirror [{proxyname}] Nexus offset.'
|
|
5906
5912
|
logger.warning(mesg, extra=await self.getLogExtra(mirror=proxyname))
|
|
5907
|
-
|
|
5908
|
-
|
|
5913
|
+
|
|
5914
|
+
logger.warning('Pool members exhausted. Running query locally.', extra=await self.getLogExtra())
|
|
5915
|
+
return None
|
|
5909
5916
|
|
|
5910
5917
|
async def storm(self, text, opts=None):
|
|
5911
5918
|
|
|
@@ -6528,7 +6535,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
6528
6535
|
|
|
6529
6536
|
cdef['reqs'] = reqs
|
|
6530
6537
|
except KeyError:
|
|
6531
|
-
raise s_exc.BadConfValu('Unrecognized time unit')
|
|
6538
|
+
raise s_exc.BadConfValu(mesg='Unrecognized time unit')
|
|
6532
6539
|
|
|
6533
6540
|
if not cdef.get('iden'):
|
|
6534
6541
|
cdef['iden'] = s_common.guid()
|
|
@@ -6985,7 +6992,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
6985
6992
|
|
|
6986
6993
|
vault = self.getVault(iden)
|
|
6987
6994
|
if vault is None:
|
|
6988
|
-
raise s_exc.NoSuchIden(mesg=f'Vault not found for iden: {iden}.')
|
|
6995
|
+
raise s_exc.NoSuchIden(mesg=f'Vault not found for iden: {iden}.', iden=iden)
|
|
6989
6996
|
|
|
6990
6997
|
return vault
|
|
6991
6998
|
|
|
@@ -7338,7 +7345,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
7338
7345
|
scope = 'roles'
|
|
7339
7346
|
ident = self.auth.role(iden)
|
|
7340
7347
|
if ident is None:
|
|
7341
|
-
raise s_exc.NoSuchIden(mesg=f'Iden {iden} is not a valid user or role.')
|
|
7348
|
+
raise s_exc.NoSuchIden(mesg=f'Iden {iden} is not a valid user or role.', iden=iden)
|
|
7342
7349
|
|
|
7343
7350
|
await self._setEasyPerm(vault, scope, ident.iden, level)
|
|
7344
7351
|
permissions = vault.get('permissions')
|
|
@@ -7359,14 +7366,14 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
7359
7366
|
Returns: Updated vault.
|
|
7360
7367
|
'''
|
|
7361
7368
|
if self.getVaultByName(name) is not None:
|
|
7362
|
-
raise s_exc.DupName(mesg=f'Vault with name {name} already exists.')
|
|
7369
|
+
raise s_exc.DupName(mesg=f'Vault with name {name} already exists.', name=name)
|
|
7363
7370
|
|
|
7364
7371
|
return await self._push(('vault:set'), iden, 'name', name)
|
|
7365
7372
|
|
|
7366
7373
|
@s_nexus.Pusher.onPush('vault:set')
|
|
7367
7374
|
async def _setVault(self, iden, key, valu):
|
|
7368
7375
|
if key not in ('name', 'permissions'): # pragma: no cover
|
|
7369
|
-
raise s_exc.BadArg('Only vault names and permissions can be changed.')
|
|
7376
|
+
raise s_exc.BadArg(mesg='Only vault names and permissions can be changed.')
|
|
7370
7377
|
|
|
7371
7378
|
vault = self.reqVault(iden)
|
|
7372
7379
|
oldv = vault.get(key)
|
synapse/data/__init__.py
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import os
|
|
2
|
-
import json
|
|
3
2
|
import logging
|
|
4
3
|
|
|
5
4
|
import synapse.common as s_common
|
|
5
|
+
|
|
6
|
+
import synapse.lib.json as s_json
|
|
6
7
|
import synapse.lib.datfile as s_datfile
|
|
7
8
|
import synapse.lib.msgpack as s_msgpack
|
|
8
9
|
|
|
@@ -26,7 +27,7 @@ def get(name, defval=None):
|
|
|
26
27
|
|
|
27
28
|
def getJSON(name):
|
|
28
29
|
with s_datfile.openDatFile(f'synapse.data/{name}.json') as fd:
|
|
29
|
-
return
|
|
30
|
+
return s_json.load(fd)
|
|
30
31
|
|
|
31
32
|
def path(*names):
|
|
32
33
|
return s_common.genpath(dirname, *names)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
���aaa�aaas�about�acap�acct�acd�acr�adiumxtra�adt�afp�afs�aim�amss�android�appdata�apt�ar�ari�ark�at�attachment�aw�barion�bb�beshare�bitcoin�bitcoincash�blob�bluetooth�bolo�brid�browserext�cabal�calculator�callto�cap�cast�casts�chrome�chrome-extension�cid�coap�coap+tcp�coap+ws�coaps�coaps+tcp�coaps+ws�com-eventbrite-attendee�content�content-type�crid�cstr�cvs�dab�dat�data�dav�dhttp�diaspora�dict�did�dis�dlna-playcontainer�dlna-playsingle�dns�dntp�doi�dpp�drm�drop�dtmi�dtn�dvb�dvx�dweb�ed2k�eid�elsi�embedded�ens�ethereum�example�facetime�fax�feed�feedready�fido�file�filesystem�finger�first-run-pen-experience�fish�fm�ftp�fuchsia-pkg�geo�gg�git�gitoid�gizmoproject�go�gopher�graph�grd�gtalk�h323�ham�hcap�hcp�hs20�http�https�hxxp�hxxps�hydrazone�hyper�iax�icap�icon�ilstring�im�imap�info�iotdisco�ipfs�ipn�ipns�ipp�ipps�irc�irc6�ircs�iris�iris.beep�iris.lwz�iris.xpc�iris.xpcs�isostore�itms�jabber�jar�jms�keyparc�lastfm�lbry�ldap�ldaps�leaptofrogans�lid�lorawan�lpa�lvlt�#machineProvisioningProgressReporter�magnet�mailserver�mailto�maps�market�matrix�message�microsoft.windows.camera�$microsoft.windows.camera.multipicker�microsoft.windows.camera.picker�mid�mms�modem�mongodb�moz�ms-access�ms-appinstaller�ms-browser-extension�ms-calculator�ms-drive-to�ms-enrollment�ms-excel�ms-eyecontrolspeech�ms-gamebarservices�ms-gamingoverlay�ms-getoffice�ms-help�ms-infopath�ms-inputapp�ms-launchremotedesktop�ms-lockscreencomponent-config�ms-media-stream-id�ms-meetnow�ms-mixedrealitycapture�ms-mobileplans�ms-newsandinterests�ms-officeapp�ms-people�ms-personacard�ms-project�ms-powerpoint�ms-publisher�ms-recall�ms-remotedesktop�ms-remotedesktop-launch�ms-restoretabcompanion�ms-screenclip�ms-screensketch�ms-search�ms-search-repair�ms-secondary-screen-controller�ms-secondary-screen-setup�ms-settings�ms-settings-airplanemode�ms-settings-bluetooth�ms-settings-camera�ms-settings-cellular�ms-settings-cloudstorage�ms-settings-connectabledevices�ms-settings-displays-topology�ms-settings-emailandaccounts�ms-settings-language�ms-settings-location�ms-settings-lock�ms-settings-nfctransactions�ms-settings-notifications�ms-settings-power�ms-settings-privacy�ms-settings-proximity�ms-settings-screenrotation�ms-settings-wifi�ms-settings-workplace�ms-spd�ms-stickers�ms-sttoverlay�ms-transit-to�ms-useractivityset�ms-virtualtouchpad�ms-visio�ms-walk-to�ms-whiteboard�ms-whiteboard-cmd�ms-widgetboard�ms-widgets�ms-word�msnim�msrp�msrps�mss�mt�mtqp�mumble�mupdate�mvn�mvrp�mvrps�news�nfs�ni�nih�nntp�notes�num�ocf�oid�onenote�onenote-cmd�opaquelocktoken�openid�openpgp4fpr�otpauth�p1�pack�palm�paparazzi�payment�payto�pkcs11�platform�pop�pres�prospero�proxy�pwid�psyc�pttp�qb�query�quic-transport�redis�rediss�reload�res�resource�rmi�rsync�rtmfp�rtmp�rtsp�rtsps�rtspu�sarif�secondlife�secret-token�service�session�sftp�sgn�shc�shelter�sieve�simpleledger�simplex�sip�sips�skype�smb�smp�sms�smtp�snews�snmp�soap.beep�soap.beeps�soldat�spiffe�spotify�ssb�ssh�starknet�steam�stun�stuns�submit�svn�swh�swid�swidpath�tag�taler�teamspeak�teapot�teapots�tel�teliaeid�telnet�tftp�things�thismessage�thzp�tip�tn3270�tool�turn�turns�tv�udp�unreal�upt�urn�ut2004�uuid-in-package�v-event�vemmi�ventrilo�ves�videotex�vnc�view-source�vscode�vscode-insiders�vsls�w3�wais�web3�wcr�webcal�web+ap�wifi�wpid�ws�wss�wtai�wyciwyg�xcon�xcon-userid�xfire�xmlrpc.beep�xmlrpc.beeps�xmpp�xftp�xrcp�xri�ymsgr�z39.50�z39.50r�z39.50s
|
synapse/lib/autodoc.py
CHANGED
|
@@ -286,11 +286,11 @@ def genCallsig(rtype):
|
|
|
286
286
|
if defv is s_common.novalu:
|
|
287
287
|
item = name
|
|
288
288
|
elif defv is None:
|
|
289
|
-
item = f'{name}
|
|
289
|
+
item = f'{name}=(null)'
|
|
290
290
|
elif defv is True:
|
|
291
|
-
item = f'{name}
|
|
291
|
+
item = f'{name}=(true)'
|
|
292
292
|
elif defv is False:
|
|
293
|
-
item = f'{name}
|
|
293
|
+
item = f'{name}=(false)'
|
|
294
294
|
elif isinstance(defv, str):
|
|
295
295
|
item = f'{name}={defv}'
|
|
296
296
|
elif isinstance(defv, int):
|
synapse/lib/base.py
CHANGED
|
@@ -128,7 +128,7 @@ class Base:
|
|
|
128
128
|
|
|
129
129
|
self.isfini = False
|
|
130
130
|
self.anitted = True # For assertion purposes
|
|
131
|
-
self.finievt =
|
|
131
|
+
self.finievt = asyncio.Event()
|
|
132
132
|
self.entered = False
|
|
133
133
|
|
|
134
134
|
# hold a weak ref to other bases we should fini if they
|
|
@@ -431,10 +431,7 @@ class Base:
|
|
|
431
431
|
self._syn_funcs.clear()
|
|
432
432
|
self._fini_funcs.clear()
|
|
433
433
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
if fevt is not None:
|
|
437
|
-
fevt.set()
|
|
434
|
+
self.finievt.set()
|
|
438
435
|
|
|
439
436
|
return 0
|
|
440
437
|
|
|
@@ -468,13 +465,6 @@ class Base:
|
|
|
468
465
|
base.waitfini(timeout=30)
|
|
469
466
|
|
|
470
467
|
'''
|
|
471
|
-
|
|
472
|
-
if self.isfini:
|
|
473
|
-
return True
|
|
474
|
-
|
|
475
|
-
if self.finievt is None:
|
|
476
|
-
self.finievt = asyncio.Event()
|
|
477
|
-
|
|
478
468
|
return await s_coro.event_wait(self.finievt, timeout)
|
|
479
469
|
|
|
480
470
|
def schedCoro(self, coro):
|
synapse/lib/cell.py
CHANGED
|
@@ -2711,6 +2711,12 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
2711
2711
|
raise s_exc.BadArg(mesg=mesg, arg='path', valu=path)
|
|
2712
2712
|
await self._streamBackupArchive(path, user, name)
|
|
2713
2713
|
|
|
2714
|
+
async def _removeStreamingBackup(self, path):
|
|
2715
|
+
logger.debug(f'Removing {path}')
|
|
2716
|
+
await s_coro.executor(shutil.rmtree, path, ignore_errors=True)
|
|
2717
|
+
logger.debug(f'Removed {path}')
|
|
2718
|
+
self.backupstreaming = False
|
|
2719
|
+
|
|
2714
2720
|
async def iterNewBackupArchive(self, user, name=None, remove=False):
|
|
2715
2721
|
|
|
2716
2722
|
if self.backupstreaming:
|
|
@@ -2728,23 +2734,13 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
2728
2734
|
mesg = 'Backup with name already exists'
|
|
2729
2735
|
raise s_exc.BadArg(mesg=mesg)
|
|
2730
2736
|
|
|
2731
|
-
|
|
2732
|
-
await self.runBackup(name)
|
|
2733
|
-
except Exception:
|
|
2734
|
-
if remove:
|
|
2735
|
-
logger.debug(f'Removing {path}')
|
|
2736
|
-
await s_coro.executor(shutil.rmtree, path, ignore_errors=True)
|
|
2737
|
-
logger.debug(f'Removed {path}')
|
|
2738
|
-
raise
|
|
2739
|
-
|
|
2737
|
+
await self.runBackup(name)
|
|
2740
2738
|
await self._streamBackupArchive(path, user, name)
|
|
2741
2739
|
|
|
2742
2740
|
finally:
|
|
2743
2741
|
if remove:
|
|
2744
|
-
|
|
2745
|
-
await
|
|
2746
|
-
logger.debug(f'Removed {path}')
|
|
2747
|
-
self.backupstreaming = False
|
|
2742
|
+
self.removetask = asyncio.create_task(self._removeStreamingBackup(path))
|
|
2743
|
+
await asyncio.shield(self.removetask)
|
|
2748
2744
|
|
|
2749
2745
|
async def isUserAllowed(self, iden, perm, gateiden=None, default=False):
|
|
2750
2746
|
user = self.auth.user(iden) # type: s_auth.User
|
synapse/lib/cli.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import os
|
|
2
|
-
import json
|
|
3
2
|
import signal
|
|
4
3
|
import asyncio
|
|
5
4
|
import logging
|
|
@@ -18,6 +17,7 @@ import synapse.common as s_common
|
|
|
18
17
|
import synapse.telepath as s_telepath
|
|
19
18
|
|
|
20
19
|
import synapse.lib.base as s_base
|
|
20
|
+
import synapse.lib.json as s_json
|
|
21
21
|
import synapse.lib.output as s_output
|
|
22
22
|
import synapse.lib.parser as s_parser
|
|
23
23
|
import synapse.lib.grammar as s_grammar
|
|
@@ -542,5 +542,5 @@ class CmdLocals(Cmd):
|
|
|
542
542
|
ret[k] = v
|
|
543
543
|
else:
|
|
544
544
|
ret[k] = repr(v)
|
|
545
|
-
mesg =
|
|
545
|
+
mesg = s_json.dumps(ret, indent=True, sort_keys=True).decode()
|
|
546
546
|
self.printf(mesg)
|
synapse/lib/config.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import copy
|
|
3
|
-
import json
|
|
4
3
|
import urllib
|
|
5
4
|
import logging
|
|
6
5
|
import argparse
|
|
@@ -12,6 +11,7 @@ import synapse.exc as s_exc
|
|
|
12
11
|
import synapse.data as s_data
|
|
13
12
|
import synapse.common as s_common
|
|
14
13
|
|
|
14
|
+
import synapse.lib.json as s_json
|
|
15
15
|
import synapse.lib.hashitem as s_hashitem
|
|
16
16
|
|
|
17
17
|
from fastjsonschema.exceptions import JsonSchemaValueException
|
|
@@ -44,7 +44,7 @@ def localSchemaRefHandler(uri):
|
|
|
44
44
|
raise s_exc.NoSuchFile(mesg=f'Local JSON schema not found for {uri}.')
|
|
45
45
|
|
|
46
46
|
with open(filename, 'r') as fp:
|
|
47
|
-
return
|
|
47
|
+
return s_json.load(fp)
|
|
48
48
|
|
|
49
49
|
# This handlers dictionary is used by the jsonschema validator to attempt to
|
|
50
50
|
# resolve schema '$ref' values locally from disk and will raise an exception
|
synapse/lib/encoding.py
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import csv
|
|
2
|
-
import json
|
|
3
2
|
import regex
|
|
4
3
|
import base64
|
|
5
4
|
import codecs
|
|
6
5
|
import xml.etree.ElementTree as x_etree
|
|
7
6
|
|
|
8
7
|
import synapse.exc as s_exc
|
|
8
|
+
|
|
9
|
+
import synapse.lib.json as s_json
|
|
9
10
|
import synapse.lib.msgpack as s_msgpack
|
|
10
11
|
|
|
11
12
|
def _de_base64(item, **opts):
|
|
@@ -176,11 +177,11 @@ def _fmt_lines(fd, gest):
|
|
|
176
177
|
yield line
|
|
177
178
|
|
|
178
179
|
def _fmt_json(fd, info):
|
|
179
|
-
yield
|
|
180
|
+
yield s_json.load(fd)
|
|
180
181
|
|
|
181
182
|
def _fmt_jsonl(fd, info):
|
|
182
183
|
for line in fd:
|
|
183
|
-
yield
|
|
184
|
+
yield s_json.loads(line)
|
|
184
185
|
|
|
185
186
|
def _fmt_mpk(fd, info):
|
|
186
187
|
yield from s_msgpack.iterfd(fd)
|
synapse/lib/httpapi.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import json
|
|
2
1
|
import base64
|
|
3
2
|
import asyncio
|
|
4
3
|
import logging
|
|
@@ -12,6 +11,7 @@ import synapse.exc as s_exc
|
|
|
12
11
|
import synapse.common as s_common
|
|
13
12
|
|
|
14
13
|
import synapse.lib.base as s_base
|
|
14
|
+
import synapse.lib.json as s_json
|
|
15
15
|
import synapse.lib.msgpack as s_msgpack
|
|
16
16
|
|
|
17
17
|
logger = logging.getLogger(__name__)
|
|
@@ -132,7 +132,7 @@ class HandlerBase:
|
|
|
132
132
|
|
|
133
133
|
def loadJsonMesg(self, byts, validator=None):
|
|
134
134
|
try:
|
|
135
|
-
item =
|
|
135
|
+
item = s_json.loads(byts)
|
|
136
136
|
if validator is not None:
|
|
137
137
|
validator(item)
|
|
138
138
|
return item
|
|
@@ -418,7 +418,7 @@ class HandlerBase:
|
|
|
418
418
|
class WebSocket(HandlerBase, t_websocket.WebSocketHandler):
|
|
419
419
|
|
|
420
420
|
async def xmit(self, name, **info):
|
|
421
|
-
await self.write_message(
|
|
421
|
+
await self.write_message(s_json.dumps({'type': name, 'data': info}))
|
|
422
422
|
|
|
423
423
|
async def _reqUserAllow(self, perm):
|
|
424
424
|
|
|
@@ -513,9 +513,7 @@ class StormNodesV1(StormHandler):
|
|
|
513
513
|
await self.cell.boss.promote('storm', user=user, info=taskinfo)
|
|
514
514
|
|
|
515
515
|
async for pode in view.iterStormPodes(query, opts=opts):
|
|
516
|
-
self.write(
|
|
517
|
-
if jsonlines:
|
|
518
|
-
self.write("\n")
|
|
516
|
+
self.write(s_json.dumps(pode, newline=jsonlines))
|
|
519
517
|
await self.flush()
|
|
520
518
|
|
|
521
519
|
class StormV1(StormHandler):
|
|
@@ -545,9 +543,7 @@ class StormV1(StormHandler):
|
|
|
545
543
|
opts.setdefault('editformat', 'nodeedits')
|
|
546
544
|
|
|
547
545
|
async for mesg in self.getCore().storm(query, opts=opts):
|
|
548
|
-
self.write(
|
|
549
|
-
if jsonlines:
|
|
550
|
-
self.write("\n")
|
|
546
|
+
self.write(s_json.dumps(mesg, newline=jsonlines))
|
|
551
547
|
await self.flush()
|
|
552
548
|
|
|
553
549
|
class StormCallV1(StormHandler):
|
|
@@ -640,9 +636,9 @@ class BeholdSockV1(WebSocket):
|
|
|
640
636
|
|
|
641
637
|
async def onInitMessage(self, byts):
|
|
642
638
|
try:
|
|
643
|
-
mesg =
|
|
639
|
+
mesg = s_json.loads(byts)
|
|
644
640
|
if mesg.get('type') != 'call:init':
|
|
645
|
-
raise s_exc.BadMesgFormat('Invalid initial message')
|
|
641
|
+
raise s_exc.BadMesgFormat(mesg='Invalid initial message')
|
|
646
642
|
|
|
647
643
|
admin = await self.isUserAdmin()
|
|
648
644
|
if not admin:
|