synapse 2.191.0__py311-none-any.whl → 2.193.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 +54 -23
- synapse/common.py +15 -0
- synapse/cortex.py +18 -20
- synapse/exc.py +6 -1
- synapse/lib/agenda.py +0 -2
- synapse/lib/ast.py +30 -12
- synapse/lib/cell.py +79 -85
- synapse/lib/cli.py +20 -11
- synapse/lib/nexus.py +2 -1
- synapse/lib/parser.py +1 -1
- synapse/lib/snap.py +4 -4
- synapse/lib/storm.py +34 -17
- synapse/lib/stormhttp.py +32 -35
- synapse/lib/stormlib/json.py +5 -2
- synapse/lib/stormtypes.py +121 -20
- synapse/lib/version.py +2 -2
- synapse/models/inet.py +17 -1
- synapse/models/infotech.py +14 -4
- synapse/models/risk.py +16 -2
- synapse/tests/test_axon.py +10 -0
- synapse/tests/test_cortex.py +55 -3
- synapse/tests/test_exc.py +3 -0
- synapse/tests/test_lib_agenda.py +157 -1
- synapse/tests/test_lib_ast.py +49 -1
- synapse/tests/test_lib_cell.py +106 -1
- synapse/tests/test_lib_httpapi.py +9 -2
- synapse/tests/test_lib_storm.py +72 -30
- synapse/tests/test_lib_stormhttp.py +57 -12
- synapse/tests/test_lib_stormlib_json.py +20 -0
- synapse/tests/test_lib_stormlib_scrape.py +2 -2
- synapse/tests/test_model_inet.py +40 -5
- synapse/tests/test_model_risk.py +2 -0
- synapse/tests/test_servers_univ.py +0 -12
- synapse/tests/test_tools_apikey.py +227 -0
- synapse/tests/test_tools_storm.py +95 -0
- synapse/tests/test_utils_getrefs.py +1 -1
- synapse/tools/apikey.py +93 -0
- synapse/utils/getrefs.py +14 -3
- synapse/vendor/cpython/lib/http/__init__.py +0 -0
- synapse/vendor/cpython/lib/http/cookies.py +59 -0
- synapse/vendor/cpython/lib/test/test_http_cookies.py +49 -0
- {synapse-2.191.0.dist-info → synapse-2.193.0.dist-info}/METADATA +2 -2
- {synapse-2.191.0.dist-info → synapse-2.193.0.dist-info}/RECORD +46 -41
- {synapse-2.191.0.dist-info → synapse-2.193.0.dist-info}/WHEEL +1 -1
- {synapse-2.191.0.dist-info → synapse-2.193.0.dist-info}/LICENSE +0 -0
- {synapse-2.191.0.dist-info → synapse-2.193.0.dist-info}/top_level.txt +0 -0
synapse/lib/stormtypes.py
CHANGED
|
@@ -3,6 +3,7 @@ import copy
|
|
|
3
3
|
import gzip
|
|
4
4
|
import json
|
|
5
5
|
import time
|
|
6
|
+
|
|
6
7
|
import regex
|
|
7
8
|
import types
|
|
8
9
|
import base64
|
|
@@ -39,6 +40,7 @@ import synapse.lib.stormctrl as s_stormctrl
|
|
|
39
40
|
logger = logging.getLogger(__name__)
|
|
40
41
|
|
|
41
42
|
AXON_MINVERS_PROXY = (2, 97, 0)
|
|
43
|
+
AXON_MINVERS_PROXYTRUE = (2, 192, 0)
|
|
42
44
|
AXON_MINVERS_SSLOPTS = '>=2.162.0'
|
|
43
45
|
|
|
44
46
|
class Undef:
|
|
@@ -73,6 +75,79 @@ def strifyHttpArg(item, multi=False):
|
|
|
73
75
|
return retn
|
|
74
76
|
return item
|
|
75
77
|
|
|
78
|
+
async def resolveCoreProxyUrl(valu):
|
|
79
|
+
'''
|
|
80
|
+
Resolve a proxy value to a proxy URL.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
valu (str|None|bool): The proxy value.
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
(str|None): A proxy URL string or None.
|
|
87
|
+
'''
|
|
88
|
+
runt = s_scope.get('runt')
|
|
89
|
+
|
|
90
|
+
match valu:
|
|
91
|
+
case None:
|
|
92
|
+
s_common.deprecated('Setting the HTTP proxy argument $lib.null', curv='2.192.0')
|
|
93
|
+
await runt.snap.warnonce('Setting the HTTP proxy argument to $lib.null is deprecated. Use $lib.true instead.')
|
|
94
|
+
return await runt.snap.core.getConfOpt('http:proxy')
|
|
95
|
+
|
|
96
|
+
case True:
|
|
97
|
+
return await runt.snap.core.getConfOpt('http:proxy')
|
|
98
|
+
|
|
99
|
+
case False:
|
|
100
|
+
runt.confirm(('storm', 'lib', 'inet', 'http', 'proxy'))
|
|
101
|
+
return None
|
|
102
|
+
|
|
103
|
+
case str():
|
|
104
|
+
runt.confirm(('storm', 'lib', 'inet', 'http', 'proxy'))
|
|
105
|
+
return valu
|
|
106
|
+
|
|
107
|
+
case _:
|
|
108
|
+
raise s_exc.BadArg(mesg='HTTP proxy argument must be a string or bool.')
|
|
109
|
+
|
|
110
|
+
async def resolveAxonProxyArg(valu):
|
|
111
|
+
'''
|
|
112
|
+
Resolve a proxy value to the kwarg to set for an Axon HTTP call.
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
valu (str|null|bool): The proxy value.
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
tuple: A retn tuple where the proxy kwarg should not be set if ok=False, otherwise a proxy URL or None.
|
|
119
|
+
'''
|
|
120
|
+
runt = s_scope.get('runt')
|
|
121
|
+
|
|
122
|
+
axonvers = runt.snap.core.axoninfo['synapse']['version']
|
|
123
|
+
if axonvers < AXON_MINVERS_PROXY:
|
|
124
|
+
await runt.snap.warnonce(f'Axon version does not support proxy argument: {axonvers} < {AXON_MINVERS_PROXY}')
|
|
125
|
+
return False, None
|
|
126
|
+
|
|
127
|
+
match valu:
|
|
128
|
+
case None:
|
|
129
|
+
s_common.deprecated('Setting the Storm HTTP proxy argument $lib.null', curv='2.192.0')
|
|
130
|
+
await runt.snap.warnonce('Setting the Storm HTTP proxy argument to $lib.null is deprecated. Use $lib.true instead.')
|
|
131
|
+
if axonvers >= AXON_MINVERS_PROXYTRUE:
|
|
132
|
+
return True, True
|
|
133
|
+
return True, None
|
|
134
|
+
|
|
135
|
+
case True:
|
|
136
|
+
if axonvers < AXON_MINVERS_PROXYTRUE:
|
|
137
|
+
return True, None
|
|
138
|
+
return True, True
|
|
139
|
+
|
|
140
|
+
case False:
|
|
141
|
+
runt.confirm(('storm', 'lib', 'inet', 'http', 'proxy'))
|
|
142
|
+
return True, False
|
|
143
|
+
|
|
144
|
+
case str():
|
|
145
|
+
runt.confirm(('storm', 'lib', 'inet', 'http', 'proxy'))
|
|
146
|
+
return True, valu
|
|
147
|
+
|
|
148
|
+
case _:
|
|
149
|
+
raise s_exc.BadArg(mesg='HTTP proxy argument must be a string or bool.')
|
|
150
|
+
|
|
76
151
|
class StormTypesRegistry:
|
|
77
152
|
# The following types are currently undefined.
|
|
78
153
|
base_undefined_types = (
|
|
@@ -126,11 +201,29 @@ class StormTypesRegistry:
|
|
|
126
201
|
raise Exception('no key!')
|
|
127
202
|
self.addStormLib(path, ctor)
|
|
128
203
|
|
|
204
|
+
for info in ctor._storm_locals:
|
|
205
|
+
rtype = info.get('type')
|
|
206
|
+
if isinstance(rtype, dict) and rtype.get('type') == 'function':
|
|
207
|
+
if (fname := rtype.get('_funcname')) == '_storm_query':
|
|
208
|
+
continue
|
|
209
|
+
|
|
210
|
+
if (func := getattr(ctor, fname, None)) is not None:
|
|
211
|
+
funcpath = '.'.join(('lib',) + ctor._storm_lib_path + (info['name'],))
|
|
212
|
+
func._storm_funcpath = f"${funcpath}"
|
|
213
|
+
|
|
129
214
|
return ctor
|
|
130
215
|
|
|
131
216
|
def registerType(self, ctor):
|
|
132
217
|
'''Decorator to register a StormPrim'''
|
|
133
218
|
self.addStormType(ctor.__name__, ctor)
|
|
219
|
+
|
|
220
|
+
for info in ctor._storm_locals:
|
|
221
|
+
rtype = info.get('type')
|
|
222
|
+
if isinstance(rtype, dict) and rtype.get('type') == 'function':
|
|
223
|
+
fname = rtype.get('_funcname')
|
|
224
|
+
if (func := getattr(ctor, fname, None)) is not None:
|
|
225
|
+
func._storm_funcpath = f"{ctor._storm_typename}.{info['name']}"
|
|
226
|
+
|
|
134
227
|
return ctor
|
|
135
228
|
|
|
136
229
|
def iterLibs(self):
|
|
@@ -553,6 +646,7 @@ class Lib(StormType):
|
|
|
553
646
|
if callable(v) and v.__name__ == 'realfunc':
|
|
554
647
|
v._storm_runtime_lib = self
|
|
555
648
|
v._storm_runtime_lib_func = k
|
|
649
|
+
v._storm_funcpath = f'${".".join(("lib",) + self.name + (k,))}'
|
|
556
650
|
|
|
557
651
|
self.locls[k] = v
|
|
558
652
|
|
|
@@ -1993,11 +2087,18 @@ class LibAxon(Lib):
|
|
|
1993
2087
|
|
|
1994
2088
|
For APIs that accept an ssl_opts argument, the dictionary may contain the following values::
|
|
1995
2089
|
|
|
1996
|
-
{
|
|
2090
|
+
({
|
|
1997
2091
|
'verify': <bool> - Perform SSL/TLS verification. Is overridden by the ssl argument.
|
|
1998
2092
|
'client_cert': <str> - PEM encoded full chain certificate for use in mTLS.
|
|
1999
2093
|
'client_key': <str> - PEM encoded key for use in mTLS. Alternatively, can be included in client_cert.
|
|
2000
|
-
}
|
|
2094
|
+
})
|
|
2095
|
+
|
|
2096
|
+
For APIs that accept a proxy argument, the following values are supported::
|
|
2097
|
+
|
|
2098
|
+
$lib.null: Deprecated - Use the proxy defined by the http:proxy configuration option if set.
|
|
2099
|
+
$lib.true: Use the proxy defined by the http:proxy configuration option if set.
|
|
2100
|
+
$lib.false: Do not use the proxy defined by the http:proxy configuration option if set.
|
|
2101
|
+
<str>: A proxy URL string.
|
|
2001
2102
|
'''
|
|
2002
2103
|
_storm_locals = (
|
|
2003
2104
|
{'name': 'wget', 'desc': """
|
|
@@ -2031,8 +2132,8 @@ class LibAxon(Lib):
|
|
|
2031
2132
|
'desc': 'Set to False to disable SSL/TLS certificate verification.', 'default': True},
|
|
2032
2133
|
{'name': 'timeout', 'type': 'int', 'desc': 'Timeout for the download operation.',
|
|
2033
2134
|
'default': None},
|
|
2034
|
-
{'name': 'proxy', 'type': ['
|
|
2035
|
-
'desc': '
|
|
2135
|
+
{'name': 'proxy', 'type': ['bool', 'str'],
|
|
2136
|
+
'desc': 'Configure proxy usage. See $lib.axon help for additional details.', 'default': True},
|
|
2036
2137
|
{'name': 'ssl_opts', 'type': 'dict',
|
|
2037
2138
|
'desc': 'Optional SSL/TLS options. See $lib.axon help for additional details.',
|
|
2038
2139
|
'default': None},
|
|
@@ -2054,8 +2155,8 @@ class LibAxon(Lib):
|
|
|
2054
2155
|
'desc': 'Set to False to disable SSL/TLS certificate verification.', 'default': True},
|
|
2055
2156
|
{'name': 'timeout', 'type': 'int', 'desc': 'Timeout for the download operation.',
|
|
2056
2157
|
'default': None},
|
|
2057
|
-
{'name': 'proxy', 'type': ['
|
|
2058
|
-
'desc': '
|
|
2158
|
+
{'name': 'proxy', 'type': ['bool', 'str'],
|
|
2159
|
+
'desc': 'Configure proxy usage. See $lib.axon help for additional details.', 'default': True},
|
|
2059
2160
|
{'name': 'ssl_opts', 'type': 'dict',
|
|
2060
2161
|
'desc': 'Optional SSL/TLS options. See $lib.axon help for additional details.',
|
|
2061
2162
|
'default': None},
|
|
@@ -2370,7 +2471,7 @@ class LibAxon(Lib):
|
|
|
2370
2471
|
return await axon.del_(sha256b)
|
|
2371
2472
|
|
|
2372
2473
|
async def wget(self, url, headers=None, params=None, method='GET', json=None, body=None,
|
|
2373
|
-
ssl=True, timeout=None, proxy=
|
|
2474
|
+
ssl=True, timeout=None, proxy=True, ssl_opts=None):
|
|
2374
2475
|
|
|
2375
2476
|
if not self.runt.allowed(('axon', 'wget')):
|
|
2376
2477
|
self.runt.confirm(('storm', 'lib', 'axon', 'wget'))
|
|
@@ -2387,20 +2488,19 @@ class LibAxon(Lib):
|
|
|
2387
2488
|
proxy = await toprim(proxy)
|
|
2388
2489
|
ssl_opts = await toprim(ssl_opts)
|
|
2389
2490
|
|
|
2390
|
-
if proxy is not None:
|
|
2391
|
-
self.runt.confirm(('storm', 'lib', 'inet', 'http', 'proxy'))
|
|
2392
|
-
|
|
2393
2491
|
params = strifyHttpArg(params, multi=True)
|
|
2394
2492
|
headers = strifyHttpArg(headers)
|
|
2395
2493
|
|
|
2396
2494
|
await self.runt.snap.core.getAxon()
|
|
2397
2495
|
|
|
2398
2496
|
kwargs = {}
|
|
2399
|
-
|
|
2400
|
-
|
|
2497
|
+
|
|
2498
|
+
ok, proxy = await resolveAxonProxyArg(proxy)
|
|
2499
|
+
if ok:
|
|
2401
2500
|
kwargs['proxy'] = proxy
|
|
2402
2501
|
|
|
2403
2502
|
if ssl_opts is not None:
|
|
2503
|
+
axonvers = self.runt.snap.core.axoninfo['synapse']['version']
|
|
2404
2504
|
mesg = f'The ssl_opts argument requires an Axon Synapse version {AXON_MINVERS_SSLOPTS}, ' \
|
|
2405
2505
|
f'but the Axon is running {axonvers}'
|
|
2406
2506
|
s_version.reqVersion(axonvers, AXON_MINVERS_SSLOPTS, mesg=mesg)
|
|
@@ -2413,7 +2513,7 @@ class LibAxon(Lib):
|
|
|
2413
2513
|
return resp
|
|
2414
2514
|
|
|
2415
2515
|
async def wput(self, sha256, url, headers=None, params=None, method='PUT',
|
|
2416
|
-
ssl=True, timeout=None, proxy=
|
|
2516
|
+
ssl=True, timeout=None, proxy=True, ssl_opts=None):
|
|
2417
2517
|
|
|
2418
2518
|
if not self.runt.allowed(('axon', 'wput')):
|
|
2419
2519
|
self.runt.confirm(('storm', 'lib', 'axon', 'wput'))
|
|
@@ -2432,23 +2532,24 @@ class LibAxon(Lib):
|
|
|
2432
2532
|
params = strifyHttpArg(params, multi=True)
|
|
2433
2533
|
headers = strifyHttpArg(headers)
|
|
2434
2534
|
|
|
2435
|
-
|
|
2436
|
-
self.runt.confirm(('storm', 'lib', 'inet', 'http', 'proxy'))
|
|
2437
|
-
|
|
2438
|
-
axon = self.runt.snap.core.axon
|
|
2439
|
-
sha256byts = s_common.uhex(sha256)
|
|
2535
|
+
await self.runt.snap.core.getAxon()
|
|
2440
2536
|
|
|
2441
2537
|
kwargs = {}
|
|
2442
|
-
|
|
2443
|
-
|
|
2538
|
+
|
|
2539
|
+
ok, proxy = await resolveAxonProxyArg(proxy)
|
|
2540
|
+
if ok:
|
|
2444
2541
|
kwargs['proxy'] = proxy
|
|
2445
2542
|
|
|
2446
2543
|
if ssl_opts is not None:
|
|
2544
|
+
axonvers = self.runt.snap.core.axoninfo['synapse']['version']
|
|
2447
2545
|
mesg = f'The ssl_opts argument requires an Axon Synapse version {AXON_MINVERS_SSLOPTS}, ' \
|
|
2448
2546
|
f'but the Axon is running {axonvers}'
|
|
2449
2547
|
s_version.reqVersion(axonvers, AXON_MINVERS_SSLOPTS, mesg=mesg)
|
|
2450
2548
|
kwargs['ssl_opts'] = ssl_opts
|
|
2451
2549
|
|
|
2550
|
+
axon = self.runt.snap.core.axon
|
|
2551
|
+
sha256byts = s_common.uhex(sha256)
|
|
2552
|
+
|
|
2452
2553
|
return await axon.wput(sha256byts, url, headers=headers, params=params, method=method,
|
|
2453
2554
|
ssl=ssl, timeout=timeout, **kwargs)
|
|
2454
2555
|
|
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, 193, 0)
|
|
227
227
|
verstring = '.'.join([str(x) for x in version])
|
|
228
|
-
commit = '
|
|
228
|
+
commit = 'ad17bf2e740ba11453b7827ce70c140f969a1430'
|
synapse/models/inet.py
CHANGED
|
@@ -1442,7 +1442,11 @@ class InetModule(s_module.CoreModule):
|
|
|
1442
1442
|
'doc': 'A channel within a web service or instance such as slack or discord.'
|
|
1443
1443
|
}),
|
|
1444
1444
|
|
|
1445
|
-
('inet:web:hashtag', ('str', {'lower': True, 'regex': r'
|
|
1445
|
+
('inet:web:hashtag', ('str', {'lower': True, 'strip': True, 'regex': r'^#[^\p{Z}#]+$'}), {
|
|
1446
|
+
# regex explanation:
|
|
1447
|
+
# - starts with pound
|
|
1448
|
+
# - one or more non-whitespace/non-pound character
|
|
1449
|
+
# The minimum hashtag is a pound with a single non-whitespace character
|
|
1446
1450
|
'doc': 'A hashtag used in a web post.',
|
|
1447
1451
|
}),
|
|
1448
1452
|
|
|
@@ -1728,6 +1732,9 @@ class InetModule(s_module.CoreModule):
|
|
|
1728
1732
|
'template': {'service:base': 'object'},
|
|
1729
1733
|
'props': (
|
|
1730
1734
|
|
|
1735
|
+
('url', ('inet:url', {}), {
|
|
1736
|
+
'doc': 'The primary URL associated with the {service:base}.'}),
|
|
1737
|
+
|
|
1731
1738
|
('status', ('inet:service:object:status', {}), {
|
|
1732
1739
|
'doc': 'The status of the {service:base}.'}),
|
|
1733
1740
|
|
|
@@ -1811,6 +1818,9 @@ class InetModule(s_module.CoreModule):
|
|
|
1811
1818
|
|
|
1812
1819
|
('inet:email:message', {}, (
|
|
1813
1820
|
|
|
1821
|
+
('id', ('str', {'strip': True}), {
|
|
1822
|
+
'doc': 'The ID parsed from the "message-id" header.'}),
|
|
1823
|
+
|
|
1814
1824
|
('to', ('inet:email', {}), {
|
|
1815
1825
|
'doc': 'The email address of the recipient.'}),
|
|
1816
1826
|
|
|
@@ -2171,6 +2181,9 @@ class InetModule(s_module.CoreModule):
|
|
|
2171
2181
|
('dst:ssh:key', ('crypto:key', {}), {
|
|
2172
2182
|
'doc': 'The key sent by the server as part of an SSH session setup.'}),
|
|
2173
2183
|
|
|
2184
|
+
('capture:host', ('it:host', {}), {
|
|
2185
|
+
'doc': 'The host which captured the flow.'}),
|
|
2186
|
+
|
|
2174
2187
|
('raw', ('data', {}), {
|
|
2175
2188
|
'doc': 'A raw record used to create the flow which may contain additional protocol details.'}),
|
|
2176
2189
|
)),
|
|
@@ -2194,6 +2207,9 @@ class InetModule(s_module.CoreModule):
|
|
|
2194
2207
|
('host', ('it:host', {}), {
|
|
2195
2208
|
'doc': 'The host that used the network egress.'}),
|
|
2196
2209
|
|
|
2210
|
+
('host:iface', ('inet:iface', {}), {
|
|
2211
|
+
'doc': 'The interface which the host used to connect out via the egress.'}),
|
|
2212
|
+
|
|
2197
2213
|
('account', ('inet:service:account', {}), {
|
|
2198
2214
|
'doc': 'The service account which used the client address to egress.'}),
|
|
2199
2215
|
|
synapse/models/infotech.py
CHANGED
|
@@ -655,6 +655,7 @@ class ItModule(s_module.CoreModule):
|
|
|
655
655
|
|
|
656
656
|
('it:host', ('guid', {}), {
|
|
657
657
|
'interfaces': ('inet:service:object',),
|
|
658
|
+
'template': {'service:base': 'host'},
|
|
658
659
|
'doc': 'A GUID that represents a host or system.'}),
|
|
659
660
|
|
|
660
661
|
('it:log:event:type:taxonomy', ('taxonomy', {}), {
|
|
@@ -784,6 +785,7 @@ class ItModule(s_module.CoreModule):
|
|
|
784
785
|
}),
|
|
785
786
|
('it:dev:repo', ('guid', {}), {
|
|
786
787
|
'interfaces': ('inet:service:object',),
|
|
788
|
+
'template': {'service:base': 'repository'},
|
|
787
789
|
'doc': 'A version control system instance.',
|
|
788
790
|
}),
|
|
789
791
|
('it:dev:repo:remote', ('guid', {}), {
|
|
@@ -791,10 +793,12 @@ class ItModule(s_module.CoreModule):
|
|
|
791
793
|
}),
|
|
792
794
|
('it:dev:repo:branch', ('guid', {}), {
|
|
793
795
|
'interfaces': ('inet:service:object',),
|
|
796
|
+
'template': {'service:base': 'repository branch'},
|
|
794
797
|
'doc': 'A branch in a version control system instance.',
|
|
795
798
|
}),
|
|
796
799
|
('it:dev:repo:commit', ('guid', {}), {
|
|
797
800
|
'interfaces': ('inet:service:object',),
|
|
801
|
+
'template': {'service:base': 'repository commit'},
|
|
798
802
|
'doc': 'A commit to a repository.',
|
|
799
803
|
}),
|
|
800
804
|
('it:dev:repo:diff', ('guid', {}), {
|
|
@@ -802,18 +806,22 @@ class ItModule(s_module.CoreModule):
|
|
|
802
806
|
}),
|
|
803
807
|
('it:dev:repo:issue:label', ('guid', {}), {
|
|
804
808
|
'interfaces': ('inet:service:object',),
|
|
809
|
+
'template': {'service:base': 'repository issue label'},
|
|
805
810
|
'doc': 'A label applied to a repository issue.',
|
|
806
811
|
}),
|
|
807
812
|
('it:dev:repo:issue', ('guid', {}), {
|
|
808
813
|
'interfaces': ('inet:service:object',),
|
|
814
|
+
'template': {'service:base': 'repository issue'},
|
|
809
815
|
'doc': 'An issue raised in a repository.',
|
|
810
816
|
}),
|
|
811
817
|
('it:dev:repo:issue:comment', ('guid', {}), {
|
|
812
818
|
'interfaces': ('inet:service:object',),
|
|
819
|
+
'template': {'service:base': 'repository issue comment'},
|
|
813
820
|
'doc': 'A comment on an issue in a repository.',
|
|
814
821
|
}),
|
|
815
822
|
('it:dev:repo:diff:comment', ('guid', {}), {
|
|
816
823
|
'interfaces': ('inet:service:object',),
|
|
824
|
+
'template': {'service:base': 'repository diff comment'},
|
|
817
825
|
'doc': 'A comment on a diff in a repository.',
|
|
818
826
|
}),
|
|
819
827
|
('it:prod:soft', ('guid', {}), {
|
|
@@ -963,12 +971,12 @@ class ItModule(s_module.CoreModule):
|
|
|
963
971
|
}),
|
|
964
972
|
('it:exec:pipe', ('guid', {}), {
|
|
965
973
|
'interfaces': ('it:host:activity',),
|
|
966
|
-
'doc': 'A named pipe created by a process at runtime.',
|
|
967
|
-
|
|
974
|
+
'doc': 'A named pipe created by a process at runtime.'}),
|
|
975
|
+
|
|
968
976
|
('it:exec:url', ('guid', {}), {
|
|
969
977
|
'interfaces': ('it:host:activity',),
|
|
970
|
-
'doc': 'An instance of a host requesting a URL.',
|
|
971
|
-
|
|
978
|
+
'doc': 'An instance of a host requesting a URL using any protocol scheme.'}),
|
|
979
|
+
|
|
972
980
|
('it:exec:bind', ('guid', {}), {
|
|
973
981
|
'interfaces': ('it:host:activity',),
|
|
974
982
|
'doc': 'An instance of a host binding a listening port.',
|
|
@@ -1046,6 +1054,7 @@ class ItModule(s_module.CoreModule):
|
|
|
1046
1054
|
|
|
1047
1055
|
('it:host:tenancy', ('guid', {}), {
|
|
1048
1056
|
'interfaces': ('inet:service:object',),
|
|
1057
|
+
'template': {'service:base': 'host tenancy'},
|
|
1049
1058
|
'doc': 'A time window where a host was a tenant run by another host.'}),
|
|
1050
1059
|
|
|
1051
1060
|
('it:software:image:type:taxonomy', ('taxonomy', {}), {
|
|
@@ -1054,6 +1063,7 @@ class ItModule(s_module.CoreModule):
|
|
|
1054
1063
|
|
|
1055
1064
|
('it:software:image', ('guid', {}), {
|
|
1056
1065
|
'interfaces': ('inet:service:object',),
|
|
1066
|
+
'template': {'service:base': 'software image'},
|
|
1057
1067
|
'doc': 'The base image used to create a container or OS.'}),
|
|
1058
1068
|
|
|
1059
1069
|
('it:storage:mount', ('guid', {}), {
|
synapse/models/risk.py
CHANGED
|
@@ -242,9 +242,18 @@ class RiskModule(s_module.CoreModule):
|
|
|
242
242
|
(('risk:mitigation', 'uses', 'inet:service:rule'), {
|
|
243
243
|
'doc': 'The mitigation uses the service rule.'}),
|
|
244
244
|
|
|
245
|
+
(('risk:mitigation', 'uses', 'it:prod:softver'), {
|
|
246
|
+
'doc': 'The mitigation uses the software version.'}),
|
|
247
|
+
|
|
248
|
+
(('risk:mitigation', 'uses', 'it:prod:hardware'), {
|
|
249
|
+
'doc': 'The mitigation uses the hardware.'}),
|
|
250
|
+
|
|
245
251
|
(('risk:leak', 'leaked', None), {
|
|
246
252
|
'doc': 'The leak included the disclosure of the target node.'}),
|
|
247
253
|
|
|
254
|
+
(('risk:leak', 'enabled', 'risk:leak'), {
|
|
255
|
+
'doc': 'The source leak enabled the target leak to occur.'}),
|
|
256
|
+
|
|
248
257
|
(('risk:extortion', 'leveraged', None), {
|
|
249
258
|
'doc': 'The extortion event was based on attacker access to the target node.'}),
|
|
250
259
|
|
|
@@ -407,10 +416,12 @@ class RiskModule(s_module.CoreModule):
|
|
|
407
416
|
'doc': 'A description of the mitigation approach for the vulnerability.'}),
|
|
408
417
|
|
|
409
418
|
('software', ('it:prod:softver', {}), {
|
|
410
|
-
'
|
|
419
|
+
'deprecated': True,
|
|
420
|
+
'doc': 'Deprecated. Please use risk:mitigation -(uses)> it:prod:softver.'}),
|
|
411
421
|
|
|
412
422
|
('hardware', ('it:prod:hardware', {}), {
|
|
413
|
-
'
|
|
423
|
+
'deprecated': True,
|
|
424
|
+
'doc': 'Deprecated. Please use risk:mitigation -(uses)> it:prod:hardware.'}),
|
|
414
425
|
|
|
415
426
|
('reporter', ('ou:org', {}), {
|
|
416
427
|
'doc': 'The organization reporting on the mitigation.'}),
|
|
@@ -1034,6 +1045,9 @@ class RiskModule(s_module.CoreModule):
|
|
|
1034
1045
|
('leaker', ('ps:contact', {}), {
|
|
1035
1046
|
'doc': 'The identity which leaked the information.'}),
|
|
1036
1047
|
|
|
1048
|
+
('recipient', ('ps:contact', {}), {
|
|
1049
|
+
'doc': 'The identity which received the leaked information.'}),
|
|
1050
|
+
|
|
1037
1051
|
('type', ('risk:leak:type:taxonomy', {}), {
|
|
1038
1052
|
'doc': 'A type taxonomy for the leak.'}),
|
|
1039
1053
|
|
synapse/tests/test_axon.py
CHANGED
|
@@ -945,10 +945,16 @@ bar baz",vv
|
|
|
945
945
|
self.false(resp.get('ok'))
|
|
946
946
|
self.isin('connect to proxy 127.0.0.1:1', resp.get('mesg', ''))
|
|
947
947
|
|
|
948
|
+
resp = await proxy.wget('http://vertex.link/', proxy=None)
|
|
949
|
+
self.false(resp.get('ok'))
|
|
950
|
+
self.isin('connect to proxy 127.0.0.1:1', resp.get('mesg', ''))
|
|
951
|
+
|
|
948
952
|
resp = await proxy.wget('vertex.link')
|
|
949
953
|
self.false(resp.get('ok'))
|
|
950
954
|
self.isin('InvalidUrlClientError: vertex.link', resp.get('mesg', ''))
|
|
951
955
|
|
|
956
|
+
await self.asyncraises(s_exc.BadArg, proxy.wget('http://vertex.link', proxy=1.1))
|
|
957
|
+
|
|
952
958
|
async def test_axon_wput(self):
|
|
953
959
|
|
|
954
960
|
async with self.getTestCore() as core:
|
|
@@ -1025,6 +1031,10 @@ bar baz",vv
|
|
|
1025
1031
|
self.false(resp.get('ok'))
|
|
1026
1032
|
self.isin('connect to proxy 127.0.0.1:1', resp.get('reason'))
|
|
1027
1033
|
|
|
1034
|
+
resp = await proxy.postfiles(fields, f'https://127.0.0.1:{port}/api/v1/pushfile', ssl=False, proxy=None)
|
|
1035
|
+
self.false(resp.get('ok'))
|
|
1036
|
+
self.isin('connect to proxy 127.0.0.1:1', resp.get('reason'))
|
|
1037
|
+
|
|
1028
1038
|
resp = await proxy.wput(sha256, 'vertex.link')
|
|
1029
1039
|
self.false(resp.get('ok'))
|
|
1030
1040
|
self.isin('InvalidUrlClientError: vertex.link', resp.get('mesg', ''))
|
synapse/tests/test_cortex.py
CHANGED
|
@@ -484,7 +484,7 @@ class CortexTest(s_t_utils.SynTest):
|
|
|
484
484
|
self.len(0, mods)
|
|
485
485
|
self.len(0, core.modsbyiface.get('lookup'))
|
|
486
486
|
|
|
487
|
-
|
|
487
|
+
core.loadStormPkg(pkgdef)
|
|
488
488
|
|
|
489
489
|
mods = await core.getStormIfaces('lookup')
|
|
490
490
|
self.len(1, mods)
|
|
@@ -513,7 +513,7 @@ class CortexTest(s_t_utils.SynTest):
|
|
|
513
513
|
vals = [r async for r in core.view.callStormIface('boom', todo)]
|
|
514
514
|
self.eq((), vals)
|
|
515
515
|
|
|
516
|
-
|
|
516
|
+
core._dropStormPkg(pkgdef)
|
|
517
517
|
self.none(core.modsbyiface.get('lookup'))
|
|
518
518
|
|
|
519
519
|
mods = await core.getStormIfaces('lookup')
|
|
@@ -558,7 +558,7 @@ class CortexTest(s_t_utils.SynTest):
|
|
|
558
558
|
nodes = await core.nodes('foo@bar.com foo@bar.com', opts={'mode': 'lookup'})
|
|
559
559
|
self.eq(['inet:email', 'inet:email'], [n.ndef[0] for n in nodes])
|
|
560
560
|
|
|
561
|
-
|
|
561
|
+
core.loadStormPkg(pkgdef)
|
|
562
562
|
self.len(1, await core.getStormIfaces('search'))
|
|
563
563
|
|
|
564
564
|
todo = s_common.todo('search', ('foo@bar.com',))
|
|
@@ -4023,6 +4023,58 @@ class CortexBasicTest(s_t_utils.SynTest):
|
|
|
4023
4023
|
gdef = await core.callStorm('return($lib.graph.add(({"name": "def", "permissions": {"default": 0}})))')
|
|
4024
4024
|
self.eq(0, gdef['permissions']['default'])
|
|
4025
4025
|
|
|
4026
|
+
async def test_graph_projection_query_validation(self):
|
|
4027
|
+
async with self.getTestCore() as core:
|
|
4028
|
+
valid = {
|
|
4029
|
+
'name': 'valid',
|
|
4030
|
+
'forms': {
|
|
4031
|
+
'inet:fqdn': {
|
|
4032
|
+
'pivots': ['<- *'],
|
|
4033
|
+
'filters': []
|
|
4034
|
+
}
|
|
4035
|
+
}
|
|
4036
|
+
}
|
|
4037
|
+
|
|
4038
|
+
self.nn(await core.addStormGraph(valid))
|
|
4039
|
+
|
|
4040
|
+
bad_form_pivot = {
|
|
4041
|
+
'name': 'bad form pivot',
|
|
4042
|
+
'forms': {
|
|
4043
|
+
'inet:fqdn': {
|
|
4044
|
+
'pivots': ['<- * |||'],
|
|
4045
|
+
'filters': []
|
|
4046
|
+
}
|
|
4047
|
+
}
|
|
4048
|
+
}
|
|
4049
|
+
|
|
4050
|
+
await self.asyncraises(s_exc.BadSyntax, core.addStormGraph(bad_form_pivot))
|
|
4051
|
+
|
|
4052
|
+
bad_form_filter = {
|
|
4053
|
+
'name': 'bad form filter',
|
|
4054
|
+
'forms': {
|
|
4055
|
+
'inet:fqdn': {
|
|
4056
|
+
'pivots': [],
|
|
4057
|
+
'filters': ['+++:wat']
|
|
4058
|
+
}
|
|
4059
|
+
}
|
|
4060
|
+
}
|
|
4061
|
+
|
|
4062
|
+
await self.asyncraises(s_exc.BadSyntax, core.addStormGraph(bad_form_filter))
|
|
4063
|
+
|
|
4064
|
+
bad_global_filter = {
|
|
4065
|
+
'name': 'bad global filter',
|
|
4066
|
+
'filters': ['+++:wat']
|
|
4067
|
+
}
|
|
4068
|
+
|
|
4069
|
+
await self.asyncraises(s_exc.BadSyntax, core.addStormGraph(bad_global_filter))
|
|
4070
|
+
|
|
4071
|
+
bad_global_pivot = {
|
|
4072
|
+
'name': 'bad global pivot',
|
|
4073
|
+
'pivots': ['-> * |||']
|
|
4074
|
+
}
|
|
4075
|
+
|
|
4076
|
+
await self.asyncraises(s_exc.BadSyntax, core.addStormGraph(bad_global_pivot))
|
|
4077
|
+
|
|
4026
4078
|
async def test_storm_two_level_assignment(self):
|
|
4027
4079
|
async with self.getTestCore() as core:
|
|
4028
4080
|
q = '$foo=baz $bar=$foo [test:str=$bar]'
|
synapse/tests/test_exc.py
CHANGED
|
@@ -27,6 +27,9 @@ class ExcTest(s_t_utils.SynTest):
|
|
|
27
27
|
e.setdefault('defv', 2)
|
|
28
28
|
self.eq("SynErr: defv=1 foo='words' hehe=1234 mesg='words'", str(e))
|
|
29
29
|
|
|
30
|
+
e.update({'foo': 'newwords', 'bar': 'baz'})
|
|
31
|
+
self.eq("SynErr: bar='baz' defv=1 foo='newwords' hehe=1234 mesg='words'", str(e))
|
|
32
|
+
|
|
30
33
|
self.eq(e.errname, 'SynErr')
|
|
31
34
|
|
|
32
35
|
e2 = s_exc.BadTypeValu(mesg='haha')
|