This is an automated email from the ASF dual-hosted git repository. abhi pushed a commit to branch ranger-2.7 in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/ranger-2.7 by this push: new 56c9f585d RANGER-5224: dedupTags removes the valid tags while deduplicating tags 56c9f585d is described below commit 56c9f585db5617226b387ea0c2a909dba082585e Author: Vyom Mani Tiwari <vyomm...@gmail.com> AuthorDate: Wed Jun 25 04:36:15 2025 +0530 RANGER-5224: dedupTags removes the valid tags while deduplicating tags --- .../org/apache/ranger/plugin/util/ServiceTags.java | 5 ++ .../apache/ranger/plugin/util/TestServiceTags.java | 92 ++++++++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceTags.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceTags.java index bca352e8b..12f026e32 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceTags.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceTags.java @@ -250,6 +250,7 @@ public int dedupTags() { final Map<Long, Long> replacedIds = new HashMap<>(); final int initialTagsCount = tags.size(); final List<Long> tagIdsToRemove = new ArrayList<>(); + final Map<Long, RangerTag> tagsToAdd = new HashMap<>(); for (Iterator<Map.Entry<Long, RangerTag>> iter = tags.entrySet().iterator(); iter.hasNext(); ) { Map.Entry<Long, RangerTag> entry = iter.next(); @@ -266,6 +267,7 @@ public int dedupTags() { cachedTag.left = tagId; } else { replacedIds.put(tagId, cachedTag.left); + tagsToAdd.put(cachedTag.left, tag); iter.remove(); } } @@ -275,6 +277,9 @@ public int dedupTags() { tags.remove(tagIdToRemove); } + // Add all the tags whose tagIds are modified back to tags + tags.putAll(tagsToAdd); + final int finalTagsCount = tags.size(); for (Map.Entry<Long, List<Long>> resourceEntry : resourceToTagIds.entrySet()) { diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/util/TestServiceTags.java b/agents-common/src/test/java/org/apache/ranger/plugin/util/TestServiceTags.java index c41d4e196..d44309805 100644 --- a/agents-common/src/test/java/org/apache/ranger/plugin/util/TestServiceTags.java +++ b/agents-common/src/test/java/org/apache/ranger/plugin/util/TestServiceTags.java @@ -25,8 +25,11 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; public class TestServiceTags { private static final RangerServiceResource[] RESOURCES = { @@ -112,6 +115,95 @@ public void testDedup_DupTagsWithAttr_MultipleCalls() { assertEquals(0, svcTags.dedupTags()); } + @Test + public void testDedupTags_DuplicateTagWithHigherId() { + // Create ServiceTags with duplicate tags + RangerTag[] tags = { + new RangerTag("PII", Collections.singletonMap("type", "email")), + new RangerTag("PII", Collections.singletonMap("type", "email")), + new RangerTag("PCI", Collections.emptyMap()), + new RangerTag("PCI", Collections.emptyMap()), + new RangerTag("PII", Collections.singletonMap("type", "email")) + }; + + ServiceTags svcTags = createServiceTags(tags, RESOURCES); + assertEquals(5, svcTags.getTags().size()); + // Should remove 3 duplicates (2 PII, 1 PCI) + assertEquals(3, svcTags.dedupTags()); + + // Verify: 2 tags remain (one PII, one PCI) + assertEquals(2, svcTags.getTags().size()); + // Find retained PII tag ID + Long piiTagId = svcTags.getTags().entrySet().stream() + .filter(e -> e.getValue().getType().equals("PII")) + .map(Map.Entry::getKey) + .findFirst() + .orElseThrow(() -> new AssertionError("PII tag not found")); + RangerTag cachedTag = svcTags.getTags().get(piiTagId); + + // Verify resource mappings + assertTrue(svcTags.getResourceToTagIds().values().stream() + .allMatch(tagIds -> tagIds.contains(piiTagId))); + + // Add a new PII tag with higher tag ID + ServiceTags svcTags1 = new ServiceTags(svcTags); + svcTags1.getTags().remove(piiTagId); + RangerTag newTag = new RangerTag("PII", Collections.singletonMap("type", "email")); + long newTagId = 23L; + newTag.setId(newTagId); + svcTags1.getTags().put(newTagId, newTag); + svcTags1.getResourceToTagIds().get(1L).add(newTagId); + + assertEquals(0, svcTags1.dedupTags()); + assertEquals(2, svcTags1.getTags().size()); + assertEquals(cachedTag, svcTags1.getTags().get(piiTagId)); + assertFalse(svcTags1.getTags().containsKey(newTagId)); + + // Verify resource mappings still include piiTagId + assertTrue(svcTags1.getResourceToTagIds().values().stream() + .allMatch(tagIds -> tagIds.contains(piiTagId))); + + // Simulate resource deletion + svcTags1.getResourceToTagIds().remove(0L); + assertEquals(0, svcTags1.dedupTags()); + assertEquals(cachedTag, svcTags1.getTags().get(piiTagId)); + assertTrue(svcTags1.getResourceToTagIds().get(1L).contains(piiTagId)); + } + + @Test + public void testDedupTags_HigherIdTagAfterLowerIdRemoval() { + // Create ServiceTags with one PII tag + RangerTag[] tags = {new RangerTag("PII", Collections.singletonMap("type", "email"))}; + ServiceTags svcTags = createServiceTags(tags, RESOURCES); + assertEquals(1, svcTags.getTags().size()); + + Long piiTagId = svcTags.getTags().entrySet().stream() + .filter(e -> e.getValue().getType().equals("PII")) + .map(Map.Entry::getKey) + .findFirst() + .orElseThrow(() -> new AssertionError("PII tag not found")); + RangerTag cachedTag = svcTags.getTags().get(piiTagId); + + // calling dedupTags() make sure that cachedTags contains PII tag. + svcTags.dedupTags(); + svcTags.getTags().remove(piiTagId); + + ServiceTags svcTags1 = new ServiceTags(svcTags); + RangerTag newTag = new RangerTag("PII", Collections.singletonMap("type", "email")); + long newTagId = 7L; // Higher tagID + newTag.setId(newTagId); + svcTags1.getTags().put(newTagId, newTag); + svcTags1.getResourceToTagIds().get(1L).add(newTagId); + + // Call dedupTags (should fail with buggy code) + assertEquals(0, svcTags1.dedupTags()); + + // With buggy dedupTags(), newTagId (7) is removed, and no PII tag remains + // With fixed dedupTags(), newTagId is replaced with a valid ID(piiTagId) + assertEquals(1, svcTags1.getTags().size()); + assertEquals(cachedTag, svcTags1.getTags().get(piiTagId)); + assertFalse(svcTags1.getTags().containsKey(newTagId)); + } private ServiceTags createServiceTags(RangerTag[] tags, RangerServiceResource[] resources) { ServiceTags ret = new ServiceTags();