synapse 2.209.0__py311-none-any.whl → 2.210.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 +14 -4
- synapse/lib/coro.py +5 -0
- synapse/lib/json.py +48 -22
- synapse/lib/nexus.py +6 -0
- synapse/lib/storm.py +10 -2
- synapse/lib/stormlib/auth.py +6 -0
- synapse/lib/stormlib/notifications.py +12 -2
- synapse/lib/version.py +2 -2
- synapse/models/entity.py +26 -0
- synapse/models/inet.py +11 -0
- synapse/models/person.py +9 -2
- synapse/tests/test_cortex.py +3 -3
- synapse/tests/test_lib_aha.py +1 -1
- synapse/tests/test_lib_cell.py +28 -8
- synapse/tests/test_lib_coro.py +23 -0
- synapse/tests/test_lib_json.py +41 -16
- synapse/tests/test_model_entity.py +21 -0
- synapse/tests/test_model_gov_intl.py +2 -2
- synapse/tests/test_model_inet.py +15 -0
- synapse/tests/test_model_media.py +1 -0
- synapse/tests/test_model_person.py +12 -0
- synapse/tests/test_telepath.py +52 -41
- synapse/tests/test_tools_aha.py +7 -8
- synapse/tests/utils.py +1 -1
- synapse/tools/aha/clone.py +7 -1
- synapse/tools/aha/easycert.py +37 -42
- synapse/tools/aha/enroll.py +7 -1
- synapse/tools/aha/list.py +60 -65
- synapse/tools/aha/mirror.py +7 -1
- synapse/tools/aha/provision/service.py +7 -1
- synapse/tools/aha/provision/user.py +7 -1
- synapse/tools/apikey.py +8 -1
- synapse/tools/axon2axon.py +7 -1
- synapse/tools/cellauth.py +6 -5
- synapse/tools/cmdr.py +2 -1
- synapse/tools/csvtool.py +7 -2
- synapse/tools/feed.py +8 -2
- synapse/tools/genpkg.py +7 -1
- synapse/tools/healthcheck.py +7 -1
- synapse/tools/livebackup.py +7 -3
- synapse/tools/modrole.py +7 -1
- synapse/tools/moduser.py +7 -2
- synapse/tools/promote.py +7 -3
- synapse/tools/pullfile.py +6 -1
- synapse/tools/pushfile.py +7 -1
- synapse/tools/reload.py +7 -4
- synapse/tools/snapshot.py +7 -1
- synapse/tools/storm.py +7 -1
- {synapse-2.209.0.dist-info → synapse-2.210.0.dist-info}/METADATA +2 -2
- {synapse-2.209.0.dist-info → synapse-2.210.0.dist-info}/RECORD +53 -52
- {synapse-2.209.0.dist-info → synapse-2.210.0.dist-info}/WHEEL +1 -1
- {synapse-2.209.0.dist-info → synapse-2.210.0.dist-info}/licenses/LICENSE +0 -0
- {synapse-2.209.0.dist-info → synapse-2.210.0.dist-info}/top_level.txt +0 -0
synapse/tests/test_lib_json.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import io
|
|
2
2
|
import json
|
|
3
3
|
|
|
4
|
-
import
|
|
4
|
+
import yyjson
|
|
5
5
|
|
|
6
6
|
import synapse.exc as s_exc
|
|
7
7
|
import synapse.common as s_common
|
|
@@ -44,9 +44,9 @@ class JsonTest(s_test.SynTest):
|
|
|
44
44
|
inval = '{"a": "😀\ud83d\ude47"}'
|
|
45
45
|
outval = {'a': '😀\ud83d\ude47'}
|
|
46
46
|
|
|
47
|
-
#
|
|
48
|
-
with self.raises(
|
|
49
|
-
|
|
47
|
+
# yyjson.loads fails because of the surrogate pairs
|
|
48
|
+
with self.raises(ValueError):
|
|
49
|
+
yyjson.loads(inval)
|
|
50
50
|
|
|
51
51
|
# stdlib json.loads passes because of voodoo magic
|
|
52
52
|
self.eq(outval, json.loads(inval))
|
|
@@ -63,9 +63,9 @@ class JsonTest(s_test.SynTest):
|
|
|
63
63
|
inval = {'a': '😀\ud83d\ude47'}
|
|
64
64
|
outval = b'{"a": "\\ud83d\\ude00\\ud83d\\ude47"}'
|
|
65
65
|
|
|
66
|
-
#
|
|
67
|
-
with self.raises(
|
|
68
|
-
|
|
66
|
+
# yyjson.dumps fails because of the surrogate pairs
|
|
67
|
+
with self.raises(UnicodeEncodeError):
|
|
68
|
+
yyjson.dumps(inval)
|
|
69
69
|
|
|
70
70
|
# stdlib json.dumps passes because of voodoo magic
|
|
71
71
|
self.eq(outval.decode(), json.dumps(inval))
|
|
@@ -85,15 +85,15 @@ class JsonTest(s_test.SynTest):
|
|
|
85
85
|
|
|
86
86
|
with self.raises(s_exc.MustBeJsonSafe) as exc:
|
|
87
87
|
s_json.dumps({}.items())
|
|
88
|
-
self.eq(exc.exception.get('mesg'), '
|
|
88
|
+
self.eq(exc.exception.get('mesg'), "TypeError: Object of type 'dict_items' is not JSON serializable")
|
|
89
89
|
|
|
90
90
|
with self.raises(s_exc.MustBeJsonSafe) as exc:
|
|
91
91
|
s_json.dumps({1: 'foo'})
|
|
92
|
-
self.eq(exc.exception.get('mesg'),
|
|
92
|
+
self.eq(exc.exception.get('mesg'), "TypeError: Dictionary keys must be strings")
|
|
93
93
|
|
|
94
94
|
with self.raises(s_exc.MustBeJsonSafe) as exc:
|
|
95
95
|
s_json.dumps({'\ud83d\ude47': {}.items()})
|
|
96
|
-
self.eq(exc.exception.get('mesg'),
|
|
96
|
+
self.eq(exc.exception.get('mesg'), "TypeError: Dictionary keys must be strings")
|
|
97
97
|
|
|
98
98
|
self.eq(b'"dict_items([])"', s_json.dumps({}.items(), default=str))
|
|
99
99
|
|
|
@@ -111,6 +111,20 @@ class JsonTest(s_test.SynTest):
|
|
|
111
111
|
s_json.dump({'c': 'd', 'a': 'b'}, buf)
|
|
112
112
|
self.eq(b'{"c":"d","a":"b"}', buf.getvalue())
|
|
113
113
|
|
|
114
|
+
async def test_lib_json_large_integers(self):
|
|
115
|
+
valu = [
|
|
116
|
+
1, 2,
|
|
117
|
+
-1, -2,
|
|
118
|
+
1.0, 2.0,
|
|
119
|
+
-1.0, -2.0,
|
|
120
|
+
2**63, -2**63, -2**63 - 1,
|
|
121
|
+
2**64, -2**64, 2**64 + 1,
|
|
122
|
+
2**128, 2**128 + 1,
|
|
123
|
+
-2**128, -2**128 - 1,
|
|
124
|
+
]
|
|
125
|
+
|
|
126
|
+
self.eq(valu, s_json.loads(s_json.dumps(valu)))
|
|
127
|
+
|
|
114
128
|
async def test_jsload(self):
|
|
115
129
|
with self.getTestDir() as dirn:
|
|
116
130
|
with s_common.genfile(dirn, 'jsload.json') as fp:
|
|
@@ -147,41 +161,52 @@ class JsonTest(s_test.SynTest):
|
|
|
147
161
|
|
|
148
162
|
buf = io.BytesIO()
|
|
149
163
|
|
|
164
|
+
msg = "Object of type '_io.BytesIO' is not JSON serializable"
|
|
150
165
|
with self.raises(s_exc.MustBeJsonSafe) as exc:
|
|
151
166
|
s_json.reqjsonsafe(buf)
|
|
152
|
-
self.isin(
|
|
167
|
+
self.isin(msg, exc.exception.get('mesg'))
|
|
153
168
|
|
|
154
169
|
with self.raises(s_exc.MustBeJsonSafe) as exc:
|
|
155
170
|
s_json.reqjsonsafe({'foo': buf})
|
|
156
|
-
self.isin(
|
|
171
|
+
self.isin(msg, exc.exception.get('mesg'))
|
|
157
172
|
|
|
158
173
|
with self.raises(s_exc.MustBeJsonSafe) as exc:
|
|
159
174
|
s_json.reqjsonsafe(['foo', buf])
|
|
160
|
-
self.isin(
|
|
175
|
+
self.isin(msg, exc.exception.get('mesg'))
|
|
161
176
|
|
|
162
177
|
items = (
|
|
163
178
|
(None, None),
|
|
164
179
|
(1234, None),
|
|
165
180
|
('1234', None),
|
|
181
|
+
('1234"', None),
|
|
166
182
|
({'asdf': 'haha'}, None),
|
|
167
183
|
({'a': (1,), 'b': [{'': 4}, 56, None, {'t': True, 'f': False}, 'oh my']}, None),
|
|
168
184
|
(b'1234', s_exc.MustBeJsonSafe),
|
|
185
|
+
(b'1234"', s_exc.MustBeJsonSafe),
|
|
186
|
+
({'a': float('nan')}, s_exc.MustBeJsonSafe),
|
|
169
187
|
({'a': 'a', 2: 2}, s_exc.MustBeJsonSafe),
|
|
170
188
|
({'a', 'b', 'c'}, s_exc.MustBeJsonSafe),
|
|
171
189
|
(s_common.novalu, s_exc.MustBeJsonSafe),
|
|
172
190
|
)
|
|
173
191
|
for (item, eret) in items:
|
|
174
192
|
if eret is None:
|
|
175
|
-
self.none(s_json.reqjsonsafe(item))
|
|
193
|
+
self.none(s_json.reqjsonsafe(item), msg=item)
|
|
176
194
|
else:
|
|
177
195
|
with self.raises(eret):
|
|
178
196
|
s_json.reqjsonsafe(item)
|
|
179
197
|
|
|
180
|
-
text
|
|
198
|
+
for text in ['😀', 'asdf', 'asdf"', '"asdf']:
|
|
199
|
+
s_json.reqjsonsafe(text)
|
|
200
|
+
|
|
201
|
+
text = ['😀\ud83d\ude47']
|
|
181
202
|
s_json.reqjsonsafe(text)
|
|
182
203
|
with self.raises(s_exc.MustBeJsonSafe) as exc:
|
|
183
204
|
s_json.reqjsonsafe(text, strict=True)
|
|
184
|
-
self.eq(exc.exception.get('mesg'), '
|
|
205
|
+
self.eq(exc.exception.get('mesg'), "'utf-8' codec can't encode characters in position 1-2: surrogates not allowed")
|
|
206
|
+
|
|
207
|
+
with self.raises(s_exc.MustBeJsonSafe) as exc:
|
|
208
|
+
s_json.reqjsonsafe(b'1234', strict=True)
|
|
209
|
+
self.eq(exc.exception.get('mesg'), 'Object of type bytes is not JSON serializable')
|
|
185
210
|
|
|
186
211
|
async def test_lib_json_data_at_rest(self):
|
|
187
212
|
async with self.getRegrCore('json-data') as core:
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import synapse.tests.utils as s_test
|
|
2
|
+
|
|
3
|
+
class EntityModelTest(s_test.SynTest):
|
|
4
|
+
|
|
5
|
+
async def test_entity_relationship(self):
|
|
6
|
+
|
|
7
|
+
async with self.getTestCore() as core:
|
|
8
|
+
|
|
9
|
+
nodes = await core.nodes('''[
|
|
10
|
+
entity:relationship=*
|
|
11
|
+
:type=tasks
|
|
12
|
+
:period=(2022, ?)
|
|
13
|
+
:source={[ ou:org=({"name": "China Ministry of State Security (MSS)"}) ]}
|
|
14
|
+
:target={[ risk:threat=({"org:name": "APT34", "reporter:name": "vertex"}) ]}
|
|
15
|
+
]''')
|
|
16
|
+
|
|
17
|
+
self.len(1, nodes)
|
|
18
|
+
self.eq(nodes[0].get('type'), 'tasks.')
|
|
19
|
+
self.eq(nodes[0].get('period'), (1640995200000, 9223372036854775807))
|
|
20
|
+
self.eq(nodes[0].get('source'), ('ou:org', '3332a704ed21dc3274d5731acc54a0ee'))
|
|
21
|
+
self.eq(nodes[0].get('target'), ('risk:threat', 'e15738ebae52273300b51c08eaad3a36'))
|
synapse/tests/test_model_inet.py
CHANGED
|
@@ -3164,6 +3164,7 @@ class InetModelTest(s_t_utils.SynTest):
|
|
|
3164
3164
|
:creator=$visiiden
|
|
3165
3165
|
:platform=$platiden
|
|
3166
3166
|
:instance=$instiden
|
|
3167
|
+
:topic=' My Topic '
|
|
3167
3168
|
]
|
|
3168
3169
|
'''
|
|
3169
3170
|
opts = {'vars': {
|
|
@@ -3175,6 +3176,7 @@ class InetModelTest(s_t_utils.SynTest):
|
|
|
3175
3176
|
self.len(1, nodes)
|
|
3176
3177
|
self.eq(nodes[0].ndef, ('inet:service:channel', s_common.guid(('general', 'channel', 'vertex', 'slack'))))
|
|
3177
3178
|
self.eq(nodes[0].get('name'), 'general')
|
|
3179
|
+
self.eq(nodes[0].get('topic'), 'my topic')
|
|
3178
3180
|
self.eq(nodes[0].get('period'), (1420070400000, 9223372036854775807))
|
|
3179
3181
|
self.eq(nodes[0].get('creator'), visiacct.ndef[1])
|
|
3180
3182
|
self.eq(nodes[0].get('platform'), platform.ndef[1])
|
|
@@ -3243,12 +3245,18 @@ class InetModelTest(s_t_utils.SynTest):
|
|
|
3243
3245
|
:group=$devsiden
|
|
3244
3246
|
:public=$lib.false
|
|
3245
3247
|
:repost=*
|
|
3248
|
+
:mentions=(
|
|
3249
|
+
(inet:service:group, $devsiden),
|
|
3250
|
+
(inet:service:account, $blckiden),
|
|
3251
|
+
(inet:service:account, $blckiden),
|
|
3252
|
+
)
|
|
3246
3253
|
)
|
|
3247
3254
|
|
|
3248
3255
|
(inet:service:message=(blackout, visi, 1715856900000, vertex, slack)
|
|
3249
3256
|
:type=chat.direct
|
|
3250
3257
|
:to=$visiiden
|
|
3251
3258
|
:public=$lib.false
|
|
3259
|
+
:mentions?=((inet:service:message:attachment, $atchiden),)
|
|
3252
3260
|
)
|
|
3253
3261
|
|
|
3254
3262
|
(inet:service:message=(blackout, general, 1715856900000, vertex, slack)
|
|
@@ -3296,10 +3304,15 @@ class InetModelTest(s_t_utils.SynTest):
|
|
|
3296
3304
|
self.eq(nodes[0].get('group'), devsgrp.ndef[1])
|
|
3297
3305
|
self.false(nodes[0].get('public'))
|
|
3298
3306
|
self.eq(nodes[0].get('type'), 'chat.group.')
|
|
3307
|
+
self.eq(
|
|
3308
|
+
nodes[0].get('mentions'),
|
|
3309
|
+
(('inet:service:account', blckacct.ndef[1]), ('inet:service:group', devsgrp.ndef[1]))
|
|
3310
|
+
)
|
|
3299
3311
|
|
|
3300
3312
|
self.eq(nodes[1].get('to'), visiacct.ndef[1])
|
|
3301
3313
|
self.false(nodes[1].get('public'))
|
|
3302
3314
|
self.eq(nodes[1].get('type'), 'chat.direct.')
|
|
3315
|
+
self.none(nodes[1].get('mentions'))
|
|
3303
3316
|
|
|
3304
3317
|
self.eq(nodes[2].get('channel'), gnrlchan.ndef[1])
|
|
3305
3318
|
self.true(nodes[2].get('public'))
|
|
@@ -3397,6 +3410,7 @@ class InetModelTest(s_t_utils.SynTest):
|
|
|
3397
3410
|
q = '''
|
|
3398
3411
|
[ inet:service:message=(visi, says, relax)
|
|
3399
3412
|
:title="Hehe Haha"
|
|
3413
|
+
:hashtags="#hehe,#haha,#hehe"
|
|
3400
3414
|
:thread={[
|
|
3401
3415
|
inet:service:thread=*
|
|
3402
3416
|
:title="Woot Woot"
|
|
@@ -3410,6 +3424,7 @@ class InetModelTest(s_t_utils.SynTest):
|
|
|
3410
3424
|
'''
|
|
3411
3425
|
nodes = await core.nodes(q)
|
|
3412
3426
|
self.len(1, nodes)
|
|
3427
|
+
self.eq(['#haha', '#hehe'], nodes[0].get('hashtags'))
|
|
3413
3428
|
self.len(1, await core.nodes('inet:service:message=(visi, says, hello) -> inet:service:thread:message'))
|
|
3414
3429
|
self.len(1, await core.nodes('''
|
|
3415
3430
|
inet:service:message:title="hehe haha"
|
|
@@ -151,6 +151,10 @@ class PsModelTest(s_t_utils.SynTest):
|
|
|
151
151
|
'users': ('visi', 'invisigoth'),
|
|
152
152
|
'crypto:address': 'btc/1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2',
|
|
153
153
|
'langs': (lang00 := s_common.guid(),),
|
|
154
|
+
'banner': file0,
|
|
155
|
+
'passwd': 'hunter2',
|
|
156
|
+
'website': 'https://blogs.vertex.link/brutus',
|
|
157
|
+
'websites': ('https://foo.com', 'https://bar.com', 'https://foo.com'),
|
|
154
158
|
}
|
|
155
159
|
opts = {'vars': {'valu': con0, 'p': props}}
|
|
156
160
|
q = '''[(ps:contact=$valu
|
|
@@ -172,6 +176,10 @@ class PsModelTest(s_t_utils.SynTest):
|
|
|
172
176
|
:death:place=$p."death:place" :death:place:loc=$p."death:place:loc"
|
|
173
177
|
:death:place:name=$p."death:place:name"
|
|
174
178
|
:service:accounts=(*, *) :langs=$p.langs
|
|
179
|
+
:banner=$p.banner
|
|
180
|
+
:passwd=$p.passwd
|
|
181
|
+
:website=$p.website
|
|
182
|
+
:websites=$p.websites
|
|
175
183
|
)]'''
|
|
176
184
|
nodes = await core.nodes(q, opts=opts)
|
|
177
185
|
self.len(1, nodes)
|
|
@@ -215,6 +223,10 @@ class PsModelTest(s_t_utils.SynTest):
|
|
|
215
223
|
self.eq(node.get('death:place:loc'), 'us.va.reston')
|
|
216
224
|
self.eq(node.get('birth:place:name'), 'reston, va, usa, earth, sol, milkyway')
|
|
217
225
|
self.eq(node.get('death:place:name'), 'reston, va, usa, earth, sol, milkyway')
|
|
226
|
+
self.eq(node.get('banner'), file0)
|
|
227
|
+
self.eq(node.get('passwd'), 'hunter2')
|
|
228
|
+
self.eq(node.get('website'), 'https://blogs.vertex.link/brutus')
|
|
229
|
+
self.eq(node.get('websites'), ('https://bar.com', 'https://foo.com'))
|
|
218
230
|
self.len(1, await core.nodes('ps:contact :birth:place -> geo:place'))
|
|
219
231
|
self.len(1, await core.nodes('ps:contact :death:place -> geo:place'))
|
|
220
232
|
self.len(2, await core.nodes('ps:contact :service:accounts -> inet:service:account'))
|
synapse/tests/test_telepath.py
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import ssl
|
|
3
|
+
import sys
|
|
3
4
|
import socket
|
|
4
5
|
import asyncio
|
|
5
6
|
import logging
|
|
6
|
-
import
|
|
7
|
+
import multiprocessing
|
|
7
8
|
|
|
8
9
|
from unittest import mock
|
|
9
10
|
|
|
10
11
|
import cryptography.hazmat.primitives.hashes as c_hashes
|
|
11
12
|
|
|
12
13
|
import synapse.exc as s_exc
|
|
13
|
-
import synapse.glob as s_glob
|
|
14
14
|
import synapse.common as s_common
|
|
15
15
|
import synapse.daemon as s_daemon
|
|
16
16
|
import synapse.telepath as s_telepath
|
|
@@ -189,6 +189,40 @@ class TeleAuth(s_telepath.Aware):
|
|
|
189
189
|
def getFooBar(self, x, y):
|
|
190
190
|
return x + y
|
|
191
191
|
|
|
192
|
+
def run_telepath_sync_genr_break(url: str,
|
|
193
|
+
evt1: multiprocessing.Event,
|
|
194
|
+
evt2: multiprocessing.Event,):
|
|
195
|
+
'''
|
|
196
|
+
This is a Process target.
|
|
197
|
+
'''
|
|
198
|
+
with s_telepath.openurl(url) as prox:
|
|
199
|
+
form = 'test:int'
|
|
200
|
+
|
|
201
|
+
q = '[' + ' '.join([f'{form}={i}' for i in range(10)]) + ' ]'
|
|
202
|
+
|
|
203
|
+
# This puts a link into the link pool
|
|
204
|
+
emesg = 12
|
|
205
|
+
msgs = list(prox.storm(q, opts={'show': ('node', 'nodeedits')}))
|
|
206
|
+
assert len(msgs) == emesg, f'Got {len(msgs)} messages, expected {emesg}'
|
|
207
|
+
|
|
208
|
+
# Get the link from the pool, add the fini callback and put it back
|
|
209
|
+
# This involves reaching into the proxy internals to do so.
|
|
210
|
+
link = prox.links.popleft()
|
|
211
|
+
link.onfini(evt1.set)
|
|
212
|
+
prox.links.append(link)
|
|
213
|
+
|
|
214
|
+
# Break from the generator right away, causing a
|
|
215
|
+
# GeneratorExit in the GenrHelp object __iter__ method.
|
|
216
|
+
mesg = None
|
|
217
|
+
for mesg in prox.storm(q):
|
|
218
|
+
break
|
|
219
|
+
# Ensure the query did yield an object
|
|
220
|
+
assert mesg is not None, 'mesg was not recieved!'
|
|
221
|
+
assert link.isfini is True, 'link.fini was not set to true'
|
|
222
|
+
|
|
223
|
+
evt2.set()
|
|
224
|
+
sys.exit(137)
|
|
225
|
+
|
|
192
226
|
class TeleTest(s_t_utils.SynTest):
|
|
193
227
|
|
|
194
228
|
async def test_telepath_basics(self):
|
|
@@ -296,47 +330,20 @@ class TeleTest(s_t_utils.SynTest):
|
|
|
296
330
|
async with await s_telepath.openurl('tcp://127.0.0.1/foo', port=dmon.addr[1]) as prox:
|
|
297
331
|
self.eq((10, 20, 30), await s_coro.executor(sync))
|
|
298
332
|
|
|
299
|
-
def test_telepath_sync_genr_break(self):
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
acm = self.getTestCoreAndProxy()
|
|
303
|
-
core, proxy = s_glob.sync(acm.__aenter__())
|
|
304
|
-
|
|
305
|
-
form = 'test:int'
|
|
306
|
-
|
|
307
|
-
q = '[' + ' '.join([f'{form}={i}' for i in range(10)]) + ' ]'
|
|
308
|
-
|
|
309
|
-
# This puts a link into the link pool
|
|
310
|
-
msgs = list(proxy.storm(q, opts={'show': ('node',)}))
|
|
311
|
-
self.len(12, msgs)
|
|
333
|
+
async def test_telepath_sync_genr_break(self):
|
|
334
|
+
async with self.getTestCore() as core:
|
|
335
|
+
url = core.getLocalUrl()
|
|
312
336
|
|
|
313
|
-
|
|
337
|
+
ctx = multiprocessing.get_context('spawn')
|
|
338
|
+
evt1 = ctx.Event()
|
|
339
|
+
evt2 = ctx.Event()
|
|
340
|
+
proc = ctx.Process(target=run_telepath_sync_genr_break, args=(url, evt1, evt2))
|
|
341
|
+
proc.start()
|
|
314
342
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
# Grab the fresh link from the pool so our original link is up next again
|
|
321
|
-
link2 = s_glob.sync(proxy.getPoolLink())
|
|
322
|
-
s_glob.sync(proxy._putPoolLink(link2))
|
|
323
|
-
|
|
324
|
-
q = f'{form} | sleep 0.1'
|
|
325
|
-
|
|
326
|
-
# Break from the generator right away, causing a
|
|
327
|
-
# GeneratorExit in the GenrHelp object __iter__ method.
|
|
328
|
-
mesg = None
|
|
329
|
-
for mesg in proxy.storm(q):
|
|
330
|
-
break
|
|
331
|
-
# Ensure the query did yield an object
|
|
332
|
-
self.nn(mesg)
|
|
333
|
-
|
|
334
|
-
# Ensure the link we have a reference too was torn down
|
|
335
|
-
self.true(evt.wait(4))
|
|
336
|
-
self.true(link.isfini)
|
|
337
|
-
|
|
338
|
-
finally:
|
|
339
|
-
s_glob.sync(acm.__aexit__(None, None, None))
|
|
343
|
+
self.true(await s_coro.executor(evt1.wait, timeout=30))
|
|
344
|
+
self.true(await s_coro.executor(evt2.wait, timeout=30))
|
|
345
|
+
proc.join(timeout=30)
|
|
346
|
+
self.eq(proc.exitcode, 137)
|
|
340
347
|
|
|
341
348
|
async def test_telepath_no_sess(self):
|
|
342
349
|
|
|
@@ -1016,6 +1023,10 @@ class TeleTest(s_t_utils.SynTest):
|
|
|
1016
1023
|
self.len(1, await wait.wait(timeout=5))
|
|
1017
1024
|
self.len(12, prox.links)
|
|
1018
1025
|
|
|
1026
|
+
# Cleanup our global state
|
|
1027
|
+
prox2._all_proxies.remove(prox2)
|
|
1028
|
+
await prox.fini()
|
|
1029
|
+
|
|
1019
1030
|
async def test_link_fini_breaking_tasks(self):
|
|
1020
1031
|
foo = Foo()
|
|
1021
1032
|
|
synapse/tests/test_tools_aha.py
CHANGED
|
@@ -38,7 +38,7 @@ class AhaToolsTest(s_t_utils.SynTest):
|
|
|
38
38
|
self.true(await waiter.wait(timeout=6))
|
|
39
39
|
|
|
40
40
|
argv = [ahaurl]
|
|
41
|
-
retn, outp = await self.execToolMain(s_a_list.
|
|
41
|
+
retn, outp = await self.execToolMain(s_a_list.main, argv)
|
|
42
42
|
self.eq(retn, 0)
|
|
43
43
|
|
|
44
44
|
outp.expect('''
|
|
@@ -48,7 +48,7 @@ class AhaToolsTest(s_t_utils.SynTest):
|
|
|
48
48
|
''', whitespace=False)
|
|
49
49
|
|
|
50
50
|
argv = [ahaurl, 'demo.net']
|
|
51
|
-
retn, outp = await self.execToolMain(s_a_list.
|
|
51
|
+
retn, outp = await self.execToolMain(s_a_list.main, argv)
|
|
52
52
|
self.eq(retn, 0)
|
|
53
53
|
outp.expect('Service network', whitespace=False)
|
|
54
54
|
outp.expect('cell0 demo.net', whitespace=False)
|
|
@@ -56,7 +56,7 @@ class AhaToolsTest(s_t_utils.SynTest):
|
|
|
56
56
|
async with self.getTestCore() as core:
|
|
57
57
|
curl = core.getLocalUrl()
|
|
58
58
|
argv = [curl]
|
|
59
|
-
retn, outp = await self.execToolMain(s_a_list.
|
|
59
|
+
retn, outp = await self.execToolMain(s_a_list.main, argv)
|
|
60
60
|
self.eq(1, retn)
|
|
61
61
|
outp.expect(f'Service at {curl} is not an Aha server')
|
|
62
62
|
|
|
@@ -67,18 +67,17 @@ class AhaToolsTest(s_t_utils.SynTest):
|
|
|
67
67
|
'dmon:listen': ephemeral_address}) as aha:
|
|
68
68
|
_, port = aha.sockaddr
|
|
69
69
|
ahaurl = f'tcp://root:root@127.0.0.1:{port}'
|
|
70
|
-
|
|
71
|
-
with self.getTestDir() as dirn:
|
|
70
|
+
with self.getTestSynDir() as syndir, self.getTestDir() as dirn:
|
|
72
71
|
argvbase = ['-a', ahaurl, '--certdir', dirn]
|
|
73
72
|
argv = argvbase + ['--ca', 'demo.net']
|
|
74
|
-
retn, outp = await self.execToolMain(s_a_easycert.
|
|
73
|
+
retn, outp = await self.execToolMain(s_a_easycert.main, argv)
|
|
75
74
|
self.eq(retn, 0)
|
|
76
75
|
outp.expect('Saved CA cert')
|
|
77
76
|
outp.expect('cas/demo.net.crt')
|
|
78
77
|
|
|
79
78
|
argv = argvbase + ['--server', '--server-sans', 'DNS:beeper.demo.net,DNS:booper.demo.net',
|
|
80
79
|
'--network', 'demo.net', 'beep.demo.net']
|
|
81
|
-
retn, outp = await self.execToolMain(s_a_easycert.
|
|
80
|
+
retn, outp = await self.execToolMain(s_a_easycert.main, argv)
|
|
82
81
|
self.eq(retn, 0)
|
|
83
82
|
outp.expect('key saved')
|
|
84
83
|
outp.expect('hosts/beep.demo.net.key')
|
|
@@ -86,7 +85,7 @@ class AhaToolsTest(s_t_utils.SynTest):
|
|
|
86
85
|
outp.expect('hosts/beep.demo.net.crt')
|
|
87
86
|
|
|
88
87
|
argv = argvbase + ['--network', 'demo.net', 'mallory@demo.net']
|
|
89
|
-
retn, outp = await self.execToolMain(s_a_easycert.
|
|
88
|
+
retn, outp = await self.execToolMain(s_a_easycert.main, argv)
|
|
90
89
|
self.eq(retn, 0)
|
|
91
90
|
outp.expect('key saved')
|
|
92
91
|
outp.expect('users/mallory@demo.net.key')
|
synapse/tests/utils.py
CHANGED
synapse/tools/aha/clone.py
CHANGED
|
@@ -5,6 +5,7 @@ import argparse
|
|
|
5
5
|
import synapse.exc as s_exc
|
|
6
6
|
import synapse.telepath as s_telepath
|
|
7
7
|
|
|
8
|
+
import synapse.lib.coro as s_coro
|
|
8
9
|
import synapse.lib.output as s_output
|
|
9
10
|
|
|
10
11
|
descr = '''
|
|
@@ -48,5 +49,10 @@ async def main(argv, outp=s_output.stdout):
|
|
|
48
49
|
outp.printf(f'ERROR: {mesg}')
|
|
49
50
|
return 1
|
|
50
51
|
|
|
52
|
+
async def _main(argv, outp=s_output.stdout): # pragma: no cover
|
|
53
|
+
ret = await main(argv, outp=outp)
|
|
54
|
+
await asyncio.wait_for(s_coro.await_bg_tasks(), timeout=60)
|
|
55
|
+
return ret
|
|
56
|
+
|
|
51
57
|
if __name__ == '__main__': # pragma: no cover
|
|
52
|
-
sys.exit(asyncio.run(
|
|
58
|
+
sys.exit(asyncio.run(_main(sys.argv[1:])))
|
synapse/tools/aha/easycert.py
CHANGED
|
@@ -8,13 +8,14 @@ import cryptography.x509 as c_x509
|
|
|
8
8
|
import synapse.common as s_common
|
|
9
9
|
import synapse.telepath as s_telepath
|
|
10
10
|
|
|
11
|
+
import synapse.lib.coro as s_coro
|
|
11
12
|
import synapse.lib.output as s_output
|
|
12
13
|
import synapse.lib.certdir as s_certdir
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
logger = logging.getLogger(__name__)
|
|
16
17
|
|
|
17
|
-
async def
|
|
18
|
+
async def main(argv, outp=s_output.stdout):
|
|
18
19
|
pars = getArgParser()
|
|
19
20
|
opts = pars.parse_args(argv)
|
|
20
21
|
|
|
@@ -22,36 +23,36 @@ async def _main(argv, outp):
|
|
|
22
23
|
s_common.deprecated('--network option.', curv='v2.206.0')
|
|
23
24
|
|
|
24
25
|
cdir = s_certdir.CertDir(path=opts.certdir)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
26
|
+
async with s_telepath.withTeleEnv():
|
|
27
|
+
async with await s_telepath.openurl(opts.aha) as prox:
|
|
28
|
+
|
|
29
|
+
name = opts.name
|
|
30
|
+
|
|
31
|
+
if opts.ca:
|
|
32
|
+
# A User may only have get permissions; so try get first
|
|
33
|
+
# before attempting to generate a new CA.
|
|
34
|
+
certbyts = await prox.getCaCert(name)
|
|
35
|
+
if not certbyts:
|
|
36
|
+
s_common.deprecated('AHA CA certificate generation.', curv='v2.206.0')
|
|
37
|
+
certbyts = await prox.genCaCert(name)
|
|
38
|
+
cert = c_x509.load_pem_x509_certificate(certbyts.encode())
|
|
39
|
+
path = cdir._saveCertTo(cert, 'cas', f'{name}.crt')
|
|
40
|
+
outp.printf(f'Saved CA cert to {path}')
|
|
41
|
+
return 0
|
|
42
|
+
elif opts.server:
|
|
43
|
+
csr = cdir.genHostCsr(name, outp=outp)
|
|
44
|
+
certbyts = await prox.signHostCsr(csr.decode(), signas=opts.network, sans=opts.server_sans)
|
|
45
|
+
cert = c_x509.load_pem_x509_certificate(certbyts.encode())
|
|
46
|
+
path = cdir._saveCertTo(cert, 'hosts', f'{name}.crt')
|
|
47
|
+
outp.printf(f'crt saved: {path}')
|
|
48
|
+
return 0
|
|
49
|
+
else:
|
|
50
|
+
csr = cdir.genUserCsr(name, outp=outp)
|
|
51
|
+
certbyts = await prox.signUserCsr(csr.decode(), signas=opts.network)
|
|
52
|
+
cert = c_x509.load_pem_x509_certificate(certbyts.encode())
|
|
53
|
+
path = cdir._saveCertTo(cert, 'users', f'{name}.crt')
|
|
54
|
+
outp.printf(f'crt saved: {path}')
|
|
55
|
+
return 0
|
|
55
56
|
|
|
56
57
|
def getArgParser():
|
|
57
58
|
desc = 'CLI tool to generate simple x509 certificates from an Aha server.'
|
|
@@ -74,17 +75,11 @@ def getArgParser():
|
|
|
74
75
|
|
|
75
76
|
return pars
|
|
76
77
|
|
|
77
|
-
async def
|
|
78
|
-
|
|
79
|
-
if outp is None:
|
|
80
|
-
outp = s_output.stdout
|
|
81
|
-
|
|
78
|
+
async def _main(argv, outp=s_output.stdout): # pragma: no cover
|
|
82
79
|
s_common.setlogging(logger, 'WARNING')
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
return 0
|
|
80
|
+
ret = await main(argv, outp=outp)
|
|
81
|
+
await asyncio.wait_for(s_coro.await_bg_tasks(), timeout=60)
|
|
82
|
+
return ret
|
|
88
83
|
|
|
89
84
|
if __name__ == '__main__': # pragma: no cover
|
|
90
|
-
sys.exit(asyncio.run(
|
|
85
|
+
sys.exit(asyncio.run(_main(sys.argv[1:])))
|
synapse/tools/aha/enroll.py
CHANGED
|
@@ -6,6 +6,7 @@ import argparse
|
|
|
6
6
|
import synapse.common as s_common
|
|
7
7
|
import synapse.telepath as s_telepath
|
|
8
8
|
|
|
9
|
+
import synapse.lib.coro as s_coro
|
|
9
10
|
import synapse.lib.output as s_output
|
|
10
11
|
import synapse.lib.certdir as s_certdir
|
|
11
12
|
import synapse.lib.msgpack as s_msgpack
|
|
@@ -99,5 +100,10 @@ async def main(argv, outp=s_output.stdout):
|
|
|
99
100
|
|
|
100
101
|
return 0
|
|
101
102
|
|
|
103
|
+
async def _main(argv, outp=s_output.stdout): # pragma: no cover
|
|
104
|
+
ret = await main(argv, outp=outp)
|
|
105
|
+
await asyncio.wait_for(s_coro.await_bg_tasks(), timeout=60)
|
|
106
|
+
return ret
|
|
107
|
+
|
|
102
108
|
if __name__ == '__main__': # pragma: no cover
|
|
103
|
-
sys.exit(asyncio.run(
|
|
109
|
+
sys.exit(asyncio.run(_main(sys.argv[1:])))
|