1 import re
2 from textwrap import dedent
3 from unittest import TestCase
4
5 from pcs.cli import nvset
6 from pcs.common.pacemaker.nvset import (
7 CibNvpairDto,
8 CibNvsetDto,
9 )
10 from pcs.common.pacemaker.rule import CibRuleExpressionDto
11 from pcs.common.types import (
12 CibRuleExpressionType,
13 CibRuleInEffectStatus,
14 )
15
16
17 def fixture_dto(in_effect):
18 return CibNvsetDto(
19 f"id-{in_effect}",
20 {"score": "150"},
21 CibRuleExpressionDto(
22 f"id-{in_effect}-rule",
23 CibRuleExpressionType.RULE,
24 in_effect,
25 {"boolean-op": "or"},
26 None,
27 None,
28 [
29 CibRuleExpressionDto(
30 f"id-{in_effect}-rule-op",
31 CibRuleExpressionType.OP_EXPRESSION,
32 CibRuleInEffectStatus.UNKNOWN,
33 {"name": "monitor"},
34 None,
35 None,
36 [],
37 "op monitor",
38 ),
39 ],
40 "op monitor",
41 ),
42 [CibNvpairDto(f"id-{in_effect}-pair1", "name1", "value1")],
43 )
44
45
46 def fixture_dto_list():
47 return [fixture_dto(in_effect.value) for in_effect in CibRuleInEffectStatus]
48
49
50 class FilterOutExpiredNvset(TestCase):
51 def test_filter(self):
52 self.maxDiff = None
53 list_with_expired_nvsets = [
54 CibNvsetDto(id="nvset-no-rule", options={}, rule=None, nvpairs=[]),
55 CibNvsetDto(
56 id="nvset-2",
57 options={},
58 rule=CibRuleExpressionDto(
59 id="rule-another-expired",
60 type=CibRuleExpressionType.DATE_EXPRESSION,
61 in_effect=CibRuleInEffectStatus.EXPIRED,
62 options={},
63 date_spec=None,
64 duration=None,
65 expressions=[],
66 as_string="",
67 ),
68 nvpairs=[],
69 ),
70 ] + fixture_dto_list()
71 expected_list = [
72 item
73 for idx, item in enumerate(list_with_expired_nvsets[:])
74 if idx not in [1, 4]
75 ]
76 self.assertEqual(
77 nvset.filter_out_expired_nvset(list_with_expired_nvsets),
78 expected_list,
79 )
80
81 def test_empty_list(self):
82 self.assertEqual(nvset.filter_out_expired_nvset([]), [])
83
84
85 class FilterNvpairsByNames(TestCase):
86 test_nvsets = [
87 CibNvsetDto(
88 id="1",
89 options={},
90 rule=None,
91 nvpairs=[
92 CibNvpairDto(id="1a", name="a", value="1"),
93 CibNvpairDto(id="1b", name="b", value="2"),
94 CibNvpairDto(id="1c", name="c", value="3"),
95 ],
96 ),
97 CibNvsetDto(
98 id="2",
99 options={},
100 rule=None,
101 nvpairs=[
102 CibNvpairDto(id="2a", name="a", value="1"),
103 CibNvpairDto(id="2b", name="b", value="2"),
104 ],
105 ),
106 ]
107
108 def test_filter_no_match(self):
109 self.assertEqual(
110 nvset.filter_nvpairs_by_names(self.test_nvsets, ["x"]),
111 [
112 CibNvsetDto(id="1", options={}, rule=None, nvpairs=[]),
113 CibNvsetDto(id="2", options={}, rule=None, nvpairs=[]),
114 ],
115 )
116
117 def test_filter_match_in_one_set(self):
118 self.assertEqual(
119 nvset.filter_nvpairs_by_names(self.test_nvsets, ["c"]),
120 [
121 CibNvsetDto(
122 id="1",
123 options={},
124 rule=None,
125 nvpairs=[
126 CibNvpairDto(id="1c", name="c", value="3"),
127 ],
128 ),
129 CibNvsetDto(id="2", options={}, rule=None, nvpairs=[]),
130 ],
131 )
132
133 def test_filter_match_in_more_set(self):
134 self.assertEqual(
135 nvset.filter_nvpairs_by_names(self.test_nvsets, ["a"]),
136 [
137 CibNvsetDto(
138 id="1",
139 options={},
140 rule=None,
141 nvpairs=[
142 CibNvpairDto(id="1a", name="a", value="1"),
143 ],
144 ),
145 CibNvsetDto(
146 id="2",
147 options={},
148 rule=None,
149 nvpairs=[
150 CibNvpairDto(id="2a", name="a", value="1"),
151 ],
152 ),
153 ],
154 )
155
156 def test_filter_multiple_filter(self):
157 self.assertEqual(
158 nvset.filter_nvpairs_by_names(self.test_nvsets, ["a", "c", "x"]),
159 [
160 CibNvsetDto(
161 id="1",
162 options={},
163 rule=None,
164 nvpairs=[
165 CibNvpairDto(id="1a", name="a", value="1"),
166 CibNvpairDto(id="1c", name="c", value="3"),
167 ],
168 ),
169 CibNvsetDto(
170 id="2",
171 options={},
172 rule=None,
173 nvpairs=[
174 CibNvpairDto(id="2a", name="a", value="1"),
175 ],
176 ),
177 ],
178 )
179
180
181 class NvsetDtoToLines(TestCase):
182 def setUp(self):
183 self.label = "Meta Attributes"
184 self.full_dto = CibNvsetDto(
185 "my-id",
186 {"score": "150"},
187 CibRuleExpressionDto(
188 "my-id-rule",
189 CibRuleExpressionType.RULE,
190 CibRuleInEffectStatus.UNKNOWN,
191 {"boolean-op": "or"},
192 None,
193 None,
194 [
195 CibRuleExpressionDto(
196 "my-id-rule-op",
197 CibRuleExpressionType.OP_EXPRESSION,
198 CibRuleInEffectStatus.UNKNOWN,
199 {"name": "monitor"},
200 None,
201 None,
202 [],
203 "op monitor",
204 ),
205 ],
206 "op monitor",
207 ),
208 [
209 CibNvpairDto("my-id-pair1", "name1", "value1"),
210 CibNvpairDto("my-id-pair2", "name 2", "value 2"),
211 CibNvpairDto("my-id-pair3", "name=3", "value=3"),
212 CibNvpairDto("my-id-pair4", "secret1", "lrm://"),
213 CibNvpairDto("my-id-pair5", "secret 2", "lrm://"),
214 CibNvpairDto("my-id-pair6", "secret=3", "lrm://"),
215 ],
216 )
217
218 def _export(self, dto, with_ids, secrets_map):
219 return (
220 "\n".join(
221 nvset.nvset_dto_to_lines(
222 dto,
223 nvset_label=self.label,
224 with_ids=with_ids,
225 secrets_map=secrets_map,
226 )
227 )
228 + "\n"
229 )
230
231 def assert_lines(self, dto, lines, secrets_map=None):
232 self.assertEqual(
233 self._export(dto, True, secrets_map),
234 lines,
235 )
236 self.assertEqual(
237 self._export(dto, False, secrets_map),
238 re.sub(r" +\(id:.*\)", "", lines),
239 )
240
241 def test_minimal(self):
242 dto = CibNvsetDto("my-id", {}, None, [])
243 output = dedent(
244 f"""\
245 {self.label}: my-id
246 """
247 )
248 self.assert_lines(dto, output)
249
250 def test_full_without_secrets_map(self):
251 output = dedent(
252 f"""\
253 {self.label}: my-id score=150
254 "name 2"="value 2" (id: my-id-pair2)
255 name1=value1 (id: my-id-pair1)
256 "name=3"="value=3" (id: my-id-pair3)
257 "secret 2"=lrm:// (id: my-id-pair5)
258 secret1=lrm:// (id: my-id-pair4)
259 "secret=3"=lrm:// (id: my-id-pair6)
260 Rule: boolean-op=or (id: my-id-rule)
261 Expression: op monitor (id: my-id-rule-op)
262 """
263 )
264 self.assert_lines(self.full_dto, output)
265
266 def test_full_with_secrets_map(self):
267 output = dedent(
268 f"""\
269 {self.label}: my-id score=150
270 "name 2"="value 2" (id: my-id-pair2)
271 name1=value1 (id: my-id-pair1)
272 "name=3"="value=3" (id: my-id-pair3)
273 "secret=3"=lrm:// (id: my-id-pair6)
274 Secret {self.label}:
275 "secret 2" (id: my-id-pair5)
276 secret1=secret_value1 (id: my-id-pair4)
277 Rule: boolean-op=or (id: my-id-rule)
278 Expression: op monitor (id: my-id-rule-op)
279 """
280 )
281 secrets_map = {
|
(1) Event Sigma main event: |
A secret, such as a password, cryptographic key, or token is stored in plaintext directly in the source code, in an application's properties, or configuration file. Users with access to the secret may then use the secret to access resources that they otherwise would not have access to. Secret type: Secret (generic). |
|
(2) Event remediation: |
Avoid setting sensitive configuration values as string literals. Instead, these values should be set using variables with the sensitive data loaded from an encrypted file or a secret store. |
282 "secret1": "secret_value1",
283 "secret 2": None,
284 }
285 self.assert_lines(self.full_dto, output, secrets_map)
286
287
288 class NvsetDtoListToLines(TestCase):
289 def setUp(self):
290 self.label = "Meta Attributes"
291
292 def _export(self, dto, with_ids):
293 return (
294 "\n".join(
295 nvset.nvset_dto_list_to_lines(
296 dto,
297 nvset_label=self.label,
298 with_ids=with_ids,
299 )
300 )
301 + "\n"
302 )
303
304 def assert_lines(self, dto, lines):
305 self.assertEqual(
306 self._export(dto, True),
307 lines,
308 )
309 self.assertEqual(
310 self._export(dto, False),
311 re.sub(r" +\(id:.*\)", "", lines),
312 )
313
314 def test_lines(self):
315 self.maxDiff = None
316 output = dedent(
317 f"""\
318 {self.label} (not yet in effect): id-NOT_YET_IN_EFFECT score=150
319 name1=value1 (id: id-NOT_YET_IN_EFFECT-pair1)
320 Rule (not yet in effect): boolean-op=or (id: id-NOT_YET_IN_EFFECT-rule)
321 Expression: op monitor (id: id-NOT_YET_IN_EFFECT-rule-op)
322 {self.label}: id-IN_EFFECT score=150
323 name1=value1 (id: id-IN_EFFECT-pair1)
324 Rule: boolean-op=or (id: id-IN_EFFECT-rule)
325 Expression: op monitor (id: id-IN_EFFECT-rule-op)
326 {self.label} (expired): id-EXPIRED score=150
327 name1=value1 (id: id-EXPIRED-pair1)
328 Rule (expired): boolean-op=or (id: id-EXPIRED-rule)
329 Expression: op monitor (id: id-EXPIRED-rule-op)
330 {self.label}: id-UNKNOWN score=150
331 name1=value1 (id: id-UNKNOWN-pair1)
332 Rule: boolean-op=or (id: id-UNKNOWN-rule)
333 Expression: op monitor (id: id-UNKNOWN-rule-op)
334 """
335 )
336 self.assert_lines(fixture_dto_list(), output)
337