You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by ab...@apache.org on 2025/06/24 23:18:36 UTC

(ranger) branch ranger-2.7 updated: RANGER-5224: dedupTags removes the valid tags while deduplicating tags

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 <vy...@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();