synapse 2.184.0__py311-none-any.whl → 2.186.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 +4 -3
- synapse/datamodel.py +41 -6
- synapse/exc.py +2 -0
- synapse/lib/ast.py +83 -22
- synapse/lib/auth.py +13 -0
- synapse/lib/cell.py +78 -2
- synapse/lib/drive.py +45 -10
- synapse/lib/modules.py +1 -0
- synapse/lib/parser.py +1 -0
- synapse/lib/snap.py +1 -6
- synapse/lib/storm.lark +12 -6
- synapse/lib/storm.py +45 -9
- synapse/lib/storm_format.py +1 -0
- synapse/lib/stormlib/stix.py +14 -5
- synapse/lib/stormtypes.py +64 -36
- synapse/lib/types.py +6 -0
- synapse/lib/version.py +2 -2
- synapse/models/doc.py +93 -0
- synapse/models/infotech.py +2 -1
- synapse/models/media.py +0 -1
- synapse/models/orgs.py +26 -3
- synapse/models/proj.py +56 -36
- synapse/models/risk.py +3 -0
- synapse/models/syn.py +64 -6
- synapse/tests/test_cortex.py +49 -6
- synapse/tests/test_lib_base.py +2 -2
- synapse/tests/test_lib_cell.py +59 -5
- synapse/tests/test_lib_grammar.py +2 -0
- synapse/tests/test_lib_storm.py +54 -1
- synapse/tests/test_lib_stormlib_stix.py +3 -2
- synapse/tests/test_model_doc.py +51 -0
- synapse/tests/test_model_orgs.py +41 -0
- synapse/tests/test_model_risk.py +2 -0
- synapse/tests/test_model_syn.py +43 -0
- synapse/tests/test_tools_promote.py +67 -0
- synapse/tests/test_tools_snapshot.py +47 -0
- synapse/tools/aha/clone.py +3 -1
- synapse/tools/aha/easycert.py +1 -1
- synapse/tools/aha/enroll.py +3 -1
- synapse/tools/aha/provision/service.py +3 -1
- synapse/tools/aha/provision/user.py +3 -1
- synapse/tools/livebackup.py +3 -1
- synapse/tools/promote.py +23 -4
- synapse/tools/snapshot.py +69 -0
- {synapse-2.184.0.dist-info → synapse-2.186.0.dist-info}/METADATA +5 -10
- {synapse-2.184.0.dist-info → synapse-2.186.0.dist-info}/RECORD +49 -44
- {synapse-2.184.0.dist-info → synapse-2.186.0.dist-info}/WHEEL +1 -1
- {synapse-2.184.0.dist-info → synapse-2.186.0.dist-info}/LICENSE +0 -0
- {synapse-2.184.0.dist-info → synapse-2.186.0.dist-info}/top_level.txt +0 -0
synapse/models/proj.py
CHANGED
|
@@ -1,14 +1,5 @@
|
|
|
1
1
|
import synapse.lib.module as s_module
|
|
2
2
|
|
|
3
|
-
prioenums = (
|
|
4
|
-
(0, 'none'),
|
|
5
|
-
(10, 'lowest'),
|
|
6
|
-
(20, 'low'),
|
|
7
|
-
(30, 'medium'),
|
|
8
|
-
(40, 'high'),
|
|
9
|
-
(50, 'highest'),
|
|
10
|
-
)
|
|
11
|
-
|
|
12
3
|
statusenums = (
|
|
13
4
|
(0, 'new'),
|
|
14
5
|
(10, 'in validation'),
|
|
@@ -47,11 +38,63 @@ class ProjectModule(s_module.CoreModule):
|
|
|
47
38
|
|
|
48
39
|
('proj', {
|
|
49
40
|
|
|
41
|
+
'interfaces': (
|
|
42
|
+
('proj:task', {
|
|
43
|
+
|
|
44
|
+
'doc': 'A common interface for tasks.',
|
|
45
|
+
|
|
46
|
+
'template': {
|
|
47
|
+
'task': 'task'},
|
|
48
|
+
|
|
49
|
+
'props': (
|
|
50
|
+
|
|
51
|
+
('id', ('str', {'strip': True}), {
|
|
52
|
+
'doc': 'The ID of the {task}.'}),
|
|
53
|
+
|
|
54
|
+
('project', ('proj:project', {}), {
|
|
55
|
+
'doc': 'The project containing the {task}.'}),
|
|
56
|
+
|
|
57
|
+
('status', ('int', {}), {
|
|
58
|
+
# TODO: make runtime setable int enum typeopts
|
|
59
|
+
'doc': 'The status of the {task}.'}),
|
|
60
|
+
|
|
61
|
+
('priority', ('meta:priority', {}), {
|
|
62
|
+
'doc': 'The priority of the {task}.'}),
|
|
63
|
+
|
|
64
|
+
('created', ('time', {}), {
|
|
65
|
+
'doc': 'The time the {task} was created.'}),
|
|
66
|
+
|
|
67
|
+
('updated', ('time', {}), {
|
|
68
|
+
'doc': 'The time the {task} was last updated.'}),
|
|
69
|
+
|
|
70
|
+
('due', ('time', {}), {
|
|
71
|
+
'doc': 'The time the {task} must be complete.'}),
|
|
72
|
+
|
|
73
|
+
('completed', ('time', {}), {
|
|
74
|
+
'doc': 'The time the {task} was completed.'}),
|
|
75
|
+
|
|
76
|
+
('creator', ('syn:user', {}), {
|
|
77
|
+
'doc': 'The user which created the {task}.'}),
|
|
78
|
+
|
|
79
|
+
('assignee', ('syn:user', {}), {
|
|
80
|
+
'doc': 'The user assigned to complete the {task}.'}),
|
|
81
|
+
|
|
82
|
+
('ext:creator', ('ps:contact', {}), {
|
|
83
|
+
'doc': 'The contact information of the creator from an external system.'}),
|
|
84
|
+
|
|
85
|
+
('ext:assignee', ('ps:contact', {}), {
|
|
86
|
+
'doc': 'The contact information of the assignee from an external system.'}),
|
|
87
|
+
),
|
|
88
|
+
}),
|
|
89
|
+
),
|
|
50
90
|
'types': (
|
|
51
91
|
('proj:epic', ('guid', {}), {
|
|
52
|
-
'doc': 'A collection of tickets related to a topic.',
|
|
53
|
-
|
|
92
|
+
'doc': 'A collection of tickets related to a topic.'}),
|
|
93
|
+
|
|
54
94
|
('proj:ticket', ('guid', {}), {
|
|
95
|
+
'interfaces': ('proj:task',),
|
|
96
|
+
'template': {
|
|
97
|
+
'task': 'ticket'},
|
|
55
98
|
'doc': 'A ticket in a ticketing system.'}),
|
|
56
99
|
|
|
57
100
|
('proj:project:type:taxonomy', ('taxonomy', {}), {
|
|
@@ -180,30 +223,16 @@ class ProjectModule(s_module.CoreModule):
|
|
|
180
223
|
|
|
181
224
|
('proj:ticket', {}, (
|
|
182
225
|
|
|
183
|
-
('project', ('proj:project', {}), {
|
|
184
|
-
'doc': 'The project containing the ticket.'}),
|
|
185
|
-
|
|
186
226
|
('ext:id', ('str', {'strip': True}), {
|
|
187
|
-
'
|
|
227
|
+
'deprecated': True,
|
|
228
|
+
'doc': 'Deprecated. Please use :id.'}),
|
|
188
229
|
|
|
189
230
|
('ext:url', ('inet:url', {}), {
|
|
190
231
|
'doc': 'A URL to the ticket in an external system.'}),
|
|
191
232
|
|
|
192
|
-
('ext:creator', ('ps:contact', {}), {
|
|
193
|
-
'doc': 'Ticket creator contact information from an external system.'}),
|
|
194
|
-
|
|
195
|
-
('ext:assignee', ('ps:contact', {}), {
|
|
196
|
-
'doc': 'Ticket assignee contact information from an external system.'}),
|
|
197
|
-
|
|
198
233
|
('epic', ('proj:epic', {}), {
|
|
199
234
|
'doc': 'The epic that includes the ticket.'}),
|
|
200
235
|
|
|
201
|
-
('created', ('time', {}), {
|
|
202
|
-
'doc': 'The time the ticket was created.'}),
|
|
203
|
-
|
|
204
|
-
('updated', ('time', {'ismax': True}), {
|
|
205
|
-
'doc': 'The last time the ticket was updated.'}),
|
|
206
|
-
|
|
207
236
|
('name', ('str', {'onespace': True}), {
|
|
208
237
|
'doc': 'The name of the ticket.'}),
|
|
209
238
|
|
|
@@ -219,17 +248,8 @@ class ProjectModule(s_module.CoreModule):
|
|
|
219
248
|
('sprint', ('proj:sprint', {}), {
|
|
220
249
|
'doc': 'The sprint that contains the ticket.'}),
|
|
221
250
|
|
|
222
|
-
('priority', ('int', {'enums': prioenums}), {
|
|
223
|
-
'doc': 'The priority of the ticket.'}),
|
|
224
|
-
|
|
225
251
|
('type', ('str', {'lower': True, 'strip': True}), {
|
|
226
252
|
'doc': 'The type of ticket. (eg story / bug)'}),
|
|
227
|
-
|
|
228
|
-
('creator', ('syn:user', {}), {
|
|
229
|
-
'doc': 'The synapse user who created the ticket.'}),
|
|
230
|
-
|
|
231
|
-
('assignee', ('syn:user', {}), {
|
|
232
|
-
'doc': 'The synapse user who the ticket is assigned to.'}),
|
|
233
253
|
)),
|
|
234
254
|
),
|
|
235
255
|
}),
|
synapse/models/risk.py
CHANGED
|
@@ -351,6 +351,9 @@ class RiskModule(s_module.CoreModule):
|
|
|
351
351
|
('mitre:attack:software', ('it:mitre:attack:software', {}), {
|
|
352
352
|
'doc': 'A mapping to a MITRE ATT&CK software if applicable.'}),
|
|
353
353
|
|
|
354
|
+
('id', ('str', {'strip': True}), {
|
|
355
|
+
'doc': 'An ID for the tool.'}),
|
|
356
|
+
|
|
354
357
|
)),
|
|
355
358
|
('risk:mitigation:type:taxonomy', {}, ()),
|
|
356
359
|
('risk:mitigation', {}, (
|
synapse/models/syn.py
CHANGED
|
@@ -2,10 +2,67 @@ import logging
|
|
|
2
2
|
|
|
3
3
|
import synapse.exc as s_exc
|
|
4
4
|
|
|
5
|
+
import synapse.lib.types as s_types
|
|
5
6
|
import synapse.lib.module as s_module
|
|
6
7
|
|
|
7
8
|
logger = logging.getLogger(__name__)
|
|
8
9
|
|
|
10
|
+
class SynUser(s_types.Guid):
|
|
11
|
+
|
|
12
|
+
def _normPyStr(self, text):
|
|
13
|
+
|
|
14
|
+
core = self.modl.core
|
|
15
|
+
if core is not None:
|
|
16
|
+
|
|
17
|
+
# direct use of an iden takes precedence...
|
|
18
|
+
user = core.auth.user(text)
|
|
19
|
+
if user is not None:
|
|
20
|
+
return user.iden, {}
|
|
21
|
+
|
|
22
|
+
user = core.auth._getUserByName(text)
|
|
23
|
+
if user is not None:
|
|
24
|
+
return user.iden, {}
|
|
25
|
+
|
|
26
|
+
return s_types.Guid._normPyStr(self, text)
|
|
27
|
+
|
|
28
|
+
def repr(self, iden):
|
|
29
|
+
|
|
30
|
+
core = self.modl.core
|
|
31
|
+
if core is not None:
|
|
32
|
+
user = core.auth.user(iden)
|
|
33
|
+
if user is not None:
|
|
34
|
+
return user.name
|
|
35
|
+
|
|
36
|
+
return iden
|
|
37
|
+
|
|
38
|
+
class SynRole(s_types.Guid):
|
|
39
|
+
|
|
40
|
+
def _normPyStr(self, text):
|
|
41
|
+
|
|
42
|
+
core = self.modl.core
|
|
43
|
+
if core is not None:
|
|
44
|
+
|
|
45
|
+
# direct use of an iden takes precedence...
|
|
46
|
+
role = core.auth.role(text)
|
|
47
|
+
if role is not None:
|
|
48
|
+
return role.iden, {}
|
|
49
|
+
|
|
50
|
+
role = core.auth._getRoleByName(text)
|
|
51
|
+
if role is not None:
|
|
52
|
+
return role.iden, {}
|
|
53
|
+
|
|
54
|
+
return s_types.Guid._normPyStr(self, text)
|
|
55
|
+
|
|
56
|
+
def repr(self, iden):
|
|
57
|
+
|
|
58
|
+
core = self.modl.core
|
|
59
|
+
if core is not None:
|
|
60
|
+
role = core.auth.role(iden)
|
|
61
|
+
if role is not None:
|
|
62
|
+
return role.name
|
|
63
|
+
|
|
64
|
+
return iden
|
|
65
|
+
|
|
9
66
|
class SynModule(s_module.CoreModule):
|
|
10
67
|
|
|
11
68
|
def initCoreModule(self):
|
|
@@ -105,6 +162,13 @@ class SynModule(s_module.CoreModule):
|
|
|
105
162
|
|
|
106
163
|
return (('syn', {
|
|
107
164
|
|
|
165
|
+
'ctors': (
|
|
166
|
+
('syn:user', 'synapse.models.syn.SynUser', {}, {
|
|
167
|
+
'doc': 'A Synapse user.'}),
|
|
168
|
+
|
|
169
|
+
('syn:role', 'synapse.models.syn.SynRole', {}, {
|
|
170
|
+
'doc': 'A Synapse role.'}),
|
|
171
|
+
),
|
|
108
172
|
'types': (
|
|
109
173
|
('syn:type', ('str', {'strip': True}), {
|
|
110
174
|
'doc': 'A Synapse type used for normalizing nodes and properties.',
|
|
@@ -130,12 +194,6 @@ class SynModule(s_module.CoreModule):
|
|
|
130
194
|
('syn:nodedata', ('comp', {'fields': (('key', 'str'), ('form', 'syn:form'))}), {
|
|
131
195
|
'doc': 'A nodedata key and the form it may be present on.',
|
|
132
196
|
}),
|
|
133
|
-
('syn:user', ('guid', {'strip': True}), {
|
|
134
|
-
'doc': 'A Synapse user GUID.'
|
|
135
|
-
}),
|
|
136
|
-
('syn:role', ('guid', {'strip': True}), {
|
|
137
|
-
'doc': 'A Synapse role GUID.'
|
|
138
|
-
}),
|
|
139
197
|
),
|
|
140
198
|
|
|
141
199
|
'forms': (
|
synapse/tests/test_cortex.py
CHANGED
|
@@ -108,6 +108,7 @@ class CortexTest(s_t_utils.SynTest):
|
|
|
108
108
|
await core00.handoff(core00.getLocalUrl())
|
|
109
109
|
|
|
110
110
|
self.false((await core00.getCellInfo())['cell']['uplink'])
|
|
111
|
+
self.none((await core00.getCellInfo())['cell']['mirror'])
|
|
111
112
|
|
|
112
113
|
# provision with the new hostname and mirror config
|
|
113
114
|
provinfo = {'mirror': '00.cortex'}
|
|
@@ -130,10 +131,13 @@ class CortexTest(s_t_utils.SynTest):
|
|
|
130
131
|
self.true(await s_coro.event_wait(core01.nexsroot.miruplink, timeout=2))
|
|
131
132
|
self.false((await core00.getCellInfo())['cell']['uplink'])
|
|
132
133
|
self.true((await core01.getCellInfo())['cell']['uplink'])
|
|
134
|
+
self.none((await core00.getCellInfo())['cell']['mirror'])
|
|
135
|
+
self.eq((await core01.getCellInfo())['cell']['mirror'], 'aha://root@00.cortex...')
|
|
133
136
|
|
|
134
137
|
outp = s_output.OutPutStr()
|
|
135
138
|
argv = ('--svcurl', core01.getLocalUrl())
|
|
136
|
-
await s_tools_promote.main(argv, outp=outp) # this is a graceful promotion
|
|
139
|
+
ret = await s_tools_promote.main(argv, outp=outp) # this is a graceful promotion
|
|
140
|
+
self.eq(ret, 0)
|
|
137
141
|
|
|
138
142
|
self.true(core01.isactive)
|
|
139
143
|
self.false(core00.isactive)
|
|
@@ -141,6 +145,10 @@ class CortexTest(s_t_utils.SynTest):
|
|
|
141
145
|
self.true(await s_coro.event_wait(core00.nexsroot.miruplink, timeout=2))
|
|
142
146
|
self.true((await core00.getCellInfo())['cell']['uplink'])
|
|
143
147
|
self.false((await core01.getCellInfo())['cell']['uplink'])
|
|
148
|
+
# Note: The following mirror may change when SYN-7659 is addressed and greater
|
|
149
|
+
# control over the topology update is available during the promotion process.
|
|
150
|
+
self.eq((await core00.getCellInfo())['cell']['mirror'], 'aha://01.cortex.synapse')
|
|
151
|
+
self.none((await core01.getCellInfo())['cell']['mirror'])
|
|
144
152
|
|
|
145
153
|
mods00 = s_common.yamlload(core00.dirn, 'cell.mods.yaml')
|
|
146
154
|
mods01 = s_common.yamlload(core01.dirn, 'cell.mods.yaml')
|
|
@@ -2942,6 +2950,36 @@ class CortexTest(s_t_utils.SynTest):
|
|
|
2942
2950
|
with self.raises(s_exc.NoSuchProp):
|
|
2943
2951
|
await core.nodes('inet:ipv4 +:asn::_pivo::notaprop')
|
|
2944
2952
|
|
|
2953
|
+
await core.nodes('[ou:org=* :hq={[ps:contact=* :email=a@v.lk]}]')
|
|
2954
|
+
await core.nodes('[ou:org=* :hq={[ps:contact=* :email=b@v.lk]}]')
|
|
2955
|
+
await core.nodes('[ou:org=* :hq={[ps:contact=* :email=c@v.lk]}]')
|
|
2956
|
+
await core.nodes('[ou:org=* :hq={[ps:contact=* :emails=(a@v.lk, b@v.lk)]}]')
|
|
2957
|
+
await core.nodes('[ou:org=* :hq={[ps:contact=* :emails=(c@v.lk, d@v.lk)]}]')
|
|
2958
|
+
await core.nodes('[ou:org=* :hq={[ps:contact=* :emails=(a@v.lk, d@v.lk)]}]')
|
|
2959
|
+
|
|
2960
|
+
nodes = await core.nodes('ou:org:hq::email::user=a')
|
|
2961
|
+
self.len(1, nodes)
|
|
2962
|
+
for node in nodes:
|
|
2963
|
+
self.eq('ou:org', node.ndef[0])
|
|
2964
|
+
|
|
2965
|
+
nodes = await core.nodes('ou:org:hq::email::user*in=(a, b)')
|
|
2966
|
+
self.len(2, nodes)
|
|
2967
|
+
for node in nodes:
|
|
2968
|
+
self.eq('ou:org', node.ndef[0])
|
|
2969
|
+
|
|
2970
|
+
nodes = await core.nodes('ou:org:hq::emails*[=a@v.lk]')
|
|
2971
|
+
self.len(2, nodes)
|
|
2972
|
+
for node in nodes:
|
|
2973
|
+
self.eq('ou:org', node.ndef[0])
|
|
2974
|
+
|
|
2975
|
+
nodes = await core.nodes('ou:org:hq::emails*[in=(a@v.lk, c@v.lk)]')
|
|
2976
|
+
self.len(3, nodes)
|
|
2977
|
+
for node in nodes:
|
|
2978
|
+
self.eq('ou:org', node.ndef[0])
|
|
2979
|
+
|
|
2980
|
+
with self.raises(s_exc.NoSuchProp):
|
|
2981
|
+
nodes = await core.nodes('ou:org:hq::email::newp=a')
|
|
2982
|
+
|
|
2945
2983
|
class CortexBasicTest(s_t_utils.SynTest):
|
|
2946
2984
|
'''
|
|
2947
2985
|
The tests that are unlikely to break with different types of layers installed
|
|
@@ -7164,16 +7202,16 @@ class CortexBasicTest(s_t_utils.SynTest):
|
|
|
7164
7202
|
|
|
7165
7203
|
nodes = await core.nodes('[ inet:ipv4=1.2.3.4 +#cno.cve.2021.12345 ]')
|
|
7166
7204
|
|
|
7167
|
-
with self.raises(s_exc.
|
|
7205
|
+
with self.raises(s_exc.BadTypeValu):
|
|
7168
7206
|
await core.nodes('[ inet:ipv4=1.2.3.4 +#cno.cve.foo ]')
|
|
7169
7207
|
|
|
7170
|
-
with self.raises(s_exc.
|
|
7208
|
+
with self.raises(s_exc.BadTypeValu):
|
|
7171
7209
|
await core.nodes('[ inet:ipv4=1.2.3.4 +#cno.cve.2021.hehe ]')
|
|
7172
7210
|
|
|
7173
|
-
with self.raises(s_exc.
|
|
7211
|
+
with self.raises(s_exc.BadTypeValu):
|
|
7174
7212
|
await core.nodes('[ inet:ipv4=1.2.3.4 +#cno.cve.2021.123456 ]')
|
|
7175
7213
|
|
|
7176
|
-
with self.raises(s_exc.
|
|
7214
|
+
with self.raises(s_exc.BadTypeValu):
|
|
7177
7215
|
await core.nodes('[ inet:ipv4=1.2.3.4 +#cno.cve.12345 ]')
|
|
7178
7216
|
|
|
7179
7217
|
nodes = await core.nodes('[ test:str=beep +?#cno.cve.12345 ]')
|
|
@@ -7191,9 +7229,14 @@ class CortexBasicTest(s_t_utils.SynTest):
|
|
|
7191
7229
|
await core.nodes('[ inet:ipv4=1.2.3.4 +#cno.cve.2021.hehe ]')
|
|
7192
7230
|
|
|
7193
7231
|
await core.setTagModel('cno.cve', 'regex', (None, None, '[0-9]{4}', '[0-9]{5}'))
|
|
7194
|
-
with self.raises(s_exc.
|
|
7232
|
+
with self.raises(s_exc.BadTypeValu):
|
|
7195
7233
|
await core.nodes('[ inet:ipv4=1.2.3.4 +#cno.cve.2021.haha ]')
|
|
7196
7234
|
|
|
7235
|
+
self.eq((False, None), await core.callStorm('return($lib.trycast(syn:tag, cno.cve.2021.haha))'))
|
|
7236
|
+
|
|
7237
|
+
with self.raises(s_exc.BadTypeValu):
|
|
7238
|
+
await core.callStorm('return($lib.cast(syn:tag, cno.cve.2021.haha))')
|
|
7239
|
+
|
|
7197
7240
|
self.none(await core.callStorm('$lib.model.tags.del(cno.cve)'))
|
|
7198
7241
|
self.none(await core.callStorm('return($lib.model.tags.get(cno.cve))'))
|
|
7199
7242
|
|
synapse/tests/test_lib_base.py
CHANGED
|
@@ -378,7 +378,7 @@ class BaseTest(s_t_utils.SynTest):
|
|
|
378
378
|
proc = ctx.Process(target=block_processing, args=(evt1,))
|
|
379
379
|
proc.start()
|
|
380
380
|
|
|
381
|
-
self.true(evt1.wait(timeout=
|
|
381
|
+
self.true(evt1.wait(timeout=30))
|
|
382
382
|
os.kill(proc.pid, signal.SIGTERM)
|
|
383
383
|
proc.join(timeout=10)
|
|
384
384
|
self.eq(proc.exitcode, 137)
|
|
@@ -396,7 +396,7 @@ class BaseTest(s_t_utils.SynTest):
|
|
|
396
396
|
proc = ctx.Process(target=block_processing, args=(evt1,))
|
|
397
397
|
proc.start()
|
|
398
398
|
|
|
399
|
-
self.true(evt1.wait(timeout=
|
|
399
|
+
self.true(evt1.wait(timeout=30))
|
|
400
400
|
os.kill(proc.pid, signal.SIGINT)
|
|
401
401
|
|
|
402
402
|
proc.join(timeout=10)
|
synapse/tests/test_lib_cell.py
CHANGED
|
@@ -8,7 +8,6 @@ import signal
|
|
|
8
8
|
import socket
|
|
9
9
|
import asyncio
|
|
10
10
|
import tarfile
|
|
11
|
-
import warnings
|
|
12
11
|
import collections
|
|
13
12
|
import multiprocessing
|
|
14
13
|
|
|
@@ -209,7 +208,12 @@ class CellTest(s_t_utils.SynTest):
|
|
|
209
208
|
|
|
210
209
|
# TODO how to handle iden match with additional property mismatch
|
|
211
210
|
|
|
212
|
-
await cell.drive.setTypeSchema('woot', testDataSchema_v0)
|
|
211
|
+
self.true(await cell.drive.setTypeSchema('woot', testDataSchema_v0, vers=0))
|
|
212
|
+
self.true(await cell.drive.setTypeSchema('woot', testDataSchema_v0, vers=1))
|
|
213
|
+
self.false(await cell.drive.setTypeSchema('woot', testDataSchema_v0, vers=1))
|
|
214
|
+
|
|
215
|
+
with self.raises(s_exc.BadVersion):
|
|
216
|
+
await cell.drive.setTypeSchema('woot', testDataSchema_v0, vers=0)
|
|
213
217
|
|
|
214
218
|
info = {'name': 'win32k.sys', 'type': 'woot'}
|
|
215
219
|
info = await cell.addDriveItem(info, reldir=rootdir)
|
|
@@ -285,6 +289,12 @@ class CellTest(s_t_utils.SynTest):
|
|
|
285
289
|
versinfo, data = await cell.getDriveData(iden, vers=(1, 1, 0))
|
|
286
290
|
self.eq('woot', data.get('woot'))
|
|
287
291
|
|
|
292
|
+
with self.raises(s_exc.NoSuchIden):
|
|
293
|
+
await cell.reqDriveInfo('d7d6107b200e2c039540fc627bc5537d')
|
|
294
|
+
|
|
295
|
+
with self.raises(s_exc.TypeMismatch):
|
|
296
|
+
await cell.getDriveInfo(iden, typename='newp')
|
|
297
|
+
|
|
288
298
|
self.nn(await cell.getDriveInfo(iden))
|
|
289
299
|
self.len(2, [vers async for vers in cell.getDriveDataVersions(iden)])
|
|
290
300
|
|
|
@@ -751,6 +761,7 @@ class CellTest(s_t_utils.SynTest):
|
|
|
751
761
|
self.ge(cnfo.get('nexsindx'), 0)
|
|
752
762
|
self.true(cnfo.get('active'))
|
|
753
763
|
self.false(cnfo.get('uplink'))
|
|
764
|
+
self.none(cnfo.get('mirror', True))
|
|
754
765
|
# A Cortex populated cellvers
|
|
755
766
|
self.isin('cortex:defaults', cnfo.get('cellvers', {}))
|
|
756
767
|
|
|
@@ -1899,7 +1910,7 @@ class CellTest(s_t_utils.SynTest):
|
|
|
1899
1910
|
proc = ctx.Process(target=lock_target, args=(dirn, evt1,))
|
|
1900
1911
|
proc.start()
|
|
1901
1912
|
|
|
1902
|
-
self.true(evt1.wait(timeout=
|
|
1913
|
+
self.true(evt1.wait(timeout=30))
|
|
1903
1914
|
|
|
1904
1915
|
with self.raises(s_exc.FatalErr) as cm:
|
|
1905
1916
|
async with await s_cell.Cell.anit(dirn) as cell:
|
|
@@ -2600,7 +2611,7 @@ class CellTest(s_t_utils.SynTest):
|
|
|
2600
2611
|
proc = ctx.Process(target=reload_target, args=(dirn, evt1, evt2))
|
|
2601
2612
|
proc.start()
|
|
2602
2613
|
|
|
2603
|
-
self.true(evt1.wait(timeout=
|
|
2614
|
+
self.true(evt1.wait(timeout=30))
|
|
2604
2615
|
|
|
2605
2616
|
async with await s_telepath.openurl(f'cell://{dirn}') as prox:
|
|
2606
2617
|
cnfo = await prox.getCellInfo()
|
|
@@ -3016,7 +3027,7 @@ class CellTest(s_t_utils.SynTest):
|
|
|
3016
3027
|
self.eq(users, s_t_utils.deguidify(json.dumps(await core.callStorm('return($lib.auth.users.list())'))))
|
|
3017
3028
|
self.eq(gates, s_t_utils.deguidify(json.dumps(await core.callStorm('return($lib.auth.gates.list())'))))
|
|
3018
3029
|
|
|
3019
|
-
with self.raises(s_exc.
|
|
3030
|
+
with self.raises(s_exc.BadTypeValu):
|
|
3020
3031
|
await core.nodes('[ it:dev:str=foo +#test.newp ]')
|
|
3021
3032
|
|
|
3022
3033
|
stream.seek(0)
|
|
@@ -3151,3 +3162,46 @@ class CellTest(s_t_utils.SynTest):
|
|
|
3151
3162
|
self.isin(cell.long_lived_slab.fini, cell._fini_funcs)
|
|
3152
3163
|
slabs = [s for s in cell.tofini if isinstance(s, s_lmdbslab.Slab) and s.lenv.path() == cell.short_slab_path]
|
|
3153
3164
|
self.len(0, slabs)
|
|
3165
|
+
|
|
3166
|
+
async def test_lib_cell_promote_schism_prevent(self):
|
|
3167
|
+
|
|
3168
|
+
async with self.getTestAha() as aha:
|
|
3169
|
+
async with await s_base.Base.anit() as base:
|
|
3170
|
+
with self.getTestDir() as dirn:
|
|
3171
|
+
dirn00 = s_common.genpath(dirn, '00.cell')
|
|
3172
|
+
dirn01 = s_common.genpath(dirn, '01.cell')
|
|
3173
|
+
dirn02 = s_common.genpath(dirn, '02.cell')
|
|
3174
|
+
|
|
3175
|
+
cell00 = await base.enter_context(self.addSvcToAha(aha, '00.cell', s_cell.Cell, dirn=dirn00))
|
|
3176
|
+
cell01 = await base.enter_context(self.addSvcToAha(aha, '01.cell', s_cell.Cell, dirn=dirn01,
|
|
3177
|
+
provinfo={'mirror': 'cell'}))
|
|
3178
|
+
cell02 = await base.enter_context(self.addSvcToAha(aha, '02.cell', s_cell.Cell, dirn=dirn02,
|
|
3179
|
+
provinfo={'mirror': 'cell'}))
|
|
3180
|
+
|
|
3181
|
+
self.true(cell00.isactive)
|
|
3182
|
+
self.false(cell01.isactive)
|
|
3183
|
+
self.false(cell02.isactive)
|
|
3184
|
+
await cell02.sync()
|
|
3185
|
+
|
|
3186
|
+
with self.raises(s_exc.BadState) as cm:
|
|
3187
|
+
await cell01.handoff('some://url')
|
|
3188
|
+
self.isin('01.cell is not the current leader', cm.exception.get('mesg'))
|
|
3189
|
+
|
|
3190
|
+
# Note: The following behavior may change when SYN-7659 is addressed and greater
|
|
3191
|
+
# control over the topology update is available during the promotion process.
|
|
3192
|
+
# Promote 02.cell -> Promote 01.cell -> Promote 00.cell -> BadState exception
|
|
3193
|
+
await cell02.promote(graceful=True)
|
|
3194
|
+
self.false(cell00.isactive)
|
|
3195
|
+
self.false(cell01.isactive)
|
|
3196
|
+
self.true(cell02.isactive)
|
|
3197
|
+
await cell02.sync()
|
|
3198
|
+
|
|
3199
|
+
await cell01.promote(graceful=True)
|
|
3200
|
+
self.false(cell00.isactive)
|
|
3201
|
+
self.true(cell01.isactive)
|
|
3202
|
+
self.false(cell02.isactive)
|
|
3203
|
+
await cell02.sync()
|
|
3204
|
+
|
|
3205
|
+
with self.raises(s_exc.BadState) as cm:
|
|
3206
|
+
await cell00.promote(graceful=True)
|
|
3207
|
+
self.isin('02.cell is not the current leader', cm.exception.get('mesg'))
|
|
@@ -727,6 +727,7 @@ Queries = [
|
|
|
727
727
|
'$p="names" ps:contact:name=foo [ :$p?-=bar ]',
|
|
728
728
|
'$pvar=stuff test:arrayprop +:$pvar*[=neato]',
|
|
729
729
|
'$pvar=ints test:arrayprop +:$pvar*[=$othervar]',
|
|
730
|
+
'$foo = ({"foo": ${ inet:fqdn }})',
|
|
730
731
|
]
|
|
731
732
|
|
|
732
733
|
# Generated with print_parse_list below
|
|
@@ -1356,6 +1357,7 @@ _ParseResults = [
|
|
|
1356
1357
|
'Query: [SetVarOper: [Const: p, Const: names], LiftPropBy: [Const: ps:contact:name, Const: =, Const: foo], EditPropSet: [RelProp: [VarValue: [Const: p]], Const: ?-=, Const: bar]]',
|
|
1357
1358
|
'Query: [SetVarOper: [Const: pvar, Const: stuff], LiftProp: [Const: test:arrayprop], FiltOper: [Const: +, ArrayCond: [RelProp: [VarValue: [Const: pvar]], Const: =, Const: neato]]]',
|
|
1358
1359
|
'Query: [SetVarOper: [Const: pvar, Const: ints], LiftProp: [Const: test:arrayprop], FiltOper: [Const: +, ArrayCond: [RelProp: [VarValue: [Const: pvar]], Const: =, VarValue: [Const: othervar]]]]',
|
|
1360
|
+
'Query: [SetVarOper: [Const: foo, DollarExpr: [ExprDict: [Const: foo, EmbedQuery: inet:fqdn]]]]',
|
|
1359
1361
|
]
|
|
1360
1362
|
|
|
1361
1363
|
class GrammarTest(s_t_utils.SynTest):
|
synapse/tests/test_lib_storm.py
CHANGED
|
@@ -147,6 +147,20 @@ class StormTest(s_t_utils.SynTest):
|
|
|
147
147
|
retn = await core.callStorm('return(({"foo": "bar", "baz": 10 , }))')
|
|
148
148
|
self.eq(retn, {'foo': 'bar', 'baz': 10})
|
|
149
149
|
|
|
150
|
+
q = '''
|
|
151
|
+
$foo = ({"bar": ${[inet:fqdn=foo.com]}})
|
|
152
|
+
for $n in $foo.bar { return($n.repr()) }
|
|
153
|
+
'''
|
|
154
|
+
retn = await core.callStorm(q)
|
|
155
|
+
self.eq(retn, 'foo.com')
|
|
156
|
+
|
|
157
|
+
q = '''
|
|
158
|
+
$foo = ([${[inet:fqdn=foo.com]}])
|
|
159
|
+
for $n in $foo.0 { return($n.repr()) }
|
|
160
|
+
'''
|
|
161
|
+
retn = await core.callStorm(q)
|
|
162
|
+
self.eq(retn, 'foo.com')
|
|
163
|
+
|
|
150
164
|
with self.raises(s_exc.BadSyntax):
|
|
151
165
|
await core.callStorm('return((["foo" "foo"]))')
|
|
152
166
|
|
|
@@ -612,6 +626,12 @@ class StormTest(s_t_utils.SynTest):
|
|
|
612
626
|
''')
|
|
613
627
|
self.eq((0, 'haha'), await core.callStorm('return($lib.queue.get(bar).get())'))
|
|
614
628
|
|
|
629
|
+
await core.nodes('$foo = (foo,) background ${ $foo.append(bar) $lib.queue.get(bar).put($foo) }')
|
|
630
|
+
self.eq((1, ['foo', 'bar']), await core.callStorm('return($lib.queue.get(bar).get(1))'))
|
|
631
|
+
|
|
632
|
+
await core.nodes('$foo = ([["foo"]]) background ${ $foo.0.append(bar) $lib.queue.get(bar).put($foo) }')
|
|
633
|
+
self.eq((2, [['foo', 'bar']]), await core.callStorm('return($lib.queue.get(bar).get(2))'))
|
|
634
|
+
|
|
615
635
|
with self.raises(s_exc.StormRuntimeError):
|
|
616
636
|
await core.nodes('[ ou:org=*] $text = $node.repr() | background $text')
|
|
617
637
|
|
|
@@ -3586,7 +3606,7 @@ class StormTest(s_t_utils.SynTest):
|
|
|
3586
3606
|
'quickly became his weapon of choice.'])
|
|
3587
3607
|
pars.help()
|
|
3588
3608
|
helptext = '\n'.join(pars.mesgs)
|
|
3589
|
-
self.isin('default
|
|
3609
|
+
self.isin('default:\n [', helptext)
|
|
3590
3610
|
|
|
3591
3611
|
pars = s_storm.Parser()
|
|
3592
3612
|
pars.add_argument('--ques', nargs='?')
|
|
@@ -3771,6 +3791,27 @@ class StormTest(s_t_utils.SynTest):
|
|
|
3771
3791
|
opts = pars.parse_args(['faz', '--cat', 'cam', 'cool'])
|
|
3772
3792
|
self.nn(opts)
|
|
3773
3793
|
|
|
3794
|
+
pars = s_storm.Parser()
|
|
3795
|
+
pars.add_argument('--baz', nargs=3, help='''
|
|
3796
|
+
This is the top line, nothing special.
|
|
3797
|
+
This is my second line with sublines that should have some leading spaces:
|
|
3798
|
+
subline 1: this is a line which has three spaces.
|
|
3799
|
+
subline 2: this is another line with five leading spaces.
|
|
3800
|
+
subline 3: yet another line with only two leading spaces.
|
|
3801
|
+
subline 4: this line has one space and is long which should wrap around because it exceeds the default display width.
|
|
3802
|
+
This is the final line with no leading spaces.''')
|
|
3803
|
+
pars.add_argument('--taz', type='bool', default=True, help='Taz option')
|
|
3804
|
+
pars.help()
|
|
3805
|
+
self.eq(' --baz <baz> : This is the top line, nothing special.', pars.mesgs[5])
|
|
3806
|
+
self.eq(' This is my second line with sublines that should have some leading spaces:', pars.mesgs[6])
|
|
3807
|
+
self.eq(' subline 1: this is a line which has three spaces.', pars.mesgs[7])
|
|
3808
|
+
self.eq(' subline 2: this is another line with five leading spaces.', pars.mesgs[8])
|
|
3809
|
+
self.eq(' subline 3: yet another line with only two leading spaces.', pars.mesgs[9])
|
|
3810
|
+
self.eq(' subline 4: this line has one space and is long which should wrap around because it', pars.mesgs[10])
|
|
3811
|
+
self.eq(' exceeds the default display width.', pars.mesgs[11])
|
|
3812
|
+
self.eq(' This is the final line with no leading spaces.', pars.mesgs[12])
|
|
3813
|
+
self.eq(' --taz <taz> : Taz option (default: True)', pars.mesgs[13])
|
|
3814
|
+
|
|
3774
3815
|
async def test_storm_cmd_help(self):
|
|
3775
3816
|
|
|
3776
3817
|
async with self.getTestCore() as core:
|
|
@@ -5085,3 +5126,15 @@ class StormTest(s_t_utils.SynTest):
|
|
|
5085
5126
|
''')
|
|
5086
5127
|
|
|
5087
5128
|
self.none(await core.callStorm('return($lib.queue.gen(haha).get().1)'))
|
|
5129
|
+
|
|
5130
|
+
await core.nodes('''
|
|
5131
|
+
$foo = (foo,)
|
|
5132
|
+
$query = ${
|
|
5133
|
+
$foo.append(bar)
|
|
5134
|
+
$lib.queue.gen(hoho).put($foo)
|
|
5135
|
+
$lib.dmon.del($auto.iden)
|
|
5136
|
+
}
|
|
5137
|
+
$lib.dmon.add($query)
|
|
5138
|
+
''')
|
|
5139
|
+
|
|
5140
|
+
self.eq(['foo', 'bar'], await core.callStorm('return($lib.queue.gen(hoho).get().1)'))
|
|
@@ -55,6 +55,7 @@ class StormLibStixTest(s_test.SynTest):
|
|
|
55
55
|
async def test_stormlib_libstix(self, conf=None):
|
|
56
56
|
|
|
57
57
|
async with self.getTestCore(conf=conf) as core:
|
|
58
|
+
visi = await core.auth.addUser('visi')
|
|
58
59
|
opts = {'vars': {
|
|
59
60
|
'ind': '6ba7d8500964902bf2e03126ed0f6cb1',
|
|
60
61
|
'news': '840b9b003a765020705ea8d203a7659c',
|
|
@@ -228,9 +229,9 @@ class StormLibStixTest(s_test.SynTest):
|
|
|
228
229
|
opts = {'vars': {'config': config}}
|
|
229
230
|
await core.callStorm('$lib.stix.export.bundle(config=$config)', opts=opts)
|
|
230
231
|
|
|
231
|
-
with self.raises(s_exc.
|
|
232
|
+
with self.raises(s_exc.AuthDeny):
|
|
232
233
|
config = {'maxsize': 10000000}
|
|
233
|
-
opts = {'vars': {'config': config}}
|
|
234
|
+
opts = {'user': visi.iden, 'vars': {'config': config}}
|
|
234
235
|
await core.callStorm('$lib.stix.export.bundle(config=$config)', opts=opts)
|
|
235
236
|
|
|
236
237
|
with self.raises(s_exc.NoSuchForm):
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import synapse.tests.utils as s_tests
|
|
2
|
+
|
|
3
|
+
class DocModelTest(s_tests.SynTest):
|
|
4
|
+
|
|
5
|
+
async def test_model_doc(self):
|
|
6
|
+
|
|
7
|
+
async with self.getTestCore() as core:
|
|
8
|
+
|
|
9
|
+
nodes = await core.nodes('''
|
|
10
|
+
[ doc:policy=*
|
|
11
|
+
:id=V-41
|
|
12
|
+
:name="Rule 41"
|
|
13
|
+
:text="If you can AAAAAAAA..."
|
|
14
|
+
:file=*
|
|
15
|
+
:created=20241018
|
|
16
|
+
:updated=20241018
|
|
17
|
+
:author={[ ps:contact=* :name=visi ]}
|
|
18
|
+
:contributors={[ ps:contact=* :name=shuka ]}
|
|
19
|
+
:version=1.2.3
|
|
20
|
+
:supersedes={[ doc:policy=* doc:policy=* ]}
|
|
21
|
+
]
|
|
22
|
+
''')
|
|
23
|
+
self.len(1, nodes)
|
|
24
|
+
self.eq('V-41', nodes[0].get('id'))
|
|
25
|
+
self.eq('rule 41', nodes[0].get('name'))
|
|
26
|
+
self.eq('If you can AAAAAAAA...', nodes[0].get('text'))
|
|
27
|
+
self.eq(1729209600000, nodes[0].get('created'))
|
|
28
|
+
self.eq(1729209600000, nodes[0].get('updated'))
|
|
29
|
+
self.eq(1099513724931, nodes[0].get('version'))
|
|
30
|
+
|
|
31
|
+
self.nn(nodes[0].get('file'))
|
|
32
|
+
self.nn(nodes[0].get('author'))
|
|
33
|
+
|
|
34
|
+
self.len(2, nodes[0].get('supersedes'))
|
|
35
|
+
self.len(1, nodes[0].get('contributors'))
|
|
36
|
+
|
|
37
|
+
self.len(1, await core.nodes('doc:policy:id=V-41 :file -> file:bytes'))
|
|
38
|
+
self.len(2, await core.nodes('doc:policy:id=V-41 :supersedes -> doc:policy'))
|
|
39
|
+
self.len(1, await core.nodes('doc:policy:id=V-41 :author -> ps:contact +:name=visi'))
|
|
40
|
+
self.len(1, await core.nodes('doc:policy:id=V-41 :contributors -> ps:contact +:name=shuka'))
|
|
41
|
+
|
|
42
|
+
nodes = await core.nodes('''
|
|
43
|
+
[ doc:standard=*
|
|
44
|
+
:id=V-99
|
|
45
|
+
:policy={ doc:policy:id=V-41 }
|
|
46
|
+
]
|
|
47
|
+
''')
|
|
48
|
+
self.len(1, nodes)
|
|
49
|
+
self.eq('V-99', nodes[0].get('id'))
|
|
50
|
+
self.nn(nodes[0].get('policy'))
|
|
51
|
+
self.len(1, await core.nodes('doc:standard -> doc:policy'))
|