synapse 2.222.0__py311-none-any.whl → 2.224.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/common.py +2 -2
- synapse/cortex.py +159 -31
- synapse/cryotank.py +1 -1
- synapse/datamodel.py +1 -1
- synapse/lib/ast.py +5 -3
- synapse/lib/layer.py +6 -6
- synapse/lib/nexus.py +1 -1
- synapse/lib/schemas.py +2 -0
- synapse/lib/snap.py +15 -9
- synapse/lib/storm.py +35 -191
- synapse/lib/stormlib/auth.py +1 -1
- synapse/lib/stormlib/imap.py +12 -4
- synapse/lib/stormlib/mime.py +15 -5
- synapse/lib/stormlib/pkg.py +598 -0
- synapse/lib/stormlib/task.py +114 -0
- synapse/lib/stormtypes.py +43 -175
- synapse/lib/trigger.py +16 -14
- synapse/lib/version.py +2 -2
- synapse/lib/view.py +17 -14
- synapse/models/files.py +1 -1
- synapse/models/inet.py +25 -0
- synapse/models/proj.py +3 -0
- synapse/models/risk.py +6 -0
- synapse/models/syn.py +8 -0
- synapse/tests/test_common.py +4 -0
- synapse/tests/test_cortex.py +52 -1
- synapse/tests/test_lib_aha.py +68 -53
- synapse/tests/test_lib_ast.py +3 -0
- synapse/tests/test_lib_cell.py +12 -12
- synapse/tests/test_lib_storm.py +128 -248
- synapse/tests/test_lib_stormlib_imap.py +14 -0
- synapse/tests/test_lib_stormlib_mime.py +24 -0
- synapse/tests/test_lib_stormlib_pkg.py +456 -0
- synapse/tests/test_lib_stormlib_task.py +98 -0
- synapse/tests/test_lib_stormtypes.py +12 -100
- synapse/tests/test_lib_trigger.py +66 -3
- synapse/tests/test_lib_view.py +53 -0
- synapse/tests/test_model_files.py +11 -0
- synapse/tests/test_model_inet.py +23 -0
- synapse/tests/test_model_proj.py +3 -1
- synapse/tests/test_model_risk.py +10 -0
- synapse/tests/test_model_syn.py +54 -2
- synapse/tools/cryo/cat.py +2 -1
- synapse/tools/cryo/list.py +2 -0
- {synapse-2.222.0.dist-info → synapse-2.224.0.dist-info}/METADATA +1 -1
- {synapse-2.222.0.dist-info → synapse-2.224.0.dist-info}/RECORD +49 -45
- {synapse-2.222.0.dist-info → synapse-2.224.0.dist-info}/WHEEL +0 -0
- {synapse-2.222.0.dist-info → synapse-2.224.0.dist-info}/licenses/LICENSE +0 -0
- {synapse-2.222.0.dist-info → synapse-2.224.0.dist-info}/top_level.txt +0 -0
synapse/lib/storm.py
CHANGED
|
@@ -439,196 +439,6 @@ stormcmds = (
|
|
|
439
439
|
}
|
|
440
440
|
''',
|
|
441
441
|
},
|
|
442
|
-
{
|
|
443
|
-
'name': 'pkg.list',
|
|
444
|
-
'descr': 'List the storm packages loaded in the cortex.',
|
|
445
|
-
'cmdargs': (
|
|
446
|
-
('--verbose', {'default': False, 'action': 'store_true',
|
|
447
|
-
'help': 'Display build time for each package.'}),
|
|
448
|
-
),
|
|
449
|
-
'storm': '''
|
|
450
|
-
init {
|
|
451
|
-
$conf = ({
|
|
452
|
-
"columns": [
|
|
453
|
-
{"name": "name", "width": 40},
|
|
454
|
-
{"name": "vers", "width": 10},
|
|
455
|
-
],
|
|
456
|
-
"separators": {
|
|
457
|
-
"row:outline": false,
|
|
458
|
-
"column:outline": false,
|
|
459
|
-
"header:row": "#",
|
|
460
|
-
"data:row": "",
|
|
461
|
-
"column": "",
|
|
462
|
-
},
|
|
463
|
-
})
|
|
464
|
-
if $cmdopts.verbose {
|
|
465
|
-
$conf.columns.append(({"name": "time", "width": 20}))
|
|
466
|
-
}
|
|
467
|
-
$printer = $lib.tabular.printer($conf)
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
$pkgs = $lib.pkg.list()
|
|
471
|
-
|
|
472
|
-
if $($pkgs.size() > 0) {
|
|
473
|
-
$lib.print('Loaded storm packages:')
|
|
474
|
-
$lib.print($printer.header())
|
|
475
|
-
for $pkg in $pkgs {
|
|
476
|
-
$row = (
|
|
477
|
-
$pkg.name, $pkg.version,
|
|
478
|
-
)
|
|
479
|
-
if $cmdopts.verbose {
|
|
480
|
-
try {
|
|
481
|
-
$row.append($lib.time.format($pkg.build.time, '%Y-%m-%d %H:%M:%S'))
|
|
482
|
-
} catch StormRuntimeError as _ {
|
|
483
|
-
$row.append('not available')
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
$lib.print($printer.row($row))
|
|
487
|
-
}
|
|
488
|
-
} else {
|
|
489
|
-
$lib.print('No storm packages installed.')
|
|
490
|
-
}
|
|
491
|
-
'''
|
|
492
|
-
},
|
|
493
|
-
{
|
|
494
|
-
'name': 'pkg.perms.list',
|
|
495
|
-
'descr': 'List any permissions declared by the package.',
|
|
496
|
-
'cmdargs': (
|
|
497
|
-
('name', {'help': 'The name (or name prefix) of the package.', 'type': 'str'}),
|
|
498
|
-
),
|
|
499
|
-
'storm': '''
|
|
500
|
-
$pdef = $lib.null
|
|
501
|
-
for $pkg in $lib.pkg.list() {
|
|
502
|
-
if $pkg.name.startswith($cmdopts.name) {
|
|
503
|
-
$pdef = $pkg
|
|
504
|
-
break
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
if (not $pdef) {
|
|
509
|
-
$lib.warn(`Package ({$cmdopts.name}) not found!`)
|
|
510
|
-
} else {
|
|
511
|
-
if $pdef.perms {
|
|
512
|
-
$lib.print(`Package ({$cmdopts.name}) defines the following permissions:`)
|
|
513
|
-
for $permdef in $pdef.perms {
|
|
514
|
-
$defv = $permdef.default
|
|
515
|
-
if ( $defv = $lib.null ) {
|
|
516
|
-
$defv = $lib.false
|
|
517
|
-
}
|
|
518
|
-
$text = `{('.').join($permdef.perm).ljust(32)} : {$permdef.desc} ( default: {$defv} )`
|
|
519
|
-
$lib.print($text)
|
|
520
|
-
}
|
|
521
|
-
} else {
|
|
522
|
-
$lib.print(`Package ({$cmdopts.name}) contains no permissions definitions.`)
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
'''
|
|
526
|
-
},
|
|
527
|
-
{
|
|
528
|
-
'name': 'pkg.del',
|
|
529
|
-
'descr': 'Remove a storm package from the cortex.',
|
|
530
|
-
'cmdargs': (
|
|
531
|
-
('name', {'help': 'The name (or name prefix) of the package to remove.'}),
|
|
532
|
-
),
|
|
533
|
-
'storm': '''
|
|
534
|
-
|
|
535
|
-
$pkgs = $lib.set()
|
|
536
|
-
|
|
537
|
-
for $pkg in $lib.pkg.list() {
|
|
538
|
-
if $pkg.name.startswith($cmdopts.name) {
|
|
539
|
-
$pkgs.add($pkg.name)
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
if $($pkgs.size() = 0) {
|
|
544
|
-
|
|
545
|
-
$lib.print('No package names match "{name}". Aborting.', name=$cmdopts.name)
|
|
546
|
-
|
|
547
|
-
} elif $($pkgs.size() = 1) {
|
|
548
|
-
|
|
549
|
-
$name = $pkgs.list().index(0)
|
|
550
|
-
$lib.print('Removing package: {name}', name=$name)
|
|
551
|
-
$lib.pkg.del($name)
|
|
552
|
-
|
|
553
|
-
} else {
|
|
554
|
-
|
|
555
|
-
$lib.print('Multiple package names match "{name}". Aborting.', name=$cmdopts.name)
|
|
556
|
-
|
|
557
|
-
}
|
|
558
|
-
'''
|
|
559
|
-
},
|
|
560
|
-
{
|
|
561
|
-
'name': 'pkg.docs',
|
|
562
|
-
'descr': 'Display documentation included in a storm package.',
|
|
563
|
-
'cmdargs': (
|
|
564
|
-
('name', {'help': 'The name (or name prefix) of the package.'}),
|
|
565
|
-
),
|
|
566
|
-
'storm': '''
|
|
567
|
-
$pdef = $lib.null
|
|
568
|
-
for $pkg in $lib.pkg.list() {
|
|
569
|
-
if $pkg.name.startswith($cmdopts.name) {
|
|
570
|
-
$pdef = $pkg
|
|
571
|
-
break
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
if (not $pdef) {
|
|
576
|
-
$lib.warn("Package ({name}) not found!", name=$cmdopts.name)
|
|
577
|
-
} else {
|
|
578
|
-
if $pdef.docs {
|
|
579
|
-
for $doc in $pdef.docs {
|
|
580
|
-
$lib.print($doc.content)
|
|
581
|
-
}
|
|
582
|
-
} else {
|
|
583
|
-
$lib.print("Package ({name}) contains no documentation.", name=$cmdopts.name)
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
'''
|
|
587
|
-
},
|
|
588
|
-
{
|
|
589
|
-
'name': 'pkg.load',
|
|
590
|
-
'descr': 'Load a storm package from an HTTP URL.',
|
|
591
|
-
'cmdargs': (
|
|
592
|
-
('url', {'help': 'The HTTP URL to load the package from.'}),
|
|
593
|
-
('--raw', {'default': False, 'action': 'store_true',
|
|
594
|
-
'help': 'Response JSON is a raw package definition without an envelope.'}),
|
|
595
|
-
('--verify', {'default': False, 'action': 'store_true',
|
|
596
|
-
'help': 'Enforce code signature verification on the storm package.'}),
|
|
597
|
-
('--ssl-noverify', {'default': False, 'action': 'store_true',
|
|
598
|
-
'help': 'Specify to disable SSL verification of the server.'}),
|
|
599
|
-
),
|
|
600
|
-
'storm': '''
|
|
601
|
-
init {
|
|
602
|
-
$ssl = $lib.true
|
|
603
|
-
if $cmdopts.ssl_noverify { $ssl = $lib.false }
|
|
604
|
-
|
|
605
|
-
$headers = ({'X-Synapse-Version': ('.').join($lib.version.synapse())})
|
|
606
|
-
|
|
607
|
-
$resp = $lib.inet.http.get($cmdopts.url, ssl_verify=$ssl, headers=$headers)
|
|
608
|
-
|
|
609
|
-
if ($resp.code != 200) {
|
|
610
|
-
$lib.warn("pkg.load got HTTP code: {code} for URL: {url}", code=$resp.code, url=$cmdopts.url)
|
|
611
|
-
$lib.exit()
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
$reply = $resp.json()
|
|
615
|
-
if $cmdopts.raw {
|
|
616
|
-
$pkg = $reply
|
|
617
|
-
} else {
|
|
618
|
-
if ($reply.status != "ok") {
|
|
619
|
-
$lib.warn("pkg.load got JSON error: {code} for URL: {url}", code=$reply.code, url=$cmdopts.url)
|
|
620
|
-
$lib.exit()
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
$pkg = $reply.result
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
$pkd = $lib.pkg.add($pkg, verify=$cmdopts.verify)
|
|
627
|
-
|
|
628
|
-
$lib.print("Loaded Package: {name} @{version}", name=$pkg.name, version=$pkg.version)
|
|
629
|
-
}
|
|
630
|
-
''',
|
|
631
|
-
},
|
|
632
442
|
{
|
|
633
443
|
'name': 'version',
|
|
634
444
|
'descr': 'Show version metadata relating to Synapse.',
|
|
@@ -1122,6 +932,7 @@ stormcmds = (
|
|
|
1122
932
|
},
|
|
1123
933
|
{
|
|
1124
934
|
'name': 'ps.list',
|
|
935
|
+
'deprecated': {'eolvers': 'v3.0.0', 'mesg': 'Use ``task.list`` instead.'},
|
|
1125
936
|
'descr': 'List running tasks in the cortex.',
|
|
1126
937
|
'cmdargs': (
|
|
1127
938
|
('--verbose', {'default': False, 'action': 'store_true', 'help': 'Enable verbose output.'}),
|
|
@@ -1148,6 +959,7 @@ stormcmds = (
|
|
|
1148
959
|
},
|
|
1149
960
|
{
|
|
1150
961
|
'name': 'ps.kill',
|
|
962
|
+
'deprecated': {'eolvers': 'v3.0.0', 'mesg': 'Use ``task.kill`` instead.'},
|
|
1151
963
|
'descr': 'Kill a running task/query within the cortex.',
|
|
1152
964
|
'cmdargs': (
|
|
1153
965
|
('iden', {'help': 'Any prefix that matches exactly one valid process iden is accepted.'}),
|
|
@@ -1301,6 +1113,16 @@ stormcmds = (
|
|
|
1301
1113
|
},
|
|
1302
1114
|
)
|
|
1303
1115
|
|
|
1116
|
+
def deprmesg(name, depritem):
|
|
1117
|
+
if (mesg := depritem.get('mesg')) is not None:
|
|
1118
|
+
return f'"{name}" is deprecated: {mesg}'
|
|
1119
|
+
|
|
1120
|
+
if (eolvers := depritem.get('eolvers')) is not None:
|
|
1121
|
+
return f'"{name}" is deprecated and will be removed in {eolvers}.'
|
|
1122
|
+
|
|
1123
|
+
eoldate = depritem.get('eoldate')
|
|
1124
|
+
return f'"{name}" is deprecated and will be removed on {eoldate}.'
|
|
1125
|
+
|
|
1304
1126
|
@s_cache.memoize(size=1024)
|
|
1305
1127
|
def queryhash(text):
|
|
1306
1128
|
return s_common.queryhash(text)
|
|
@@ -2096,6 +1918,7 @@ class Parser:
|
|
|
2096
1918
|
self.root = root
|
|
2097
1919
|
self.exited = False
|
|
2098
1920
|
self.mesgs = []
|
|
1921
|
+
self.deprs = {}
|
|
2099
1922
|
|
|
2100
1923
|
self.optargs = {}
|
|
2101
1924
|
self.posargs = []
|
|
@@ -2121,7 +1944,7 @@ class Parser:
|
|
|
2121
1944
|
|
|
2122
1945
|
choices = opts.get('choices')
|
|
2123
1946
|
if choices is not None and opts.get('action') in ('store_true', 'store_false'):
|
|
2124
|
-
mesg =
|
|
1947
|
+
mesg = 'Argument choices are not supported when action is store_true or store_false'
|
|
2125
1948
|
raise s_exc.BadArg(mesg=mesg, argtype=str(argtype))
|
|
2126
1949
|
|
|
2127
1950
|
dest = self._get_dest(names)
|
|
@@ -2178,6 +2001,9 @@ class Parser:
|
|
|
2178
2001
|
|
|
2179
2002
|
dest = argdef.get('dest')
|
|
2180
2003
|
|
|
2004
|
+
if (deprecated := argdef.get('deprecated')) is not None:
|
|
2005
|
+
self.deprs[item] = deprecated
|
|
2006
|
+
|
|
2181
2007
|
oact = argdef.get('action', 'store')
|
|
2182
2008
|
if oact == 'store_true':
|
|
2183
2009
|
opts[dest] = True
|
|
@@ -2367,6 +2193,12 @@ class Parser:
|
|
|
2367
2193
|
|
|
2368
2194
|
self._printf(f'Usage: {self.prog} [options] {posargs}')
|
|
2369
2195
|
|
|
2196
|
+
if self.cdef is not None and (deprecated := self.cdef.get('deprecated')) is not None:
|
|
2197
|
+
dmsg = deprmesg(self.prog, deprecated)
|
|
2198
|
+
self._printf('')
|
|
2199
|
+
self._printf(f'Deprecated: {dmsg}')
|
|
2200
|
+
self._printf('')
|
|
2201
|
+
|
|
2370
2202
|
if self.cdef is not None and (endpoints := self.cdef.get('endpoints')):
|
|
2371
2203
|
self._printf('')
|
|
2372
2204
|
self._printf('Endpoints:')
|
|
@@ -2476,6 +2308,10 @@ class Parser:
|
|
|
2476
2308
|
wrap_first = self._wrap_text(first, wrap_w)
|
|
2477
2309
|
self._printf(f'{base:<{base_w-2}}: {wrap_first[0]}')
|
|
2478
2310
|
|
|
2311
|
+
if (deprecated := argdef.get('deprecated')) is not None:
|
|
2312
|
+
mesg = deprmesg(names[0], deprecated)
|
|
2313
|
+
self._printf(f'{"":<{base_w-2}} Deprecated: {mesg}')
|
|
2314
|
+
|
|
2479
2315
|
for ln in wrap_first[1:]: self._printf(f'{"":<{base_w}}{ln}')
|
|
2480
2316
|
for ln in helplst[1:]:
|
|
2481
2317
|
lead_s = len(ln) - len(ln.lstrip())
|
|
@@ -2591,6 +2427,10 @@ class Cmd:
|
|
|
2591
2427
|
except s_exc.BadSyntax: # pragma: no cover
|
|
2592
2428
|
pass
|
|
2593
2429
|
|
|
2430
|
+
for item, depr in self.pars.deprs.items():
|
|
2431
|
+
mesg = deprmesg(item, depr)
|
|
2432
|
+
await self.runt.snap.warnonce(mesg)
|
|
2433
|
+
|
|
2594
2434
|
for line in self.pars.mesgs:
|
|
2595
2435
|
await self.runt.snap.printf(line)
|
|
2596
2436
|
|
|
@@ -2712,6 +2552,10 @@ class PureCmd(Cmd):
|
|
|
2712
2552
|
}
|
|
2713
2553
|
}
|
|
2714
2554
|
|
|
2555
|
+
if (deprecated := self.cdef.get('deprecated')) is not None:
|
|
2556
|
+
mesg = deprmesg(name, deprecated)
|
|
2557
|
+
await self.runt.warnonce(mesg)
|
|
2558
|
+
|
|
2715
2559
|
if self.runtsafe:
|
|
2716
2560
|
data = {'pathvars': {}}
|
|
2717
2561
|
async def genx():
|
synapse/lib/stormlib/auth.py
CHANGED
|
@@ -1810,7 +1810,7 @@ class LibUser(s_stormtypes.Lib):
|
|
|
1810
1810
|
'returns': {'type': 'boolean',
|
|
1811
1811
|
'desc': 'True if the user has the requested permission, false otherwise.', }}},
|
|
1812
1812
|
{'name': 'vars', 'desc': "Get a dictionary representing the current user's persistent variables.",
|
|
1813
|
-
'type': '
|
|
1813
|
+
'type': 'user:vars:dict', },
|
|
1814
1814
|
{'name': 'profile', 'desc': "Get a dictionary representing the current user's profile information.",
|
|
1815
1815
|
'type': 'auth:user:profile', },
|
|
1816
1816
|
{'name': 'iden', 'desc': 'The user GUID for the current storm user.', 'type': 'str'},
|
synapse/lib/stormlib/imap.py
CHANGED
|
@@ -526,14 +526,22 @@ class ImapLib(s_stormtypes.Lib):
|
|
|
526
526
|
|
|
527
527
|
try:
|
|
528
528
|
imap = await s_common.wait_for(coro, timeout)
|
|
529
|
-
except
|
|
529
|
+
except TimeoutError:
|
|
530
530
|
raise s_exc.TimeOut(mesg='Timed out waiting for IMAP server hello.') from None
|
|
531
531
|
|
|
532
532
|
async def fini():
|
|
533
|
-
async def
|
|
534
|
-
|
|
533
|
+
async def imapfini():
|
|
534
|
+
if imap.isfini:
|
|
535
|
+
return
|
|
536
|
+
|
|
537
|
+
try:
|
|
538
|
+
await s_common.wait_for(imap.logout(), 5)
|
|
539
|
+
except TimeoutError:
|
|
540
|
+
pass # pragma: no cover
|
|
541
|
+
|
|
535
542
|
await imap.fini()
|
|
536
|
-
|
|
543
|
+
|
|
544
|
+
self.runt.snap.core.schedCoro(imapfini())
|
|
537
545
|
|
|
538
546
|
self.runt.snap.onfini(fini)
|
|
539
547
|
|
synapse/lib/stormlib/mime.py
CHANGED
|
@@ -3,9 +3,9 @@ import bs4
|
|
|
3
3
|
import synapse.lib.coro as s_coro
|
|
4
4
|
import synapse.lib.stormtypes as s_stormtypes
|
|
5
5
|
|
|
6
|
-
def htmlToText(html):
|
|
6
|
+
def htmlToText(html, separator='\n', strip=True):
|
|
7
7
|
soup = bs4.BeautifulSoup(html, 'html5lib')
|
|
8
|
-
return soup.get_text(separator=
|
|
8
|
+
return soup.get_text(separator=separator, strip=strip)
|
|
9
9
|
|
|
10
10
|
@s_stormtypes.registry.registerLib
|
|
11
11
|
class LibMimeHtml(s_stormtypes.Lib):
|
|
@@ -17,8 +17,12 @@ class LibMimeHtml(s_stormtypes.Lib):
|
|
|
17
17
|
'type': {'type': 'function', '_funcname': 'totext',
|
|
18
18
|
'args': (
|
|
19
19
|
{'name': 'html', 'type': 'str', 'desc': 'The HTML text to be parsed.'},
|
|
20
|
+
{'name': 'separator', 'type': 'str', 'default': '\n',
|
|
21
|
+
'desc': 'The string used to join text.'},
|
|
22
|
+
{'name': 'strip', 'type': 'boolean', 'default': True,
|
|
23
|
+
'desc': 'Strip whitespace from the beginning and end of tag text.'},
|
|
20
24
|
),
|
|
21
|
-
'returns': {'type': 'str', 'desc': 'The
|
|
25
|
+
'returns': {'type': 'str', 'desc': 'The separator-joined inner HTML text.', }
|
|
22
26
|
}},
|
|
23
27
|
)
|
|
24
28
|
|
|
@@ -30,6 +34,12 @@ class LibMimeHtml(s_stormtypes.Lib):
|
|
|
30
34
|
}
|
|
31
35
|
|
|
32
36
|
@s_stormtypes.stormfunc(readonly=True)
|
|
33
|
-
async def totext(self, html):
|
|
37
|
+
async def totext(self, html, separator='\n', strip=True):
|
|
34
38
|
html = await s_stormtypes.tostr(html)
|
|
35
|
-
|
|
39
|
+
separator = await s_stormtypes.tostr(separator, noneok=True)
|
|
40
|
+
strip = await s_stormtypes.tobool(strip)
|
|
41
|
+
|
|
42
|
+
if separator is None:
|
|
43
|
+
separator = ''
|
|
44
|
+
|
|
45
|
+
return await s_coro.semafork(htmlToText, html, separator, strip)
|