Skip to content

Commit f4fb6b9

Browse files
committed
Adding json type files to crawl_n_mask
We're adding json type files to crawl_n_mask. It checks the extension and return the value of the masked key different between yaml and json formats.
1 parent 221015d commit f4fb6b9

File tree

2 files changed

+41
-40
lines changed

2 files changed

+41
-40
lines changed

plugins/modules/crawl_n_mask.py

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,6 @@ def crawl(module, path) -> bool:
191191
# Check if any parent directory (not the root) is excluded
192192
if any(part in EXCLUDED_DIRS for part in rel_path.split(os.sep)):
193193
continue
194-
195194
for f in files:
196195
if not re.search(excluded_file_ext_regex, f):
197196
if mask(module, os.path.join(root, f)):
@@ -206,7 +205,15 @@ def _get_masked_string(value):
206205
return value[:2] + MASK_STR + value[-2:]
207206

208207

209-
def partial_mask(value):
208+
def format_masked(prefix, value, suffix, extension):
209+
return (
210+
f"{prefix}'{value}'{suffix}"
211+
if extension == "yaml"
212+
else f"{prefix}\"{value}\"{suffix}"
213+
)
214+
215+
216+
def partial_mask(value, extension):
210217
"""
211218
Check length of the string. If it is too long, take 2 chars
212219
from beginning, then add mask string and add 2 chars from the
@@ -215,22 +222,23 @@ def partial_mask(value):
215222
"""
216223
if not value.strip():
217224
return
218-
219-
if "'" in value:
220-
parsed_value = value.split("'")
225+
if "'" in value or extension == "json":
226+
parsed_value = (value.split("\"")
227+
if extension == "json"
228+
else value.split("'"))
221229
if len(parsed_value) > 2 and parsed_value[1] != "":
222230
prefix = parsed_value[0]
223231
value = _get_masked_string(parsed_value[1])
224232
suffix = parsed_value[2]
225-
return f"{prefix}'{value}'{suffix}"
233+
return format_masked(prefix, value, suffix, extension)
226234
else:
227235
match = re.match(r"^(\s*)(.*?)(\n?)$", value)
228236
if match:
229237
parts = list(match.groups())
230238
prefix = parts[0]
231239
value = _get_masked_string(parts[1])
232240
suffix = parts[2]
233-
return f"{prefix}'{value}'{suffix}"
241+
return format_masked(prefix, value, suffix, extension)
234242

235243

236244
def mask(module, path: str) -> bool:
@@ -240,16 +248,17 @@ def mask(module, path: str) -> bool:
240248
respective masking methods for that file.
241249
"""
242250
changed = False
243-
if (
251+
if path.endswith("json"):
252+
changed = mask_file(module, path, "json")
253+
elif (
244254
path.endswith((tuple(["yaml", "yml"])))
245255
or os.path.basename(path).split(".")[0] in ALLOWED_YAML_FILES
246256
):
247-
extension = "yaml"
248-
changed = mask_file(module, path, extension)
257+
changed = mask_file(module, path, "yaml")
249258
return changed
250259

251260

252-
def mask_yaml(infile, outfile, changed) -> bool:
261+
def mask_by_extension(infile, outfile, changed, extension) -> bool:
253262
"""
254263
Read the file, search for colon (':'), take value and
255264
mask sensitive data
@@ -259,12 +268,12 @@ def mask_yaml(infile, outfile, changed) -> bool:
259268
if ":" not in line:
260269
outfile.write(line)
261270
continue
262-
263271
key, sep, value = line.partition(":")
272+
comparable_key = key.strip().replace('"', "")
264273
masked_value = value
265274
for word in PROTECT_KEYS:
266-
if key.strip() == word:
267-
masked = partial_mask(value)
275+
if comparable_key == word.strip():
276+
masked = partial_mask(value, extension)
268277
if not masked:
269278
continue
270279
masked_value = masked_value.replace(value, masked)
@@ -293,14 +302,12 @@ def mask_file(module, path, extension) -> bool:
293302
try:
294303
with file_path.open("r", encoding="utf-8") as infile:
295304
with temp_path.open("w", encoding="utf-8") as outfile:
296-
if extension == "yaml":
297-
changed = mask_yaml(infile, outfile, changed)
298-
replace_file(temp_path, file_path, changed)
299-
return changed
305+
changed = mask_by_extension(infile, outfile, changed, extension)
306+
replace_file(temp_path, file_path, changed)
307+
return changed
300308
except Exception as e:
301309
print(f"An unexpected error occurred on masking file {file_path}: {e}")
302310

303-
304311
def run_module():
305312
# define available arguments/parameters a user can pass to the module
306313
module_args = dict(

tests/unit/modules/test_crawl_n_mask.py

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -41,25 +41,19 @@ def test_crawl_false(self, test_dir, expected_files):
4141
changed = cnm.crawl(module, test_dir)
4242
assert not changed
4343

44-
def test_partial_mask_scenario_1(self):
45-
example_value = " 'test1234'\n"
46-
expected_value = " 'te**********34'\n"
47-
test_value = cnm.partial_mask(example_value)
48-
assert expected_value == test_value
49-
50-
def test_partial_mask_scenario_2(self):
51-
example_value = " osp_ci_framework_keytab\n"
52-
expected_value = " 'os**********ab'\n"
53-
test_value = cnm.partial_mask(example_value)
54-
assert expected_value == test_value
55-
56-
def test_partial_mask_scenario_3(self):
57-
example_value = " ''\n"
58-
test_value = cnm.partial_mask(example_value)
59-
assert test_value is None
60-
61-
def test_partial_mask_scenario_4(self):
62-
example_value = "tet"
63-
expected_value = "'te**********'"
64-
test_value = cnm.partial_mask(example_value)
44+
@pytest.mark.parametrize(
45+
"file_format, example_value, expected_value",
46+
[
47+
("yaml", " 'test1234'\n", " 'te**********34'\n"),
48+
("yaml", " osp_ci_framework_keytab\n", " 'os**********ab'\n"),
49+
("yaml", " ''\n", None),
50+
("yaml", "tet", "'te**********'"),
51+
("json", " 'test1234'\n", " te**********34\n"),
52+
("json", " osp_ci_framework_keytab\n", " os**********ab\n"),
53+
("json", " ''\n", None),
54+
("json", "tet", "te**********"),
55+
],
56+
)
57+
def test_partial_mask(self, file_format, example_value, expected_value):
58+
test_value = cnm.partial_mask(example_value, file_format)
6559
assert expected_value == test_value

0 commit comments

Comments
 (0)