synapse 2.152.0__py311-none-any.whl → 2.154.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 +19 -16
- synapse/cortex.py +203 -15
- synapse/exc.py +0 -2
- synapse/lib/ast.py +42 -23
- synapse/lib/autodoc.py +2 -2
- synapse/lib/cache.py +16 -1
- synapse/lib/cell.py +5 -5
- synapse/lib/httpapi.py +198 -2
- synapse/lib/layer.py +5 -2
- synapse/lib/modelrev.py +36 -3
- synapse/lib/node.py +2 -5
- synapse/lib/parser.py +1 -1
- synapse/lib/schemas.py +51 -0
- synapse/lib/snap.py +10 -0
- synapse/lib/storm.lark +24 -4
- synapse/lib/storm.py +98 -19
- synapse/lib/storm_format.py +1 -1
- synapse/lib/stormhttp.py +11 -4
- synapse/lib/stormlib/auth.py +16 -2
- synapse/lib/stormlib/backup.py +1 -0
- synapse/lib/stormlib/basex.py +2 -0
- synapse/lib/stormlib/cell.py +7 -0
- synapse/lib/stormlib/compression.py +3 -0
- synapse/lib/stormlib/cortex.py +1168 -0
- synapse/lib/stormlib/ethereum.py +1 -0
- synapse/lib/stormlib/graph.py +2 -0
- synapse/lib/stormlib/hashes.py +5 -0
- synapse/lib/stormlib/hex.py +6 -0
- synapse/lib/stormlib/infosec.py +6 -1
- synapse/lib/stormlib/ipv6.py +1 -0
- synapse/lib/stormlib/iters.py +58 -1
- synapse/lib/stormlib/json.py +5 -0
- synapse/lib/stormlib/mime.py +1 -0
- synapse/lib/stormlib/model.py +19 -3
- synapse/lib/stormlib/modelext.py +1 -0
- synapse/lib/stormlib/notifications.py +2 -0
- synapse/lib/stormlib/pack.py +2 -0
- synapse/lib/stormlib/random.py +1 -0
- synapse/lib/stormlib/smtp.py +0 -7
- synapse/lib/stormlib/stats.py +223 -0
- synapse/lib/stormlib/stix.py +8 -0
- synapse/lib/stormlib/storm.py +1 -0
- synapse/lib/stormlib/version.py +3 -0
- synapse/lib/stormlib/xml.py +3 -0
- synapse/lib/stormlib/yaml.py +2 -0
- synapse/lib/stormtypes.py +250 -170
- synapse/lib/trigger.py +180 -4
- synapse/lib/types.py +1 -1
- synapse/lib/version.py +2 -2
- synapse/lib/view.py +55 -6
- synapse/models/inet.py +21 -6
- synapse/models/orgs.py +48 -2
- synapse/models/risk.py +126 -2
- synapse/models/syn.py +6 -0
- synapse/tests/files/stormpkg/badapidef.yaml +13 -0
- synapse/tests/files/stormpkg/storm/modules/apimod +10 -0
- synapse/tests/files/stormpkg/testpkg.yaml +23 -0
- synapse/tests/test_axon.py +7 -2
- synapse/tests/test_cortex.py +231 -35
- synapse/tests/test_lib_ast.py +138 -43
- synapse/tests/test_lib_autodoc.py +1 -1
- synapse/tests/test_lib_modelrev.py +9 -0
- synapse/tests/test_lib_node.py +55 -0
- synapse/tests/test_lib_storm.py +14 -1
- synapse/tests/test_lib_stormhttp.py +65 -6
- synapse/tests/test_lib_stormlib_auth.py +12 -3
- synapse/tests/test_lib_stormlib_cortex.py +1327 -0
- synapse/tests/test_lib_stormlib_iters.py +116 -0
- synapse/tests/test_lib_stormlib_stats.py +187 -0
- synapse/tests/test_lib_stormlib_storm.py +8 -0
- synapse/tests/test_lib_stormsvc.py +24 -1
- synapse/tests/test_lib_stormtypes.py +124 -69
- synapse/tests/test_lib_trigger.py +315 -0
- synapse/tests/test_lib_view.py +1 -2
- synapse/tests/test_model_base.py +26 -0
- synapse/tests/test_model_inet.py +22 -0
- synapse/tests/test_model_orgs.py +28 -0
- synapse/tests/test_model_risk.py +73 -0
- synapse/tests/test_tools_autodoc.py +25 -0
- synapse/tests/test_tools_genpkg.py +9 -3
- synapse/tests/utils.py +39 -0
- synapse/tools/autodoc.py +42 -2
- {synapse-2.152.0.dist-info → synapse-2.154.0.dist-info}/METADATA +2 -2
- {synapse-2.152.0.dist-info → synapse-2.154.0.dist-info}/RECORD +87 -79
- {synapse-2.152.0.dist-info → synapse-2.154.0.dist-info}/WHEEL +1 -1
- {synapse-2.152.0.dist-info → synapse-2.154.0.dist-info}/LICENSE +0 -0
- {synapse-2.152.0.dist-info → synapse-2.154.0.dist-info}/top_level.txt +0 -0
synapse/lib/trigger.py
CHANGED
|
@@ -21,6 +21,8 @@ Conditions = set((
|
|
|
21
21
|
'node:add',
|
|
22
22
|
'node:del',
|
|
23
23
|
'prop:set',
|
|
24
|
+
'edge:add',
|
|
25
|
+
'edge:del'
|
|
24
26
|
))
|
|
25
27
|
|
|
26
28
|
RecursionDepth = contextvars.ContextVar('RecursionDepth', default=0)
|
|
@@ -37,11 +39,13 @@ TrigSchema = {
|
|
|
37
39
|
'user': {'type': 'string', 'pattern': s_config.re_iden},
|
|
38
40
|
'view': {'type': 'string', 'pattern': s_config.re_iden},
|
|
39
41
|
'form': {'type': 'string', 'pattern': _formre},
|
|
42
|
+
'n2form': {'type': 'string', 'pattern': _formre},
|
|
40
43
|
'tag': {'type': 'string', 'pattern': _tagre},
|
|
41
44
|
'prop': {'type': 'string', 'pattern': _propre},
|
|
45
|
+
'verb': {'type': 'string', },
|
|
42
46
|
'name': {'type': 'string', },
|
|
43
47
|
'doc': {'type': 'string', },
|
|
44
|
-
'cond': {'enum': ['node:add', 'node:del', 'tag:add', 'tag:del', 'prop:set']},
|
|
48
|
+
'cond': {'enum': ['node:add', 'node:del', 'tag:add', 'tag:del', 'prop:set', 'edge:add', 'edge:del']},
|
|
45
49
|
'storm': {'type': 'string'},
|
|
46
50
|
'async': {'type': 'boolean'},
|
|
47
51
|
'enabled': {'type': 'boolean'},
|
|
@@ -69,6 +73,14 @@ TrigSchema = {
|
|
|
69
73
|
'if': {'properties': {'cond': {'const': 'prop:set'}}},
|
|
70
74
|
'then': {'required': ['prop']},
|
|
71
75
|
},
|
|
76
|
+
{
|
|
77
|
+
'if': {'properties': {'cond': {'const': 'edge:add'}}},
|
|
78
|
+
'then': {'required': ['verb']},
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
'if': {'properties': {'cond': {'const': 'edge:del'}}},
|
|
82
|
+
'then': {'required': ['verb']},
|
|
83
|
+
},
|
|
72
84
|
],
|
|
73
85
|
}
|
|
74
86
|
TrigSchemaValidator = s_config.getJsValidator(TrigSchema)
|
|
@@ -89,9 +101,9 @@ class Triggers:
|
|
|
89
101
|
self.view = view
|
|
90
102
|
self.triggers = {}
|
|
91
103
|
|
|
92
|
-
self.tagadd = collections.defaultdict(list) # (form, tag): [
|
|
93
|
-
self.tagset = collections.defaultdict(list) # (form, tag): [
|
|
94
|
-
self.tagdel = collections.defaultdict(list) # (form, tag): [
|
|
104
|
+
self.tagadd = collections.defaultdict(list) # (form, tag): [ Trigger ... ]
|
|
105
|
+
self.tagset = collections.defaultdict(list) # (form, tag): [ Trigger ... ]
|
|
106
|
+
self.tagdel = collections.defaultdict(list) # (form, tag): [ Trigger ... ]
|
|
95
107
|
|
|
96
108
|
self.tagaddglobs = collections.defaultdict(s_cache.TagGlobs) # form: TagGlobs
|
|
97
109
|
self.tagsetglobs = collections.defaultdict(s_cache.TagGlobs) # form: TagGlobs
|
|
@@ -101,6 +113,15 @@ class Triggers:
|
|
|
101
113
|
self.nodedel = collections.defaultdict(list) # form: [ Trigger ... ]
|
|
102
114
|
self.propset = collections.defaultdict(list) # prop: [ Trigger ... ]
|
|
103
115
|
|
|
116
|
+
self.edgeadd = collections.defaultdict(list) # (n1form, verb, n2form: [ Trigger ... ]
|
|
117
|
+
self.edgedel = collections.defaultdict(list) # (n1form, verb, n2form: [ Trigger ... ]
|
|
118
|
+
|
|
119
|
+
self.edgeaddglobs = collections.defaultdict(s_cache.EdgeGlobs) # (n1form, n2form: [ EdgeGlobs ... ]
|
|
120
|
+
self.edgedelglobs = collections.defaultdict(s_cache.EdgeGlobs) # (n1form, n2form: [ EdgeGlobs ... ]
|
|
121
|
+
|
|
122
|
+
self.edgeaddcache = s_cache.LruDict()
|
|
123
|
+
self.edgedelcache = s_cache.LruDict()
|
|
124
|
+
|
|
104
125
|
@contextlib.contextmanager
|
|
105
126
|
def _recursion_check(self):
|
|
106
127
|
|
|
@@ -182,6 +203,106 @@ class Triggers:
|
|
|
182
203
|
for _, trig in globs.get(tag):
|
|
183
204
|
await trig.execute(node, vars=vars, view=view)
|
|
184
205
|
|
|
206
|
+
async def runEdgeAdd(self, n1, verb, n2, view=None):
|
|
207
|
+
n1form = n1.form.name if n1 else None
|
|
208
|
+
n2form = n2.form.name if n2 else None
|
|
209
|
+
n2iden = n2.iden() if n2 else None
|
|
210
|
+
varz = {'auto': {'opts': {'verb': verb, 'n2iden': n2iden}}}
|
|
211
|
+
with self._recursion_check():
|
|
212
|
+
cachekey = (n1form, verb, n2form)
|
|
213
|
+
cached = self.edgeaddcache.get(cachekey)
|
|
214
|
+
if cached is None:
|
|
215
|
+
cached = []
|
|
216
|
+
for trig in self.edgeadd.get((None, verb, None), ()):
|
|
217
|
+
cached.append(trig)
|
|
218
|
+
|
|
219
|
+
globs = self.edgeaddglobs.get((None, None))
|
|
220
|
+
if globs:
|
|
221
|
+
for _, trig in globs.get(verb):
|
|
222
|
+
cached.append(trig)
|
|
223
|
+
|
|
224
|
+
if n1:
|
|
225
|
+
for trig in self.edgeadd.get((n1form, verb, None), ()):
|
|
226
|
+
cached.append(trig)
|
|
227
|
+
|
|
228
|
+
globs = self.edgeaddglobs.get((n1form, None))
|
|
229
|
+
if globs:
|
|
230
|
+
for _, trig in globs.get(verb):
|
|
231
|
+
cached.append(trig)
|
|
232
|
+
|
|
233
|
+
if n2:
|
|
234
|
+
for trig in self.edgeadd.get((None, verb, n2form), ()):
|
|
235
|
+
cached.append(trig)
|
|
236
|
+
|
|
237
|
+
globs = self.edgeaddglobs.get((None, n2form))
|
|
238
|
+
if globs:
|
|
239
|
+
for _, trig in globs.get(verb):
|
|
240
|
+
cached.append(trig)
|
|
241
|
+
|
|
242
|
+
if n1 and n2:
|
|
243
|
+
for trig in self.edgeadd.get((n1form, verb, n2form), ()):
|
|
244
|
+
cached.append(trig)
|
|
245
|
+
|
|
246
|
+
globs = self.edgeaddglobs.get((n1form, n2form))
|
|
247
|
+
if globs:
|
|
248
|
+
for _, trig in globs.get(verb):
|
|
249
|
+
cached.append(trig)
|
|
250
|
+
|
|
251
|
+
self.edgeaddcache[cachekey] = cached
|
|
252
|
+
|
|
253
|
+
for trig in cached:
|
|
254
|
+
await trig.execute(n1, vars=varz, view=view)
|
|
255
|
+
|
|
256
|
+
async def runEdgeDel(self, n1, verb, n2, view=None):
|
|
257
|
+
n1form = n1.form.name if n1 else None
|
|
258
|
+
n2form = n2.form.name if n2 else None
|
|
259
|
+
n2iden = n2.iden() if n2 else None
|
|
260
|
+
varz = {'auto': {'opts': {'verb': verb, 'n2iden': n2iden}}}
|
|
261
|
+
with self._recursion_check():
|
|
262
|
+
cachekey = (n1form, verb, n2form)
|
|
263
|
+
cached = self.edgedelcache.get(cachekey)
|
|
264
|
+
if cached is None:
|
|
265
|
+
cached = []
|
|
266
|
+
for trig in self.edgedel.get((None, verb, None), ()):
|
|
267
|
+
cached.append(trig)
|
|
268
|
+
|
|
269
|
+
globs = self.edgedelglobs.get((None, None))
|
|
270
|
+
if globs:
|
|
271
|
+
for _, trig in globs.get(verb):
|
|
272
|
+
cached.append(trig)
|
|
273
|
+
|
|
274
|
+
if n1:
|
|
275
|
+
for trig in self.edgedel.get((n1form, verb, None), ()):
|
|
276
|
+
cached.append(trig)
|
|
277
|
+
|
|
278
|
+
globs = self.edgedelglobs.get((n1form, None))
|
|
279
|
+
if globs:
|
|
280
|
+
for _, trig in globs.get(verb):
|
|
281
|
+
cached.append(trig)
|
|
282
|
+
|
|
283
|
+
if n2:
|
|
284
|
+
for trig in self.edgedel.get((None, verb, n2form), ()):
|
|
285
|
+
cached.append(trig)
|
|
286
|
+
|
|
287
|
+
globs = self.edgedelglobs.get((None, n2form))
|
|
288
|
+
if globs:
|
|
289
|
+
for _, trig in globs.get(verb):
|
|
290
|
+
cached.append(trig)
|
|
291
|
+
|
|
292
|
+
if n1 and n2:
|
|
293
|
+
for trig in self.edgedel.get((n1form, verb, n2form), ()):
|
|
294
|
+
cached.append(trig)
|
|
295
|
+
|
|
296
|
+
globs = self.edgedelglobs.get((n1form, n2form))
|
|
297
|
+
if globs:
|
|
298
|
+
for _, trig in globs.get(verb):
|
|
299
|
+
cached.append(trig)
|
|
300
|
+
|
|
301
|
+
self.edgedelcache[cachekey] = cached
|
|
302
|
+
|
|
303
|
+
for trig in cached:
|
|
304
|
+
await trig.execute(n1, vars=varz, view=view)
|
|
305
|
+
|
|
185
306
|
async def load(self, tdef):
|
|
186
307
|
|
|
187
308
|
trig = Trigger(self.view, tdef)
|
|
@@ -194,6 +315,8 @@ class Triggers:
|
|
|
194
315
|
tag = trig.tdef.get('tag')
|
|
195
316
|
form = trig.tdef.get('form')
|
|
196
317
|
prop = trig.tdef.get('prop')
|
|
318
|
+
verb = trig.tdef.get('verb')
|
|
319
|
+
n2form = trig.tdef.get('n2form')
|
|
197
320
|
|
|
198
321
|
if cond not in Conditions:
|
|
199
322
|
raise s_exc.NoSuchCond(name=cond)
|
|
@@ -206,6 +329,9 @@ class Triggers:
|
|
|
206
329
|
if tag is None:
|
|
207
330
|
raise s_exc.BadOptValu(mesg='missing tag')
|
|
208
331
|
s_chop.validateTagMatch(tag)
|
|
332
|
+
if cond in ('edge:add', 'edge:del') and verb is None:
|
|
333
|
+
raise s_exc.BadOptValu(mesg='verb must be present for edge:add or edge:del')
|
|
334
|
+
|
|
209
335
|
if prop is not None and cond != 'prop:set':
|
|
210
336
|
raise s_exc.BadOptValu(mesg='prop parameter invalid')
|
|
211
337
|
|
|
@@ -237,6 +363,20 @@ class Triggers:
|
|
|
237
363
|
else:
|
|
238
364
|
self.tagdelglobs[form].add(tag, trig)
|
|
239
365
|
|
|
366
|
+
elif cond == 'edge:add':
|
|
367
|
+
self.edgeaddcache.clear()
|
|
368
|
+
if '*' not in verb:
|
|
369
|
+
self.edgeadd[(form, verb, n2form)].append(trig)
|
|
370
|
+
else:
|
|
371
|
+
self.edgeaddglobs[(form, n2form)].add(verb, trig)
|
|
372
|
+
|
|
373
|
+
elif cond == 'edge:del':
|
|
374
|
+
self.edgedelcache.clear()
|
|
375
|
+
if '*' not in verb:
|
|
376
|
+
self.edgedel[(form, verb, n2form)].append(trig)
|
|
377
|
+
else:
|
|
378
|
+
self.edgedelglobs[(form, n2form)].add(verb, trig)
|
|
379
|
+
|
|
240
380
|
self.triggers[trig.iden] = trig
|
|
241
381
|
return trig
|
|
242
382
|
|
|
@@ -292,6 +432,34 @@ class Triggers:
|
|
|
292
432
|
globs.rem(tag, trig)
|
|
293
433
|
return trig
|
|
294
434
|
|
|
435
|
+
if cond == 'edge:add':
|
|
436
|
+
verb = trig.tdef['verb']
|
|
437
|
+
form = trig.tdef.get('form')
|
|
438
|
+
n2form = trig.tdef.get('n2form')
|
|
439
|
+
|
|
440
|
+
self.edgeaddcache.clear()
|
|
441
|
+
if '*' not in verb:
|
|
442
|
+
self.edgeadd[(form, verb, n2form)].remove(trig)
|
|
443
|
+
return trig
|
|
444
|
+
|
|
445
|
+
globs = self.edgeaddglobs.get((form, n2form))
|
|
446
|
+
globs.rem(verb, trig)
|
|
447
|
+
return trig
|
|
448
|
+
|
|
449
|
+
if cond == 'edge:del':
|
|
450
|
+
verb = trig.tdef['verb']
|
|
451
|
+
form = trig.tdef.get('form')
|
|
452
|
+
n2form = trig.tdef.get('n2form')
|
|
453
|
+
|
|
454
|
+
self.edgedelcache.clear()
|
|
455
|
+
if '*' not in verb:
|
|
456
|
+
self.edgedel[(form, verb, n2form)].remove(trig)
|
|
457
|
+
return trig
|
|
458
|
+
|
|
459
|
+
globs = self.edgedelglobs.get((form, n2form))
|
|
460
|
+
globs.rem(verb, trig)
|
|
461
|
+
return trig
|
|
462
|
+
|
|
295
463
|
raise AssertionError('trigger has invalid condition')
|
|
296
464
|
|
|
297
465
|
def get(self, iden):
|
|
@@ -440,6 +608,14 @@ class Trigger:
|
|
|
440
608
|
if prop is not None:
|
|
441
609
|
props['prop'] = prop
|
|
442
610
|
|
|
611
|
+
verb = self.tdef.get('verb')
|
|
612
|
+
if verb is not None:
|
|
613
|
+
props['verb'] = verb
|
|
614
|
+
|
|
615
|
+
n2form = self.tdef.get('n2form')
|
|
616
|
+
if n2form is not None:
|
|
617
|
+
props['n2form'] = n2form
|
|
618
|
+
|
|
443
619
|
pnorms = {}
|
|
444
620
|
for prop, valu in props.items():
|
|
445
621
|
formprop = form.props.get(prop)
|
synapse/lib/types.py
CHANGED
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, 154, 0)
|
|
227
227
|
verstring = '.'.join([str(x) for x in version])
|
|
228
|
-
commit = '
|
|
228
|
+
commit = '6c9600992a0ca2563239bc86b6631bd599707e3f'
|
synapse/lib/view.py
CHANGED
|
@@ -746,6 +746,7 @@ class View(s_nexus.Pusher): # type: ignore
|
|
|
746
746
|
|
|
747
747
|
await self.info.set('layers', [lyr.iden for lyr in self.layers])
|
|
748
748
|
await self.core.feedBeholder('view:addlayer', {'iden': self.iden, 'layer': layriden, 'indx': indx}, gates=[self.iden, layriden])
|
|
749
|
+
self.core._calcViewsByLayer()
|
|
749
750
|
|
|
750
751
|
@s_nexus.Pusher.onPushAuto('view:setlayers')
|
|
751
752
|
async def setLayers(self, layers):
|
|
@@ -753,14 +754,11 @@ class View(s_nexus.Pusher): # type: ignore
|
|
|
753
754
|
Set the view layers from a list of idens.
|
|
754
755
|
NOTE: view layers are stored "top down" (the write layer is self.layers[0])
|
|
755
756
|
'''
|
|
756
|
-
|
|
757
|
-
if view.parent is self:
|
|
758
|
-
raise s_exc.ReadOnlyLayer(mesg='May not change layers that have been forked from')
|
|
757
|
+
layrs = []
|
|
759
758
|
|
|
760
759
|
if self.parent is not None:
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
layrs = []
|
|
760
|
+
mesg = 'You cannot set the layers of a forked view.'
|
|
761
|
+
raise s_exc.BadArg(mesg=mesg)
|
|
764
762
|
|
|
765
763
|
for iden in layers:
|
|
766
764
|
layr = self.core.layers.get(iden)
|
|
@@ -777,6 +775,39 @@ class View(s_nexus.Pusher): # type: ignore
|
|
|
777
775
|
await self.info.set('layers', layers)
|
|
778
776
|
await self.core.feedBeholder('view:setlayers', {'iden': self.iden, 'layers': layers}, gates=[self.iden, layers[0]])
|
|
779
777
|
|
|
778
|
+
await self._calcChildViews()
|
|
779
|
+
self.core._calcViewsByLayer()
|
|
780
|
+
|
|
781
|
+
async def _calcChildViews(self):
|
|
782
|
+
|
|
783
|
+
todo = collections.deque([self])
|
|
784
|
+
|
|
785
|
+
byparent = collections.defaultdict(list)
|
|
786
|
+
for view in self.core.views.values():
|
|
787
|
+
if view.parent is None:
|
|
788
|
+
continue
|
|
789
|
+
|
|
790
|
+
byparent[view.parent].append(view)
|
|
791
|
+
|
|
792
|
+
while todo:
|
|
793
|
+
|
|
794
|
+
view = todo.pop()
|
|
795
|
+
|
|
796
|
+
for child in byparent.get(view, ()):
|
|
797
|
+
|
|
798
|
+
layers = [child.layers[0]]
|
|
799
|
+
layers.extend(view.layers)
|
|
800
|
+
|
|
801
|
+
child.layers = layers
|
|
802
|
+
|
|
803
|
+
# convert layers to a list of idens...
|
|
804
|
+
lids = [layr.iden for layr in layers]
|
|
805
|
+
await child.info.set('layers', lids)
|
|
806
|
+
|
|
807
|
+
await self.core.feedBeholder('view:setlayers', {'iden': child.iden, 'layers': lids}, gates=[child.iden, lids[0]])
|
|
808
|
+
|
|
809
|
+
todo.append(child)
|
|
810
|
+
|
|
780
811
|
async def fork(self, ldef=None, vdef=None):
|
|
781
812
|
'''
|
|
782
813
|
Make a new view inheriting from this view with the same layers and a new write layer on top
|
|
@@ -961,6 +992,24 @@ class View(s_nexus.Pusher): # type: ignore
|
|
|
961
992
|
|
|
962
993
|
await self.triggers.runPropSet(node, prop, oldv, view=view)
|
|
963
994
|
|
|
995
|
+
async def runEdgeAdd(self, n1, edge, n2, view=None):
|
|
996
|
+
if not n1.snap.trigson:
|
|
997
|
+
return
|
|
998
|
+
|
|
999
|
+
if view is None:
|
|
1000
|
+
view = self.iden
|
|
1001
|
+
|
|
1002
|
+
await self.triggers.runEdgeAdd(n1, edge, n2, view=view)
|
|
1003
|
+
|
|
1004
|
+
async def runEdgeDel(self, n1, edge, n2, view=None):
|
|
1005
|
+
if not n1.snap.trigson:
|
|
1006
|
+
return
|
|
1007
|
+
|
|
1008
|
+
if view is None:
|
|
1009
|
+
view = self.iden
|
|
1010
|
+
|
|
1011
|
+
await self.triggers.runEdgeDel(n1, edge, n2, view=view)
|
|
1012
|
+
|
|
964
1013
|
async def addTrigger(self, tdef):
|
|
965
1014
|
'''
|
|
966
1015
|
Adds a trigger to the view.
|
synapse/models/inet.py
CHANGED
|
@@ -28,6 +28,8 @@ udots = regex.compile(r'[\u3002\uff0e\uff61]')
|
|
|
28
28
|
cidrmasks = [((0xffffffff - (2 ** (32 - i) - 1)), (2 ** (32 - i))) for i in range(33)]
|
|
29
29
|
ipv4max = 2 ** 32 - 1
|
|
30
30
|
|
|
31
|
+
rfc6598 = ipaddress.IPv4Network('100.64.0.0/10')
|
|
32
|
+
|
|
31
33
|
def getAddrType(ip):
|
|
32
34
|
|
|
33
35
|
if ip.is_multicast:
|
|
@@ -45,6 +47,9 @@ def getAddrType(ip):
|
|
|
45
47
|
if ip.is_reserved:
|
|
46
48
|
return 'reserved'
|
|
47
49
|
|
|
50
|
+
if ip in rfc6598:
|
|
51
|
+
return 'shared'
|
|
52
|
+
|
|
48
53
|
return 'unicast'
|
|
49
54
|
|
|
50
55
|
class Addr(s_types.Str):
|
|
@@ -924,6 +929,11 @@ class Url(s_types.Str):
|
|
|
924
929
|
except Exception:
|
|
925
930
|
pass
|
|
926
931
|
|
|
932
|
+
# allow MSFT specific wild card syntax
|
|
933
|
+
# https://learn.microsoft.com/en-us/windows/win32/http/urlprefix-strings
|
|
934
|
+
if host is None and part == '+':
|
|
935
|
+
host = '+'
|
|
936
|
+
|
|
927
937
|
if host and local:
|
|
928
938
|
raise s_exc.BadTypeValu(valu=orig, name=self.name,
|
|
929
939
|
mesg='Host specified on local-only file URI') from None
|
|
@@ -950,10 +960,12 @@ class Url(s_types.Str):
|
|
|
950
960
|
if port is not None:
|
|
951
961
|
hostparts = f'{hostparts}:{port}'
|
|
952
962
|
|
|
953
|
-
if proto != 'file':
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
963
|
+
if proto != 'file' and host is None:
|
|
964
|
+
raise s_exc.BadTypeValu(valu=orig, name=self.name, mesg='Missing address/url')
|
|
965
|
+
|
|
966
|
+
if not hostparts and not pathpart:
|
|
967
|
+
raise s_exc.BadTypeValu(valu=orig, name=self.name,
|
|
968
|
+
mesg='Missing address/url') from None
|
|
957
969
|
|
|
958
970
|
base = f'{proto}://{hostparts}{pathpart}'
|
|
959
971
|
subs['base'] = base
|
|
@@ -2305,6 +2317,7 @@ class InetModule(s_module.CoreModule):
|
|
|
2305
2317
|
('name:en', ('inet:user', {}), {
|
|
2306
2318
|
'doc': 'The English version of the name associated with the (may be different from '
|
|
2307
2319
|
'the account identifier, e.g., a display name).',
|
|
2320
|
+
'deprecated': True,
|
|
2308
2321
|
}),
|
|
2309
2322
|
('aliases', ('array', {'type': 'inet:user', 'uniq': True, 'sorted': True}), {
|
|
2310
2323
|
'doc': 'An array of alternate names for the user.',
|
|
@@ -2322,7 +2335,8 @@ class InetModule(s_module.CoreModule):
|
|
|
2322
2335
|
'doc': 'The localized version of the real name of the account owner / registrant.'
|
|
2323
2336
|
}),
|
|
2324
2337
|
('realname:en', ('ps:name', {}), {
|
|
2325
|
-
'doc': 'The English version of the real name of the account owner / registrant.'
|
|
2338
|
+
'doc': 'The English version of the real name of the account owner / registrant.',
|
|
2339
|
+
'deprecated': True,
|
|
2326
2340
|
}),
|
|
2327
2341
|
('signup', ('time', {}), {
|
|
2328
2342
|
'doc': 'The date and time the account was registered.'
|
|
@@ -2540,7 +2554,8 @@ class InetModule(s_module.CoreModule):
|
|
|
2540
2554
|
}),
|
|
2541
2555
|
('name:en', ('inet:group', {}), {
|
|
2542
2556
|
'doc': 'The English version of the name associated with the group (may be different '
|
|
2543
|
-
'from the localized name).'
|
|
2557
|
+
'from the localized name).',
|
|
2558
|
+
'deprecated': True,
|
|
2544
2559
|
}),
|
|
2545
2560
|
('url', ('inet:url', {}), {
|
|
2546
2561
|
'doc': 'The service provider URL where the group is hosted.'
|
synapse/models/orgs.py
CHANGED
|
@@ -202,6 +202,8 @@ class OuModule(s_module.CoreModule):
|
|
|
202
202
|
('ou:jobtitle', ('str', {'lower': True, 'onespace': True}), {
|
|
203
203
|
'doc': 'A title for a position within an org.',
|
|
204
204
|
}),
|
|
205
|
+
('ou:requirement', ('guid', {}), {
|
|
206
|
+
'doc': 'A specific requirement.'}),
|
|
205
207
|
),
|
|
206
208
|
'edges': (
|
|
207
209
|
(('ou:campaign', 'uses', 'ou:technique'), {
|
|
@@ -219,6 +221,8 @@ class OuModule(s_module.CoreModule):
|
|
|
219
221
|
'doc': 'The campaign made use of the target node.'}),
|
|
220
222
|
(('ou:contribution', 'includes', None), {
|
|
221
223
|
'doc': 'The contribution includes the specific node.'}),
|
|
224
|
+
((None, 'meets', 'ou:requirement'), {
|
|
225
|
+
'doc': 'The requirement is met by the source node.'}),
|
|
222
226
|
),
|
|
223
227
|
'forms': (
|
|
224
228
|
('ou:jobtype', {}, ()),
|
|
@@ -634,8 +638,10 @@ class OuModule(s_module.CoreModule):
|
|
|
634
638
|
'doc': 'Deprecated for scalability. Please use -(uses)> ou:technique.',
|
|
635
639
|
}),
|
|
636
640
|
('goals', ('array', {'type': 'ou:goal', 'sorted': True, 'uniq': True}), {
|
|
637
|
-
'doc': 'The assessed goals of the organization.'
|
|
638
|
-
|
|
641
|
+
'doc': 'The assessed goals of the organization.'}),
|
|
642
|
+
|
|
643
|
+
('tag', ('syn:tag', {}), {
|
|
644
|
+
'doc': 'A base tag used to encode assessments made by the organization.'}),
|
|
639
645
|
)),
|
|
640
646
|
('ou:team', {}, (
|
|
641
647
|
('org', ('ou:org', {}), {}),
|
|
@@ -708,6 +714,7 @@ class OuModule(s_module.CoreModule):
|
|
|
708
714
|
'doc': 'An array of alternative names for the industry.'}),
|
|
709
715
|
|
|
710
716
|
('subs', ('array', {'type': 'ou:industry', 'split': ',', 'uniq': True, 'sorted': True}), {
|
|
717
|
+
'deprecated': True,
|
|
711
718
|
'doc': 'Deprecated. Please use ou:industry:type taxonomy.'}),
|
|
712
719
|
|
|
713
720
|
('sic', ('array', {'type': 'ou:sic', 'split': ',', 'uniq': True, 'sorted': True}), {
|
|
@@ -1122,6 +1129,45 @@ class OuModule(s_module.CoreModule):
|
|
|
1122
1129
|
}),
|
|
1123
1130
|
# TODO duration ('duration'
|
|
1124
1131
|
)),
|
|
1132
|
+
('ou:requirement', {}, (
|
|
1133
|
+
|
|
1134
|
+
('name', ('str', {'lower': True, 'onespace': True}), {
|
|
1135
|
+
'doc': 'A name for the requirement.'}),
|
|
1136
|
+
|
|
1137
|
+
('text', ('str', {}), {
|
|
1138
|
+
'disp': {'hint': 'text'},
|
|
1139
|
+
'doc': 'The text of the stated requirement.'}),
|
|
1140
|
+
|
|
1141
|
+
('optional', ('bool', {}), {
|
|
1142
|
+
'doc': 'Set to true if the requirement is optional.'}),
|
|
1143
|
+
|
|
1144
|
+
('priority', ('meta:priority', {}), {
|
|
1145
|
+
'doc': 'The priority of the requirement.'}),
|
|
1146
|
+
|
|
1147
|
+
('goal', ('ou:goal', {}), {
|
|
1148
|
+
'doc': 'The goal that the requirement is designed to achieve.'}),
|
|
1149
|
+
|
|
1150
|
+
('active', ('bool', {}), {
|
|
1151
|
+
'doc': 'Set to true if the requirement is currently active.'}),
|
|
1152
|
+
|
|
1153
|
+
('issued', ('time', {}), {
|
|
1154
|
+
'doc': 'The time that the requirement was first issued.'}),
|
|
1155
|
+
|
|
1156
|
+
('period', ('ival', {}), {
|
|
1157
|
+
'doc': 'The time window where the goal must be met. Can be ongoing.'}),
|
|
1158
|
+
|
|
1159
|
+
('issuer', ('ps:contact', {}), {
|
|
1160
|
+
'doc': 'The contact information of the entity which issued the requirement.'}),
|
|
1161
|
+
|
|
1162
|
+
('assignee', ('ps:contact', {}), {
|
|
1163
|
+
'doc': 'The contact information of the entity which is assigned to meet the requirement.'}),
|
|
1164
|
+
|
|
1165
|
+
('deps', ('array', {'type': 'ou:requirement', 'sorted': True, 'uniq': True}), {
|
|
1166
|
+
'doc': 'A list of sub-requirements which must be met to complete the requirement.'}),
|
|
1167
|
+
|
|
1168
|
+
('deps:min', ('int', {'min': 0}), {
|
|
1169
|
+
'doc': 'The minimum number dependant requirements which must be met. If unset, assume all must be met.'}),
|
|
1170
|
+
)),
|
|
1125
1171
|
)
|
|
1126
1172
|
}
|
|
1127
1173
|
|