Skip to content

Commit 63c7918

Browse files
committed
modifications based on the feedback
1 parent 9dc2b56 commit 63c7918

File tree

6 files changed

+86
-24
lines changed

6 files changed

+86
-24
lines changed

aws_lambda_powertools/utilities/data_masking/base.py

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import functools
44
import logging
55
import warnings
6+
from copy import deepcopy
67
from typing import TYPE_CHECKING, Any, Callable, Mapping, Sequence, overload
78

89
from jsonpath_ng.ext import parse
@@ -304,21 +305,11 @@ def _apply_masking_rules(self, data: dict, masking_rules: dict) -> dict:
304305
Returns:
305306
dict: The masked data dictionary
306307
"""
307-
result = data.copy()
308+
result = deepcopy(data)
308309

309310
for path, rule in masking_rules.items():
310311
try:
311-
if ".." in path:
312-
# Handle recursive descent paths (e.g., "address..name")
313-
base_path, field = path.split("..")
314-
jsonpath_expr = parse(f"$.{base_path}..{field}")
315-
elif "[" in path:
316-
# Handle array notation paths (e.g., "address[*].street")
317-
jsonpath_expr = parse(f"$.{path}")
318-
else:
319-
# Handle simple field names (e.g., "email")
320-
jsonpath_expr = parse(f"$.{path}")
321-
312+
jsonpath_expr = parse(f"$.{path}")
322313
matches = jsonpath_expr.find(result)
323314

324315
if not matches:
@@ -329,14 +320,8 @@ def _apply_masking_rules(self, data: dict, masking_rules: dict) -> dict:
329320
try:
330321
value = match.value
331322
if value is not None:
332-
if isinstance(value, dict):
333-
# Handle dictionary values by masking each field
334-
for k, v in value.items():
335-
if v is not None:
336-
value[k] = self.provider.erase(str(v), **rule)
337-
else:
338-
masked_value = self.provider.erase(str(value), **rule)
339-
match.full_path.update(result, masked_value)
323+
masked_value = self.provider.erase(str(value), **rule)
324+
match.full_path.update(result, masked_value)
340325

341326
except Exception as e:
342327
warnings.warn(f"Error masking value for path {path}: {str(e)}", stacklevel=2)

docs/utilities/data_masking.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ The `erase` method also supports additional flags for more advanced and flexible
123123

124124
=== "dynamic_mask"
125125

126-
(bool) When set to `True`, this flag enables custom masking behavior. It activates the use of advanced masking techniques such as pattern-based or regex-based masking.
126+
(bool) Enables dynamic masking behavior when set to `True`, by maintaining the original length and structure of the text replacing with *.
127127

128128
> Expression: `data_masker.erase(data, fields=["address.zip"], dynamic_mask=True)`
129129

@@ -152,6 +152,16 @@ The `erase` method also supports additional flags for more advanced and flexible
152152
```python hl_lines="20"
153153
--8<-- "examples/data_masking/src/custom_data_masking.py"
154154
```
155+
=== "Input example"
156+
157+
```json
158+
--8<-- "examples/data_masking/src/payload_custom_masking.json"
159+
```
160+
=== "Masking rules output example"
161+
162+
```json hl_lines="4 5 10 21"
163+
--8<-- "examples/data_masking/src/output_custom_masking.json"
164+
```
155165

156166
### Encrypting data
157167

examples/data_masking/src/custom_data_masking.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ def lambda_handler(event: dict, context: LambdaContext) -> dict:
1313
masking_rules = {
1414
"email": {"regex_pattern": "(.)(.*)(@.*)", "mask_format": r"\1****\3"},
1515
"age": {"dynamic_mask": True},
16-
"address.zip": {"dynamic_mask": True, "custom_mask": "xxx"},
17-
"address.street": {"dynamic_mask": False},
16+
"address.zip": {"custom_mask": "xxx"},
17+
"$.other_address[?(@.postcode > 12000)]": {"custom_mask": "Masked"},
1818
}
1919

2020
result = data_masker.erase(data, masking_rules=masking_rules)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"id": 1,
3+
"name": "John Doe",
4+
"age": "**",
5+
"email": "j****@example.com",
6+
"address": {
7+
"street": "123 Main St",
8+
"city": "Anytown",
9+
"state": "CA",
10+
"zip": "xxx",
11+
"postcode": 12345,
12+
"product": {
13+
"name": "Car"
14+
}
15+
},
16+
"other_address": [
17+
{
18+
"postcode": 11345,
19+
"street": "123 Any Drive"
20+
},
21+
"Masked"
22+
],
23+
"company_address": {
24+
"street": "456 ACME Ave",
25+
"city": "Anytown",
26+
"state": "CA",
27+
"zip": "12345"
28+
}
29+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"body": {
3+
"id": 1,
4+
"name": "Jane Doe",
5+
"age": 30,
6+
"email": "[email protected]",
7+
"address": {
8+
"street": "123 Main St",
9+
"city": "Anytown",
10+
"state": "CA",
11+
"zip": "12345",
12+
"postcode": 12345,
13+
"product": {
14+
"name": "Car"
15+
}
16+
},
17+
"other_address": [
18+
{
19+
"postcode": 11345,
20+
"street": "123 Any Drive"
21+
},
22+
{
23+
"postcode": 67890,
24+
"street": "100 Main Street,"
25+
}
26+
],
27+
"company_address": {
28+
"street": "456 ACME Ave",
29+
"city": "Anytown",
30+
"state": "CA",
31+
"zip": "12345"
32+
}
33+
}
34+
}

tests/unit/data_masking/_aws_encryption_sdk/test_unit_data_masking.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,12 +218,16 @@ def test_parsing_nonexistent_fields_warning_on_missing_field():
218218

219219

220220
def test_regex_mask(data_masker):
221-
data = "Hello! My name is Fulano Ciclano"
221+
# GIVEN a str data type
222+
data = "Hello! My name is John Doe"
223+
224+
# WHEN erase is called with regex pattern and mask format
222225
regex_pattern = r"\b[A-Z][a-z]+ [A-Z][a-z]+\b"
223226
mask_format = "XXXX XXXX"
224227

225228
result = data_masker.erase(data, regex_pattern=regex_pattern, mask_format=mask_format)
226229

230+
# THEN the result is the regex part masked by the masked format
227231
assert result == "Hello! My name is XXXX XXXX"
228232

229233

0 commit comments

Comments
 (0)