Skip to content

Commit

Permalink
fix(masking): fixes 2 issues - one which hides non-structured objects…
Browse files Browse the repository at this point in the history
… rather than shows them anyway, and fixes multi-nested fields
  • Loading branch information
jamfor352 committed Nov 20, 2024
1 parent 1d31915 commit 5ce42cd
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 6 deletions.
4 changes: 3 additions & 1 deletion src/main/java/org/akhq/utils/JsonMaskByDefaultMasker.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ public Record maskRecord(Record record) {
.findFirst()
.map(filter -> applyMasking(record, filter.getKeys()))
.orElseGet(() -> applyMasking(record, List.of()));
} else {
record.setValue("This record is unable to be masked as it is not a structured object. This record is unavailable to view due to safety measures from json_mask_by_default to not leak sensitive data. Please contact akhq administrator.");
}
} catch (Exception e) {
LOG.error("Error masking record at topic {}, partition {}, offset {} due to {}", record.getTopic(), record.getPartition(), record.getOffset(), e.getMessage());
Expand All @@ -59,7 +61,7 @@ private void maskAllExcept(String currentKey, JsonObject node, List<String> keys
JsonObject objectNode = node.getAsJsonObject();
for(Map.Entry<String, JsonElement> entry : objectNode.entrySet()) {
if(entry.getValue().isJsonObject()) {
maskAllExcept(entry.getKey() + ".", entry.getValue().getAsJsonObject(), keys);
maskAllExcept(currentKey + entry.getKey() + ".", entry.getValue().getAsJsonObject(), keys);
} else {
if(!keys.contains(currentKey + entry.getKey())) {
objectNode.addProperty(entry.getKey(), jsonMaskReplacement);
Expand Down
56 changes: 51 additions & 5 deletions src/test/java/org/akhq/utils/JsonMaskByDefaultMaskerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,15 @@ void forNonJsonValueShouldReturnItself() {
Record maskedRecord = masker.maskRecord(record);

assertEquals(
record,
maskedRecord
"This record is unable to be masked as it is not a structured object. " +
"This record is unavailable to view due to safety measures from json_mask_by_default to not leak " +
"sensitive data. Please contact akhq administrator.",
maskedRecord.getValue()
);
}

@Test
void forNonJsonValueThatLooksLikeJsonValueShouldReturnItself() {
void forNonJsonValueThatLooksLikeJsonValueShouldReturnDisclaimer() {
Record record = sampleRecord(
"users",
"some-key",
Expand All @@ -96,8 +98,10 @@ void forNonJsonValueThatLooksLikeJsonValueShouldReturnItself() {
Record maskedRecord = masker.maskRecord(record);

assertEquals(
record,
maskedRecord
"This record is unable to be masked as it is not a structured object. " +
"This record is unavailable to view due to safety measures from json_mask_by_default to not leak " +
"sensitive data. Please contact akhq administrator.",
maskedRecord.getValue()
);
}

Expand All @@ -117,6 +121,23 @@ void ifJsonParsingThrowsExceptionShouldReturnFalse() {
}
}

@Test
void ifRecordHasMultiLevelNestedValuesShouldBeProcessedCorrectly() {
Record record = sampleRecord(
"users",
"some-key",
sampleValueWithMultilevelNestedValues()
);

Record maskedRecord = masker.maskRecord(record);

assertEquals(
"""
{"specialId":123,"status":"ACTIVE","name":"xxxx","dateOfBirth":"xxxx","address":{"firstLine":"xxxx","town":"xxxx","country":"United Kingdom"},"metadata":{"trusted":true,"rating":"10","notes":"xxxx","other":{"shouldBeUnmasked":"Example multi-level-nested-value","shouldBeMasked":"xxxx"}}}""",
maskedRecord.getValue()
);
}

private String sampleValue() {
return """
{
Expand All @@ -137,4 +158,29 @@ private String sampleValue() {
}
""";
}

private String sampleValueWithMultilevelNestedValues() {
return """
{
"specialId": 123,
"status": "ACTIVE",
"name": "John Smith",
"dateOfBirth": "01-01-1991",
"address": {
"firstLine": "123 Example Avenue",
"town": "Faketown",
"country": "United Kingdom"
},
"metadata": {
"trusted": true,
"rating": "10",
"notes": "All in good order",
"other": {
"shouldBeUnmasked": "Example multi-level-nested-value",
"shouldBeMasked": "Example multi-level-nested-value"
}
}
}
""";
}
}
42 changes: 42 additions & 0 deletions src/test/java/org/akhq/utils/JsonShowByDefaultMaskerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,23 @@ void forNonJsonValueThatLooksLikeJsonValueShouldReturnItself() {
);
}

@Test
void ifRecordHasMultiLevelNestedValuesShouldBeProcessedCorrectly() {
Record record = sampleRecord(
"users",
"some-key",
sampleValueWithMultilevelNestedValues()
);

Record maskedRecord = masker.maskRecord(record);

assertEquals(
"""
{"specialId":123,"status":"ACTIVE","name":"xxxx","dateOfBirth":"xxxx","address":{"firstLine":"xxxx","town":"xxxx","country":"United Kingdom"},"metadata":{"trusted":true,"rating":"10","notes":"All in good order","other":{"shouldBeUnmasked":"Example multi-level-nested-value","shouldBeMasked":"xxxx"}}}""",
maskedRecord.getValue()
);
}

private String sampleValue() {
return """
{
Expand All @@ -119,4 +136,29 @@ private String sampleValue() {
}
""";
}

private String sampleValueWithMultilevelNestedValues() {
return """
{
"specialId": 123,
"status": "ACTIVE",
"name": "John Smith",
"dateOfBirth": "01-01-1991",
"address": {
"firstLine": "123 Example Avenue",
"town": "Faketown",
"country": "United Kingdom"
},
"metadata": {
"trusted": true,
"rating": "10",
"notes": "All in good order",
"other": {
"shouldBeUnmasked": "Example multi-level-nested-value",
"shouldBeMasked": "Example multi-level-nested-value"
}
}
}
""";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ akhq:
- address.country
- metadata.trusted
- metadata.rating
- metadata.other.shouldBeUnmasked
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ akhq:
- dateOfBirth
- address.firstLine
- address.town
- metadata.other.shouldBeMasked

0 comments on commit 5ce42cd

Please sign in to comment.