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.

Files changed (53) hide show
  1. synapse/lib/cell.py +14 -4
  2. synapse/lib/coro.py +5 -0
  3. synapse/lib/json.py +48 -22
  4. synapse/lib/nexus.py +6 -0
  5. synapse/lib/storm.py +10 -2
  6. synapse/lib/stormlib/auth.py +6 -0
  7. synapse/lib/stormlib/notifications.py +12 -2
  8. synapse/lib/version.py +2 -2
  9. synapse/models/entity.py +26 -0
  10. synapse/models/inet.py +11 -0
  11. synapse/models/person.py +9 -2
  12. synapse/tests/test_cortex.py +3 -3
  13. synapse/tests/test_lib_aha.py +1 -1
  14. synapse/tests/test_lib_cell.py +28 -8
  15. synapse/tests/test_lib_coro.py +23 -0
  16. synapse/tests/test_lib_json.py +41 -16
  17. synapse/tests/test_model_entity.py +21 -0
  18. synapse/tests/test_model_gov_intl.py +2 -2
  19. synapse/tests/test_model_inet.py +15 -0
  20. synapse/tests/test_model_media.py +1 -0
  21. synapse/tests/test_model_person.py +12 -0
  22. synapse/tests/test_telepath.py +52 -41
  23. synapse/tests/test_tools_aha.py +7 -8
  24. synapse/tests/utils.py +1 -1
  25. synapse/tools/aha/clone.py +7 -1
  26. synapse/tools/aha/easycert.py +37 -42
  27. synapse/tools/aha/enroll.py +7 -1
  28. synapse/tools/aha/list.py +60 -65
  29. synapse/tools/aha/mirror.py +7 -1
  30. synapse/tools/aha/provision/service.py +7 -1
  31. synapse/tools/aha/provision/user.py +7 -1
  32. synapse/tools/apikey.py +8 -1
  33. synapse/tools/axon2axon.py +7 -1
  34. synapse/tools/cellauth.py +6 -5
  35. synapse/tools/cmdr.py +2 -1
  36. synapse/tools/csvtool.py +7 -2
  37. synapse/tools/feed.py +8 -2
  38. synapse/tools/genpkg.py +7 -1
  39. synapse/tools/healthcheck.py +7 -1
  40. synapse/tools/livebackup.py +7 -3
  41. synapse/tools/modrole.py +7 -1
  42. synapse/tools/moduser.py +7 -2
  43. synapse/tools/promote.py +7 -3
  44. synapse/tools/pullfile.py +6 -1
  45. synapse/tools/pushfile.py +7 -1
  46. synapse/tools/reload.py +7 -4
  47. synapse/tools/snapshot.py +7 -1
  48. synapse/tools/storm.py +7 -1
  49. {synapse-2.209.0.dist-info → synapse-2.210.0.dist-info}/METADATA +2 -2
  50. {synapse-2.209.0.dist-info → synapse-2.210.0.dist-info}/RECORD +53 -52
  51. {synapse-2.209.0.dist-info → synapse-2.210.0.dist-info}/WHEEL +1 -1
  52. {synapse-2.209.0.dist-info → synapse-2.210.0.dist-info}/licenses/LICENSE +0 -0
  53. {synapse-2.209.0.dist-info → synapse-2.210.0.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,7 @@
1
1
  import io
2
2
  import json
3
3
 
4
- import orjson
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
- # orjson.dumps fails because of the surrogate pairs
48
- with self.raises(orjson.JSONDecodeError):
49
- orjson.loads(inval)
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
- # orjson.dumps fails because of the surrogate pairs
67
- with self.raises(TypeError):
68
- orjson.dumps(inval)
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'), 'Type is not JSON serializable: dict_items')
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'), 'Dict key must be str')
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'), 'Object of type dict_items is not JSON serializable')
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('Type is not JSON serializable: _io.BytesIO', exc.exception.get('mesg'))
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('Type is not JSON serializable: _io.BytesIO', exc.exception.get('mesg'))
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('Type is not JSON serializable: _io.BytesIO', exc.exception.get('mesg'))
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 = '😀\ud83d\ude47'
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'), 'str is not valid UTF-8: surrogates not allowed')
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'))
@@ -1,6 +1,6 @@
1
- from synapse.tests.utils import SynTest
1
+ import synapse.tests.utils as s_t_utils
2
2
 
3
- class IntlGovTest(SynTest):
3
+ class IntlGovTest(s_t_utils.SynTest):
4
4
 
5
5
  async def test_models_intl(self):
6
6
 
@@ -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"
@@ -1,5 +1,6 @@
1
1
  import logging
2
2
 
3
+ import synapse.exc as s_exc
3
4
  import synapse.common as s_common
4
5
 
5
6
  import synapse.tests.utils as s_t_utils
@@ -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'))
@@ -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 threading
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
- try:
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
- evt = threading.Event()
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
- # Get the link from the pool, add the fini callback and put it back
316
- link = s_glob.sync(proxy.getPoolLink())
317
- link.onfini(evt.set)
318
- s_glob.sync(proxy._putPoolLink(link))
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
 
@@ -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._main, argv)
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._main, argv)
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._main, argv)
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._main, argv)
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._main, argv)
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._main, argv)
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
@@ -864,7 +864,7 @@ class HttpReflector(s_httpapi.Handler):
864
864
  for k, items in self.request.arguments.items():
865
865
  for v in items:
866
866
  d[k].append(v.decode())
867
- return d
867
+ return dict(d)
868
868
 
869
869
  async def get(self):
870
870
  resp = {}
@@ -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(main(sys.argv[1:])))
58
+ sys.exit(asyncio.run(_main(sys.argv[1:])))
@@ -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 _main(argv, outp):
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
- async with await s_telepath.openurl(opts.aha) as prox:
27
-
28
- name = opts.name
29
-
30
- if opts.ca:
31
- # A User may only have get permissions; so try get first
32
- # before attempting to generate a new CA.
33
- certbyts = await prox.getCaCert(name)
34
- if not certbyts:
35
- s_common.deprecated('AHA CA certificate generation.', curv='v2.206.0')
36
- certbyts = await prox.genCaCert(name)
37
- cert = c_x509.load_pem_x509_certificate(certbyts.encode())
38
- path = cdir._saveCertTo(cert, 'cas', f'{name}.crt')
39
- outp.printf(f'Saved CA cert to {path}')
40
- return 0
41
- elif opts.server:
42
- csr = cdir.genHostCsr(name, outp=outp)
43
- certbyts = await prox.signHostCsr(csr.decode(), signas=opts.network, sans=opts.server_sans)
44
- cert = c_x509.load_pem_x509_certificate(certbyts.encode())
45
- path = cdir._saveCertTo(cert, 'hosts', f'{name}.crt')
46
- outp.printf(f'crt saved: {path}')
47
- return 0
48
- else:
49
- csr = cdir.genUserCsr(name, outp=outp)
50
- certbyts = await prox.signUserCsr(csr.decode(), signas=opts.network)
51
- cert = c_x509.load_pem_x509_certificate(certbyts.encode())
52
- path = cdir._saveCertTo(cert, 'users', f'{name}.crt')
53
- outp.printf(f'crt saved: {path}')
54
- return 0
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 main(argv, outp=None): # pragma: no cover
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
- async with s_telepath.withTeleEnv():
85
- await _main(argv, outp)
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(main(sys.argv[1:])))
85
+ sys.exit(asyncio.run(_main(sys.argv[1:])))
@@ -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(main(sys.argv[1:])))
109
+ sys.exit(asyncio.run(_main(sys.argv[1:])))