synapse 2.164.0__py311-none-any.whl → 2.166.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 +3 -3
- synapse/cmds/cortex.py +1 -6
- synapse/common.py +7 -1
- synapse/cortex.py +145 -192
- synapse/datamodel.py +36 -1
- synapse/lib/agenda.py +87 -97
- synapse/lib/aha.py +51 -0
- synapse/lib/ast.py +22 -23
- synapse/lib/base.py +0 -6
- synapse/lib/boss.py +3 -0
- synapse/lib/cell.py +70 -39
- synapse/lib/certdir.py +9 -0
- synapse/lib/hiveauth.py +65 -12
- synapse/lib/httpapi.py +1 -0
- synapse/lib/modelrev.py +121 -33
- synapse/lib/modules.py +1 -0
- synapse/lib/nexus.py +64 -26
- synapse/lib/parser.py +2 -0
- synapse/lib/schemas.py +14 -0
- synapse/lib/snap.py +50 -4
- synapse/lib/storm.lark +4 -3
- synapse/lib/storm.py +96 -22
- synapse/lib/storm_format.py +1 -0
- synapse/lib/stormlib/aha.py +7 -1
- synapse/lib/stormlib/auth.py +13 -5
- synapse/lib/stormlib/cache.py +202 -0
- synapse/lib/stormlib/cortex.py +147 -8
- synapse/lib/stormlib/gen.py +53 -6
- synapse/lib/stormlib/math.py +1 -1
- synapse/lib/stormlib/model.py +11 -1
- synapse/lib/stormlib/spooled.py +109 -0
- synapse/lib/stormlib/vault.py +1 -1
- synapse/lib/stormtypes.py +113 -17
- synapse/lib/trigger.py +36 -47
- synapse/lib/types.py +29 -2
- synapse/lib/version.py +2 -2
- synapse/lib/view.py +80 -53
- synapse/models/economic.py +174 -5
- synapse/models/files.py +2 -0
- synapse/models/inet.py +77 -2
- synapse/models/infotech.py +12 -12
- synapse/models/orgs.py +72 -21
- synapse/models/person.py +40 -11
- synapse/models/risk.py +78 -24
- synapse/models/science.py +102 -0
- synapse/telepath.py +117 -35
- synapse/tests/test_cortex.py +84 -158
- synapse/tests/test_datamodel.py +22 -0
- synapse/tests/test_lib_agenda.py +52 -96
- synapse/tests/test_lib_aha.py +126 -4
- synapse/tests/test_lib_ast.py +412 -6
- synapse/tests/test_lib_cell.py +24 -8
- synapse/tests/test_lib_certdir.py +32 -0
- synapse/tests/test_lib_grammar.py +9 -1
- synapse/tests/test_lib_httpapi.py +0 -1
- synapse/tests/test_lib_jupyter.py +0 -1
- synapse/tests/test_lib_modelrev.py +41 -0
- synapse/tests/test_lib_nexus.py +38 -0
- synapse/tests/test_lib_storm.py +95 -5
- synapse/tests/test_lib_stormlib_cache.py +272 -0
- synapse/tests/test_lib_stormlib_cortex.py +71 -0
- synapse/tests/test_lib_stormlib_gen.py +37 -2
- synapse/tests/test_lib_stormlib_model.py +2 -0
- synapse/tests/test_lib_stormlib_spooled.py +190 -0
- synapse/tests/test_lib_stormlib_vault.py +12 -3
- synapse/tests/test_lib_stormsvc.py +0 -10
- synapse/tests/test_lib_stormtypes.py +60 -8
- synapse/tests/test_lib_trigger.py +20 -2
- synapse/tests/test_lib_types.py +17 -1
- synapse/tests/test_model_economic.py +114 -0
- synapse/tests/test_model_files.py +2 -0
- synapse/tests/test_model_inet.py +73 -1
- synapse/tests/test_model_infotech.py +2 -2
- synapse/tests/test_model_orgs.py +10 -1
- synapse/tests/test_model_risk.py +30 -2
- synapse/tests/test_model_science.py +59 -0
- synapse/tests/test_model_syn.py +0 -1
- synapse/tests/test_telepath.py +30 -7
- synapse/tests/test_tools_modrole.py +81 -0
- synapse/tests/test_tools_moduser.py +105 -0
- synapse/tools/modrole.py +59 -7
- synapse/tools/moduser.py +78 -10
- {synapse-2.164.0.dist-info → synapse-2.166.0.dist-info}/METADATA +2 -2
- {synapse-2.164.0.dist-info → synapse-2.166.0.dist-info}/RECORD +87 -83
- {synapse-2.164.0.dist-info → synapse-2.166.0.dist-info}/WHEEL +1 -1
- synapse/lib/provenance.py +0 -111
- synapse/tests/test_lib_provenance.py +0 -37
- {synapse-2.164.0.dist-info → synapse-2.166.0.dist-info}/LICENSE +0 -0
- {synapse-2.164.0.dist-info → synapse-2.166.0.dist-info}/top_level.txt +0 -0
synapse/datamodel.py
CHANGED
|
@@ -116,6 +116,9 @@ class Prop:
|
|
|
116
116
|
self.setperms.append(('node', 'prop', 'set', form.name, self.name))
|
|
117
117
|
self.delperms.append(('node', 'prop', 'del', form.name, self.name))
|
|
118
118
|
|
|
119
|
+
self.setperms.reverse() # Make them in precedence order
|
|
120
|
+
self.delperms.reverse() # Make them in precedence order
|
|
121
|
+
|
|
119
122
|
self.form = form
|
|
120
123
|
self.type = None
|
|
121
124
|
self.typedef = typedef
|
|
@@ -870,10 +873,42 @@ class Model:
|
|
|
870
873
|
for ifname in form.type.info.get('interfaces', ()):
|
|
871
874
|
self._addFormIface(form, ifname)
|
|
872
875
|
|
|
876
|
+
self._checkFormDisplay(form)
|
|
877
|
+
|
|
873
878
|
self.formprefixcache.clear()
|
|
874
879
|
|
|
875
880
|
return form
|
|
876
881
|
|
|
882
|
+
def _checkFormDisplay(self, form):
|
|
883
|
+
|
|
884
|
+
formtype = self.types.get(form.full)
|
|
885
|
+
|
|
886
|
+
display = formtype.info.get('display')
|
|
887
|
+
if display is None:
|
|
888
|
+
return
|
|
889
|
+
|
|
890
|
+
for column in display.get('columns', ()):
|
|
891
|
+
coltype = column.get('type')
|
|
892
|
+
colopts = column.get('opts')
|
|
893
|
+
|
|
894
|
+
if coltype == 'prop':
|
|
895
|
+
curf = form
|
|
896
|
+
propname = colopts.get('name')
|
|
897
|
+
parts = propname.split('::')
|
|
898
|
+
|
|
899
|
+
for partname in parts:
|
|
900
|
+
prop = curf.prop(partname)
|
|
901
|
+
if prop is None:
|
|
902
|
+
mesg = (f'Form {form.name} defines prop column {propname}'
|
|
903
|
+
f' but {curf.full} has no property named {partname}.')
|
|
904
|
+
raise s_exc.BadFormDef(mesg=mesg)
|
|
905
|
+
|
|
906
|
+
curf = self.form(prop.type.name)
|
|
907
|
+
|
|
908
|
+
else:
|
|
909
|
+
mesg = f'Form {form.name} defines column with invalid type ({coltype}).'
|
|
910
|
+
raise s_exc.BadFormDef(mesg=mesg)
|
|
911
|
+
|
|
877
912
|
def delForm(self, formname):
|
|
878
913
|
|
|
879
914
|
form = self.forms.get(formname)
|
|
@@ -960,7 +995,7 @@ class Model:
|
|
|
960
995
|
iface = self.ifaces.get(name)
|
|
961
996
|
|
|
962
997
|
if iface is None:
|
|
963
|
-
mesg = f'Form {form.name} depends on non-
|
|
998
|
+
mesg = f'Form {form.name} depends on non-existent interface: {name}'
|
|
964
999
|
raise s_exc.NoSuchName(mesg=mesg)
|
|
965
1000
|
|
|
966
1001
|
if iface.get('deprecated'):
|
synapse/lib/agenda.py
CHANGED
|
@@ -16,7 +16,6 @@ import synapse.common as s_common
|
|
|
16
16
|
|
|
17
17
|
import synapse.lib.base as s_base
|
|
18
18
|
import synapse.lib.coro as s_coro
|
|
19
|
-
import synapse.lib.provenance as s_provenance
|
|
20
19
|
|
|
21
20
|
# Agenda: manages running one-shot and periodic tasks in the future ("appointments")
|
|
22
21
|
|
|
@@ -259,6 +258,7 @@ class _Appt:
|
|
|
259
258
|
_synced_attrs = {
|
|
260
259
|
'doc',
|
|
261
260
|
'name',
|
|
261
|
+
'pool',
|
|
262
262
|
'created',
|
|
263
263
|
'enabled',
|
|
264
264
|
'errcount',
|
|
@@ -271,10 +271,11 @@ class _Appt:
|
|
|
271
271
|
'lastfinishtime',
|
|
272
272
|
}
|
|
273
273
|
|
|
274
|
-
def __init__(self, stor, iden, recur, indx, query, creator, recs, nexttime=None, view=None, created=None):
|
|
274
|
+
def __init__(self, stor, iden, recur, indx, query, creator, recs, nexttime=None, view=None, created=None, pool=False):
|
|
275
275
|
self.doc = ''
|
|
276
276
|
self.name = ''
|
|
277
277
|
self.stor = stor
|
|
278
|
+
self.pool = pool
|
|
278
279
|
self.iden = iden
|
|
279
280
|
self.recur = recur # does this appointment repeat
|
|
280
281
|
self.indx = indx # incremented for each appt added ever. Used for nexttime tiebreaking for stable ordering
|
|
@@ -339,6 +340,7 @@ class _Appt:
|
|
|
339
340
|
'ver': 1,
|
|
340
341
|
'doc': self.doc,
|
|
341
342
|
'name': self.name,
|
|
343
|
+
'pool': self.pool,
|
|
342
344
|
'enabled': self.enabled,
|
|
343
345
|
'recur': self.recur,
|
|
344
346
|
'iden': self.iden,
|
|
@@ -366,6 +368,7 @@ class _Appt:
|
|
|
366
368
|
appt = cls(stor, val['iden'], val['recur'], val['indx'], val['query'], val['creator'], recs, nexttime=val['nexttime'], view=val.get('view'))
|
|
367
369
|
appt.doc = val.get('doc', '')
|
|
368
370
|
appt.name = val.get('name', '')
|
|
371
|
+
appt.pool = val.get('pool', False)
|
|
369
372
|
appt.created = val.get('created', None)
|
|
370
373
|
appt.laststarttime = val['laststarttime']
|
|
371
374
|
appt.lastfinishtime = val['lastfinishtime']
|
|
@@ -449,46 +452,9 @@ class Agenda(s_base.Base):
|
|
|
449
452
|
self.onfini(self._wake_event.set)
|
|
450
453
|
|
|
451
454
|
self._hivenode = await self.core.hive.open(('agenda', 'appts')) # Persistent storage
|
|
452
|
-
self.onfini(self.stop)
|
|
453
455
|
|
|
454
|
-
self.enabled = False
|
|
455
|
-
self._schedtask = None # The task of the scheduler loop. Doesn't run until we're enabled
|
|
456
|
-
|
|
457
|
-
self._running_tasks = [] # The actively running cron job tasks
|
|
458
456
|
await self._load_all()
|
|
459
457
|
|
|
460
|
-
async def start(self):
|
|
461
|
-
'''
|
|
462
|
-
Enable cron jobs to start running, start the scheduler loop
|
|
463
|
-
|
|
464
|
-
Go through all the appointments, making sure the query is valid, and remove the ones that aren't. (We can't
|
|
465
|
-
evaluate queries until enabled because not all the modules are loaded yet.)
|
|
466
|
-
'''
|
|
467
|
-
if self.enabled:
|
|
468
|
-
return
|
|
469
|
-
|
|
470
|
-
await self._load_all()
|
|
471
|
-
for iden, appt in self.appts.items():
|
|
472
|
-
try:
|
|
473
|
-
await self.core.getStormQuery(appt.query)
|
|
474
|
-
except Exception as e:
|
|
475
|
-
logger.exception(f'Invalid appointment {iden} {appt.name} found in storage. Disabling. {e}',
|
|
476
|
-
extra={'synapse': {'iden': iden, 'name': appt.name, 'text': appt.query}})
|
|
477
|
-
appt.enabled = False
|
|
478
|
-
|
|
479
|
-
self._schedtask = self.schedCoro(self._scheduleLoop())
|
|
480
|
-
self.enabled = True
|
|
481
|
-
|
|
482
|
-
async def stop(self):
|
|
483
|
-
"Cancel the scheduler loop, and set self.enabled to False."
|
|
484
|
-
if not self.enabled:
|
|
485
|
-
return
|
|
486
|
-
self._schedtask.cancel()
|
|
487
|
-
for task in self._running_tasks:
|
|
488
|
-
await task.fini()
|
|
489
|
-
|
|
490
|
-
self.enabled = False
|
|
491
|
-
|
|
492
458
|
async def _load_all(self):
|
|
493
459
|
'''
|
|
494
460
|
Load all the appointments from persistent storage
|
|
@@ -599,6 +565,8 @@ class Agenda(s_base.Base):
|
|
|
599
565
|
view = cdef.get('view')
|
|
600
566
|
created = cdef.get('created')
|
|
601
567
|
|
|
568
|
+
pool = cdef.get('pool', False)
|
|
569
|
+
|
|
602
570
|
recur = incunit is not None
|
|
603
571
|
indx = self._next_indx
|
|
604
572
|
self._next_indx += 1
|
|
@@ -639,7 +607,7 @@ class Agenda(s_base.Base):
|
|
|
639
607
|
incvals = (incvals, )
|
|
640
608
|
recs.extend(ApptRec(rd, incunit, v) for (rd, v) in itertools.product(reqdicts, incvals))
|
|
641
609
|
|
|
642
|
-
appt = _Appt(self, iden, recur, indx, query, creator, recs, nexttime=nexttime, view=view, created=created)
|
|
610
|
+
appt = _Appt(self, iden, recur, indx, query, creator, recs, nexttime=nexttime, view=view, created=created, pool=pool)
|
|
643
611
|
self._addappt(iden, appt)
|
|
644
612
|
|
|
645
613
|
appt.doc = cdef.get('doc', '')
|
|
@@ -683,8 +651,7 @@ class Agenda(s_base.Base):
|
|
|
683
651
|
if not query:
|
|
684
652
|
raise ValueError('empty query')
|
|
685
653
|
|
|
686
|
-
|
|
687
|
-
await self.core.getStormQuery(query)
|
|
654
|
+
await self.core.getStormQuery(query)
|
|
688
655
|
|
|
689
656
|
appt.query = query
|
|
690
657
|
appt.enabled = True # in case it was disabled for a bad query
|
|
@@ -736,7 +703,14 @@ class Agenda(s_base.Base):
|
|
|
736
703
|
self.tickoff += offs
|
|
737
704
|
self._wake_event.set()
|
|
738
705
|
|
|
739
|
-
async def
|
|
706
|
+
async def clearRunningStatus(self):
|
|
707
|
+
'''Used for clearing the running state at startup or change of leadership.'''
|
|
708
|
+
for appt in list(self.appts.values()):
|
|
709
|
+
if appt.isrunning:
|
|
710
|
+
logger.debug(f'Clearing the isrunning flag for {appt.iden}')
|
|
711
|
+
await self.core.addCronEdits(appt.iden, {'isrunning': False})
|
|
712
|
+
|
|
713
|
+
async def runloop(self):
|
|
740
714
|
'''
|
|
741
715
|
Task loop to issue query tasks at the right times.
|
|
742
716
|
'''
|
|
@@ -766,7 +740,7 @@ class Agenda(s_base.Base):
|
|
|
766
740
|
if appt.nexttime:
|
|
767
741
|
heapq.heappush(self.apptheap, appt)
|
|
768
742
|
|
|
769
|
-
if not appt.enabled
|
|
743
|
+
if not appt.enabled:
|
|
770
744
|
continue
|
|
771
745
|
|
|
772
746
|
if appt.isrunning: # pragma: no cover
|
|
@@ -818,12 +792,10 @@ class Agenda(s_base.Base):
|
|
|
818
792
|
return
|
|
819
793
|
|
|
820
794
|
info = {'iden': appt.iden, 'query': appt.query, 'view': view.iden}
|
|
821
|
-
task = await self.core.boss.execute(self._runJob(user, appt), f'Cron {appt.iden}', user, info=info)
|
|
822
795
|
|
|
823
|
-
|
|
824
|
-
self.
|
|
825
|
-
|
|
826
|
-
task.onfini(functools.partial(self._running_tasks.remove, task))
|
|
796
|
+
coro = self._runJob(user, appt)
|
|
797
|
+
task = self.core.runActiveTask(coro)
|
|
798
|
+
appt.task = await self.core.boss.promotetask(task, f'Cron {appt.iden}', user, info=info)
|
|
827
799
|
|
|
828
800
|
async def _markfailed(self, appt, reason):
|
|
829
801
|
now = self._getNowTick()
|
|
@@ -848,57 +820,75 @@ class Agenda(s_base.Base):
|
|
|
848
820
|
}
|
|
849
821
|
await self.core.addCronEdits(appt.iden, edits)
|
|
850
822
|
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
823
|
+
logger.info(f'Agenda executing for iden={appt.iden}, name={appt.name} user={user.name}, view={appt.view}, query={appt.query}',
|
|
824
|
+
extra={'synapse': {'iden': appt.iden, 'name': appt.name, 'user': user.iden, 'text': appt.query,
|
|
825
|
+
'username': user.name, 'view': appt.view}})
|
|
826
|
+
starttime = self._getNowTick()
|
|
827
|
+
success = False
|
|
828
|
+
try:
|
|
829
|
+
opts = {
|
|
830
|
+
'user': user.iden,
|
|
831
|
+
'view': appt.view,
|
|
832
|
+
'mirror': appt.pool,
|
|
833
|
+
'vars': {'auto': {'iden': appt.iden, 'type': 'cron'}},
|
|
834
|
+
}
|
|
835
|
+
opts = self.core._initStormOpts(opts)
|
|
836
|
+
|
|
837
|
+
await self.core.feedBeholder('cron:start', {'iden': appt.iden})
|
|
838
|
+
|
|
839
|
+
async for mesg in self.core.storm(appt.query, opts=opts):
|
|
840
|
+
|
|
841
|
+
if mesg[0] == 'node':
|
|
867
842
|
count += 1
|
|
868
|
-
except asyncio.CancelledError:
|
|
869
|
-
result = 'cancelled'
|
|
870
|
-
raise
|
|
871
|
-
except Exception as e:
|
|
872
|
-
result = f'raised exception {e}'
|
|
873
|
-
logger.exception(f'Agenda job {appt.iden} {appt.name} raised exception',
|
|
874
|
-
extra={'synapse': {'iden': appt.iden, 'name': appt.name}}
|
|
875
|
-
)
|
|
876
|
-
else:
|
|
877
|
-
success = True
|
|
878
|
-
result = f'finished successfully with {count} nodes'
|
|
879
|
-
finally:
|
|
880
|
-
finishtime = self._getNowTick()
|
|
881
|
-
if not success:
|
|
882
|
-
appt.lasterrs.append(result)
|
|
883
|
-
edits = {
|
|
884
|
-
'errcount': appt.errcount + 1,
|
|
885
|
-
# we only care about the last five errors
|
|
886
|
-
'lasterrs': list(appt.lasterrs[-5:]),
|
|
887
|
-
}
|
|
888
|
-
await self.core.addCronEdits(appt.iden, edits)
|
|
889
843
|
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
844
|
+
elif mesg[0] == 'err':
|
|
845
|
+
excname, errinfo = mesg[1]
|
|
846
|
+
errinfo.pop('eline', None)
|
|
847
|
+
errinfo.pop('efile', None)
|
|
848
|
+
excctor = getattr(s_exc, excname, s_exc.SynErr)
|
|
849
|
+
raise excctor(**errinfo)
|
|
850
|
+
|
|
851
|
+
except asyncio.CancelledError:
|
|
852
|
+
result = 'cancelled'
|
|
853
|
+
raise
|
|
854
|
+
|
|
855
|
+
except Exception as e:
|
|
856
|
+
result = f'raised exception {e}'
|
|
857
|
+
logger.exception(f'Agenda job {appt.iden} {appt.name} raised exception',
|
|
858
|
+
extra={'synapse': {'iden': appt.iden, 'name': appt.name}}
|
|
859
|
+
)
|
|
860
|
+
else:
|
|
861
|
+
success = True
|
|
862
|
+
result = f'finished successfully with {count} nodes'
|
|
863
|
+
|
|
864
|
+
finally:
|
|
865
|
+
finishtime = self._getNowTick()
|
|
866
|
+
if not success:
|
|
867
|
+
appt.lasterrs.append(result)
|
|
895
868
|
edits = {
|
|
896
|
-
'
|
|
897
|
-
|
|
898
|
-
'
|
|
869
|
+
'errcount': appt.errcount + 1,
|
|
870
|
+
# we only care about the last five errors
|
|
871
|
+
'lasterrs': list(appt.lasterrs[-5:]),
|
|
899
872
|
}
|
|
873
|
+
|
|
874
|
+
if self.core.isactive:
|
|
875
|
+
await self.core.addCronEdits(appt.iden, edits)
|
|
876
|
+
|
|
877
|
+
took = finishtime - starttime
|
|
878
|
+
mesg = f'Agenda completed query for iden={appt.iden} name={appt.name} with result "{result}" ' \
|
|
879
|
+
f'took {took:.3f}s'
|
|
880
|
+
if not self.core.isactive:
|
|
881
|
+
mesg = mesg + ' Agenda status will not be saved since the Cortex is no longer the leader.'
|
|
882
|
+
logger.info(mesg, extra={'synapse': {'iden': appt.iden, 'name': appt.name, 'user': user.iden,
|
|
883
|
+
'result': result, 'username': user.name, 'took': took}})
|
|
884
|
+
edits = {
|
|
885
|
+
'lastfinishtime': finishtime,
|
|
886
|
+
'isrunning': False,
|
|
887
|
+
'lastresult': result,
|
|
888
|
+
}
|
|
889
|
+
if self.core.isactive:
|
|
900
890
|
await self.core.addCronEdits(appt.iden, edits)
|
|
901
891
|
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
892
|
+
if not self.isfini:
|
|
893
|
+
# fire beholder event before invoking nexus change (in case readonly)
|
|
894
|
+
await self.core.feedBeholder('cron:stop', {'iden': appt.iden})
|
synapse/lib/aha.py
CHANGED
|
@@ -327,6 +327,20 @@ class AhaApi(s_cell.CellApi):
|
|
|
327
327
|
'''
|
|
328
328
|
return await self.cell.delAhaUserEnroll(iden)
|
|
329
329
|
|
|
330
|
+
@s_cell.adminapi()
|
|
331
|
+
async def clearAhaSvcProvs(self):
|
|
332
|
+
'''
|
|
333
|
+
Remove all unused service provisioning values.
|
|
334
|
+
'''
|
|
335
|
+
return await self.cell.clearAhaSvcProvs()
|
|
336
|
+
|
|
337
|
+
@s_cell.adminapi()
|
|
338
|
+
async def clearAhaUserEnrolls(self):
|
|
339
|
+
'''
|
|
340
|
+
Remove all unused user enrollment provisioning values.
|
|
341
|
+
'''
|
|
342
|
+
return await self.cell.clearAhaUserEnrolls()
|
|
343
|
+
|
|
330
344
|
class ProvDmon(s_daemon.Daemon):
|
|
331
345
|
|
|
332
346
|
async def __anit__(self, aha):
|
|
@@ -386,6 +400,9 @@ class EnrollApi:
|
|
|
386
400
|
mesg = f'Invalid user CSR CN={name}.'
|
|
387
401
|
raise s_exc.BadArg(mesg=mesg)
|
|
388
402
|
|
|
403
|
+
logger.info(f'Signing user CSR for [{username}], signas={ahanetw}',
|
|
404
|
+
extra=await self.aha.getLogExtra(name=username, signas=ahanetw))
|
|
405
|
+
|
|
389
406
|
pkey, cert = self.aha.certdir.signUserCsr(xcsr, ahanetw, save=False)
|
|
390
407
|
return self.aha.certdir._certToByts(cert)
|
|
391
408
|
|
|
@@ -415,6 +432,9 @@ class ProvApi:
|
|
|
415
432
|
mesg = f'Invalid host CSR CN={name}.'
|
|
416
433
|
raise s_exc.BadArg(mesg=mesg)
|
|
417
434
|
|
|
435
|
+
logger.info(f'Signing host CSR for [{hostname}], signas={ahanetw}',
|
|
436
|
+
extra=await self.aha.getLogExtra(name=hostname, signas=ahanetw))
|
|
437
|
+
|
|
418
438
|
pkey, cert = self.aha.certdir.signHostCsr(xcsr, ahanetw, save=False)
|
|
419
439
|
return self.aha.certdir._certToByts(cert)
|
|
420
440
|
|
|
@@ -431,6 +451,9 @@ class ProvApi:
|
|
|
431
451
|
mesg = f'Invalid user CSR CN={name}.'
|
|
432
452
|
raise s_exc.BadArg(mesg=mesg)
|
|
433
453
|
|
|
454
|
+
logger.info(f'Signing user CSR for [{username}], signas={ahanetw}',
|
|
455
|
+
extra=await self.aha.getLogExtra(name=username, signas=ahanetw))
|
|
456
|
+
|
|
434
457
|
pkey, cert = self.aha.certdir.signUserCsr(xcsr, ahanetw, save=False)
|
|
435
458
|
return self.aha.certdir._certToByts(cert)
|
|
436
459
|
|
|
@@ -1010,6 +1033,9 @@ class AhaCell(s_cell.Cell):
|
|
|
1010
1033
|
mesg = 'The AHA server does not have a provision:listen URL!'
|
|
1011
1034
|
raise s_exc.NeedConfValu(mesg=mesg)
|
|
1012
1035
|
|
|
1036
|
+
if not name:
|
|
1037
|
+
raise s_exc.BadArg(mesg='Empty name values are not allowed for provisioning.')
|
|
1038
|
+
|
|
1013
1039
|
if provinfo is None:
|
|
1014
1040
|
provinfo = {}
|
|
1015
1041
|
|
|
@@ -1039,6 +1065,10 @@ class AhaCell(s_cell.Cell):
|
|
|
1039
1065
|
|
|
1040
1066
|
hostname = f'{name}.{netw}'
|
|
1041
1067
|
|
|
1068
|
+
if len(hostname) > 64:
|
|
1069
|
+
mesg = f'Hostname value must not exceed 64 characters in length. {hostname=}, len={len(hostname)}'
|
|
1070
|
+
raise s_exc.BadArg(mesg=mesg)
|
|
1071
|
+
|
|
1042
1072
|
conf.setdefault('aha:name', name)
|
|
1043
1073
|
dmon_port = provinfo.get('dmon:port', 0)
|
|
1044
1074
|
dmon_listen = f'ssl://0.0.0.0:{dmon_port}?hostname={hostname}&ca={netw}'
|
|
@@ -1124,6 +1154,20 @@ class AhaCell(s_cell.Cell):
|
|
|
1124
1154
|
self.slab.put(iden.encode(), s_msgpack.en(provinfo), db='aha:provs')
|
|
1125
1155
|
return iden
|
|
1126
1156
|
|
|
1157
|
+
@s_nexus.Pusher.onPushAuto('aha:svc:prov:clear')
|
|
1158
|
+
async def clearAhaSvcProvs(self):
|
|
1159
|
+
for iden, byts in self.slab.scanByFull(db='aha:provs'):
|
|
1160
|
+
self.slab.delete(iden, db='aha:provs')
|
|
1161
|
+
provinfo = s_msgpack.un(byts)
|
|
1162
|
+
logger.info(f'Deleted service provisioning service={provinfo.get("conf").get("aha:name")}, iden={iden.decode()}')
|
|
1163
|
+
|
|
1164
|
+
@s_nexus.Pusher.onPushAuto('aha:enroll:clear')
|
|
1165
|
+
async def clearAhaUserEnrolls(self):
|
|
1166
|
+
for iden, byts in self.slab.scanByFull(db='aha:enrolls'):
|
|
1167
|
+
self.slab.delete(iden, db='aha:enrolls')
|
|
1168
|
+
userinfo = s_msgpack.un(byts)
|
|
1169
|
+
logger.info(f'Deleted user enrollment username={userinfo.get("name")}, iden={iden.decode()}')
|
|
1170
|
+
|
|
1127
1171
|
@s_nexus.Pusher.onPushAuto('aha:svc:prov:del')
|
|
1128
1172
|
async def delAhaSvcProv(self, iden):
|
|
1129
1173
|
self.slab.delete(iden.encode(), db='aha:provs')
|
|
@@ -1140,8 +1184,15 @@ class AhaCell(s_cell.Cell):
|
|
|
1140
1184
|
mesg = 'AHA server requires aha:network configuration.'
|
|
1141
1185
|
raise s_exc.NeedConfValu(mesg=mesg)
|
|
1142
1186
|
|
|
1187
|
+
if not name:
|
|
1188
|
+
raise s_exc.BadArg(mesg='Empty name values are not allowed for provisioning.')
|
|
1189
|
+
|
|
1143
1190
|
username = f'{name}@{ahanetw}'
|
|
1144
1191
|
|
|
1192
|
+
if len(username) > 64:
|
|
1193
|
+
mesg = f'Username value must not exceed 64 characters in length. username={username}, len={len(username)}'
|
|
1194
|
+
raise s_exc.BadArg(mesg=mesg)
|
|
1195
|
+
|
|
1145
1196
|
user = await self.auth.getUserByName(username)
|
|
1146
1197
|
|
|
1147
1198
|
if user is not None:
|
synapse/lib/ast.py
CHANGED
|
@@ -24,7 +24,6 @@ import synapse.lib.scrape as s_scrape
|
|
|
24
24
|
import synapse.lib.msgpack as s_msgpack
|
|
25
25
|
import synapse.lib.spooled as s_spooled
|
|
26
26
|
import synapse.lib.stormctrl as s_stormctrl
|
|
27
|
-
import synapse.lib.provenance as s_provenance
|
|
28
27
|
import synapse.lib.stormtypes as s_stormtypes
|
|
29
28
|
|
|
30
29
|
from synapse.lib.stormtypes import tobool, toint, toprim, tostr, tonumber, tocmprvalu, undef
|
|
@@ -1180,33 +1179,32 @@ class CmdOper(Oper):
|
|
|
1180
1179
|
mesg = f'Command ({name}) is not marked safe for readonly use.'
|
|
1181
1180
|
raise self.addExcInfo(s_exc.IsReadOnly(mesg=mesg))
|
|
1182
1181
|
|
|
1183
|
-
|
|
1184
|
-
async def genx():
|
|
1182
|
+
async def genx():
|
|
1185
1183
|
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1184
|
+
async for node, path in genr:
|
|
1185
|
+
argv = await self.kids[1].compute(runt, path)
|
|
1186
|
+
if not await scmd.setArgv(argv):
|
|
1187
|
+
raise s_stormctrl.StormExit()
|
|
1190
1188
|
|
|
1191
|
-
|
|
1189
|
+
yield node, path
|
|
1192
1190
|
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1191
|
+
# must pull through the genr to get opts set
|
|
1192
|
+
# ( many commands expect self.opts is set at run() )
|
|
1193
|
+
genr, empty = await pullone(genx())
|
|
1196
1194
|
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1195
|
+
try:
|
|
1196
|
+
if runtsafe:
|
|
1197
|
+
argv = await self.kids[1].compute(runt, None)
|
|
1198
|
+
if not await scmd.setArgv(argv):
|
|
1199
|
+
raise s_stormctrl.StormExit()
|
|
1200
|
+
|
|
1201
|
+
if runtsafe or not empty:
|
|
1202
|
+
async with contextlib.aclosing(scmd.execStormCmd(runt, genr)) as agen:
|
|
1203
|
+
async for item in agen:
|
|
1204
|
+
yield item
|
|
1207
1205
|
|
|
1208
|
-
|
|
1209
|
-
|
|
1206
|
+
finally:
|
|
1207
|
+
await genr.aclose()
|
|
1210
1208
|
|
|
1211
1209
|
class SetVarOper(Oper):
|
|
1212
1210
|
|
|
@@ -3359,6 +3357,7 @@ class VarValue(Value):
|
|
|
3359
3357
|
def prepare(self):
|
|
3360
3358
|
assert isinstance(self.kids[0], Const)
|
|
3361
3359
|
self.name = self.kids[0].value()
|
|
3360
|
+
self.isconst = False
|
|
3362
3361
|
|
|
3363
3362
|
def isRuntSafe(self, runt):
|
|
3364
3363
|
return runt.isRuntVar(self.name)
|
synapse/lib/base.py
CHANGED
|
@@ -477,8 +477,6 @@ class Base:
|
|
|
477
477
|
asyncio.Task: An asyncio.Task object.
|
|
478
478
|
|
|
479
479
|
'''
|
|
480
|
-
import synapse.lib.provenance as s_provenance # avoid import cycle
|
|
481
|
-
|
|
482
480
|
if __debug__:
|
|
483
481
|
assert inspect.isawaitable(coro)
|
|
484
482
|
import synapse.lib.threads as s_threads # avoid import cycle
|
|
@@ -491,10 +489,6 @@ class Base:
|
|
|
491
489
|
|
|
492
490
|
s_scope.clone(task)
|
|
493
491
|
|
|
494
|
-
# In rare cases, (Like this function being triggered from call_soon_threadsafe), there's no task context
|
|
495
|
-
if asyncio.current_task():
|
|
496
|
-
s_provenance.dupstack(task)
|
|
497
|
-
|
|
498
492
|
def taskDone(task):
|
|
499
493
|
self._active_tasks.remove(task)
|
|
500
494
|
try:
|
synapse/lib/boss.py
CHANGED
|
@@ -41,6 +41,9 @@ class Boss(s_base.Base):
|
|
|
41
41
|
s_task.Task: The Synapse Task object.
|
|
42
42
|
'''
|
|
43
43
|
task = asyncio.current_task()
|
|
44
|
+
return await self.promotetask(task, name, user, info=info, taskiden=taskiden)
|
|
45
|
+
|
|
46
|
+
async def promotetask(self, task, name, user, info=None, taskiden=None):
|
|
44
47
|
|
|
45
48
|
synt = getattr(task, '_syn_task', None)
|
|
46
49
|
|