This is an automated email from the ASF dual-hosted git repository.
vyommani pushed a commit to branch ranger-2.10
in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/ranger-2.10 by this push:
new 81e98cbbe RANGER-5799: Validate class assignability before
instantiating configured service-def classes (#1323)
81e98cbbe is described below
commit 81e98cbbee434ae0aeaf76755e29a654baf03445
Author: Vyom Mani Tiwari <[email protected]>
AuthorDate: Wed Oct 21 19:53:51 2026 +0530
RANGER-5799: Validate class assignability before instantiating configured
service-def classes (#1323)
---
.../RangerAbstractGeolocationProvider.java | 12 +++-
.../plugin/contextenricher/RangerTagEnricher.java | 13 +++-
.../contextenricher/RangerUserStoreEnricher.java | 13 +++-
.../policyengine/RangerPolicyRepository.java | 10 ++-
.../TestRangerPolicyRepositoryContextEnricher.java | 73 ++++++++++++++++++++++
.../java/org/apache/ranger/biz/ServiceMgr.java | 5 +-
.../java/org/apache/ranger/biz/TestServiceMgr.java | 6 +-
7 files changed, 119 insertions(+), 13 deletions(-)
diff --git
a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerAbstractGeolocationProvider.java
b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerAbstractGeolocationProvider.java
index 1dc76edbd..f5ba9b2fa 100644
---
a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerAbstractGeolocationProvider.java
+++
b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerAbstractGeolocationProvider.java
@@ -27,6 +27,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.lang.reflect.InvocationTargetException;
import java.util.Map;
public abstract class RangerAbstractGeolocationProvider extends
RangerAbstractContextEnricher {
@@ -62,10 +63,15 @@ public void init() {
if (context != null) {
try {
// Get the class definition and ensure it is of
the correct type
+ Class<?> cls = Class.forName(geoSourceLoader,
false, RangerAbstractGeolocationProvider.class.getClassLoader());
+ if
(!GeolocationStore.class.isAssignableFrom(cls)) {
+ throw new ClassCastException("class " +
geoSourceLoader + " is not assignable to " + GeolocationStore.class.getName());
+ }
+
@SuppressWarnings("unchecked")
- Class<GeolocationStore> geoSourceLoaderClass =
(Class<GeolocationStore>) Class.forName(geoSourceLoader);
+ Class<GeolocationStore> geoSourceLoaderClass =
(Class<GeolocationStore>) cls;
// instantiate the loader class and initialize
it with options
- geoStore = geoSourceLoaderClass.newInstance();
+ geoStore =
geoSourceLoaderClass.getDeclaredConstructor().newInstance();
}
catch (ClassNotFoundException exception) {
LOG.error("RangerAbstractGeolocationProvider.init() - Class " + geoSourceLoader
+ " not found, exception=" + exception);
@@ -76,7 +82,7 @@ public void init() {
catch (IllegalAccessException exception) {
LOG.error("RangerAbstractGeolocationProvider.init() - Class " + geoSourceLoader
+ " could not be instantiated, exception=" + exception);
}
- catch (InstantiationException exception) {
+ catch (InstantiationException | NoSuchMethodException |
InvocationTargetException exception) {
LOG.error("RangerAbstractGeolocationProvider.init() - Class " + geoSourceLoader
+ " could not be instantiated, exception=" + exception);
}
diff --git
a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java
b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java
index 779ee8a4b..3e99b2f15 100644
---
a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java
+++
b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java
@@ -58,6 +58,7 @@
import java.io.FileWriter;
import java.io.Reader;
import java.io.Writer;
+import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -116,10 +117,16 @@ public void init() {
if (StringUtils.isNotBlank(tagRetrieverClassName)) {
try {
+ Class<?> cls =
Class.forName(tagRetrieverClassName, false,
RangerTagEnricher.class.getClassLoader());
+
+ if
(!RangerTagRetriever.class.isAssignableFrom(cls)) {
+ throw new ClassCastException("class " +
tagRetrieverClassName + " is not assignable to " +
RangerTagRetriever.class.getName());
+ }
+
@SuppressWarnings("unchecked")
- Class<RangerTagRetriever> tagRetriverClass =
(Class<RangerTagRetriever>) Class.forName(tagRetrieverClassName);
+ Class<RangerTagRetriever> tagRetriverClass =
(Class<RangerTagRetriever>) cls;
- tagRetriever = tagRetriverClass.newInstance();
+ tagRetriever =
tagRetriverClass.getDeclaredConstructor().newInstance();
} catch (ClassNotFoundException exception) {
LOG.error("Class " + tagRetrieverClassName + "
not found, exception=" + exception);
@@ -127,7 +134,7 @@ public void init() {
LOG.error("Class " + tagRetrieverClassName + "
is not a type of RangerTagRetriever, exception=" + exception);
} catch (IllegalAccessException exception) {
LOG.error("Class " + tagRetrieverClassName + "
illegally accessed, exception=" + exception);
- } catch (InstantiationException exception) {
+ } catch (InstantiationException | NoSuchMethodException
| InvocationTargetException exception) {
LOG.error("Class " + tagRetrieverClassName + "
could not be instantiated, exception=" + exception);
}
diff --git
a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerUserStoreEnricher.java
b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerUserStoreEnricher.java
index f2845e8d4..24d646395 100644
---
a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerUserStoreEnricher.java
+++
b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerUserStoreEnricher.java
@@ -28,6 +28,7 @@
import org.apache.ranger.plugin.util.RangerPerfTracer;
import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
import java.io.File;
+import java.lang.reflect.InvocationTargetException;
import java.util.Timer;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
@@ -66,10 +67,16 @@ public void init() {
if (StringUtils.isNotBlank(userStoreRetrieverClassName)) {
try {
+ Class<?> cls = Class.forName(userStoreRetrieverClassName,
false, RangerUserStoreEnricher.class.getClassLoader());
+
+ if (!RangerUserStoreRetriever.class.isAssignableFrom(cls)) {
+ throw new ClassCastException("class " +
userStoreRetrieverClassName + " is not assignable to " +
RangerUserStoreRetriever.class.getName());
+ }
+
@SuppressWarnings("unchecked")
- Class<RangerUserStoreRetriever> userStoreRetriverClass =
(Class<RangerUserStoreRetriever>) Class.forName(userStoreRetrieverClassName);
+ Class<RangerUserStoreRetriever> userStoreRetriverClass =
(Class<RangerUserStoreRetriever>) cls;
- userStoreRetriever = userStoreRetriverClass.newInstance();
+ userStoreRetriever =
userStoreRetriverClass.getDeclaredConstructor().newInstance();
} catch (ClassNotFoundException exception) {
LOG.error("Class " + userStoreRetrieverClassName + " not
found, exception=" + exception);
@@ -77,7 +84,7 @@ public void init() {
LOG.error("Class " + userStoreRetrieverClassName + " is not a
type of RangerUserStoreRetriever, exception=" + exception);
} catch (IllegalAccessException exception) {
LOG.error("Class " + userStoreRetrieverClassName + " illegally
accessed, exception=" + exception);
- } catch (InstantiationException exception) {
+ } catch (InstantiationException | NoSuchMethodException |
InvocationTargetException exception) {
LOG.error("Class " + userStoreRetrieverClassName + " could not
be instantiated, exception=" + exception);
}
diff --git
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java
index 7bb4611bd..317d206b6 100644
---
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java
+++
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java
@@ -1052,10 +1052,16 @@ private RangerContextEnricher
buildContextEnricher(RangerServiceDef.RangerContex
if (!StringUtils.isEmpty(clsName)) {
try {
+ Class<?> cls = Class.forName(clsName, false,
RangerPolicyRepository.class.getClassLoader());
+
+ if (!RangerContextEnricher.class.isAssignableFrom(cls)) {
+ throw new ClassCastException("class " + clsName + " is
not assignable to " + RangerContextEnricher.class.getName());
+ }
+
@SuppressWarnings("unchecked")
- Class<RangerContextEnricher> enricherClass =
(Class<RangerContextEnricher>) Class.forName(clsName);
+ Class<? extends RangerContextEnricher> enricherClass =
(Class<? extends RangerContextEnricher>) cls;
- ret = enricherClass.newInstance();
+ ret = enricherClass.getDeclaredConstructor().newInstance();
} catch (Exception excp) {
LOG.error("failed to instantiate context enricher '" +
clsName + "' for '" + name + "'", excp);
}
diff --git
a/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestRangerPolicyRepositoryContextEnricher.java
b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestRangerPolicyRepositoryContextEnricher.java
new file mode 100644
index 000000000..c7dc86764
--- /dev/null
+++
b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestRangerPolicyRepositoryContextEnricher.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ranger.plugin.policyengine;
+
+import org.apache.ranger.authorization.hadoop.config.RangerPluginConfig;
+import org.apache.ranger.plugin.contextenricher.RangerContextEnricher;
+import org.apache.ranger.plugin.contextenricher.RangerTagEnricher;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import
org.apache.ranger.plugin.model.RangerServiceDef.RangerContextEnricherDef;
+import org.apache.ranger.plugin.util.ServicePolicies;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.Collections;
+import java.util.List;
+
+public class TestRangerPolicyRepositoryContextEnricher {
+ private static RangerPolicyRepository buildRepository(String
enricherClassName) {
+ RangerServiceDef serviceDef = new RangerServiceDef();
+
+ serviceDef.setName("test-enricher-svc");
+ serviceDef.setContextEnrichers(Collections.singletonList(
+ new RangerContextEnricherDef(1L, "testEnricher",
enricherClassName, Collections.emptyMap())));
+
+ ServicePolicies servicePolicies = new ServicePolicies();
+
+ servicePolicies.setServiceName("test-enricher-svc-instance");
+ servicePolicies.setServiceDef(serviceDef);
+ servicePolicies.setPolicies(Collections.emptyList());
+
+ RangerPluginContext pluginContext = new RangerPluginContext(new
RangerPluginConfig("test-enricher-svc", "test-enricher-svc-instance",
"test-enricher-svc", "cl1", "on-prem", null));
+
+ return new RangerPolicyRepository(servicePolicies, pluginContext);
+ }
+
+ @Test
+ public void testMaliciousEnricherClassIsNotInstantiated() {
+ // java.lang.Thread has a public no-arg constructor and is on the
classpath,
+ // but does not implement RangerContextEnricher.
+ RangerPolicyRepository repository =
buildRepository(Thread.class.getName());
+
+ List<RangerContextEnricher> enrichers =
repository.getContextEnrichers();
+
+ Assertions.assertTrue(enrichers == null || enrichers.isEmpty(),
+ "a class not assignable to RangerContextEnricher must not be
instantiated as one");
+ }
+
+ @Test
+ public void testLegitimateEnricherClassIsStillInstantiated() {
+ RangerPolicyRepository repository =
buildRepository(RangerTagEnricher.class.getName());
+
+ List<RangerContextEnricher> enrichers =
repository.getContextEnrichers();
+
+ Assertions.assertNotNull(enrichers);
+ Assertions.assertEquals(1, enrichers.size());
+ Assertions.assertEquals(RangerTagEnricher.class,
enrichers.get(0).getClass());
+ }
+}
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/ServiceMgr.java
b/security-admin/src/main/java/org/apache/ranger/biz/ServiceMgr.java
index 6202d0539..3c283f7f2 100755
--- a/security-admin/src/main/java/org/apache/ranger/biz/ServiceMgr.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/ServiceMgr.java
@@ -848,7 +848,10 @@ private Class<? extends RangerBaseService>
getClassForServiceType(RangerServiceD
} else {
URL[]
pluginFiles = getPluginFilesForServiceType(serviceType);
URLClassLoader
clsLoader = new URLClassLoader(pluginFiles,
Thread.currentThread().getContextClassLoader());
- Class<?>
cls = Class.forName(clsName, true, clsLoader);
+ Class<?>
cls = Class.forName(clsName, false, clsLoader);
+ if
(!RangerBaseService.class.isAssignableFrom(cls)) {
+ throw
new ClassCastException("class " + clsName + " is not assignable to " +
RangerBaseService.class.getName());
+ }
ret = (Class<?
extends RangerBaseService>) cls;
}
diff --git
a/security-admin/src/test/java/org/apache/ranger/biz/TestServiceMgr.java
b/security-admin/src/test/java/org/apache/ranger/biz/TestServiceMgr.java
index e9669ffba..b0f075076 100644
--- a/security-admin/src/test/java/org/apache/ranger/biz/TestServiceMgr.java
+++ b/security-admin/src/test/java/org/apache/ranger/biz/TestServiceMgr.java
@@ -314,7 +314,11 @@ public void
test11_getRangerServiceByService_rejectsImplClassNotAssignableToRang
def.setImplClass(Thread.class.getName());
when(store.getServiceDefByName("evil")).thenReturn(def);
- Assertions.assertThrows(ClassCastException.class, () ->
mgr.getRangerServiceByService(svc, store));
+ RangerBaseService built = mgr.getRangerServiceByService(svc, store);
+
+ Assertions.assertNotNull(built);
+ Assertions.assertEquals(RangerDefaultService.class, built.getClass());
+ Assertions.assertEquals("s", built.getServiceName());
}
@Test