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();

Reply via email to