This is an automated email from the ASF dual-hosted git repository.

abhi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git


The following commit(s) were added to refs/heads/master by this push:
     new 4d56c7fcf RANGER-5224: dedupTags removes the valid tags while 
deduplicating tags (#592)
4d56c7fcf is described below

commit 4d56c7fcf14d3896606f38d303f20b4afa8c339f
Author: Vyom Mani Tiwari <[email protected]>
AuthorDate: Wed Jun 25 04:36:15 2025 +0530

    RANGER-5224: dedupTags removes the valid tags while deduplicating tags 
(#592)
---
 .../org/apache/ranger/plugin/util/ServiceTags.java |  5 ++
 .../apache/ranger/plugin/util/TestServiceTags.java | 93 ++++++++++++++++++++++
 2 files changed, 98 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 c5b0811fe..74b2464a8 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
@@ -247,6 +247,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();
@@ -263,6 +264,7 @@ public int dedupTags() {
                     cachedTag.left = tagId;
                 } else {
                     replacedIds.put(tagId, cachedTag.left);
+                    tagsToAdd.put(cachedTag.left, tag);
                     iter.remove();
                 }
             }
@@ -272,6 +274,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 1c8e41c5b..a2d52427f 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,96 @@ 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();
 

Reply via email to