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

dineshkumar-yadav 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 8ce349aef RANGER-5708 : Correct early publication of KnoxRangerPlugin 
in RangerPDPKnoxFilter (#1121)
8ce349aef is described below

commit 8ce349aef19adde77129e3affc3838ec6273b76a
Author: Rohit Gupta <[email protected]>
AuthorDate: Mon Aug 10 11:52:23 2026 +0530

    RANGER-5708 : Correct early publication of KnoxRangerPlugin in 
RangerPDPKnoxFilter (#1121)
    
    Co-authored-by: rohitgupta <[email protected]>
---
 .../authorization/knox/RangerPDPKnoxFilter.java    |  6 +-
 .../knox/TestRangerPDPKnoxFilter.java              | 82 ++++++++++++++++++++++
 2 files changed, 86 insertions(+), 2 deletions(-)

diff --git 
a/knox-agent/src/main/java/org/apache/ranger/authorization/knox/RangerPDPKnoxFilter.java
 
b/knox-agent/src/main/java/org/apache/ranger/authorization/knox/RangerPDPKnoxFilter.java
index 5d81a7903..c554a5e8f 100644
--- 
a/knox-agent/src/main/java/org/apache/ranger/authorization/knox/RangerPDPKnoxFilter.java
+++ 
b/knox-agent/src/main/java/org/apache/ranger/authorization/knox/RangerPDPKnoxFilter.java
@@ -77,9 +77,11 @@ public void init(FilterConfig filterConfig) {
 
                     LOG.info("Creating KnoxRangerPlugin");
 
-                    plugin = new KnoxRangerPlugin();
+                    me = new KnoxRangerPlugin();
 
-                    plugin.init();
+                    me.init();
+
+                    plugin = me;
                 }
             }
         }
diff --git 
a/knox-agent/src/test/java/org/apache/ranger/authorization/knox/TestRangerPDPKnoxFilter.java
 
b/knox-agent/src/test/java/org/apache/ranger/authorization/knox/TestRangerPDPKnoxFilter.java
index 12dd3ab88..612d5d82e 100644
--- 
a/knox-agent/src/test/java/org/apache/ranger/authorization/knox/TestRangerPDPKnoxFilter.java
+++ 
b/knox-agent/src/test/java/org/apache/ranger/authorization/knox/TestRangerPDPKnoxFilter.java
@@ -25,11 +25,13 @@
 import org.apache.ranger.audit.provider.MiscUtil;
 import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
 import org.apache.ranger.plugin.policyengine.RangerAccessResult;
+import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.MethodOrderer;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.TestMethodOrder;
 import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.MockedConstruction;
 import org.mockito.MockedStatic;
 import org.mockito.Mockito;
 import org.mockito.junit.jupiter.MockitoExtension;
@@ -47,8 +49,17 @@
 import java.security.PrivilegedExceptionAction;
 import java.util.Arrays;
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
 
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockConstruction;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -60,6 +71,11 @@
 @ExtendWith(MockitoExtension.class)
 @TestMethodOrder(MethodOrderer.MethodName.class)
 public class TestRangerPDPKnoxFilter {
+    @AfterEach
+    void tearDown() throws Exception {
+        setStaticPlugin(null);
+    }
+
     @Test
     public void test01_init_initializesPluginOnce() {
         RangerPDPKnoxFilter filter = new RangerPDPKnoxFilter();
@@ -167,6 +183,72 @@ public void 
test06_getTopologyName_extractsThirdTokenOrNull() {
         Assertions.assertEquals("two", invokeGetTopologyName(filter, 
"/one/two/three"));
     }
 
+    void test07_concurrentTopologyInit_blocksSecondTopologyUntilPluginReady() 
throws Exception {
+        setStaticPlugin(null);
+
+        // topology A pauses inside plugin.init() until releaseTopologyA
+        CountDownLatch topologyAInPluginInit = new CountDownLatch(1);
+        CountDownLatch releaseTopologyA      = new CountDownLatch(1);
+        AtomicBoolean topologyBInitFinished = new AtomicBoolean(false);
+
+        try (MockedStatic<MiscUtil> miscUtil = 
Mockito.mockStatic(MiscUtil.class)) {
+            miscUtil.when(() -> 
MiscUtil.setUGIFromJAASConfig(anyString())).thenAnswer(invocation -> null);
+            miscUtil.when(MiscUtil::getUGILoginUser).thenReturn(null);
+
+            try (MockedConstruction<KnoxRangerPlugin> ignored =
+                         mockConstruction(KnoxRangerPlugin.class, (mock, 
context) ->
+                                 doAnswer(invocation -> {
+                                     topologyAInPluginInit.countDown();
+                                     releaseTopologyA.await(10, 
TimeUnit.SECONDS);
+                                     return null;
+                                 }).when(mock).init())) {
+                FilterConfig config = Mockito.mock(FilterConfig.class);
+                
when(config.getInitParameter("resource.role")).thenReturn("WEBHDFS");
+
+                RangerPDPKnoxFilter filterTopologyA = new 
RangerPDPKnoxFilter();
+                RangerPDPKnoxFilter filterTopologyB = new 
RangerPDPKnoxFilter();
+                ExecutorService executor = Executors.newFixedThreadPool(2);
+
+                // Thread 1: topology B tries to init while topology A is 
still in plugin.init()
+                Future<?> topologyBInit = executor.submit(() -> {
+                    try {
+                        topologyAInPluginInit.await(10, TimeUnit.SECONDS);
+                        filterTopologyB.init(config);
+                        topologyBInitFinished.set(true);
+                    } catch (Exception e) {
+                        throw new RuntimeException(e);
+                    }
+                });
+
+                // Thread 2: verify topology B is still waiting, then let 
topology A finish
+                Future<?> checker = executor.submit(() -> {
+                    try {
+                        topologyAInPluginInit.await(10, TimeUnit.SECONDS);
+                        Thread.sleep(200);
+                        Assertions.assertFalse(topologyBInitFinished.get(),
+                                "topology B init must block until plugin is 
ready");
+                        releaseTopologyA.countDown();
+                    } catch (Exception e) {
+                        throw new RuntimeException(e);
+                    }
+                });
+
+                // Main thread: topology A init (Mockito construction mock 
works on this thread)
+                filterTopologyA.init(config);
+
+                checker.get(10, TimeUnit.SECONDS);
+                topologyBInit.get(10, TimeUnit.SECONDS);
+                executor.shutdownNow();
+            }
+        }
+    }
+
+    private static void setStaticPlugin(KnoxRangerPlugin plugin) throws 
Exception {
+        Field f = RangerPDPKnoxFilter.class.getDeclaredField("plugin");
+        f.setAccessible(true);
+        f.set(null, plugin);
+    }
+
     private String invokeGetInitParameter(RangerPDPKnoxFilter filter, 
FilterConfig cfg, String name) {
         try {
             Method m = 
RangerPDPKnoxFilter.class.getDeclaredMethod("getInitParameter", 
FilterConfig.class, String.class);

Reply via email to