synapse 2.177.0__py311-none-any.whl → 2.179.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/cortex.py +170 -31
- synapse/datamodel.py +47 -1
- synapse/exc.py +1 -0
- synapse/lib/aha.py +362 -88
- synapse/lib/ast.py +26 -22
- synapse/lib/base.py +39 -12
- synapse/lib/cell.py +315 -119
- synapse/lib/config.py +15 -11
- synapse/lib/coro.py +27 -0
- synapse/lib/drive.py +551 -0
- synapse/lib/layer.py +0 -5
- synapse/lib/link.py +1 -1
- synapse/lib/lmdbslab.py +3 -3
- synapse/lib/nexus.py +24 -12
- synapse/lib/schemas.py +39 -0
- synapse/lib/snap.py +17 -7
- synapse/lib/storm.py +3 -1
- synapse/lib/stormhttp.py +1 -0
- synapse/lib/stormlib/imap.py +6 -2
- synapse/lib/stormlib/modelext.py +29 -3
- synapse/lib/stormlib/smtp.py +12 -2
- synapse/lib/stormlib/stix.py +40 -17
- synapse/lib/stormlib/vault.py +2 -2
- synapse/lib/stormtypes.py +1 -1
- synapse/lib/types.py +9 -0
- synapse/lib/version.py +2 -2
- synapse/lookup/pe.py +303 -38
- synapse/models/dns.py +24 -1
- synapse/models/geospace.py +4 -1
- synapse/models/infotech.py +26 -1
- synapse/telepath.py +32 -17
- synapse/tests/files/aha/certs/cas/synapse.crt +28 -0
- synapse/tests/files/aha/certs/cas/synapse.key +51 -0
- synapse/tests/files/aha/certs/hosts/00.aha.loop.vertex.link.crt +30 -0
- synapse/tests/files/aha/certs/hosts/00.aha.loop.vertex.link.key +51 -0
- synapse/tests/files/aha/certs/users/root@synapse.crt +29 -0
- synapse/tests/files/aha/certs/users/root@synapse.key +51 -0
- synapse/tests/files/rstorm/testsvc.py +1 -1
- synapse/tests/test_axon.py +1 -1
- synapse/tests/test_cortex.py +67 -60
- synapse/tests/test_lib_agenda.py +3 -3
- synapse/tests/test_lib_aha.py +353 -490
- synapse/tests/test_lib_base.py +20 -0
- synapse/tests/test_lib_cell.py +273 -22
- synapse/tests/test_lib_config.py +4 -3
- synapse/tests/test_lib_coro.py +12 -0
- synapse/tests/test_lib_nexus.py +8 -0
- synapse/tests/test_lib_stormhttp.py +40 -0
- synapse/tests/test_lib_stormlib_aha.py +35 -35
- synapse/tests/test_lib_stormlib_cell.py +4 -15
- synapse/tests/test_lib_stormlib_imap.py +14 -3
- synapse/tests/test_lib_stormlib_modelext.py +55 -3
- synapse/tests/test_lib_stormlib_smtp.py +51 -0
- synapse/tests/test_lib_stormlib_stix.py +15 -0
- synapse/tests/test_lib_stormlib_vault.py +11 -1
- synapse/tests/test_lib_stormtypes.py +5 -0
- synapse/tests/test_lib_types.py +9 -0
- synapse/tests/test_model_dns.py +8 -0
- synapse/tests/test_model_geospace.py +3 -1
- synapse/tests/test_model_infotech.py +47 -0
- synapse/tests/test_model_syn.py +11 -0
- synapse/tests/test_tools_aha.py +78 -101
- synapse/tests/test_utils_stormcov.py +1 -1
- synapse/tests/utils.py +86 -120
- synapse/tools/aha/clone.py +50 -0
- synapse/tools/aha/enroll.py +2 -1
- synapse/tools/backup.py +2 -2
- synapse/tools/changelog.py +31 -1
- {synapse-2.177.0.dist-info → synapse-2.179.0.dist-info}/METADATA +48 -48
- {synapse-2.177.0.dist-info → synapse-2.179.0.dist-info}/RECORD +73 -65
- {synapse-2.177.0.dist-info → synapse-2.179.0.dist-info}/WHEEL +1 -1
- {synapse-2.177.0.dist-info → synapse-2.179.0.dist-info}/LICENSE +0 -0
- {synapse-2.177.0.dist-info → synapse-2.179.0.dist-info}/top_level.txt +0 -0
synapse/lib/nexus.py
CHANGED
|
@@ -91,7 +91,6 @@ class NexsRoot(s_base.Base):
|
|
|
91
91
|
self.writeholds = set()
|
|
92
92
|
|
|
93
93
|
self.applytask = None
|
|
94
|
-
self.applylock = asyncio.Lock()
|
|
95
94
|
|
|
96
95
|
self.ready = asyncio.Event()
|
|
97
96
|
self.donexslog = self.cell.conf.get('nexslog:en')
|
|
@@ -110,9 +109,7 @@ class NexsRoot(s_base.Base):
|
|
|
110
109
|
|
|
111
110
|
logpath = s_common.genpath(self.dirn, 'slabs', 'nexuslog')
|
|
112
111
|
|
|
113
|
-
self.
|
|
114
|
-
self.nexsslab = await s_lmdbslab.Slab.anit(path, map_async=self.map_async)
|
|
115
|
-
self.nexsslab.addResizeCallback(cell.checkFreeSpace)
|
|
112
|
+
self.nexsslab = await cell._initSlabFile(path)
|
|
116
113
|
|
|
117
114
|
self.nexshot = await self.nexsslab.getHotCount('nexs:indx')
|
|
118
115
|
|
|
@@ -126,8 +123,7 @@ class NexsRoot(s_base.Base):
|
|
|
126
123
|
elif vers != 2:
|
|
127
124
|
raise s_exc.BadStorageVersion(mesg=f'Got nexus log version {vers}. Expected 2. Accidental downgrade?')
|
|
128
125
|
|
|
129
|
-
|
|
130
|
-
self.nexslog = await s_multislabseqn.MultiSlabSeqn.anit(logpath, slabopts=slabopts, cell=cell)
|
|
126
|
+
self.nexslog = await s_multislabseqn.MultiSlabSeqn.anit(logpath, cell=cell)
|
|
131
127
|
|
|
132
128
|
# just in case were previously configured differently
|
|
133
129
|
logindx = self.nexslog.index()
|
|
@@ -147,6 +143,9 @@ class NexsRoot(s_base.Base):
|
|
|
147
143
|
|
|
148
144
|
self.onfini(fini)
|
|
149
145
|
|
|
146
|
+
def getNexsKids(self):
|
|
147
|
+
return list(self._nexskids.values())
|
|
148
|
+
|
|
150
149
|
async def _migrateV1toV2(self, nexspath, logpath):
|
|
151
150
|
'''
|
|
152
151
|
Close the slab, move it to the new multislab location, then copy out the nexshot
|
|
@@ -195,8 +194,7 @@ class NexsRoot(s_base.Base):
|
|
|
195
194
|
|
|
196
195
|
# Open a fresh slab where the old one used to be
|
|
197
196
|
logger.warning(f'Re-opening fresh nexslog slab at {nexspath} for nexshot')
|
|
198
|
-
self.nexsslab = await
|
|
199
|
-
self.nexsslab.addResizeCallback(self.cell.checkFreeSpace)
|
|
197
|
+
self.nexsslab = await self.cell._initSlabFile(nexspath)
|
|
200
198
|
|
|
201
199
|
self.nexshot = await self.nexsslab.getHotCount('nexs:indx')
|
|
202
200
|
|
|
@@ -230,7 +228,7 @@ class NexsRoot(s_base.Base):
|
|
|
230
228
|
|
|
231
229
|
async def enNexsLog(self):
|
|
232
230
|
|
|
233
|
-
async with self.
|
|
231
|
+
async with self.cell.nexslock:
|
|
234
232
|
|
|
235
233
|
if self.donexslog:
|
|
236
234
|
return
|
|
@@ -309,7 +307,6 @@ class NexsRoot(s_base.Base):
|
|
|
309
307
|
If I'm not a follower, mutate, otherwise, ask the leader to make the change and wait for the follower loop
|
|
310
308
|
to hand me the result through a future.
|
|
311
309
|
'''
|
|
312
|
-
|
|
313
310
|
# pick up a reference to avoid race when we eventually can promote
|
|
314
311
|
client = self.client
|
|
315
312
|
|
|
@@ -344,7 +341,7 @@ class NexsRoot(s_base.Base):
|
|
|
344
341
|
if meta is None:
|
|
345
342
|
meta = {}
|
|
346
343
|
|
|
347
|
-
async with self.
|
|
344
|
+
async with self.cell.nexslock:
|
|
348
345
|
self.reqNotReadOnly()
|
|
349
346
|
# Keep a reference to the shielded task to ensure it isn't GC'd
|
|
350
347
|
self.applytask = asyncio.create_task(self._eat((nexsiden, event, args, kwargs, meta)))
|
|
@@ -577,6 +574,9 @@ class NexsRoot(s_base.Base):
|
|
|
577
574
|
if respfutu is not None:
|
|
578
575
|
respfutu.set_result(retn)
|
|
579
576
|
|
|
577
|
+
except s_exc.LinkShutDown:
|
|
578
|
+
logger.warning(f'mirror loop: leader closed the connection.')
|
|
579
|
+
|
|
580
580
|
except Exception as exc: # pragma: no cover
|
|
581
581
|
logger.exception(f'error in mirror loop: {exc}')
|
|
582
582
|
|
|
@@ -634,9 +634,21 @@ class Pusher(s_base.Base, metaclass=RegMethType):
|
|
|
634
634
|
assert prev is not None, f'Failed removing {self.nexsiden}'
|
|
635
635
|
|
|
636
636
|
self.onfini(onfini)
|
|
637
|
-
|
|
638
637
|
self.nexsroot = nexsroot
|
|
639
638
|
|
|
639
|
+
async def modNexsRoot(self, ctor):
|
|
640
|
+
|
|
641
|
+
kids = [self]
|
|
642
|
+
if self.nexsroot is not None:
|
|
643
|
+
kids = self.nexsroot.getNexsKids()
|
|
644
|
+
await self.nexsroot.fini()
|
|
645
|
+
|
|
646
|
+
nexsroot = await ctor()
|
|
647
|
+
|
|
648
|
+
[kid.setNexsRoot(nexsroot) for kid in kids]
|
|
649
|
+
|
|
650
|
+
await nexsroot.startup()
|
|
651
|
+
|
|
640
652
|
@classmethod
|
|
641
653
|
def onPush(cls, event: str, passitem=False) -> Callable:
|
|
642
654
|
'''
|
synapse/lib/schemas.py
CHANGED
|
@@ -274,6 +274,7 @@ reqValidSslCtxOpts = s_config.getJsValidator({
|
|
|
274
274
|
'verify': {'type': 'boolean', 'default': True},
|
|
275
275
|
'client_cert': {'type': ['string', 'null'], 'default': None},
|
|
276
276
|
'client_key': {'type': ['string', 'null'], 'default': None},
|
|
277
|
+
'ca_cert': {'type': ['string', 'null'], 'default': None},
|
|
277
278
|
},
|
|
278
279
|
'additionalProperties': False,
|
|
279
280
|
})
|
|
@@ -454,3 +455,41 @@ tabularConfSchema = {
|
|
|
454
455
|
}
|
|
455
456
|
|
|
456
457
|
reqValidTabularConf = s_config.getJsValidator(tabularConfSchema)
|
|
458
|
+
|
|
459
|
+
emptySchema = {'object': {}, 'additionalProperties': False}
|
|
460
|
+
re_drivename = r'^[\w_.-]{1,128}$'
|
|
461
|
+
|
|
462
|
+
driveInfoSchema = {
|
|
463
|
+
'type': 'object',
|
|
464
|
+
'properties': {
|
|
465
|
+
'iden': {'type': 'string', 'pattern': s_config.re_iden},
|
|
466
|
+
'parent': {'type': 'string', 'pattern': s_config.re_iden},
|
|
467
|
+
'type': {'type': 'string', 'pattern': re_drivename},
|
|
468
|
+
'name': {'type': 'string', 'pattern': re_drivename},
|
|
469
|
+
'perm': s_msgpack.deepcopy(easyPermSchema),
|
|
470
|
+
'kids': {'type': 'number', 'minimum': 0},
|
|
471
|
+
'created': {'type': 'number'},
|
|
472
|
+
'creator': {'type': 'string', 'pattern': s_config.re_iden},
|
|
473
|
+
# these are also data version info...
|
|
474
|
+
'size': {'type': 'number', 'minimum': 0},
|
|
475
|
+
'updated': {'type': 'number'},
|
|
476
|
+
'updater': {'type': 'string', 'pattern': s_config.re_iden},
|
|
477
|
+
'version': {'type': 'array', 'items': {'type': 'number', 'minItems': 3, 'maxItems': 3}},
|
|
478
|
+
},
|
|
479
|
+
'required': ('iden', 'parent', 'name', 'created', 'creator', 'kids'),
|
|
480
|
+
'additionalProperties': False,
|
|
481
|
+
}
|
|
482
|
+
reqValidDriveInfo = s_config.getJsValidator(driveInfoSchema)
|
|
483
|
+
|
|
484
|
+
driveDataVersSchema = {
|
|
485
|
+
'type': 'object',
|
|
486
|
+
'properties': {
|
|
487
|
+
'size': {'type': 'number', 'minimum': 0},
|
|
488
|
+
'updated': {'type': 'number'},
|
|
489
|
+
'updater': {'type': 'string', 'pattern': s_config.re_iden},
|
|
490
|
+
'version': {'type': 'array', 'items': {'type': 'number', 'minItems': 3, 'maxItems': 3}},
|
|
491
|
+
},
|
|
492
|
+
'required': ('size', 'version', 'updated', 'updater'),
|
|
493
|
+
'additionalProperties': False,
|
|
494
|
+
}
|
|
495
|
+
reqValidDriveDataVers = s_config.getJsValidator(driveDataVersSchema)
|
synapse/lib/snap.py
CHANGED
|
@@ -316,6 +316,10 @@ class ProtoNode:
|
|
|
316
316
|
mesg = f'Tagprop {name} does not exist in this Cortex.'
|
|
317
317
|
return await self.ctx.snap._raiseOnStrict(s_exc.NoSuchTagProp, mesg)
|
|
318
318
|
|
|
319
|
+
if prop.locked:
|
|
320
|
+
mesg = f'Tagprop {name} is locked.'
|
|
321
|
+
return await self.ctx.snap._raiseOnStrict(s_exc.IsDeprLocked, mesg)
|
|
322
|
+
|
|
319
323
|
try:
|
|
320
324
|
norm, info = prop.type.norm(valu)
|
|
321
325
|
except s_exc.BadTypeValu as e:
|
|
@@ -1029,7 +1033,7 @@ class Snap(s_base.Base):
|
|
|
1029
1033
|
if node is not None:
|
|
1030
1034
|
yield node
|
|
1031
1035
|
|
|
1032
|
-
async def nodesByPropValu(self, full, cmpr, valu, reverse=False):
|
|
1036
|
+
async def nodesByPropValu(self, full, cmpr, valu, reverse=False, norm=True):
|
|
1033
1037
|
if cmpr == 'type=':
|
|
1034
1038
|
if reverse:
|
|
1035
1039
|
async for node in self.nodesByPropTypeValu(full, valu, reverse=reverse):
|
|
@@ -1050,10 +1054,13 @@ class Snap(s_base.Base):
|
|
|
1050
1054
|
mesg = f'No property named "{full}".'
|
|
1051
1055
|
raise s_exc.NoSuchProp(mesg=mesg)
|
|
1052
1056
|
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
+
if norm:
|
|
1058
|
+
cmprvals = prop.type.getStorCmprs(cmpr, valu)
|
|
1059
|
+
# an empty return probably means ?= with invalid value
|
|
1060
|
+
if not cmprvals:
|
|
1061
|
+
return
|
|
1062
|
+
else:
|
|
1063
|
+
cmprvals = ((cmpr, valu, prop.type.stortype),)
|
|
1057
1064
|
|
|
1058
1065
|
if prop.isrunt:
|
|
1059
1066
|
for storcmpr, storvalu, _ in cmprvals:
|
|
@@ -1108,7 +1115,7 @@ class Snap(s_base.Base):
|
|
|
1108
1115
|
async for node in self.nodesByPropArray(prop.full, '=', valu, reverse=reverse):
|
|
1109
1116
|
yield node
|
|
1110
1117
|
|
|
1111
|
-
async def nodesByPropArray(self, full, cmpr, valu, reverse=False):
|
|
1118
|
+
async def nodesByPropArray(self, full, cmpr, valu, reverse=False, norm=True):
|
|
1112
1119
|
|
|
1113
1120
|
prop = self.core.model.prop(full)
|
|
1114
1121
|
if prop is None:
|
|
@@ -1119,7 +1126,10 @@ class Snap(s_base.Base):
|
|
|
1119
1126
|
mesg = f'Array syntax is invalid on non array type: {prop.type.name}.'
|
|
1120
1127
|
raise s_exc.BadTypeValu(mesg=mesg)
|
|
1121
1128
|
|
|
1122
|
-
|
|
1129
|
+
if norm:
|
|
1130
|
+
cmprvals = prop.type.arraytype.getStorCmprs(cmpr, valu)
|
|
1131
|
+
else:
|
|
1132
|
+
cmprvals = ((cmpr, valu, prop.type.arraytype.stortype),)
|
|
1123
1133
|
|
|
1124
1134
|
if prop.isform:
|
|
1125
1135
|
async for (buid, sodes) in self.core._liftByPropArray(prop.name, None, cmprvals, self.layers, reverse=reverse):
|
synapse/lib/storm.py
CHANGED
|
@@ -53,7 +53,9 @@ When condition is tag:add or tag:del, you may optionally provide a form name
|
|
|
53
53
|
to restrict the trigger to fire only on tags added or deleted from nodes of
|
|
54
54
|
those forms.
|
|
55
55
|
|
|
56
|
-
The added tag is provided to the query
|
|
56
|
+
The added tag is provided to the query in the ``$auto`` dictionary variable under
|
|
57
|
+
``$auto.opts.tag``. Usage of the ``$tag`` variable is deprecated and it will no longer
|
|
58
|
+
be populated in Synapse v3.0.0.
|
|
57
59
|
|
|
58
60
|
Simple one level tag globbing is supported, only at the end after a period,
|
|
59
61
|
that is aka.* matches aka.foo and aka.bar but not aka.foo.bar. aka* is not
|
synapse/lib/stormhttp.py
CHANGED
|
@@ -95,6 +95,7 @@ class LibHttp(s_stormtypes.Lib):
|
|
|
95
95
|
'verify': <bool> - Perform SSL/TLS verification. Is overridden by the ssl_verify argument.
|
|
96
96
|
'client_cert': <str> - PEM encoded full chain certificate for use in mTLS.
|
|
97
97
|
'client_key': <str> - PEM encoded key for use in mTLS. Alternatively, can be included in client_cert.
|
|
98
|
+
'ca_cert': <str> - A PEM encoded full chain CA certificate for use when verifying the request.
|
|
98
99
|
}
|
|
99
100
|
'''
|
|
100
101
|
_storm_locals = (
|
synapse/lib/stormlib/imap.py
CHANGED
|
@@ -50,6 +50,8 @@ class ImapLib(s_stormtypes.Lib):
|
|
|
50
50
|
'desc': 'The time to wait for all commands on the server to execute.'},
|
|
51
51
|
{'type': 'bool', 'name': 'ssl', 'default': True,
|
|
52
52
|
'desc': 'Use SSL to connect to the IMAP server.'},
|
|
53
|
+
{'type': 'bool', 'name': 'ssl_verify', 'default': True,
|
|
54
|
+
'desc': 'Perform SSL/TLS verification.'},
|
|
53
55
|
),
|
|
54
56
|
'returns': {
|
|
55
57
|
'type': 'inet:imap:server',
|
|
@@ -69,17 +71,19 @@ class ImapLib(s_stormtypes.Lib):
|
|
|
69
71
|
'connect': self.connect,
|
|
70
72
|
}
|
|
71
73
|
|
|
72
|
-
async def connect(self, host, port=993, timeout=30, ssl=True):
|
|
74
|
+
async def connect(self, host, port=993, timeout=30, ssl=True, ssl_verify=True):
|
|
73
75
|
|
|
74
76
|
self.runt.confirm(('storm', 'inet', 'imap', 'connect'))
|
|
75
77
|
|
|
76
78
|
ssl = await s_stormtypes.tobool(ssl)
|
|
77
79
|
host = await s_stormtypes.tostr(host)
|
|
78
80
|
port = await s_stormtypes.toint(port)
|
|
81
|
+
ssl_verify = await s_stormtypes.tobool(ssl_verify)
|
|
79
82
|
timeout = await s_stormtypes.toint(timeout, noneok=True)
|
|
80
83
|
|
|
81
84
|
if ssl:
|
|
82
|
-
|
|
85
|
+
ctx = self.runt.snap.core.getCachedSslCtx(opts=None, verify=ssl_verify)
|
|
86
|
+
imap_cli = aioimaplib.IMAP4_SSL(host=host, port=port, timeout=timeout, ssl_context=ctx)
|
|
83
87
|
else:
|
|
84
88
|
imap_cli = aioimaplib.IMAP4(host=host, port=port, timeout=timeout)
|
|
85
89
|
|
synapse/lib/stormlib/modelext.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import synapse.exc as s_exc
|
|
2
|
+
import synapse.common as s_common
|
|
2
3
|
import synapse.lib.grammar as s_grammar
|
|
3
4
|
|
|
4
5
|
import synapse.lib.stormtypes as s_stormtypes
|
|
@@ -54,6 +55,8 @@ class LibModelExt(s_stormtypes.Lib):
|
|
|
54
55
|
'args': (
|
|
55
56
|
{'name': 'formname', 'type': 'str', 'desc': 'The form with the extended property.', },
|
|
56
57
|
{'name': 'propname', 'type': 'str', 'desc': 'The extended property to remove.', },
|
|
58
|
+
{'name': 'force', 'type': 'boolean', 'default': False,
|
|
59
|
+
'desc': 'Delete the property from all nodes before removing the definition.', },
|
|
57
60
|
),
|
|
58
61
|
'returns': {'type': 'null', }}},
|
|
59
62
|
{'name': 'delUnivProp',
|
|
@@ -61,12 +64,16 @@ class LibModelExt(s_stormtypes.Lib):
|
|
|
61
64
|
'type': {'type': 'function', '_funcname': 'delUnivProp',
|
|
62
65
|
'args': (
|
|
63
66
|
{'name': 'propname', 'type': 'str', 'desc': 'Name of the universal property to remove.', },
|
|
67
|
+
{'name': 'force', 'type': 'boolean', 'default': False,
|
|
68
|
+
'desc': 'Delete the property from all nodes before removing the definition.', },
|
|
64
69
|
),
|
|
65
70
|
'returns': {'type': 'null', }}},
|
|
66
71
|
{'name': 'delTagProp', 'desc': 'Remove an extended tag property definition from the model.',
|
|
67
72
|
'type': {'type': 'function', '_funcname': 'delTagProp',
|
|
68
73
|
'args': (
|
|
69
74
|
{'name': 'propname', 'type': 'str', 'desc': 'Name of the tag property to remove.', },
|
|
75
|
+
{'name': 'force', 'type': 'boolean', 'default': False,
|
|
76
|
+
'desc': 'Delete the tag property from all nodes before removing the definition.', },
|
|
70
77
|
),
|
|
71
78
|
'returns': {'type': 'null', }}},
|
|
72
79
|
{'name': 'getExtModel', 'desc': 'Get all extended model elements.',
|
|
@@ -163,20 +170,39 @@ class LibModelExt(s_stormtypes.Lib):
|
|
|
163
170
|
s_stormtypes.confirm(('model', 'form', 'del', formname))
|
|
164
171
|
await self.runt.snap.core.delForm(formname)
|
|
165
172
|
|
|
166
|
-
async def delFormProp(self, formname, propname):
|
|
173
|
+
async def delFormProp(self, formname, propname, force=False):
|
|
167
174
|
formname = await s_stormtypes.tostr(formname)
|
|
168
175
|
propname = await s_stormtypes.tostr(propname)
|
|
176
|
+
force = await s_stormtypes.tobool(force)
|
|
169
177
|
s_stormtypes.confirm(('model', 'prop', 'del', formname))
|
|
178
|
+
|
|
179
|
+
if force is True:
|
|
180
|
+
meta = {'user': self.runt.snap.user.iden, 'time': s_common.now()}
|
|
181
|
+
await self.runt.snap.core._delAllFormProp(formname, propname, meta)
|
|
182
|
+
|
|
170
183
|
await self.runt.snap.core.delFormProp(formname, propname)
|
|
171
184
|
|
|
172
|
-
async def delUnivProp(self, propname):
|
|
185
|
+
async def delUnivProp(self, propname, force=False):
|
|
173
186
|
propname = await s_stormtypes.tostr(propname)
|
|
187
|
+
force = await s_stormtypes.tobool(force)
|
|
174
188
|
s_stormtypes.confirm(('model', 'univ', 'del'))
|
|
189
|
+
|
|
190
|
+
if force:
|
|
191
|
+
meta = {'user': self.runt.snap.user.iden, 'time': s_common.now()}
|
|
192
|
+
await self.runt.snap.core._delAllUnivProp(propname, meta)
|
|
193
|
+
|
|
175
194
|
await self.runt.snap.core.delUnivProp(propname)
|
|
176
195
|
|
|
177
|
-
async def delTagProp(self, propname):
|
|
196
|
+
async def delTagProp(self, propname, force=False):
|
|
178
197
|
propname = await s_stormtypes.tostr(propname)
|
|
198
|
+
force = await s_stormtypes.tobool(force)
|
|
199
|
+
|
|
179
200
|
s_stormtypes.confirm(('model', 'tagprop', 'del'))
|
|
201
|
+
|
|
202
|
+
if force:
|
|
203
|
+
meta = {'user': self.runt.snap.user.iden, 'time': s_common.now()}
|
|
204
|
+
await self.runt.snap.core._delAllTagProp(propname, meta)
|
|
205
|
+
|
|
180
206
|
await self.runt.snap.core.delTagProp(propname)
|
|
181
207
|
|
|
182
208
|
@s_stormtypes.stormfunc(readonly=True)
|
synapse/lib/stormlib/smtp.py
CHANGED
|
@@ -96,6 +96,8 @@ class SmtpMessage(s_stormtypes.StormType):
|
|
|
96
96
|
'desc': 'Use the STARTTLS directive with the SMTP server.'},
|
|
97
97
|
{'name': 'timeout', 'type': 'int', 'default': 60,
|
|
98
98
|
'desc': 'The timeout (in seconds) to wait for message delivery.'},
|
|
99
|
+
{'type': 'bool', 'name': 'ssl_verify', 'default': True,
|
|
100
|
+
'desc': 'Perform SSL/TLS verification.'},
|
|
99
101
|
),
|
|
100
102
|
'returns': {'type': 'list', 'desc': 'An ($ok, $valu) tuple.'}}},
|
|
101
103
|
|
|
@@ -148,7 +150,8 @@ class SmtpMessage(s_stormtypes.StormType):
|
|
|
148
150
|
async def _getEmailHtml(self):
|
|
149
151
|
return self.bodyhtml
|
|
150
152
|
|
|
151
|
-
async def send(self, host, port=25, user=None, passwd=None, usetls=False, starttls=False, timeout=60
|
|
153
|
+
async def send(self, host, port=25, user=None, passwd=None, usetls=False, starttls=False, timeout=60,
|
|
154
|
+
ssl_verify=True):
|
|
152
155
|
|
|
153
156
|
self.runt.confirm(('storm', 'inet', 'smtp', 'send'))
|
|
154
157
|
|
|
@@ -161,6 +164,7 @@ class SmtpMessage(s_stormtypes.StormType):
|
|
|
161
164
|
port = await s_stormtypes.toint(port)
|
|
162
165
|
usetls = await s_stormtypes.tobool(usetls)
|
|
163
166
|
starttls = await s_stormtypes.tobool(starttls)
|
|
167
|
+
ssl_verify = await s_stormtypes.tobool(ssl_verify)
|
|
164
168
|
|
|
165
169
|
if usetls and starttls:
|
|
166
170
|
raise s_exc.BadArg(mesg='usetls and starttls are mutually exclusive arguments.')
|
|
@@ -183,6 +187,10 @@ class SmtpMessage(s_stormtypes.StormType):
|
|
|
183
187
|
|
|
184
188
|
recipients = [await s_stormtypes.tostr(e) for e in self.recipients]
|
|
185
189
|
|
|
190
|
+
ctx = None
|
|
191
|
+
if usetls or starttls:
|
|
192
|
+
ctx = self.runt.snap.core.getCachedSslCtx(opts=None, verify=ssl_verify)
|
|
193
|
+
|
|
186
194
|
futu = aiosmtplib.send(message,
|
|
187
195
|
port=port,
|
|
188
196
|
hostname=host,
|
|
@@ -191,7 +199,9 @@ class SmtpMessage(s_stormtypes.StormType):
|
|
|
191
199
|
use_tls=usetls,
|
|
192
200
|
start_tls=starttls,
|
|
193
201
|
username=user,
|
|
194
|
-
password=passwd
|
|
202
|
+
password=passwd,
|
|
203
|
+
tls_context=ctx,
|
|
204
|
+
)
|
|
195
205
|
|
|
196
206
|
await s_common.wait_for(futu, timeout=timeout)
|
|
197
207
|
|
synapse/lib/stormlib/stix.py
CHANGED
|
@@ -875,14 +875,19 @@ class LibStixImport(s_stormtypes.Lib):
|
|
|
875
875
|
bundle = await s_stormtypes.toprim(bundle)
|
|
876
876
|
config = await s_stormtypes.toprim(config)
|
|
877
877
|
|
|
878
|
+
if not isinstance(config, dict):
|
|
879
|
+
mesg = 'STIX ingest config must be a dictionary.'
|
|
880
|
+
raise s_exc.BadArg(mesg=mesg)
|
|
881
|
+
|
|
878
882
|
config.setdefault('bundle', {})
|
|
879
883
|
config.setdefault('objects', {})
|
|
880
884
|
config.setdefault('relationships', [])
|
|
881
885
|
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
+
try:
|
|
887
|
+
rellook = {r['type']: r for r in config.get('relationships', ())}
|
|
888
|
+
except Exception as e:
|
|
889
|
+
mesg = f'Error processing relationships in STIX bundle ingest config: {e}.'
|
|
890
|
+
raise s_exc.BadArg(mesg=mesg)
|
|
886
891
|
|
|
887
892
|
bundlenode = None
|
|
888
893
|
|
|
@@ -890,13 +895,41 @@ class LibStixImport(s_stormtypes.Lib):
|
|
|
890
895
|
if bundleconf is None:
|
|
891
896
|
bundleconf = {}
|
|
892
897
|
|
|
898
|
+
if not isinstance(bundleconf, dict):
|
|
899
|
+
mesg = 'STIX ingest config bundle value must be a dictionary.'
|
|
900
|
+
raise s_exc.BadArg(mesg=mesg)
|
|
901
|
+
|
|
893
902
|
bundlestorm = bundleconf.get('storm')
|
|
894
903
|
if bundlestorm:
|
|
904
|
+
if not isinstance(bundlestorm, str):
|
|
905
|
+
mesg = 'STIX ingest config storm query must be a string.'
|
|
906
|
+
raise s_exc.BadArg(mesg=mesg)
|
|
907
|
+
|
|
895
908
|
bundlenode = await self._callStorm(bundlestorm, {'bundle': bundle})
|
|
896
909
|
|
|
897
910
|
self.runt.layerConfirm(('node', 'edge', 'add', 'refs'))
|
|
898
911
|
|
|
899
|
-
|
|
912
|
+
try:
|
|
913
|
+
nodesbyid = await self._ingestObjects(bundle, config, rellook)
|
|
914
|
+
except Exception as e:
|
|
915
|
+
mesg = f'Error processing objects in STIX bundle ingest: {e}.'
|
|
916
|
+
raise s_exc.BadArg(mesg=mesg)
|
|
917
|
+
|
|
918
|
+
if bundlenode is not None:
|
|
919
|
+
for node in nodesbyid.values():
|
|
920
|
+
await bundlenode.addEdge('refs', node.iden())
|
|
921
|
+
await asyncio.sleep(0)
|
|
922
|
+
yield bundlenode
|
|
923
|
+
|
|
924
|
+
for node in nodesbyid.values():
|
|
925
|
+
yield node
|
|
926
|
+
|
|
927
|
+
async def _ingestObjects(self, bundle, config, rellook):
|
|
928
|
+
|
|
929
|
+
nodesbyid = {}
|
|
930
|
+
relationships = []
|
|
931
|
+
|
|
932
|
+
for obj in bundle.get('objects', ()):
|
|
900
933
|
|
|
901
934
|
objtype = obj.get('type')
|
|
902
935
|
|
|
@@ -971,7 +1004,7 @@ class LibStixImport(s_stormtypes.Lib):
|
|
|
971
1004
|
await self.runt.snap.warnonce(f'STIX bundle ingest has no relationship definition for: {reltype}.')
|
|
972
1005
|
|
|
973
1006
|
# attempt to resolve object_refs
|
|
974
|
-
for obj in bundle.get('objects'):
|
|
1007
|
+
for obj in bundle.get('objects', ()):
|
|
975
1008
|
|
|
976
1009
|
node = nodesbyid.get(obj.get('id'))
|
|
977
1010
|
if node is None:
|
|
@@ -984,17 +1017,7 @@ class LibStixImport(s_stormtypes.Lib):
|
|
|
984
1017
|
|
|
985
1018
|
await node.addEdge('refs', refsnode.iden())
|
|
986
1019
|
|
|
987
|
-
|
|
988
|
-
for node in nodesbyid.values():
|
|
989
|
-
await bundlenode.addEdge('refs', node.iden())
|
|
990
|
-
await asyncio.sleep(0)
|
|
991
|
-
yield bundlenode
|
|
992
|
-
|
|
993
|
-
for node in nodesbyid.values():
|
|
994
|
-
yield node
|
|
995
|
-
|
|
996
|
-
if bundlenode:
|
|
997
|
-
yield bundlenode
|
|
1020
|
+
return nodesbyid
|
|
998
1021
|
|
|
999
1022
|
async def _callStorm(self, text, varz):
|
|
1000
1023
|
|
synapse/lib/stormlib/vault.py
CHANGED
|
@@ -649,7 +649,7 @@ class Vault(s_stormtypes.Prim):
|
|
|
649
649
|
'type': {'type': 'function', '_funcname': '_methSetPerm',
|
|
650
650
|
'args': (
|
|
651
651
|
{'name': 'iden', 'type': 'str', 'desc': 'The user or role to modify.'},
|
|
652
|
-
{'name': 'level', 'type': 'str', 'desc': 'The easyperm level for the iden. $lib.
|
|
652
|
+
{'name': 'level', 'type': 'str', 'desc': 'The easyperm level for the iden. $lib.null to remove an existing permission.'},
|
|
653
653
|
),
|
|
654
654
|
'returns': {'type': 'boolean', 'desc': '$lib.true if the permission was set, $lib.false otherwise.', }}},
|
|
655
655
|
|
|
@@ -744,7 +744,7 @@ class Vault(s_stormtypes.Prim):
|
|
|
744
744
|
s_stormtypes.confirmEasyPerm(vault, s_cell.PERM_ADMIN, mesg=mesg)
|
|
745
745
|
|
|
746
746
|
iden = await s_stormtypes.tostr(iden)
|
|
747
|
-
level = await s_stormtypes.toint(level)
|
|
747
|
+
level = await s_stormtypes.toint(level, noneok=True)
|
|
748
748
|
|
|
749
749
|
return await self.runt.snap.core.setVaultPerm(self.valu, iden, level)
|
|
750
750
|
|
synapse/lib/stormtypes.py
CHANGED
|
@@ -5277,7 +5277,7 @@ class Number(Prim):
|
|
|
5277
5277
|
def __init__(self, valu, path=None):
|
|
5278
5278
|
try:
|
|
5279
5279
|
valu = s_common.hugenum(valu)
|
|
5280
|
-
except decimal.DecimalException as e:
|
|
5280
|
+
except (TypeError, decimal.DecimalException) as e:
|
|
5281
5281
|
mesg = f'Failed to make number from {valu!r}'
|
|
5282
5282
|
raise s_exc.BadCast(mesg=mesg) from e
|
|
5283
5283
|
|
synapse/lib/types.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import sys
|
|
1
2
|
import asyncio
|
|
2
3
|
import decimal
|
|
3
4
|
import logging
|
|
@@ -78,6 +79,14 @@ class Type:
|
|
|
78
79
|
|
|
79
80
|
self.postTypeInit()
|
|
80
81
|
|
|
82
|
+
normopts = dict(self.opts)
|
|
83
|
+
for optn, valu in normopts.items():
|
|
84
|
+
if isinstance(valu, float):
|
|
85
|
+
normopts[optn] = str(valu)
|
|
86
|
+
|
|
87
|
+
ctor = '.'.join([self.__class__.__module__, self.__class__.__qualname__])
|
|
88
|
+
self.typehash = sys.intern(s_common.guid((ctor, s_common.flatten(normopts))))
|
|
89
|
+
|
|
81
90
|
def _storLiftSafe(self, cmpr, valu):
|
|
82
91
|
try:
|
|
83
92
|
return self.storlifts['=']('=', valu)
|
synapse/lib/version.py
CHANGED
|
@@ -223,6 +223,6 @@ def reqVersion(valu, reqver,
|
|
|
223
223
|
##############################################################################
|
|
224
224
|
# The following are touched during the release process by bumpversion.
|
|
225
225
|
# Do not modify these directly.
|
|
226
|
-
version = (2,
|
|
226
|
+
version = (2, 179, 0)
|
|
227
227
|
verstring = '.'.join([str(x) for x in version])
|
|
228
|
-
commit = '
|
|
228
|
+
commit = '1c51c58523e9012655d8d18bfa1ad149e5536c25'
|