This is an automated email from the ASF dual-hosted git repository. madhan pushed a commit to branch ranger-2.8 in repository https://gitbox.apache.org/repos/asf/ranger.git
commit 96ee94a7682db61faf4a615699cbab0320323d70 Author: Madhan Neethiraj <[email protected]> AuthorDate: Tue Mar 3 22:25:12 2026 -0800 RANGER-5505: update RangerEmbeddedAuthorizer to support caller provided audit handler (#864) (cherry picked from commit 4817d1b8eb1facd877a5298cd9eb5509894bcde8) --- .../authz/embedded/RangerAuthzAuditHandler.java | 13 +-- .../ranger/authz/embedded/RangerAuthzConfig.java | 9 +- .../authz/embedded/RangerEmbeddedAuthorizer.java | 97 ++++++++++++++-------- .../authz/embedded/TestEmbeddedAuthorizer.java | 71 ++++++++++++++-- .../authz/embedded/TestRangerAuthzConfig.java | 6 ++ .../src/test/resources/test_hive/tests_authz.json | 7 +- .../test/resources/test_s3/tests_multi_authz.json | 7 +- 7 files changed, 159 insertions(+), 51 deletions(-) diff --git a/authz-embedded/src/main/java/org/apache/ranger/authz/embedded/RangerAuthzAuditHandler.java b/authz-embedded/src/main/java/org/apache/ranger/authz/embedded/RangerAuthzAuditHandler.java index a16c5ede6..f9eab585a 100644 --- a/authz-embedded/src/main/java/org/apache/ranger/authz/embedded/RangerAuthzAuditHandler.java +++ b/authz-embedded/src/main/java/org/apache/ranger/authz/embedded/RangerAuthzAuditHandler.java @@ -22,20 +22,19 @@ import org.apache.ranger.audit.model.AuthzAuditEvent; import org.apache.ranger.plugin.audit.RangerDefaultAuditHandler; import org.apache.ranger.plugin.policyengine.RangerAccessResult; -import org.apache.ranger.plugin.service.RangerBasePlugin; import java.util.ArrayList; import java.util.Collection; public class RangerAuthzAuditHandler extends RangerDefaultAuditHandler implements AutoCloseable { - private final RangerBasePlugin plugin; + private final String appType; private final Collection<AuthzAuditEvent> auditEvents = new ArrayList<>(); private boolean deniedExists; - public RangerAuthzAuditHandler(RangerBasePlugin plugin) { + public RangerAuthzAuditHandler(String appType) { super(); - this.plugin = plugin; + this.appType = appType; } @Override @@ -44,7 +43,7 @@ public void processResult(RangerAccessResult result) { AuthzAuditEvent auditEvent = getAuthzEvents(result); if (auditEvent != null) { - auditEvent.setAgentId(plugin.getAppId()); + auditEvent.setAgentId(appType); if (result.getIsAccessDetermined() && !result.getIsAllowed()) { deniedExists = true; @@ -66,4 +65,8 @@ public void processResults(Collection<RangerAccessResult> results) { public void close() { auditEvents.forEach(super::logAuthzAudit); } + + protected Collection<AuthzAuditEvent> getAuditEvents() { + return auditEvents; + } } diff --git a/authz-embedded/src/main/java/org/apache/ranger/authz/embedded/RangerAuthzConfig.java b/authz-embedded/src/main/java/org/apache/ranger/authz/embedded/RangerAuthzConfig.java index 71ba854a8..39271dbc8 100644 --- a/authz-embedded/src/main/java/org/apache/ranger/authz/embedded/RangerAuthzConfig.java +++ b/authz-embedded/src/main/java/org/apache/ranger/authz/embedded/RangerAuthzConfig.java @@ -24,7 +24,8 @@ import java.util.Properties; public class RangerAuthzConfig { - public static final String PROP_PREFIX_INIT_SERVICES = "ranger.authz.init.services"; + public static final String PROP_APP_TYPE = "ranger.authz.app.type"; + public static final String PROP_INIT_SERVICES = "ranger.authz.init.services"; public static final String PROP_PREFIX_DEFAULT = "ranger.authz.default."; public static final String PROP_PREFIX_AUDIT = "ranger.authz.audit."; public static final String PROP_PREFIX_SERVICE = "ranger.authz.service."; @@ -37,7 +38,7 @@ public RangerAuthzConfig(Properties properties) { } public String[] getInitServices() { - String initServices = properties.getProperty(PROP_PREFIX_INIT_SERVICES); + String initServices = properties.getProperty(PROP_INIT_SERVICES); if (StringUtils.isBlank(initServices)) { return new String[0]; @@ -46,6 +47,10 @@ public String[] getInitServices() { return initServices.split(","); } + public String getAppType() { + return properties.getProperty(PROP_APP_TYPE); + } + public Properties getAuditProperties() { Properties ret = new Properties(); diff --git a/authz-embedded/src/main/java/org/apache/ranger/authz/embedded/RangerEmbeddedAuthorizer.java b/authz-embedded/src/main/java/org/apache/ranger/authz/embedded/RangerEmbeddedAuthorizer.java index d76d04a46..8d77570df 100644 --- a/authz-embedded/src/main/java/org/apache/ranger/authz/embedded/RangerEmbeddedAuthorizer.java +++ b/authz-embedded/src/main/java/org/apache/ranger/authz/embedded/RangerEmbeddedAuthorizer.java @@ -48,17 +48,21 @@ public class RangerEmbeddedAuthorizer extends RangerAuthorizer { private static final Logger LOG = LoggerFactory.getLogger(RangerEmbeddedAuthorizer.class); private final RangerAuthzConfig config; + private final String appType; private final Map<String, RangerAuthzPlugin> plugins = new HashMap<>(); public RangerEmbeddedAuthorizer(Properties properties) { super(properties); - this.config = new RangerAuthzConfig(properties); + this.config = new RangerAuthzConfig(properties); + this.appType = config.getAppType(); } @Override public void init() throws RangerAuthzException { - AuditProviderFactory.getInstance().init(config.getAuditProperties(), "ranger-authz"); + String appType = StringUtils.isNotBlank(this.appType) ? this.appType : "ranger-authz"; + + AuditProviderFactory.getInstance().init(config.getAuditProperties(), appType); String[] initServices = config.getInitServices(); @@ -83,8 +87,9 @@ public RangerAuthzResult authorize(RangerAuthzRequest request) throws RangerAuth validateRequest(request); RangerAuthzPlugin plugin = getOrCreatePlugin(request.getContext().getServiceName(), request.getContext().getServiceType()); + String appType = StringUtils.isNotBlank(this.appType) ? this.appType : plugin.getPlugin().getAppId(); - try (RangerAuthzAuditHandler auditHandler = new RangerAuthzAuditHandler(plugin.getPlugin())) { + try (RangerAuthzAuditHandler auditHandler = new RangerAuthzAuditHandler(appType)) { return authorize(request, plugin, auditHandler); } } @@ -93,45 +98,28 @@ public RangerAuthzResult authorize(RangerAuthzRequest request) throws RangerAuth public RangerMultiAuthzResult authorize(RangerMultiAuthzRequest request) throws RangerAuthzException { validateRequest(request); - RangerAuthzPlugin plugin = getOrCreatePlugin(request.getContext().getServiceName(), request.getContext().getServiceType()); - RangerMultiAuthzResult result = new RangerMultiAuthzResult(request.getRequestId()); + RangerAuthzPlugin plugin = getOrCreatePlugin(request.getContext().getServiceName(), request.getContext().getServiceType()); + String appType = StringUtils.isNotBlank(this.appType) ? this.appType : plugin.getPlugin().getAppId(); - if (request.getAccesses() != null) { - int allowedCount = 0; - int deniedCount = 0; - int notDeterminedCount = 0; + try (RangerAuthzAuditHandler auditHandler = new RangerAuthzAuditHandler(appType)) { + return authorize(request, plugin, auditHandler); + } + } - result.setAccesses(new ArrayList<>(request.getAccesses().size())); + public RangerAuthzResult authorize(RangerAuthzRequest request, RangerAuthzAuditHandler auditHandler) throws RangerAuthzException { + validateRequest(request); - try (RangerAuthzAuditHandler auditHandler = new RangerAuthzAuditHandler(plugin.getPlugin())) { - for (RangerAccessInfo accessInfo : request.getAccesses()) { - RangerAuthzRequest authzRequest = new RangerAuthzRequest(null, request.getUser(), accessInfo, request.getContext()); - RangerAuthzResult authzResult = authorize(authzRequest, plugin, auditHandler); + RangerAuthzPlugin plugin = getOrCreatePlugin(request.getContext().getServiceName(), request.getContext().getServiceType()); - if (authzResult.getDecision() == AccessDecision.ALLOW) { - allowedCount++; - } else if (authzResult.getDecision() == AccessDecision.DENY) { - deniedCount++; - } else if (authzResult.getDecision() == AccessDecision.NOT_DETERMINED) { - notDeterminedCount++; - } + return authorize(request, plugin, auditHandler); + } - result.getAccesses().add(authzResult); - } - } + public RangerMultiAuthzResult authorize(RangerMultiAuthzRequest request, RangerAuthzAuditHandler auditHandler) throws RangerAuthzException { + validateRequest(request); - if (allowedCount == request.getAccesses().size()) { - result.setDecision(AccessDecision.ALLOW); - } else if (deniedCount == request.getAccesses().size()) { - result.setDecision(AccessDecision.DENY); - } else if (notDeterminedCount == request.getAccesses().size()) { - result.setDecision(AccessDecision.NOT_DETERMINED); - } else { - result.setDecision(AccessDecision.PARTIAL); - } - } + RangerAuthzPlugin plugin = getOrCreatePlugin(request.getContext().getServiceName(), request.getContext().getServiceType()); - return result; + return authorize(request, plugin, auditHandler); } @Override @@ -179,6 +167,45 @@ private RangerAuthzResult authorize(RangerAuthzRequest request, RangerAuthzPlugi return plugin.authorize(request, auditHandler); } + private RangerMultiAuthzResult authorize(RangerMultiAuthzRequest request, RangerAuthzPlugin plugin, RangerAuthzAuditHandler auditHandler) throws RangerAuthzException { + RangerMultiAuthzResult result = new RangerMultiAuthzResult(request.getRequestId()); + + if (request.getAccesses() != null) { + int allowedCount = 0; + int deniedCount = 0; + int notDeterminedCount = 0; + + result.setAccesses(new ArrayList<>(request.getAccesses().size())); + + for (RangerAccessInfo accessInfo : request.getAccesses()) { + RangerAuthzRequest authzRequest = new RangerAuthzRequest(null, request.getUser(), accessInfo, request.getContext()); + RangerAuthzResult authzResult = authorize(authzRequest, plugin, auditHandler); + + if (authzResult.getDecision() == AccessDecision.ALLOW) { + allowedCount++; + } else if (authzResult.getDecision() == AccessDecision.DENY) { + deniedCount++; + } else if (authzResult.getDecision() == AccessDecision.NOT_DETERMINED) { + notDeterminedCount++; + } + + result.getAccesses().add(authzResult); + } + + if (allowedCount == request.getAccesses().size()) { + result.setDecision(AccessDecision.ALLOW); + } else if (deniedCount == request.getAccesses().size()) { + result.setDecision(AccessDecision.DENY); + } else if (notDeterminedCount == request.getAccesses().size()) { + result.setDecision(AccessDecision.NOT_DETERMINED); + } else { + result.setDecision(AccessDecision.PARTIAL); + } + } + + return result; + } + private RangerAuthzPlugin getOrCreatePlugin(String serviceName, String serviceType) throws RangerAuthzException { RangerAuthzPlugin ret = plugins.get(serviceName); diff --git a/authz-embedded/src/test/java/org/apache/ranger/authz/embedded/TestEmbeddedAuthorizer.java b/authz-embedded/src/test/java/org/apache/ranger/authz/embedded/TestEmbeddedAuthorizer.java index 5636ae3c2..91b1db792 100644 --- a/authz-embedded/src/test/java/org/apache/ranger/authz/embedded/TestEmbeddedAuthorizer.java +++ b/authz-embedded/src/test/java/org/apache/ranger/authz/embedded/TestEmbeddedAuthorizer.java @@ -22,6 +22,7 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.ranger.audit.model.AuthzAuditEvent; import org.apache.ranger.authz.model.RangerAccessContext; import org.apache.ranger.authz.model.RangerAuthzRequest; import org.apache.ranger.authz.model.RangerAuthzResult; @@ -32,6 +33,7 @@ import org.junit.jupiter.api.Test; import java.io.InputStream; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Properties; @@ -111,11 +113,21 @@ private void runAuthzTest(String testName) throws Exception { continue; } - RangerAuthzRequest request = test.request; + RangerAuthzRequest request = test.request; RangerAuthzResult expected = test.result; - RangerAuthzResult result = authorizer.authorize(request); - assertEquals(expected, result); + if (test.audits == null) { + RangerAuthzResult result = authorizer.authorize(request); + + assertEquals(expected, result); + } else { + try (TestAuthzAuditHandler auditHandler = new TestAuthzAuditHandler("test")) { + RangerAuthzResult result = authorizer.authorize(request, auditHandler); + + assertEquals(expected, result); + auditEquals(test.audits, auditHandler.getAuditEvents()); + } + } } } finally { if (authorizer != null) { @@ -142,9 +154,19 @@ private void runMultiAuthzTest(String testName) throws Exception { RangerMultiAuthzRequest request = test.request; RangerMultiAuthzResult expected = test.result; - RangerMultiAuthzResult result = authorizer.authorize(request); - assertEquals(expected, result); + if (test.audits == null) { + RangerMultiAuthzResult result = authorizer.authorize(request); + + assertEquals(expected, result); + } else { + try (TestAuthzAuditHandler auditHandler = new TestAuthzAuditHandler("test")) { + RangerMultiAuthzResult result = authorizer.authorize(request, auditHandler); + + assertEquals(expected, result); + auditEquals(test.audits, auditHandler.getAuditEvents()); + } + } } } finally { if (authorizer != null) { @@ -187,14 +209,39 @@ private List<TestResourcePermissionsData> loadTestResourcePermissionsData(String } } + private static void auditEquals(List<AuthzAuditEvent> expected, Collection<AuthzAuditEvent> actual) { + assertEquals(expected.size(), actual.size()); + + AuthzAuditEvent[] actualAudits = actual.toArray(new AuthzAuditEvent[0]); + + for (int i = 0; i < expected.size(); i++) { + auditEquals(expected.get(i), actualAudits[i]); + } + } + + private static void auditEquals(AuthzAuditEvent expected, AuthzAuditEvent actual) { + assertEquals(expected.getUser(), actual.getUser()); + assertEquals(expected.getAccessType(), actual.getAccessType()); + assertEquals(expected.getAction(), actual.getAction()); + assertEquals(expected.getRepositoryName(), actual.getRepositoryName()); + assertEquals(expected.getResourceType(), actual.getResourceType()); + assertEquals(expected.getResourcePath(), actual.getResourcePath()); + assertEquals(expected.getAccessResult(), actual.getAccessResult()); + assertEquals(expected.getPolicyId(), actual.getPolicyId()); + assertEquals(expected.getAgentId(), actual.getAgentId()); + assertEquals(expected.getAclEnforcer(), actual.getAclEnforcer()); + } + private static class TestAuthzData { - public RangerAuthzRequest request; - public RangerAuthzResult result; + public RangerAuthzRequest request; + public RangerAuthzResult result; + public List<AuthzAuditEvent> audits; } private static class TestMultiAuthzData { public RangerMultiAuthzRequest request; public RangerMultiAuthzResult result; + public List<AuthzAuditEvent> audits; } private static class TestResourcePermissionsData { @@ -202,4 +249,14 @@ private static class TestResourcePermissionsData { public RangerAccessContext context; public RangerResourcePermissions permissions; } + + private static class TestAuthzAuditHandler extends RangerAuthzAuditHandler { + public TestAuthzAuditHandler(String appType) { + super(appType); + } + + public Collection<AuthzAuditEvent> getAuditEvents() { + return super.getAuditEvents(); + } + } } diff --git a/authz-embedded/src/test/java/org/apache/ranger/authz/embedded/TestRangerAuthzConfig.java b/authz-embedded/src/test/java/org/apache/ranger/authz/embedded/TestRangerAuthzConfig.java index fd9c77a1b..da84da4b6 100644 --- a/authz-embedded/src/test/java/org/apache/ranger/authz/embedded/TestRangerAuthzConfig.java +++ b/authz-embedded/src/test/java/org/apache/ranger/authz/embedded/TestRangerAuthzConfig.java @@ -24,6 +24,7 @@ import java.util.Properties; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; public class TestRangerAuthzConfig { @@ -35,6 +36,7 @@ public void testEmptyConfig() { assertTrue(config.getServiceProperties("prod_hive", "hive").isEmpty()); assertTrue(config.getServiceProperties("dev_hdfs", "hdfs").isEmpty()); assertTrue(config.getAuditProperties().isEmpty()); + assertNull(config.getAppType()); } @Test @@ -44,6 +46,7 @@ public void testDefaultConfigs() { validateDevHiveProperties(config.getServiceProperties("dev_hive", "hive")); validateProdHiveProperties(config.getServiceProperties("prod_hive", "hive")); validateDevHdfsProperties(config.getServiceProperties("dev_hdfs", "hdfs")); + assertEquals("ranger-pdp", config.getAppType()); } @Test @@ -75,6 +78,7 @@ public void testAllAuthzConfigs() { validateDevHdfsProperties(config.getServiceProperties("dev_hdfs", "hdfs")); validateAuditConfigV2(config.getAuditProperties()); validateAuditConfigV3(config.getAuditProperties()); + assertEquals("ranger-pdp", config.getAppType()); } private void validateDevHiveProperties(Properties prop) { @@ -156,6 +160,8 @@ private void validateAuditConfigV3(Properties props) { private static Properties createDefaultProperties() { Properties props = new Properties(); + props.setProperty("ranger.authz.app.type", "ranger-pdp"); + props.setProperty("ranger.authz.default.policy.source.impl", "org.apache.ranger.admin.client.RangerAdminRESTClient"); props.setProperty("ranger.authz.default.policy.rest.url", "http://localhost:6080"); props.setProperty("ranger.authz.default.policy.rest.ssl.config.file", "/etc/hive/conf/ranger-policymgr-ssl.xml"); diff --git a/authz-embedded/src/test/resources/test_hive/tests_authz.json b/authz-embedded/src/test/resources/test_hive/tests_authz.json index 765ffe080..42d9ad007 100644 --- a/authz-embedded/src/test/resources/test_hive/tests_authz.json +++ b/authz-embedded/src/test/resources/test_hive/tests_authz.json @@ -15,7 +15,12 @@ "permissions": { "select": { "permission": "select", "access": { "decision": "ALLOW", "policy": { "id": 1, "version": 1 } } } } - } + }, + "audits": [ + { + "reqUser": "tbl1-r-user", "access": "select", "action": "select", "repo": "dev_hive", "resType": "table", "resource": "mydb/tbl1", "result": 1, "policy": 1, "agent": "test", "enforcer": "ranger-acl" + } + ] }, { "request": { diff --git a/authz-embedded/src/test/resources/test_s3/tests_multi_authz.json b/authz-embedded/src/test/resources/test_s3/tests_multi_authz.json index 407aa733a..f0f9f5bef 100644 --- a/authz-embedded/src/test/resources/test_s3/tests_multi_authz.json +++ b/authz-embedded/src/test/resources/test_s3/tests_multi_authz.json @@ -22,7 +22,12 @@ } } ] - } + }, + "audits": [ + { + "reqUser": "path1-r-user", "access": "read", "action": "read", "repo": "dev_s3", "resType": "path", "resource": "mybucket/data/path1/file.orc", "result": 1, "policy": 1, "agent": "test", "enforcer": "ranger-acl" + } + ] }, { "request": {
