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