diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestRangerPluginCapability.java b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestRangerPluginCapability.java index d64a1ed7aa..3c3c01fb72 100644 --- a/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestRangerPluginCapability.java +++ b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestRangerPluginCapability.java @@ -25,25 +25,52 @@ import org.apache.commons.lang3.StringUtils; import org.apache.ranger.authorization.utils.JsonUtils; import org.apache.ranger.plugin.util.RangerPluginCapability; -import org.junit.Test; +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.junit.jupiter.MockitoExtension; import java.io.InputStream; import java.io.InputStreamReader; import java.util.Arrays; import java.util.List; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +/** +* @generated by Cursor +* @description +*/ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) public class TestRangerPluginCapability { private static final Gson gsonBuilder = new GsonBuilder().setDateFormat("yyyyMMdd-HH:mm:ss.SSS-Z").setPrettyPrinting().create(); @Test - public void testRangerPluginCapabilities() { + public void test01_RangerPluginCapabilitiesFromResource() { String[] tests = {"/policyengine/plugin/test_plugin_capability.json"}; runTestsFromResourceFiles(tests); } + @Test + public void test02_toStringAndUnknownBit() { + // Construct a capability with a bit beyond defined enum to trigger "unknown" + long beyond = 1L << 62; // well beyond current enum size + RangerPluginCapability me = new RangerPluginCapability(beyond); + RangerPluginCapability other = new RangerPluginCapability(); + + List diff = me.compare(other); + assertTrue(diff.contains("unknown")); + + String json = me.toString(); + assertNotNull(json); + // toString returns JSON array + assertTrue(json.startsWith("[")); + } + private void runTestsFromResourceFiles(String[] resourceNames) { for (String resourceName : resourceNames) { InputStream inStream = this.getClass().getResourceAsStream(resourceName); @@ -69,7 +96,7 @@ private void runTests(InputStreamReader reader, String fileName) { List difference = me.compare(other); - assertTrue(fileName + "-" + testCase.name + "-" + Arrays.toString(difference.toArray()), StringUtils.equals(JsonUtils.listToJson(difference), JsonUtils.listToJson(testCase.difference))); + assertTrue(StringUtils.equals(JsonUtils.listToJson(difference), JsonUtils.listToJson(testCase.difference)), fileName + "-" + testCase.name + "-" + Arrays.toString(difference.toArray())); } } diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/service/TestRangerAuthContext.java b/agents-common/src/test/java/org/apache/ranger/plugin/service/TestRangerAuthContext.java new file mode 100644 index 0000000000..ecfa4352db --- /dev/null +++ b/agents-common/src/test/java/org/apache/ranger/plugin/service/TestRangerAuthContext.java @@ -0,0 +1,136 @@ +/* + * 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.service; + +import org.apache.ranger.plugin.model.RangerRole; +import org.apache.ranger.plugin.policyengine.RangerPolicyEngine; +import org.apache.ranger.plugin.util.RangerCommonConstants; +import org.apache.ranger.plugin.util.RangerRoles; +import org.apache.ranger.plugin.util.RangerUserStore; +import org.apache.ranger.ugsyncutil.transform.Mapper; +import org.apache.ranger.ugsyncutil.util.UgsyncCommonConstants; +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.junit.jupiter.MockitoExtension; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** +* @generated by Cursor +* @description +*/ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +public class TestRangerAuthContext { + public static class NoopMapper implements Mapper { + @Override + public void init(String baseProperty, List regexPatterns, String regexSeparator) { + } + + @Override + public String transform(String attrValue) { + return attrValue; + } + } + + @Test + public void test1_RoleAggregationForUserAndGroups() { + RangerRole roleA = new RangerRole(); + roleA.setName("roleA"); + roleA.setUsers(Collections.singletonList(new RangerRole.RoleMember("u1", false))); + + RangerRole roleB = new RangerRole(); + roleB.setName("roleB"); + roleB.setGroups(Collections.singletonList(new RangerRole.RoleMember("g1", false))); + + RangerRole roleC = new RangerRole(); + roleC.setName("roleC"); + roleC.setGroups(Collections.singletonList(new RangerRole.RoleMember(RangerPolicyEngine.GROUP_PUBLIC, false))); + + Set rset = new HashSet<>(); + rset.add(roleA); + rset.add(roleB); + rset.add(roleC); + + RangerRoles roles = new RangerRoles(); + roles.setRoleVersion(5L); + roles.setRangerRoles(rset); + + RangerAuthContext ctx = new RangerAuthContext(new HashMap<>(), null, roles, new RangerUserStore()); + + Set rolesOut = ctx.getRolesForUserAndGroups("u1", Collections.singleton("g1")); + assertTrue(rolesOut.contains("roleA")); + assertTrue(rolesOut.contains("roleB")); + assertTrue(rolesOut.contains("roleC")); + assertEquals(5L, ctx.getRoleVersion()); + } + + @Test + public void test2_OnServiceConfigsUpdateSetsTransformers() { + RangerAuthContext ctx = new RangerAuthContext(new HashMap<>(), null, new RangerRoles(), new RangerUserStore()); + Map cfg = new HashMap<>(); + cfg.put(RangerCommonConstants.PLUGINS_CONF_USERNAME_CASE_CONVERSION_PARAM, "lower"); + cfg.put(RangerCommonConstants.PLUGINS_CONF_GROUPNAME_CASE_CONVERSION_PARAM, "upper"); + ctx.onServiceConfigsUpdate(cfg); + assertNotNull(ctx.getUserNameCaseConversion()); + assertNotNull(ctx.getGroupNameCaseConversion()); + assertEquals(UgsyncCommonConstants.CaseConversion.TO_LOWER, ctx.getUserNameCaseConversion()); + assertEquals(UgsyncCommonConstants.CaseConversion.TO_UPPER, ctx.getGroupNameCaseConversion()); + } + + @Test + public void test3_OnServiceConfigsUpdateRegexPatternsAggregation() { + RangerAuthContext ctx = new RangerAuthContext(new HashMap<>(), null, new RangerRoles(), new RangerUserStore()); + Map cfg = new HashMap<>(); + cfg.put(RangerCommonConstants.PLUGINS_CONF_MAPPING_USERNAME_HANDLER, this.getClass().getName() + "$NoopMapper"); + cfg.put(RangerCommonConstants.PLUGINS_CONF_MAPPING_USERNAME, "^(.+)@example\\.com$"); + cfg.put(RangerCommonConstants.PLUGINS_CONF_MAPPING_USERNAME + ".1", "^user_(.+)$"); + cfg.put(RangerCommonConstants.PLUGINS_CONF_MAPPING_SEPARATOR, ":"); + cfg.put(RangerCommonConstants.PLUGINS_CONF_MAPPING_GROUPNAME_HANDLER, this.getClass().getName() + "$NoopMapper"); + cfg.put(RangerCommonConstants.PLUGINS_CONF_MAPPING_GROUPNAME, "^grp_(.+)$"); + cfg.put(RangerCommonConstants.PLUGINS_CONF_MAPPING_GROUPNAME + ".1", "^team_(.+)$"); + cfg.put(RangerCommonConstants.PLUGINS_CONF_MAPPING_SEPARATOR, ":"); + + ctx.onServiceConfigsUpdate(cfg); + + // handlers should be set + assertNotNull(ctx.getUserNameTransformer()); + assertNotNull(ctx.getGroupNameTransformer()); + } + + @Test + public void test4_UserStoreVersionPassThrough() { + RangerUserStore us = new RangerUserStore(); + us.setUserStoreVersion(42L); + RangerAuthContext ctx = new RangerAuthContext(new HashMap<>(), null, new RangerRoles(), us); + assertEquals(42L, ctx.getUserStoreVersion()); + } +} diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/service/TestRangerBasePlugin.java b/agents-common/src/test/java/org/apache/ranger/plugin/service/TestRangerBasePlugin.java index fef1b828bf..674a870e20 100644 --- a/agents-common/src/test/java/org/apache/ranger/plugin/service/TestRangerBasePlugin.java +++ b/agents-common/src/test/java/org/apache/ranger/plugin/service/TestRangerBasePlugin.java @@ -26,17 +26,23 @@ import com.google.gson.JsonElement; import com.google.gson.JsonParseException; import org.apache.commons.lang3.StringUtils; +import org.apache.ranger.audit.provider.AuditHandler; import org.apache.ranger.authorization.hadoop.config.RangerPluginConfig; import org.apache.ranger.plugin.audit.RangerDefaultAuditHandler; +import org.apache.ranger.plugin.model.RangerPolicy; +import org.apache.ranger.plugin.model.RangerRole; import org.apache.ranger.plugin.model.RangerServiceDef; import org.apache.ranger.plugin.policyengine.RangerAccessRequest; import org.apache.ranger.plugin.policyengine.RangerAccessRequestImpl; import org.apache.ranger.plugin.policyengine.RangerAccessResource; import org.apache.ranger.plugin.policyengine.RangerAccessResourceImpl; import org.apache.ranger.plugin.policyengine.RangerAccessResult; +import org.apache.ranger.plugin.policyengine.RangerAccessResultProcessor; import org.apache.ranger.plugin.policyengine.RangerPolicyEngine; import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions; import org.apache.ranger.plugin.policyengine.RangerResourceACLs; +import org.apache.ranger.plugin.policyengine.RangerResourceACLs.AccessResult; +import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator; import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil; import org.apache.ranger.plugin.util.RangerAccessRequestUtil; import org.apache.ranger.plugin.util.RangerRoles; @@ -45,29 +51,47 @@ import org.apache.ranger.plugin.util.ServiceGdsInfo; import org.apache.ranger.plugin.util.ServicePolicies; import org.apache.ranger.plugin.util.ServiceTags; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +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.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Date; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +/** +* @generated by Cursor +* @description +*/ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) public class TestRangerBasePlugin { static Gson gsonBuilder; static RangerPolicyEngineOptions peOptions; - @BeforeClass + @BeforeAll public static void setUpBeforeClass() throws Exception { gsonBuilder = new GsonBuilder().setDateFormat("yyyyMMdd-HH:mm:ss.SSSZ") .setPrettyPrinting() @@ -84,10 +108,457 @@ public static void setUpBeforeClass() throws Exception { } @Test - public void testBasePluginHive() throws Exception { + public void test1_BasePluginHive() throws Exception { runTestsFromResourceFile("/plugin/test_base_plugin_hive.json"); } + @Test + public void test2_MergedResourceACLs() { + RangerResourceACLs base = new RangerResourceACLs(); + RangerResourceACLs chained = new RangerResourceACLs(); + + // craft simple ACL entries to verify merge logic does not throw and returns base reference + base.setUserAccessInfo("u1", "select", 1, null); + chained.setUserAccessInfo("u2", "select", 1, null); + base.getDatasets().add("d1"); + chained.getDatasets().add("d2"); + base.getProjects().add("p1"); + chained.getProjects().add("p2"); + + RangerResourceACLs merged = RangerBasePlugin.getMergedResourceACLs(base, chained); + assertNotNull(merged); + assertEquals(base, merged); + assertEquals(2, merged.getDatasets().size()); + assertEquals(2, merged.getProjects().size()); + assertNotNull(merged.getUserACLs().get("u1")); + } + + @Test + public void test3_CreateAdminClient_UsesCustomImplIfConfiguredElseFallsBack() { + RangerPolicyEngineOptions peOptionsLocal = new RangerPolicyEngineOptions(); + peOptionsLocal.disablePolicyRefresher = true; + peOptionsLocal.disableTagRetriever = true; + peOptionsLocal.disableUserStoreRetriever = true; + peOptionsLocal.disableGdsInfoRetriever = true; + + RangerPluginConfig cfg = new RangerPluginConfig("hbase", "svc", "app", null, null, peOptionsLocal); + + // Provide REST URL to avoid empty URLs list in REST client + cfg.set("ranger.plugin.hbase.policy.rest.url", "http://localhost:6080"); + + // invalid class first -> fallback to REST client + cfg.set("ranger.plugin.hbase.policy.source.impl", "com.example.DoesNotExist"); + assertNotNull(RangerBasePlugin.createAdminClient(cfg)); + + // set to a valid test implementation + cfg.set("ranger.plugin.hbase.policy.source.impl", "org.apache.ranger.plugin.policyengine.RangerAdminClientImpl"); + assertNotNull(RangerBasePlugin.createAdminClient(cfg)); + } + + @Test + public void test4_GetServiceDefIdWhenNull() { + RangerPolicyEngineOptions peOptionsLocal = new RangerPolicyEngineOptions(); + peOptionsLocal.disablePolicyRefresher = true; + RangerPluginConfig pluginConfig = new RangerPluginConfig("dummy", "svc", "app", null, null, peOptionsLocal); + RangerBasePlugin plugin = new RangerBasePlugin(pluginConfig); + // don't initialize policy engine; getServiceDef() returns null + assertEquals(-1, plugin.getServiceDefId()); + } + + @Test + public void test5_LogErrorMessageRateLimit() { + RangerPolicyEngineOptions opts = new RangerPolicyEngineOptions(); + opts.disablePolicyRefresher = true; + opts.disableTagRetriever = true; + opts.disableUserStoreRetriever = true; + opts.disableGdsInfoRetriever = true; + RangerPluginConfig cfg = new RangerPluginConfig("dummy", "svc", "app", null, null, opts); + RangerBasePlugin plugin = new RangerBasePlugin(cfg); + + boolean first = plugin.logErrorMessage("E1"); + boolean second = plugin.logErrorMessage("E1"); + + assertEquals(true, first); + assertEquals(false, second); + } + + @Test + public void test6_UGILogin_KeytabMissingThrows() { + RangerPolicyEngineOptions opts = new RangerPolicyEngineOptions(); + RangerPluginConfig cfg = new RangerPluginConfig("dummy", "svc", "app", null, null, opts); + String prefix = cfg.getPropertyPrefix() + ".ugi"; + cfg.set(prefix + ".initialize", "true"); + cfg.set(prefix + ".login.type", "keytab"); + // Intentionally do not set principal/keytab to trigger exception + assertThrows(RuntimeException.class, () -> new RangerBasePlugin(cfg)); + } + + @Test + public void test7_UGILogin_JaasMissingThrows() { + RangerPolicyEngineOptions opts = new RangerPolicyEngineOptions(); + RangerPluginConfig cfg = new RangerPluginConfig("dummy", "svc", "app", null, null, opts); + String prefix = cfg.getPropertyPrefix() + ".ugi"; + cfg.set(prefix + ".initialize", "true"); + cfg.set(prefix + ".login.type", "jaas"); + // Intentionally do not set jaas appconfig to trigger exception + assertThrows(RuntimeException.class, () -> new RangerBasePlugin(cfg)); + } + + @Test + public void test8_UGILogin_InvalidTypeNoThrow() { + RangerPolicyEngineOptions opts = new RangerPolicyEngineOptions(); + opts.disablePolicyRefresher = true; + opts.disableTagRetriever = true; + opts.disableUserStoreRetriever = true; + opts.disableGdsInfoRetriever = true; + RangerPluginConfig cfg = new RangerPluginConfig("dummy", "svc", "app", null, null, opts); + String prefix = cfg.getPropertyPrefix() + ".ugi"; + cfg.set(prefix + ".initialize", "true"); + cfg.set(prefix + ".login.type", "unknown"); + new RangerBasePlugin(cfg); // should not throw + } + + @Test + public void test9_IsAccessAllowedCollection_SynchronousRefreshAndResultProcessorCalled() throws Exception { + RangerPolicyEngineOptions opts = new RangerPolicyEngineOptions(); + opts.disablePolicyRefresher = true; + opts.disableTagRetriever = true; + opts.disableUserStoreRetriever = true; + opts.disableGdsInfoRetriever = true; + RangerPluginConfig cfg = new RangerPluginConfig("hive", "svc", "app", null, null, opts); + // Build minimal policies with serviceDef and serviceConfig to enable synchronous refresh + ServicePolicies policies = new ServicePolicies(); + policies.setServiceName("svc"); + policies.setServiceDef(EmbeddedServiceDefsUtil.instance().getEmbeddedServiceDef(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_HIVE_NAME)); + HashMap sc = new HashMap<>(); + sc.put(cfg.getPropertyPrefix() + ".policy.refresh.synchronous", "true"); + policies.setServiceConfig(sc); + + RangerBasePlugin plugin = new RangerBasePlugin(cfg); + plugin.setPolicies(policies); + + RangerAccessResourceImpl res = new RangerAccessResourceImpl(); + res.setValue("database", "db1"); + RangerAccessRequestImpl r1 = new RangerAccessRequestImpl(); + r1.setResource(res); + r1.setAccessType("select"); + RangerAccessRequestImpl r2 = new RangerAccessRequestImpl(); + r2.setResource(res); + r2.setAccessType("update"); + + RangerAccessResultProcessor rp = Mockito.mock(RangerAccessResultProcessor.class); + List reqs = new ArrayList<>(); + reqs.add(r1); + reqs.add(r2); + + Collection results = plugin.isAccessAllowed(reqs, rp); + assertNotNull(results); + verify(rp, times(1)).processResults(results); + } + + @Test + public void test10_MergedACLs_PriorityAndDenyWins() { + RangerResourceACLs base = new RangerResourceACLs(); + RangerResourceACLs chained = new RangerResourceACLs(); + + // Prepare policies with different priorities + RangerPolicy basePolicyNormal = new RangerPolicy(); + basePolicyNormal.setPolicyPriority(RangerPolicy.POLICY_PRIORITY_NORMAL); + RangerPolicy chainedHigher = new RangerPolicy(); + chainedHigher.setPolicyPriority(RangerPolicy.POLICY_PRIORITY_OVERRIDE); + + // Case 1: base missing access -> chained should be used + chained.setUserAccessInfo("uA", "select", RangerPolicyEvaluator.ACCESS_ALLOWED, chainedHigher); + RangerBasePlugin.getMergedResourceACLs(base, chained); + AccessResult ar1 = base.getUserACLs().get("uA").get("select"); + assertNotNull(ar1); + assertEquals(RangerPolicyEvaluator.ACCESS_ALLOWED, ar1.getResult()); + + // Case 2: both present, chained lower priority and denied -> lower priority should not override higher-priority base allow + RangerPolicy basePolicyOverride = new RangerPolicy(); + basePolicyOverride.setPolicyPriority(RangerPolicy.POLICY_PRIORITY_OVERRIDE); + base.setGroupAccessInfo("g1", "update", RangerPolicyEvaluator.ACCESS_ALLOWED, basePolicyOverride); + RangerPolicy chainedLower = new RangerPolicy(); + chainedLower.setPolicyPriority(RangerPolicy.POLICY_PRIORITY_NORMAL); + chained.setGroupAccessInfo("g1", "update", RangerPolicyEvaluator.ACCESS_DENIED, chainedLower); + RangerBasePlugin.getMergedResourceACLs(base, chained); + AccessResult ar2 = base.getGroupACLs().get("g1").get("update"); + assertEquals(RangerPolicyEvaluator.ACCESS_ALLOWED, ar2.getResult()); + + // Case 3: same priority and both allowed -> chained used per code path + base.setRoleAccessInfo("r1", "create", RangerPolicyEvaluator.ACCESS_ALLOWED, basePolicyNormal); + chained.setRoleAccessInfo("r1", "create", RangerPolicyEvaluator.ACCESS_ALLOWED, chainedLower); + RangerBasePlugin.getMergedResourceACLs(base, chained); + AccessResult ar3 = base.getRoleACLs().get("r1").get("create"); + assertEquals(RangerPolicyEvaluator.ACCESS_ALLOWED, ar3.getResult()); + + // Case 4: same priority but chained denies and base allowed -> deny should override + base.setUserAccessInfo("uB", "drop", RangerPolicyEvaluator.ACCESS_ALLOWED, basePolicyNormal); + chained.setUserAccessInfo("uB", "drop", RangerPolicyEvaluator.ACCESS_DENIED, chainedLower); + RangerBasePlugin.getMergedResourceACLs(base, chained); + AccessResult ar4 = base.getUserACLs().get("uB").get("drop"); + assertEquals(RangerPolicyEvaluator.ACCESS_DENIED, ar4.getResult()); + } + + @Test + public void test11_RegisterAuthContextListener_NotifiesOnAuthContextChange() throws Exception { + RangerPolicyEngineOptions opts = new RangerPolicyEngineOptions(); + opts.disablePolicyRefresher = true; + opts.disableTagRetriever = true; + opts.disableUserStoreRetriever = true; + opts.disableGdsInfoRetriever = true; + RangerPluginConfig cfg = new RangerPluginConfig("hive", "svc", "app", null, null, opts); + + ServicePolicies policies = new ServicePolicies(); + policies.setServiceName("svc"); + policies.setServiceDef(EmbeddedServiceDefsUtil.instance().getEmbeddedServiceDef(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_HIVE_NAME)); + + RangerBasePlugin plugin = new RangerBasePlugin(cfg); + + // simple listener that flips a flag when notified + final boolean[] notified = new boolean[] {false}; + plugin.registerAuthContextEventListener(new RangerAuthContextListener() { + @Override + public void contextChanged() { + notified[0] = true; + } + }); + + plugin.setPolicies(policies); + assertEquals(true, notified[0]); + } + + @Test + public void test12_GettersDefaultValuesWithoutPolicyEngine() { + RangerPolicyEngineOptions opts = new RangerPolicyEngineOptions(); + opts.disablePolicyRefresher = true; + RangerPluginConfig cfg = new RangerPluginConfig("dummy", "svc", "app", null, null, opts); + RangerBasePlugin plugin = new RangerBasePlugin(cfg); + + assertEquals(-1L, plugin.getPoliciesVersion()); + assertEquals(-1L, plugin.getTagsVersion()); + assertEquals(-1L, plugin.getRolesVersion()); + assertEquals(-1L, plugin.getUserStoreVersion()); + assertEquals(null, plugin.getResourceAccessInfo(null)); + assertEquals(null, plugin.getResourceACLs(null)); + assertEquals(null, plugin.getRolesFromUserAndGroups("u", new HashSet<>())); + assertEquals(null, plugin.getRangerRoles()); + assertEquals(false, plugin.isServiceAdmin("u")); + } + + @Test + public void test13_EnrichersReturnNullByDefault() { + RangerPolicyEngineOptions opts = new RangerPolicyEngineOptions(); + opts.disablePolicyRefresher = true; + RangerPluginConfig cfg = new RangerPluginConfig("dummy", "svc", "app", null, null, opts); + RangerBasePlugin plugin = new RangerBasePlugin(cfg); + + assertEquals(null, plugin.getTagEnricher()); + assertEquals(null, plugin.getUserStoreEnricher()); + assertEquals(null, plugin.getGdsEnricher()); + assertEquals(null, plugin.getGdsPolicyEngine()); + } + + @Test + public void test14_IsAccessAllowedSingleRequest_ProcessorIsCalled() throws Exception { + RangerPolicyEngineOptions opts = new RangerPolicyEngineOptions(); + opts.disablePolicyRefresher = true; + opts.disableTagRetriever = true; + opts.disableUserStoreRetriever = true; + opts.disableGdsInfoRetriever = true; + RangerPluginConfig cfg = new RangerPluginConfig("hive", "svc", "app", null, null, opts); + + ServicePolicies policies = new ServicePolicies(); + policies.setServiceName("svc"); + policies.setServiceDef(EmbeddedServiceDefsUtil.instance().getEmbeddedServiceDef(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_HIVE_NAME)); + + RangerBasePlugin plugin = new RangerBasePlugin(cfg); + plugin.setPolicies(policies); + + RangerAccessResourceImpl res = new RangerAccessResourceImpl(); + res.setValue("database", "db1"); + RangerAccessRequestImpl req = new RangerAccessRequestImpl(); + req.setResource(res); + req.setAccessType("select"); + + RangerAccessResultProcessor rp = Mockito.mock(RangerAccessResultProcessor.class); + RangerAccessResult ret = plugin.isAccessAllowed(req, rp); + assertNotNull(ret); + verify(rp, times(1)).processResult(Mockito.any(RangerAccessResult.class)); + } + + @Test + public void test15_GetResourceAccessInfoNonNullWhenInitialized() throws Exception { + RangerPolicyEngineOptions opts = new RangerPolicyEngineOptions(); + opts.disablePolicyRefresher = true; + opts.disableTagRetriever = true; + opts.disableUserStoreRetriever = true; + opts.disableGdsInfoRetriever = true; + RangerPluginConfig cfg = new RangerPluginConfig("hive", "svc", "app", null, null, opts); + + ServicePolicies policies = new ServicePolicies(); + policies.setServiceName("svc"); + policies.setServiceDef(EmbeddedServiceDefsUtil.instance().getEmbeddedServiceDef(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_HIVE_NAME)); + + RangerBasePlugin plugin = new RangerBasePlugin(cfg); + plugin.setPolicies(policies); + + RangerAccessResourceImpl res = new RangerAccessResourceImpl(); + res.setValue("database", "db1"); + RangerAccessRequestImpl req = new RangerAccessRequestImpl(); + req.setResource(res); + req.setAccessType("select"); + + assertNotNull(plugin.getResourceAccessInfo(req)); + } + + @Test + public void test16_GetAuditProviderAlwaysNonNull() { + AuditHandler h = RangerBasePlugin.getAuditProvider("svc"); + assertNotNull(h); + } + + @Test + public void test17_GetServiceConfigsEmptyByDefault() throws Exception { + RangerPolicyEngineOptions opts = new RangerPolicyEngineOptions(); + opts.disablePolicyRefresher = true; + opts.disableTagRetriever = true; + opts.disableUserStoreRetriever = true; + opts.disableGdsInfoRetriever = true; + RangerPluginConfig cfg = new RangerPluginConfig("hive", "svc", "app", null, null, opts); + + ServicePolicies policies = new ServicePolicies(); + policies.setServiceName("svc"); + policies.setServiceDef(EmbeddedServiceDefsUtil.instance().getEmbeddedServiceDef(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_HIVE_NAME)); + + RangerBasePlugin plugin = new RangerBasePlugin(cfg); + plugin.setPolicies(policies); + assertEquals(0, plugin.getServiceConfigs().size()); + } + + @Test + public void test18_SetPoliciesNullUsesDefaultPoliciesCreatesEngine() { + RangerPolicyEngineOptions opts = new RangerPolicyEngineOptions(); + opts.disablePolicyRefresher = true; + opts.disableTagRetriever = true; + opts.disableUserStoreRetriever = true; + opts.disableGdsInfoRetriever = true; + RangerPluginConfig cfg = new RangerPluginConfig("hive", "svc", "app", null, null, opts); + + RangerBasePlugin plugin = new RangerBasePlugin(cfg); + // passing null should use default embedded service def for given serviceType + plugin.setPolicies(null); + assertNotNull(plugin.getServiceDef()); + assertEquals("svc", plugin.getServiceName()); + } + + @Test + public void test19_RolesMappingAPIsReturnExpected() throws Exception { + RangerPolicyEngineOptions opts = new RangerPolicyEngineOptions(); + opts.disablePolicyRefresher = true; + opts.disableTagRetriever = true; + opts.disableUserStoreRetriever = true; + opts.disableGdsInfoRetriever = true; + RangerPluginConfig cfg = new RangerPluginConfig("hive", "svc", "app", null, null, opts); + + ServicePolicies policies = new ServicePolicies(); + policies.setServiceName("svc"); + policies.setServiceDef(EmbeddedServiceDefsUtil.instance().getEmbeddedServiceDef(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_HIVE_NAME)); + + // build roles: role1 with user u1 and group g1 + RangerRole role1 = new RangerRole(); + role1.setName("role1"); + List users = new ArrayList<>(); + users.add(new RangerRole.RoleMember("u1", false)); + role1.setUsers(users); + List groups = new ArrayList<>(); + groups.add(new RangerRole.RoleMember("g1", false)); + role1.setGroups(groups); + + RangerRoles rangerRoles = new RangerRoles(); + Set rrset = new HashSet<>(); + rrset.add(role1); + rangerRoles.setRangerRoles(rrset); + + RangerBasePlugin plugin = new RangerBasePlugin(cfg); + plugin.setPolicies(policies); + plugin.setRoles(rangerRoles); + + Set groupsInput = new HashSet<>(); + groupsInput.add("gX"); + Set rolesFromUser = plugin.getRolesFromUserAndGroups("u1", groupsInput); + assertNotNull(rolesFromUser); + // u1 maps to role1 via users + Assertions.assertTrue(rolesFromUser.contains("role1")); + + Set rolesFromGroup = plugin.getRolesFromUserAndGroups(null, new HashSet<>(Arrays.asList("g1"))); + assertNotNull(rolesFromGroup); + Assertions.assertTrue(rolesFromGroup.contains("role1")); + + Set byUser = plugin.getRangerRoleForPrincipal("u1", "USER"); + assertNotNull(byUser); + Assertions.assertTrue(byUser.stream().anyMatch(r -> "role1".equals(r.getName()))); + + Set byGroup = plugin.getRangerRoleForPrincipal("g1", "GROUP"); + assertNotNull(byGroup); + Assertions.assertTrue(byGroup.stream().anyMatch(r -> "role1".equals(r.getName()))); + } + + @Test + public void test20_EvalAuditPolicies_NoThrowOnNullOrRealResult() throws Exception { + RangerPolicyEngineOptions opts = new RangerPolicyEngineOptions(); + opts.disablePolicyRefresher = true; + opts.disableTagRetriever = true; + opts.disableUserStoreRetriever = true; + opts.disableGdsInfoRetriever = true; + RangerPluginConfig cfg = new RangerPluginConfig("hive", "svc", "app", null, null, opts); + + ServicePolicies policies = new ServicePolicies(); + policies.setServiceName("svc"); + policies.setServiceDef(EmbeddedServiceDefsUtil.instance().getEmbeddedServiceDef(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_HIVE_NAME)); + + RangerBasePlugin plugin = new RangerBasePlugin(cfg); + plugin.setPolicies(policies); + + RangerAccessResourceImpl res = new RangerAccessResourceImpl(); + res.setValue("database", "db1"); + RangerAccessRequestImpl req = new RangerAccessRequestImpl(); + req.setResource(res); + req.setAccessType("select"); + + RangerAccessResult result = plugin.isAccessAllowed(req); + plugin.evalAuditPolicies(result); + } + + @Test + public void test21_BasicGettersNonNull() { + RangerPolicyEngineOptions opts = new RangerPolicyEngineOptions(); + RangerPluginConfig cfg = new RangerPluginConfig("svcType", "svc", "appId", null, null, opts); + RangerBasePlugin plugin = new RangerBasePlugin(cfg); + assertEquals("svcType", plugin.getServiceType()); + assertEquals("appId", plugin.getAppId()); + assertNotNull(plugin.getConfig()); + } + + @Test + public void test22_CreateRangerAuthContextNotNullAfterPolicies() throws Exception { + RangerPolicyEngineOptions opts = new RangerPolicyEngineOptions(); + opts.disablePolicyRefresher = true; + opts.disableTagRetriever = true; + opts.disableUserStoreRetriever = true; + opts.disableGdsInfoRetriever = true; + RangerPluginConfig cfg = new RangerPluginConfig("hive", "svc", "app", null, null, opts); + + ServicePolicies policies = new ServicePolicies(); + policies.setServiceName("svc"); + policies.setServiceDef(EmbeddedServiceDefsUtil.instance().getEmbeddedServiceDef(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_HIVE_NAME)); + + RangerBasePlugin plugin = new RangerBasePlugin(cfg); + plugin.setPolicies(policies); + assertNotNull(plugin.createRangerAuthContext()); + assertNotNull(plugin.getCurrentRangerAuthContext()); + } + private void runTestsFromResourceFile(String resourceFile) throws Exception { InputStream inStream = this.getClass().getResourceAsStream(resourceFile); InputStreamReader reader = new InputStreamReader(inStream); @@ -98,13 +569,13 @@ private void runTestsFromResourceFile(String resourceFile) throws Exception { private void runTests(Reader reader, String testName) throws Exception { RangerBasePluginTestCase testCase = readTestCase(reader); - assertNotNull("invalid input: " + testName, testCase); - assertNotNull("invalid input: " + testName, testCase.policies); - assertNotNull("invalid input: " + testName, testCase.tags); - assertNotNull("invalid input: " + testName, testCase.roles); - assertNotNull("invalid input: " + testName, testCase.userStore); - assertNotNull("invalid input: " + testName, testCase.gdsInfo); - assertNotNull("invalid input: " + testName, testCase.tests); + assertNotNull(testCase, "invalid input: " + testName); + assertNotNull(testCase.policies, "invalid input: " + testName); + assertNotNull(testCase.tags, "invalid input: " + testName); + assertNotNull(testCase.roles, "invalid input: " + testName); + assertNotNull(testCase.userStore, "invalid input: " + testName); + assertNotNull(testCase.gdsInfo, "invalid input: " + testName); + assertNotNull(testCase.tests, "invalid input: " + testName); RangerPluginConfig pluginConfig = new RangerPluginConfig(testCase.policies.getServiceDef().getName(), testCase.policies.getServiceName(), "hive", "cl1", "on-prem", peOptions); RangerBasePlugin plugin = new RangerBasePlugin(pluginConfig, testCase.policies, testCase.tags, testCase.roles, testCase.userStore, testCase.gdsInfo); @@ -115,31 +586,31 @@ private void runTests(Reader reader, String testName) throws Exception { if (test.result != null) { RangerAccessResult result = plugin.isAccessAllowed(request); - assertNotNull("result was null! - " + test.name, result); - assertEquals("isAllowed mismatched! - " + test.name, test.result.getIsAllowed(), result.getIsAllowed()); - assertEquals("isAccessDetermined mismatched! - " + test.name, test.result.getIsAccessDetermined(), result.getIsAccessDetermined()); - assertEquals("isAllowed mismatched! - " + test.name, test.result.getPolicyId(), result.getPolicyId()); - assertEquals("isAudited mismatched! - " + test.name, test.result.getIsAudited(), result.getIsAudited()); - assertEquals("isAuditedDetermined mismatched! - " + test.name, test.result.getIsAuditedDetermined(), result.getIsAuditedDetermined()); + assertNotNull(result, "result was null! - " + test.name); + assertEquals(test.result.getIsAllowed(), result.getIsAllowed(), "isAllowed mismatched! - " + test.name); + assertEquals(test.result.getIsAccessDetermined(), result.getIsAccessDetermined(), "isAccessDetermined mismatched! - " + test.name); + assertEquals(test.result.getPolicyId(), result.getPolicyId(), "isAllowed mismatched! - " + test.name); + assertEquals(test.result.getIsAudited(), result.getIsAudited(), "isAudited mismatched! - " + test.name); + assertEquals(test.result.getIsAuditedDetermined(), result.getIsAuditedDetermined(), "isAuditedDetermined mismatched! - " + test.name); result = plugin.evalDataMaskPolicies(request, new RangerDefaultAuditHandler()); if (test.result.getMaskType() != null) { - assertNotNull("result was null! - " + test.name, result); - assertEquals("maskType mismatched! - " + test.name, test.result.getMaskType(), result.getMaskType()); - assertEquals("maskedValue mismatched! - " + test.name, test.result.getMaskedValue(), result.getMaskedValue()); - assertEquals("maskCondition mismatched! - " + test.name, test.result.getMaskCondition(), result.getMaskCondition()); + assertNotNull(result, "result was null! - " + test.name); + assertEquals(test.result.getMaskType(), result.getMaskType(), "maskType mismatched! - " + test.name); + assertEquals(test.result.getMaskedValue(), result.getMaskedValue(), "maskedValue mismatched! - " + test.name); + assertEquals(test.result.getMaskCondition(), result.getMaskCondition(), "maskCondition mismatched! - " + test.name); } else { - assertEquals("maskType mismatched! - " + test.name, test.result.getMaskType(), result != null ? result.getMaskType() : null); + assertEquals(test.result.getMaskType(), result != null ? result.getMaskType() : null, "maskType mismatched! - " + test.name); } result = plugin.evalRowFilterPolicies(request, new RangerDefaultAuditHandler()); if (test.result.getFilterExpr() != null) { - assertNotNull("result was null! - " + test.name, result); - assertEquals("filterExpr mismatched! - " + test.name, test.result.getFilterExpr(), result.getFilterExpr()); + assertNotNull(result, "result was null! - " + test.name); + assertEquals(test.result.getFilterExpr(), result.getFilterExpr(), "filterExpr mismatched! - " + test.name); } else { - assertEquals("filterExpr mismatched! - " + test.name, test.result.getFilterExpr(), result != null ? result.getFilterExpr() : null); + assertEquals(test.result.getFilterExpr(), result != null ? result.getFilterExpr() : null, "filterExpr mismatched! - " + test.name); } } @@ -147,7 +618,7 @@ private void runTests(Reader reader, String testName) throws Exception { RangerAccessRequest req = new RangerAccessRequestImpl(request.getResource(), RangerPolicyEngine.ANY_ACCESS, null, null, null); RangerResourceACLs acls = plugin.getResourceACLs(req); - assertEquals(test.name, test.acls, acls); + assertEquals(test.acls, acls, test.name); } } } diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/service/TestRangerBaseService.java b/agents-common/src/test/java/org/apache/ranger/plugin/service/TestRangerBaseService.java new file mode 100644 index 0000000000..9dd1255f80 --- /dev/null +++ b/agents-common/src/test/java/org/apache/ranger/plugin/service/TestRangerBaseService.java @@ -0,0 +1,265 @@ +/* + * 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.service; + +import org.apache.ranger.authorization.hadoop.config.RangerAdminConfig; +import org.apache.ranger.plugin.model.RangerPolicy; +import org.apache.ranger.plugin.model.RangerService; +import org.apache.ranger.plugin.model.RangerServiceDef; +import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef; +import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef; +import org.apache.ranger.plugin.model.validation.RangerServiceDefHelper; +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.junit.jupiter.MockitoExtension; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** +* @generated by Cursor +* @description +*/ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +public class TestRangerBaseService { + public static class DummyService extends RangerBaseService { + @Override + public Map validateConfig() { + Map m = new HashMap<>(); + m.put("ok", Boolean.TRUE); + return m; + } + + @Override + public List lookupResource(ResourceLookupContext context) { + return Collections.singletonList("X"); + } + } + + private RangerServiceDef buildServiceDef() { + RangerServiceDef def = new RangerServiceDef(); + def.setId(1L); + def.setName("dummy"); + + List resources = new ArrayList<>(); + RangerResourceDef db = new RangerResourceDef(); + db.setName("database"); + db.setLevel(1); + db.setRecursiveSupported(Boolean.TRUE); + db.setMandatory(Boolean.TRUE); + db.setIsValidLeaf(Boolean.FALSE); + RangerResourceDef table = new RangerResourceDef(); + table.setName("table"); + table.setLevel(2); + table.setParent("database"); + table.setRecursiveSupported(Boolean.TRUE); + table.setMandatory(Boolean.TRUE); + table.setIsValidLeaf(Boolean.TRUE); + resources.add(db); + resources.add(table); + def.setResources(resources); + + List accessTypes = new ArrayList<>(); + RangerAccessTypeDef select = new RangerAccessTypeDef(); + select.setName("select"); + RangerAccessTypeDef update = new RangerAccessTypeDef(); + update.setName("update"); + accessTypes.add(select); + accessTypes.add(update); + def.setAccessTypes(accessTypes); + + Map options = new HashMap<>(); + options.put("create.default.policy.per.hierarchy", "true"); + def.setOptions(options); + + return def; + } + + private RangerService buildService(Map configs) { + RangerService svc = new RangerService(); + svc.setName("svc1"); + svc.setType("dummy"); + svc.setConfigs(configs); + return svc; + } + + @Test + public void test1_DefaultPoliciesCreatedPerHierarchy() throws Exception { + DummyService svc = new DummyService(); + RangerServiceDef def = buildServiceDef(); + RangerService service = buildService(new LinkedHashMap<>()); + + svc.init(def, service); + + List policies = svc.getDefaultRangerPolicies(); + assertNotNull(policies); + assertTrue(policies.size() >= 1); + RangerPolicy p0 = policies.get(0); + assertEquals("svc1", p0.getService()); + assertTrue(p0.getResources().containsKey("database")); + assertTrue(p0.getResources().containsKey("table")); + assertTrue(p0.getPolicyItems().get(0).getAccesses().stream().anyMatch(a -> "select".equals(a.getType()))); + } + + @Test + public void test2_CreateDefaultPolicyResourceAndAllowedAccesses() { + DummyService svc = new DummyService(); + RangerServiceDef def = buildServiceDef(); + RangerService service = buildService(new LinkedHashMap<>()); + svc.init(def, service); + + RangerServiceDefHelper helper = new RangerServiceDefHelper(def); + Set> hierarchies = helper.filterHierarchies_containsOnlyMandatoryResources(RangerPolicy.POLICY_TYPE_ACCESS); + assertTrue(!hierarchies.isEmpty()); + List first = hierarchies.iterator().next(); + + Map res = svc.createDefaultPolicyResource(first); + assertTrue(res.containsKey("database")); + assertTrue(res.get("database").getIsRecursive()); + + List accesses = svc.getAllowedAccesses(res); + assertTrue(accesses.stream().anyMatch(a -> "select".equals(a.getType()))); + assertTrue(accesses.stream().anyMatch(a -> "update".equals(a.getType()))); + } + + @Test + public void test3_CustomDefaultPoliciesFromConfigs() throws Exception { + DummyService svc = new DummyService(); + RangerServiceDef def = buildServiceDef(); + Map cfg = new LinkedHashMap<>(); + cfg.put("default-policy.1.name", "p-custom"); + cfg.put("default-policy.1.description", "desc"); + cfg.put("default-policy.1.isDenyAllElse", "true"); + cfg.put("default-policy.1.resource.database", "db1,db2"); + cfg.put("default-policy.1.resource.table", "t1"); + cfg.put("default-policy.1.policyItem.1.users", "u1,u2"); + cfg.put("default-policy.1.policyItem.1.groups", "g1"); + cfg.put("default-policy.1.policyItem.1.roles", "r1"); + cfg.put("default-policy.1.policyItem.1.accessTypes", "select,update"); + cfg.put("default-policy.1.policyItem.1.isDelegateAdmin", "true"); + + RangerService service = buildService(cfg); + svc.init(def, service); + + List policies = svc.getDefaultRangerPolicies(); + assertNotNull(policies); + boolean found = policies.stream().anyMatch(p -> p.getResources().containsKey("database") + && p.getResources().containsKey("table") + && p.getPolicyItems() != null + && p.getPolicyItems().stream().anyMatch(pi -> pi.getAccesses() != null && pi.getAccesses().stream().anyMatch(a -> "select".equals(a.getType()) || "update".equals(a.getType())))); + assertTrue(found); + } + + @Test + public void test4_GetLookupUserKerberosBranches() throws IOException { + DummyService svc = new DummyService(); + RangerAdminConfig rac = RangerAdminConfig.getInstance(); + String user = svc.getLookupUser("kerberos", rac.get("ranger.lookup.kerberos.principal"), rac.get("ranger.lookup.kerberos.keytab")); + assertEquals(null, user); + } + + @Test + public void test5_CreateDefaultPolicyPerHierarchy_FromServiceAndServiceDefOptions() throws Exception { + DummyService svc = new DummyService(); + RangerServiceDef def = buildServiceDef(); + // remove option from service-def to test default true + def.setOptions(new HashMap<>()); + Map cfg1 = new LinkedHashMap<>(); + // no explicit config -> should fallback to default true + RangerService service1 = buildService(cfg1); + svc.init(def, service1); + List p1 = svc.getDefaultRangerPolicies(); + assertFalse(p1.isEmpty()); + + // now set service config to false to suppress creation + Map cfg2 = new LinkedHashMap<>(); + cfg2.put("create.default.policy.per.hierarchy", "false"); + RangerService service2 = buildService(cfg2); + svc.init(def, service2); + List p2 = svc.getDefaultRangerPolicies(); + assertTrue(p2.isEmpty()); + } + + @Test + public void test6_GetResourcesForPrefix_WithFlags() throws Exception { + DummyService svc = new DummyService(); + RangerServiceDef def = buildServiceDef(); + Map cfg = new LinkedHashMap<>(); + cfg.put("default-policy.1.name", "p1"); + cfg.put("default-policy.1.resource.database", "db1,db2"); + cfg.put("default-policy.1.resource.database.is-excludes", "true"); + cfg.put("default-policy.1.resource.database.is-recursive", "true"); + cfg.put("default-policy.1.policyItem.1.users", "u1"); + cfg.put("default-policy.1.policyItem.1.accessTypes", "select"); + cfg.put("setup.additional.default.policies", "true"); + RangerService service = buildService(cfg); + svc.init(def, service); + List policies = svc.getDefaultRangerPolicies(); + assertTrue(policies.stream().anyMatch(p -> Boolean.TRUE.equals(p.getResources().get("database").getIsExcludes()) + && Boolean.TRUE.equals(p.getResources().get("database").getIsRecursive()))); + } + + @Test + public void test7_GetUserAndGroupLists_MergesServiceConfigs() { + DummyService svc = new DummyService(); + RangerServiceDef def = buildServiceDef(); + Map cfg = new LinkedHashMap<>(); + cfg.put("username", "svcUser"); + cfg.put("default.policy.users", "u1,u2"); + cfg.put("default.policy.groups", "g1,g2"); + RangerService service = buildService(cfg); + svc.init(def, service); + + // access private via public API: getDefaultRangerPolicies should include these in first policy item + List policies; + try { + policies = svc.getDefaultRangerPolicies(); + } catch (Exception e) { + throw new RuntimeException(e); + } + RangerPolicy first = policies.get(0); + List users = first.getPolicyItems().get(0).getUsers(); + List groups = first.getPolicyItems().get(0).getGroups(); + assertTrue(users.contains("svcUser")); + assertTrue(users.contains("u1") && users.contains("u2")); + assertTrue(groups.contains("g1") && groups.contains("g2")); + } + + @Test + public void test8_GetLookupUser_SimpleAuthReturnsNull() throws IOException { + DummyService svc = new DummyService(); + String user = svc.getLookupUser("simple", null, null); + assertEquals(null, user); + } +} diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/service/TestRangerChainedPlugin.java b/agents-common/src/test/java/org/apache/ranger/plugin/service/TestRangerChainedPlugin.java new file mode 100644 index 0000000000..e463d34bd9 --- /dev/null +++ b/agents-common/src/test/java/org/apache/ranger/plugin/service/TestRangerChainedPlugin.java @@ -0,0 +1,127 @@ +/* + * 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.service; + +import org.apache.ranger.authorization.hadoop.config.RangerPluginConfig; +import org.apache.ranger.plugin.policyengine.RangerAccessRequest; +import org.apache.ranger.plugin.policyengine.RangerAccessResult; +import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions; +import org.apache.ranger.plugin.policyengine.RangerResourceACLs; +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.junit.jupiter.MockitoExtension; + +import java.util.ArrayList; +import java.util.Collection; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +/** +* @generated by Cursor +* @description +*/ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +public class TestRangerChainedPlugin { + private static class NoopChainedPlugin extends RangerChainedPlugin { + protected NoopChainedPlugin(RangerBasePlugin rootPlugin, String serviceType, String serviceName) { + super(rootPlugin, serviceType, serviceName); + } + + @Override + public RangerAccessResult isAccessAllowed(RangerAccessRequest request) { + return null; + } + + @Override + public Collection isAccessAllowed(Collection requests) { + return new ArrayList<>(); + } + + @Override + public RangerResourceACLs getResourceACLs(RangerAccessRequest request) { + return null; + } + + @Override + public RangerResourceACLs getResourceACLs(RangerAccessRequest request, Integer policyType) { + return null; + } + + @Override + protected RangerBasePlugin buildChainedPlugin(String serviceType, String serviceName, String appId) { + return new RangerBasePlugin(new RangerPluginConfig(serviceType, serviceName, appId, null, null, new RangerPolicyEngineOptions())) { + @Override + public void init() { + // no-op to avoid threads + } + }; + } + } + + @Test + public void test1_InitAndBypassFlagDefaultFalse() { + // Disable background components via policy engine options in config + RangerPolicyEngineOptions opts = new RangerPolicyEngineOptions(); + opts.disablePolicyRefresher = true; + opts.disableTagRetriever = true; + opts.disableUserStoreRetriever = true; + opts.disableGdsInfoRetriever = true; + RangerPluginConfig cfg = new RangerPluginConfig("dummy", "svc", "app", null, null, opts); + RangerBasePlugin root = new RangerBasePlugin(cfg) { + @Override + public void init() { + // no-op + } + }; + NoopChainedPlugin cp = new NoopChainedPlugin(root, "dummy", "svc2"); + // Do not call cp.init() to avoid starting threads; just assert defaults and no-ops + assertEquals(false, cp.skipAccessCheckIfAlreadyDetermined); + assertNull(cp.evalDataMaskPolicies(null)); + assertNull(cp.evalRowFilterPolicies(null)); + assertNotNull(cp.isAccessAllowed(new ArrayList<>())); + } + + @Test + public void test2_IsAuthorizeOnlyWithChainedPluginDefaultFalseAndInitDelegation() { + RangerPolicyEngineOptions opts = new RangerPolicyEngineOptions(); + opts.disablePolicyRefresher = true; + opts.disableTagRetriever = true; + opts.disableUserStoreRetriever = true; + opts.disableGdsInfoRetriever = true; + RangerPluginConfig cfg = new RangerPluginConfig("dummy", "svc", "app", null, null, opts); + + RangerBasePlugin root = new RangerBasePlugin(cfg) { + @Override + public void init() { + // no-op + } + }; + NoopChainedPlugin cp = new NoopChainedPlugin(root, "dummy", "svc2"); + + // call init which should delegate to inner plugin.init() but overridden to no-op + cp.init(); + assertEquals(false, cp.isAuthorizeOnlyWithChainedPlugin()); + } +} diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/service/TestRangerDefaultRequestProcessor.java b/agents-common/src/test/java/org/apache/ranger/plugin/service/TestRangerDefaultRequestProcessor.java new file mode 100644 index 0000000000..9b44117223 --- /dev/null +++ b/agents-common/src/test/java/org/apache/ranger/plugin/service/TestRangerDefaultRequestProcessor.java @@ -0,0 +1,335 @@ +/* + * 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.service; + +import org.apache.ranger.authorization.hadoop.config.RangerPluginConfig; +import org.apache.ranger.plugin.model.RangerRole; +import org.apache.ranger.plugin.model.RangerServiceDef; +import org.apache.ranger.plugin.policyengine.PolicyEngine; +import org.apache.ranger.plugin.policyengine.RangerAccessRequestImpl; +import org.apache.ranger.plugin.policyengine.RangerAccessResource; +import org.apache.ranger.plugin.policyengine.RangerMutableResource; +import org.apache.ranger.plugin.policyengine.RangerPluginContext; +import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions; +import org.apache.ranger.plugin.util.RangerAccessRequestUtil; +import org.apache.ranger.plugin.util.RangerCommonConstants; +import org.apache.ranger.plugin.util.RangerRoles; +import org.apache.ranger.plugin.util.RangerUserStore; +import org.apache.ranger.ugsyncutil.transform.Mapper; +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.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** +* @generated by Cursor +* @description +*/ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +public class TestRangerDefaultRequestProcessor { + private static class TestResource implements RangerMutableResource { + private RangerServiceDef serviceDef; + + @Override + public void setOwnerUser(String ownerUser) { + } + + @Override + public void setValue(String type, Object value) { + } + + @Override + public void setServiceDef(RangerServiceDef serviceDef) { + this.serviceDef = serviceDef; + } + + @Override + public RangerServiceDef getServiceDef() { + return serviceDef; + } + + @Override + public Map getAsMap() { + return new HashMap<>(); + } + + @Override + public String getAsString() { + return ""; + } + + @Override + public Set getKeys() { + return new HashSet<>(); + } + + @Override + public Object getValue(String resourceElement) { + return null; + } + + @Override + public String getOwnerUser() { + return null; + } + + @Override + public boolean exists(String name) { + return false; + } + + @Override + public String getLeafName() { + return null; + } + + @Override + public String getCacheKey() { + return ""; + } + + @Override + public RangerAccessResource getReadOnlyCopy() { + return this; + } + } + + public static class NoopMapper implements Mapper { + @Override + public void init(String baseProperty, List regexPatterns, String regexSeparator) { + } + + @Override + public String transform(String attrValue) { + return attrValue; + } + } + + @Test + public void test1_PreProcessSetsClusterAndEmailConversionAndGroups() { + RangerPolicyEngineOptions opts = new RangerPolicyEngineOptions(); + opts.disablePolicyRefresher = true; + + RangerPluginConfig mockCfg = Mockito.mock(RangerPluginConfig.class); + Mockito.when(mockCfg.isUseRangerGroups()).thenReturn(true); + Mockito.when(mockCfg.isUseOnlyRangerGroups()).thenReturn(false); + Mockito.when(mockCfg.isConvertEmailToUsername()).thenReturn(false); + + RangerPluginContext mockPluginCtx = Mockito.mock(RangerPluginContext.class); + Mockito.when(mockPluginCtx.getConfig()).thenReturn(mockCfg); + Mockito.when(mockPluginCtx.getClusterName()).thenReturn("clX"); + Mockito.when(mockPluginCtx.getClusterType()).thenReturn("typeY"); + + RangerServiceDef sd = new RangerServiceDef(); + sd.setName("dummy"); + + PolicyEngine pe = Mockito.mock(PolicyEngine.class); + Mockito.when(pe.getPluginContext()).thenReturn(mockPluginCtx); + Mockito.when(pe.getUseForwardedIPAddress()).thenReturn(false); + Mockito.when(pe.getTrustedProxyAddresses()).thenReturn(null); + + RangerUserStore us = new RangerUserStore(); + Map> userAttrs = new HashMap<>(); + Map attrs = new HashMap<>(); + attrs.put(RangerCommonConstants.SCRIPT_FIELD__EMAIL_ADDRESS, "user1@example.com"); + userAttrs.put("user1", attrs); + us.setUserAttrMapping(userAttrs); + Map> ug = new HashMap<>(); + ug.put("user1@example.com", new HashSet<>(Collections.singletonList("rg1"))); + us.setUserGroupMapping(ug); + + RangerAuthContext ac = new RangerAuthContext(new HashMap<>(), null, new RangerRoles(), us); + Mockito.when(mockPluginCtx.getAuthContext()).thenReturn(ac); + + RangerDefaultRequestProcessor rp = new RangerDefaultRequestProcessor(pe); + + RangerAccessRequestImpl req = new RangerAccessRequestImpl(); + TestResource tr = new TestResource(); + tr.setServiceDef(sd); + req.setResource(tr); + req.setUser("user1@example.com"); + req.setUserGroups(new HashSet<>(Collections.singletonList("g0"))); + + rp.preProcess(req); + + assertEquals("clX", req.getClusterName()); + assertEquals("typeY", req.getClusterType()); + assertEquals("user1@example.com", req.getUser()); + assertNotNull(req.getUserGroups()); + assertTrue(req.getUserGroups().contains("g0")); + assertEquals("user1@example.com", RangerAccessRequestUtil.getCurrentUserFromContext(req.getContext())); + } + + @Test + public void test2_PreProcessConvertsEmailAndReplacesGroupsAndSetsRoles() { + RangerPolicyEngineOptions opts = new RangerPolicyEngineOptions(); + opts.disablePolicyRefresher = true; + + RangerPluginConfig mockCfg = Mockito.mock(RangerPluginConfig.class); + Mockito.when(mockCfg.isUseRangerGroups()).thenReturn(true); + Mockito.when(mockCfg.isUseOnlyRangerGroups()).thenReturn(true); + Mockito.when(mockCfg.isConvertEmailToUsername()).thenReturn(true); + + // Enable name transformation feature flag to allow transformation steps + Mockito.when(mockCfg.getPropertyPrefix()).thenReturn("ranger.plugin.dummy"); + Mockito.when(mockCfg.getBoolean("ranger.plugin.dummy" + RangerCommonConstants.PLUGIN_CONFIG_SUFFIX_NAME_TRANSFORMATION, false)).thenReturn(true); + + RangerPluginContext mockPluginCtx = Mockito.mock(RangerPluginContext.class); + Mockito.when(mockPluginCtx.getConfig()).thenReturn(mockCfg); + Mockito.when(mockPluginCtx.getClusterName()).thenReturn("clA"); + Mockito.when(mockPluginCtx.getClusterType()).thenReturn("typeB"); + + RangerServiceDef sd = new RangerServiceDef(); + sd.setName("dummy"); + + PolicyEngine pe = Mockito.mock(PolicyEngine.class); + Mockito.when(pe.getPluginContext()).thenReturn(mockPluginCtx); + Mockito.when(pe.getUseForwardedIPAddress()).thenReturn(false); + Mockito.when(pe.getTrustedProxyAddresses()).thenReturn(null); + Mockito.when(pe.getServiceDef()).thenReturn(sd); + + // Prepare user store mapping for email->username and ranger groups for username + RangerUserStore us = new RangerUserStore(); + Map> userAttrs = new HashMap<>(); + Map attrs = new HashMap<>(); + attrs.put(RangerCommonConstants.SCRIPT_FIELD__EMAIL_ADDRESS, "u2@example.com"); + userAttrs.put("u2", attrs); + us.setUserAttrMapping(userAttrs); + Map> ug = new HashMap<>(); + ug.put("u2", new HashSet<>(Collections.singletonList("rg9"))); + us.setUserGroupMapping(ug); + + // Set roles so that roles are computed and populated onto the request when empty + RangerRoles roles = new RangerRoles(); + Set roleSet = new HashSet<>(); + RangerRole r = new RangerRole(); + r.setName("roleX"); + r.setUsers(Collections.singletonList(new RangerRole.RoleMember("u2", false))); + roleSet.add(r); + roles.setRangerRoles(roleSet); + + RangerAuthContext ac = new RangerAuthContext(new HashMap<>(), null, roles, us); + Mockito.when(mockPluginCtx.getAuthContext()).thenReturn(ac); + + RangerDefaultRequestProcessor rp = new RangerDefaultRequestProcessor(pe); + + RangerAccessRequestImpl req = new RangerAccessRequestImpl(); + TestResource tr = new TestResource(); + req.setResource(tr); // serviceDef is null initially to exercise setResourceServiceDef + req.setUser("u2@example.com"); + req.setUserGroups(new HashSet<>(Collections.singletonList("g1"))); + + rp.preProcess(req); + + assertEquals("u2", req.getUser()); // email converted to username via user store + assertNotNull(req.getUserGroups()); + assertEquals(1, req.getUserGroups().size()); + assertTrue(req.getUserGroups().contains("rg9")); // replaced with only ranger groups + assertNotNull(req.getUserRoles()); + assertTrue(req.getUserRoles().contains("roleX")); + assertNotNull(((RangerMutableResource) req.getResource()).getServiceDef()); + } + + @Test + public void test3_PreProcessEarlyReturnWhenAlreadyPreprocessed() { + RangerPluginContext mockPluginCtx = Mockito.mock(RangerPluginContext.class); + RangerPluginConfig mockCfg = Mockito.mock(RangerPluginConfig.class); + Mockito.when(mockPluginCtx.getConfig()).thenReturn(mockCfg); + + PolicyEngine pe = Mockito.mock(PolicyEngine.class); + Mockito.when(pe.getPluginContext()).thenReturn(mockPluginCtx); + + RangerDefaultRequestProcessor rp = new RangerDefaultRequestProcessor(pe); + + RangerAccessRequestImpl req = new RangerAccessRequestImpl(); + TestResource tr = new TestResource(); + req.setResource(tr); + + // mark as already preprocessed + RangerAccessRequestUtil.setIsRequestPreprocessed(req.getContext(), Boolean.TRUE); + + rp.preProcess(req); + + // cluster should remain unset due to early return + assertEquals(null, req.getClusterName()); + assertEquals(null, req.getClusterType()); + } + + @Test + public void test4_NameAndGroupCaseConversionWithoutMapper() { + RangerPluginConfig mockCfg = Mockito.mock(RangerPluginConfig.class); + Mockito.when(mockCfg.isUseRangerGroups()).thenReturn(false); + Mockito.when(mockCfg.isUseOnlyRangerGroups()).thenReturn(false); + Mockito.when(mockCfg.isConvertEmailToUsername()).thenReturn(false); + Mockito.when(mockCfg.getPropertyPrefix()).thenReturn("ranger.plugin.svc"); + Mockito.when(mockCfg.getBoolean("ranger.plugin.svc" + RangerCommonConstants.PLUGIN_CONFIG_SUFFIX_NAME_TRANSFORMATION, false)).thenReturn(true); + + RangerPluginContext mockPluginCtx = Mockito.mock(RangerPluginContext.class); + Mockito.when(mockPluginCtx.getConfig()).thenReturn(mockCfg); + Mockito.when(mockPluginCtx.getClusterName()).thenReturn("clZ"); + Mockito.when(mockPluginCtx.getClusterType()).thenReturn("typeZ"); + + PolicyEngine pe = Mockito.mock(PolicyEngine.class); + Mockito.when(pe.getPluginContext()).thenReturn(mockPluginCtx); + Mockito.when(pe.getUseForwardedIPAddress()).thenReturn(false); + Mockito.when(pe.getTrustedProxyAddresses()).thenReturn(null); + + RangerAuthContext ac = new RangerAuthContext(new HashMap<>(), null, new RangerRoles(), new RangerUserStore()); + Map cfg = new HashMap<>(); + cfg.put(RangerCommonConstants.PLUGINS_CONF_USERNAME_CASE_CONVERSION_PARAM, "lower"); + cfg.put(RangerCommonConstants.PLUGINS_CONF_GROUPNAME_CASE_CONVERSION_PARAM, "upper"); + cfg.put(RangerCommonConstants.PLUGINS_CONF_MAPPING_GROUPNAME_HANDLER, this.getClass().getName() + "$NoopMapper"); + cfg.put(RangerCommonConstants.PLUGINS_CONF_MAPPING_GROUPNAME, "(.*)"); + cfg.put(RangerCommonConstants.PLUGINS_CONF_MAPPING_SEPARATOR, ":"); + ac.onServiceConfigsUpdate(cfg); + Mockito.when(mockPluginCtx.getAuthContext()).thenReturn(ac); + + RangerDefaultRequestProcessor rp = new RangerDefaultRequestProcessor(pe); + + RangerAccessRequestImpl req = new RangerAccessRequestImpl(); + TestResource tr = new TestResource(); + req.setResource(tr); + req.setUser("USERX"); + Set groups = new HashSet<>(); + groups.add("grp"); + groups.add("Grp2"); + req.setUserGroups(groups); + + rp.preProcess(req); + + assertEquals("userx", req.getUser()); + assertTrue(req.getUserGroups().contains("GRP")); + assertTrue(req.getUserGroups().contains("GRP2")); + } +} diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/service/TestRangerDefaultService.java b/agents-common/src/test/java/org/apache/ranger/plugin/service/TestRangerDefaultService.java new file mode 100644 index 0000000000..b09dd9dd49 --- /dev/null +++ b/agents-common/src/test/java/org/apache/ranger/plugin/service/TestRangerDefaultService.java @@ -0,0 +1,53 @@ +/* + * 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.service; + +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.junit.jupiter.MockitoExtension; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +/** +* @generated by Cursor +* @description +*/ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +public class TestRangerDefaultService { + @Test + public void test1_validateConfigThrows() { + RangerDefaultService svc = new RangerDefaultService(); + Exception ex = assertThrows(Exception.class, svc::validateConfig); + assertEquals(RangerDefaultService.ERROR_MSG_VALIDATE_CONFIG_NOT_IMPLEMENTED, ex.getMessage()); + } + + @Test + public void test2_lookupResourceReturnsEmptyList() throws Exception { + RangerDefaultService svc = new RangerDefaultService(); + List res = svc.lookupResource(new ResourceLookupContext()); + assertEquals(0, res.size()); + } +} diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/service/TestResourceLookupContext.java b/agents-common/src/test/java/org/apache/ranger/plugin/service/TestResourceLookupContext.java new file mode 100644 index 0000000000..eb463303b1 --- /dev/null +++ b/agents-common/src/test/java/org/apache/ranger/plugin/service/TestResourceLookupContext.java @@ -0,0 +1,64 @@ +/* + * 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.service; + +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.junit.jupiter.MockitoExtension; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** +* @generated by Cursor +* @description +*/ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +public class TestResourceLookupContext { + @Test + public void test1_GettersSettersAndToString() { + ResourceLookupContext ctx = new ResourceLookupContext(); + ctx.setUserInput("abc"); + ctx.setResourceName("table"); + + Map> resources = new HashMap<>(); + List vals = new ArrayList<>(); + vals.add("v1"); + resources.put("key", vals); + ctx.setResources(resources); + + assertEquals("abc", ctx.getUserInput()); + assertEquals("table", ctx.getResourceName()); + assertEquals(1, ctx.getResources().get("key").size()); + + String s = ctx.toString(); + assertTrue(s.contains("resourceName=table")); + assertTrue(s.contains("userInput=abc")); + assertTrue(s.contains("resources={key=[v1]")); + } +} diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/store/TestAbstractGdsStore.java b/agents-common/src/test/java/org/apache/ranger/plugin/store/TestAbstractGdsStore.java new file mode 100644 index 0000000000..cc0cf1c5c4 --- /dev/null +++ b/agents-common/src/test/java/org/apache/ranger/plugin/store/TestAbstractGdsStore.java @@ -0,0 +1,151 @@ +/* + * 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.store; + +import org.apache.ranger.plugin.model.RangerGds; +import org.apache.ranger.plugin.model.RangerPolicy; +import org.apache.ranger.plugin.util.SearchFilter; +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.junit.jupiter.MockitoExtension; + +import java.util.Collection; +import java.util.List; + +/** + * @generated by Cursor + * @description + */ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +public class TestAbstractGdsStore { + private static class MyGdsStore extends AbstractGdsStore { + @Override + public void deleteAllGdsObjectsForService(Long serviceId) { + } + + @Override + public void deleteAllGdsObjectsForSecurityZone(Long zoneId) { + } + + @Override + public void onSecurityZoneUpdate(Long zoneId, Collection updatedServices, + Collection removedServices) { + } + + @Override + public List getProjectPolicies(Long projectId) throws Exception { + return null; + } + + @Override + public RangerPolicy addDatasetPolicy(Long datasetId, RangerPolicy policy) throws Exception { + return null; + } + + @Override + public RangerPolicy updateDatasetPolicy(Long datasetId, RangerPolicy policy) throws Exception { + return null; + } + + @Override + public void deleteDatasetPolicy(Long datasetId, Long policyId) throws Exception { + } + + @Override + public void deleteDatasetPolicies(Long datasetId) throws Exception { + } + + @Override + public RangerPolicy getDatasetPolicy(Long datasetId, Long policyId) throws Exception { + return null; + } + + @Override + public List getDatasetPolicies(Long datasetId) throws Exception { + return null; + } + + @Override + public RangerPolicy addProjectPolicy(Long projectId, RangerPolicy policy) throws Exception { + return null; + } + + @Override + public RangerPolicy updateProjectPolicy(Long projectId, RangerPolicy policy) throws Exception { + return null; + } + + @Override + public void deleteProjectPolicy(Long projectId, Long policyId) throws Exception { + } + + @Override + public void deleteProjectPolicies(Long projectId) throws Exception { + } + + @Override + public RangerPolicy getProjectPolicy(Long projectId, Long policyId) throws Exception { + return null; + } + } + + @Test + public void test01_defaultReturnsNullsAndNoThrow() throws Exception { + MyGdsStore s = new MyGdsStore(); + Assertions.assertNull(s.createDataset(new RangerGds.RangerDataset())); + Assertions.assertNull(s.updateDataset(new RangerGds.RangerDataset())); + s.deleteDataset(1L, true); + Assertions.assertNull(s.getDataset(1L)); + Assertions.assertNull(s.getDatasetByName("n")); + Assertions.assertNull(s.getDatasetNames(new SearchFilter())); + Assertions.assertNull(s.searchDatasets(new SearchFilter())); + Assertions.assertNull(s.createProject(new RangerGds.RangerProject())); + Assertions.assertNull(s.updateProject(new RangerGds.RangerProject())); + s.deleteProject(1L, true); + Assertions.assertNull(s.getProject(1L)); + Assertions.assertNull(s.getProjectByName("p")); + Assertions.assertNull(s.getProjectNames(new SearchFilter())); + Assertions.assertNull(s.searchProjects(new SearchFilter())); + Assertions.assertNull(s.createDataShare(new RangerGds.RangerDataShare())); + Assertions.assertNull(s.updateDataShare(new RangerGds.RangerDataShare())); + s.deleteDataShare(1L, true); + Assertions.assertNull(s.getDataShare(1L)); + Assertions.assertNull(s.searchDataShares(new SearchFilter())); + Assertions.assertNull(s.addSharedResources(null)); + Assertions.assertNull(s.updateSharedResource(new RangerGds.RangerSharedResource())); + s.removeSharedResources(null); + Assertions.assertNull(s.getSharedResource(1L)); + Assertions.assertNull(s.searchSharedResources(new SearchFilter())); + Assertions.assertNull(s.addDataShareInDataset(new RangerGds.RangerDataShareInDataset())); + Assertions.assertNull(s.updateDataShareInDataset(new RangerGds.RangerDataShareInDataset())); + s.removeDataShareInDataset(1L); + Assertions.assertNull(s.getDataShareInDataset(1L)); + Assertions.assertNull(s.searchDataShareInDatasets(new SearchFilter())); + Assertions.assertNull(s.addDatasetInProject(new RangerGds.RangerDatasetInProject())); + Assertions.assertNull(s.updateDatasetInProject(new RangerGds.RangerDatasetInProject())); + s.removeDatasetInProject(1L); + Assertions.assertNull(s.getDatasetInProject(1L)); + Assertions.assertNull(s.searchDatasetInProjects(new SearchFilter())); + } +} diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/store/TestAbstractPredicateUtil.java b/agents-common/src/test/java/org/apache/ranger/plugin/store/TestAbstractPredicateUtil.java new file mode 100644 index 0000000000..9af269dab9 --- /dev/null +++ b/agents-common/src/test/java/org/apache/ranger/plugin/store/TestAbstractPredicateUtil.java @@ -0,0 +1,573 @@ +/* + * 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.store; + +import org.apache.ranger.plugin.model.RangerPolicy; +import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem; +import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource; +import org.apache.ranger.plugin.model.RangerSecurityZone; +import org.apache.ranger.plugin.model.RangerService; +import org.apache.ranger.plugin.model.RangerServiceDef; +import org.apache.ranger.plugin.util.SearchFilter; +import org.apache.ranger.plugin.util.ServicePolicies; +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.junit.jupiter.MockitoExtension; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @generated by Cursor + * @description + */ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +public class TestAbstractPredicateUtil { + @Test + public void test01_basicFilterByServiceAndPolicy() { + RangerPolicy p1 = new RangerPolicy(); + p1.setId(1L); + p1.setService("svc1"); + p1.setName("read-policy"); + + RangerPolicy p2 = new RangerPolicy(); + p2.setId(2L); + p2.setService("svc2"); + p2.setName("write-policy"); + + List list = new ArrayList<>(Arrays.asList(p1, p2)); + + AbstractPredicateUtil util = new AbstractPredicateUtil(); + SearchFilter f = new SearchFilter(); + f.setParam(SearchFilter.SERVICE_NAME, "svc1"); + f.setParam(SearchFilter.POLICY_NAME_PARTIAL, "read"); + util.applyFilter(list, f); + + Assertions.assertEquals(1, list.size()); + Assertions.assertEquals("svc1", list.get(0).getService()); + } + + @Test + public void test02_sortingByPolicyIdDesc() { + RangerPolicy p1 = new RangerPolicy(); + p1.setId(1L); + RangerPolicy p2 = new RangerPolicy(); + p2.setId(3L); + RangerPolicy p3 = new RangerPolicy(); + p3.setId(2L); + List list = new ArrayList<>(Arrays.asList(p1, p2, p3)); + + AbstractPredicateUtil util = new AbstractPredicateUtil(); + SearchFilter f = new SearchFilter(); + f.setSortBy(SearchFilter.POLICY_ID); + f.setSortType("desc"); + util.applyFilter(list, f); + Assertions.assertEquals(3L, list.get(0).getId().longValue()); + Assertions.assertEquals(1L, list.get(2).getId().longValue()); + } + + @Test + public void test03_filterResourcesWildcardMatch() { + RangerPolicy p = new RangerPolicy(); + Map res = new HashMap<>(); + res.put("path", new RangerPolicyResource("/data/*")); + p.setResources(res); + List list = new ArrayList<>(Collections.singletonList(p)); + + AbstractPredicateUtil util = new AbstractPredicateUtil(); + SearchFilter f = new SearchFilter(); + f.setParam(SearchFilter.RESOURCE_PREFIX + "path", "/data/2024"); + util.applyFilter(list, f); + Assertions.assertEquals(1, list.size()); + } + + @Test + public void test04_rolePredicateUtilByUserGroupRole() { + RangerPolicyItem item = new RangerPolicyItem(); + item.addUser("alice"); + item.addGroup("analytics"); + item.addRole("analyst"); + RangerPolicy p = new RangerPolicy(); + p.addPolicyItem(item); + List policies = new ArrayList<>(Collections.singletonList(p)); + + AbstractPredicateUtil util = new AbstractPredicateUtil(); + SearchFilter f = new SearchFilter(); + f.setParam(SearchFilter.USER, "ali"); + f.setParam(SearchFilter.GROUP, "lyt"); + f.setParam(SearchFilter.ROLE, "ana"); + util.applyFilter(policies, f); + Assertions.assertEquals(1, policies.size()); + } + + @Test + public void test05_servicePredicateUtilUsesServiceStore() throws Exception { + ServiceStore stub = new ServiceStore() { + @Override + public void init() { + } + + @Override + public RangerServiceDef createServiceDef(RangerServiceDef serviceDef) { + return null; + } + + @Override + public RangerServiceDef updateServiceDef(RangerServiceDef serviceDef) { + return null; + } + + @Override + public void deleteServiceDef(Long id, Boolean forceDelete) { + } + + @Override + public void updateTagServiceDefForAccessTypes() { + } + + @Override + public RangerServiceDef getServiceDef(Long id) { + return null; + } + + @Override + public RangerServiceDef getServiceDefByName(String name) { + return null; + } + + @Override + public RangerServiceDef getServiceDefByDisplayName(String name) { + return null; + } + + @Override + public List getServiceDefs(SearchFilter filter) { + return null; + } + + @Override + public PList getPaginatedServiceDefs(SearchFilter filter) { + return null; + } + + @Override + public RangerService createService(RangerService service) { + return null; + } + + @Override + public RangerService updateService(RangerService service, Map options) { + return null; + } + + @Override + public void deleteService(Long id) { + } + + @Override + public boolean serviceExists(String name) { + return false; + } + + @Override + public RangerService getService(Long id) { + return null; + } + + @Override + public RangerService getServiceByName(String name) { + RangerService s = new RangerService(); + s.setName(name); + s.setId(100L); + s.setType("hive"); + return s; + } + + @Override + public RangerService getServiceByDisplayName(String displayName) { + return null; + } + + @Override + public List getServices(SearchFilter filter) { + return null; + } + + @Override + public PList getPaginatedServices(SearchFilter filter) { + return null; + } + + @Override + public RangerPolicy createPolicy(RangerPolicy policy) { + return null; + } + + @Override + public RangerPolicy createDefaultPolicy(RangerPolicy policy) { + return null; + } + + @Override + public RangerPolicy updatePolicy(RangerPolicy policy) { + return null; + } + + @Override + public void deletePolicy(RangerPolicy policy, RangerService service) { + } + + @Override + public void deletePolicy(RangerPolicy policy) { + } + + @Override + public boolean policyExists(Long id) { + return false; + } + + @Override + public RangerPolicy getPolicy(Long id) { + return null; + } + + @Override + public List getPolicies(SearchFilter filter) { + return null; + } + + @Override + public Long getPolicyId(Long serviceId, String policyName, Long zoneId) { + return null; + } + + @Override + public PList getPaginatedPolicies(SearchFilter filter) { + return null; + } + + @Override + public List getPoliciesByResourceSignature(String serviceName, String policySignature, + Boolean isPolicyEnabled) { + return null; + } + + @Override + public List getServicePolicies(Long serviceId, SearchFilter filter) { + return null; + } + + @Override + public PList getPaginatedServicePolicies(Long serviceId, SearchFilter filter) { + return null; + } + + @Override + public List getServicePolicies(String serviceName, SearchFilter filter) { + return null; + } + + @Override + public PList getPaginatedServicePolicies(String serviceName, SearchFilter filter) { + return null; + } + + @Override + public ServicePolicies getServicePoliciesIfUpdated(String serviceName, + Long lastKnownVersion, boolean needsBackwardCompatibility) { + return null; + } + + @Override + public Long getServicePolicyVersion(String serviceName) { + return null; + } + + @Override + public ServicePolicies getServicePolicyDeltasOrPolicies(String serviceName, + Long lastKnownVersion) { + return null; + } + + @Override + public ServicePolicies getServicePolicyDeltas(String serviceName, + Long lastKnownVersion, Long cachedPolicyVersion) { + return null; + } + + @Override + public ServicePolicies getServicePolicies(String serviceName, + Long lastKnownVersion) { + return null; + } + + @Override + public RangerPolicy getPolicyFromEventTime(String eventTimeStr, Long policyId) { + return null; + } + + @Override + public Boolean getPopulateExistingBaseFields() { + return null; + } + + @Override + public void setPopulateExistingBaseFields(Boolean populateExistingBaseFields) { + } + + @Override + public RangerSecurityZone getSecurityZone(Long id) { + return null; + } + + @Override + public RangerSecurityZone getSecurityZone(String name) { + return null; + } + + @Override + public long getPoliciesCount(String serviceName) { + return 0; + } + + @Override + public Map getServiceConfigForPlugin(Long serviceId) { + return null; + } + + @Override + public List getPoliciesWithMetaAttributes(List policies) { + return null; + } + }; + + ServicePredicateUtil util = new ServicePredicateUtil(stub); + RangerPolicy pol = new RangerPolicy(); + pol.setService("svc1"); + List list = new ArrayList<>(Collections.singletonList(pol)); + SearchFilter f = new SearchFilter(); + f.setParam(SearchFilter.SERVICE_TYPE, "hive"); + util.applyFilter(list, f); + Assertions.assertEquals(1, list.size()); + } + + @Test + public void test06_securityZonePredicateUtil() { + RangerSecurityZone z = new RangerSecurityZone(); + z.setId(1L); + z.setName("zone-a"); + Map services = new HashMap<>(); + services.put("svc1", new RangerSecurityZone.RangerSecurityZoneService()); + z.setServices(services); + z.setCreatedBy("admin"); + List zones = new ArrayList<>(Collections.singletonList(z)); + + SecurityZonePredicateUtil util = new SecurityZonePredicateUtil(); + SearchFilter f = new SearchFilter(); + f.setParam(SearchFilter.SERVICE_NAME, "svc1"); + f.setParam(SearchFilter.ZONE_ID, "1"); + f.setParam(SearchFilter.ZONE_NAME, "zone-a"); + f.setParam(SearchFilter.NOT_ZONE_NAME, "zone-b"); + f.setParam(SearchFilter.ZONE_NAME_PARTIAL, "zone"); + f.setParam(SearchFilter.CREATED_BY, "admin"); + util.applyFilter(zones, f); + Assertions.assertEquals(1, zones.size()); + } + + @Test + public void test07_isRecursivePredicate() { + RangerPolicy p = new RangerPolicy(); + Map res = new HashMap<>(); + RangerPolicyResource r = new RangerPolicyResource("/a", false, true); + res.put("path", r); + p.setResources(res); + List list = new ArrayList<>(Collections.singletonList(p)); + + AbstractPredicateUtil util = new AbstractPredicateUtil(); + SearchFilter f = new SearchFilter(); + f.setParam(SearchFilter.IS_RECURSIVE, "true"); + util.applyFilter(list, f); + Assertions.assertEquals(1, list.size()); + + // Now set recursive to false and ensure mismatch when filter is true + res.put("path", new RangerPolicyResource("/a", false, false)); + p.setResources(res); + list = new ArrayList<>(Collections.singletonList(p)); + util.applyFilter(list, f); + Assertions.assertEquals(0, list.size()); + } + + @Test + public void test08_policyPriorityFilter() { + RangerPolicy p = new RangerPolicy(); + p.setPolicyPriority(RangerPolicy.POLICY_PRIORITY_OVERRIDE); + List list = new ArrayList<>(Collections.singletonList(p)); + + AbstractPredicateUtil util = new AbstractPredicateUtil(); + SearchFilter f = new SearchFilter(); + f.setParam(SearchFilter.POLICY_PRIORITY, RangerPolicy.POLICY_PRIORITY_NAME_OVERRIDE); + util.applyFilter(list, f); + Assertions.assertEquals(1, list.size()); + + f.setParam(SearchFilter.POLICY_PRIORITY, RangerPolicy.POLICY_PRIORITY_NAME_NORMAL); + list = new ArrayList<>(Collections.singletonList(p)); + util.applyFilter(list, f); + Assertions.assertEquals(0, list.size()); + } + + @Test + public void test09_zoneNamePredicateForPolicy() { + RangerPolicy p = new RangerPolicy(); + p.setZoneName("zone-x"); + List list = new ArrayList<>(Collections.singletonList(p)); + + AbstractPredicateUtil util = new AbstractPredicateUtil(); + SearchFilter f = new SearchFilter(); + f.setParam(SearchFilter.ZONE_NAME, "zone-x"); + util.applyFilter(list, f); + Assertions.assertEquals(1, list.size()); + + f.setParam(SearchFilter.ZONE_NAME, "other"); + list = new ArrayList<>(Collections.singletonList(p)); + util.applyFilter(list, f); + Assertions.assertEquals(0, list.size()); + } + + @Test + public void test10_tagServiceNamePredicateForService() { + RangerService s = new RangerService(); + s.setTagService("tagsvc"); + List list = new ArrayList<>(Collections.singletonList(s)); + + AbstractPredicateUtil util = new AbstractPredicateUtil(); + SearchFilter f = new SearchFilter(); + f.setParam(SearchFilter.TAG_SERVICE_NAME, "tagsvc"); + util.applyFilter(list, f); + Assertions.assertEquals(1, list.size()); + + f.setParam(SearchFilter.TAG_SERVICE_NAME, "other"); + list = new ArrayList<>(Collections.singletonList(s)); + util.applyFilter(list, f); + Assertions.assertEquals(0, list.size()); + } + + @Test + public void test11_reverseOrderWhenNoSorterButDesc() { + RangerPolicy p1 = new RangerPolicy(); + p1.setId(1L); + RangerPolicy p2 = new RangerPolicy(); + p2.setId(2L); + List list = new ArrayList<>(Arrays.asList(p1, p2)); + + AbstractPredicateUtil util = new AbstractPredicateUtil(); + SearchFilter f = new SearchFilter(); + f.setSortType("desc"); // no sortBy + util.applyFilter(list, f); + Assertions.assertEquals(2L, list.get(0).getId().longValue()); + } + + @Test + public void test12_isEnabledPredicateTrueAndFalse() { + RangerPolicy enabled = new RangerPolicy(); + enabled.setIsEnabled(true); + RangerPolicy disabled = new RangerPolicy(); + disabled.setIsEnabled(false); + List list = new ArrayList<>(Arrays.asList(enabled, disabled)); + + AbstractPredicateUtil util = new AbstractPredicateUtil(); + SearchFilter f = new SearchFilter(); + f.setParam(SearchFilter.IS_ENABLED, "true"); + List copy = new ArrayList<>(list); + util.applyFilter(copy, f); + Assertions.assertEquals(1, copy.size()); + Assertions.assertTrue(copy.get(0).getIsEnabled()); + + f.setParam(SearchFilter.IS_ENABLED, "false"); + copy = new ArrayList<>(list); + util.applyFilter(copy, f); + Assertions.assertEquals(1, copy.size()); + Assertions.assertFalse(copy.get(0).getIsEnabled()); + } + + @Test + public void test13_policyResourceContainsMatch() { + RangerPolicy p = new RangerPolicy(); + Map res = new HashMap<>(); + res.put("db", new RangerPolicyResource("sales")); + p.setResources(res); + List list = new ArrayList<>(Collections.singletonList(p)); + + AbstractPredicateUtil util = new AbstractPredicateUtil(); + SearchFilter f = new SearchFilter(); + f.setParam(SearchFilter.POL_RESOURCE, "ale"); // partial in 'sales' + util.applyFilter(list, f); + Assertions.assertEquals(1, list.size()); + } + + @Test + public void test14_resourceSignaturePredicate() { + RangerPolicy p = new RangerPolicy(); + p.setResourceSignature("sig-123"); + List list = new ArrayList<>(Collections.singletonList(p)); + + AbstractPredicateUtil util = new AbstractPredicateUtil(); + SearchFilter f = new SearchFilter(); + f.setParam(SearchFilter.RESOURCE_SIGNATURE, "sig-123"); + util.applyFilter(list, f); + Assertions.assertEquals(1, list.size()); + + list = new ArrayList<>(Collections.singletonList(p)); + f.setParam(SearchFilter.RESOURCE_SIGNATURE, "other"); + util.applyFilter(list, f); + Assertions.assertEquals(0, list.size()); + } + + @Test + public void test15_sorterMapOtherSorters() { + RangerServiceDef sd1 = new RangerServiceDef(); + sd1.setName("a"); + RangerServiceDef sd2 = new RangerServiceDef(); + sd2.setName("b"); + List defs = new ArrayList<>(Arrays.asList(sd2, sd1)); + AbstractPredicateUtil util = new AbstractPredicateUtil(); + SearchFilter f = new SearchFilter(); + f.setSortBy(SearchFilter.SERVICE_TYPE); + util.applyFilter(defs, f); + Assertions.assertEquals("a", defs.get(0).getName()); + + RangerPolicy p1 = new RangerPolicy(); + p1.setName("alpha"); + RangerPolicy p2 = new RangerPolicy(); + p2.setName("beta"); + List policies = new ArrayList<>(Arrays.asList(p2, p1)); + f = new SearchFilter(); + f.setSortBy(SearchFilter.POLICY_NAME); + util.applyFilter(policies, f); + Assertions.assertEquals("alpha", policies.get(0).getName()); + } +} diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/store/TestAbstractServiceStore.java b/agents-common/src/test/java/org/apache/ranger/plugin/store/TestAbstractServiceStore.java new file mode 100644 index 0000000000..3f3710ac03 --- /dev/null +++ b/agents-common/src/test/java/org/apache/ranger/plugin/store/TestAbstractServiceStore.java @@ -0,0 +1,1047 @@ +/* + * 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.store; + +import org.apache.ranger.authorization.hadoop.config.RangerAdminConfig; +import org.apache.ranger.plugin.model.RangerPolicy; +import org.apache.ranger.plugin.model.RangerSecurityZone; +import org.apache.ranger.plugin.model.RangerService; +import org.apache.ranger.plugin.model.RangerServiceDef; +import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef; +import org.apache.ranger.plugin.util.SearchFilter; +import org.apache.ranger.plugin.util.ServicePolicies; +import org.apache.ranger.services.tag.RangerServiceTag; +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.junit.jupiter.MockitoExtension; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * @generated by Cursor + * @description + */ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +public class TestAbstractServiceStore { + public static class MyServiceStore extends AbstractServiceStore { + private final List sds; + private final List svcs; + private final List pols; + + MyServiceStore(List sds, List svcs, List pols) { + this.sds = sds; + this.svcs = svcs; + this.pols = pols; + } + + @Override + protected void updateServicesForServiceDefUpdate(RangerServiceDef serviceDef) { + } + + @Override + public void init() { + } + + @Override + public RangerServiceDef createServiceDef(RangerServiceDef serviceDef) { + return null; + } + + @Override + public RangerServiceDef updateServiceDef(RangerServiceDef serviceDef) { + return null; + } + + @Override + public void deleteServiceDef(Long id, Boolean forceDelete) { + } + + @Override + public RangerServiceDef getServiceDef(Long id) { + return null; + } + + @Override + public RangerServiceDef getServiceDefByName(String name) { + return null; + } + + @Override + public RangerServiceDef getServiceDefByDisplayName(String name) { + return null; + } + + @Override + public List getServiceDefs(SearchFilter filter) { + return sds; + } + + @Override + public PList getPaginatedServiceDefs(SearchFilter filter) throws Exception { + return super.getPaginatedServiceDefs(filter); + } + + @Override + public RangerService createService(RangerService service) { + return null; + } + + @Override + public RangerService updateService(RangerService service, Map options) { + return null; + } + + @Override + public void deleteService(Long id) { + } + + @Override + public boolean serviceExists(String name) { + return false; + } + + @Override + public RangerService getService(Long id) { + return null; + } + + @Override + public RangerService getServiceByName(String name) { + return null; + } + + @Override + public RangerService getServiceByDisplayName(String displayName) { + return null; + } + + @Override + public List getServices(SearchFilter filter) { + return svcs; + } + + @Override + public PList getPaginatedServices(SearchFilter filter) throws Exception { + return super.getPaginatedServices(filter); + } + + @Override + public RangerPolicy createPolicy(RangerPolicy policy) { + return null; + } + + @Override + public RangerPolicy createDefaultPolicy(RangerPolicy policy) { + return null; + } + + @Override + public RangerPolicy updatePolicy(RangerPolicy policy) { + return null; + } + + @Override + public void deletePolicy(RangerPolicy policy, RangerService service) { + } + + @Override + public void deletePolicy(RangerPolicy policy) { + } + + @Override + public boolean policyExists(Long id) { + return false; + } + + @Override + public RangerPolicy getPolicy(Long id) { + return null; + } + + @Override + public List getPolicies(SearchFilter filter) { + return pols; + } + + @Override + public PList getPaginatedPolicies(SearchFilter filter) throws Exception { + return super.getPaginatedPolicies(filter); + } + + @Override + public Long getPolicyId(Long serviceId, String policyName, Long zoneId) { + return null; + } + + @Override + public List getServicePolicies(Long serviceId, SearchFilter filter) { + return pols; + } + + @Override + public PList getPaginatedServicePolicies(Long serviceId, SearchFilter filter) throws Exception { + return super.getPaginatedServicePolicies(serviceId, filter); + } + + @Override + public List getServicePolicies(String serviceName, SearchFilter filter) { + return pols; + } + + @Override + public PList getPaginatedServicePolicies(String serviceName, SearchFilter filter) + throws Exception { + return super.getPaginatedServicePolicies(serviceName, filter); + } + + @Override + public ServicePolicies getServicePoliciesIfUpdated(String serviceName, Long lastKnownVersion, + boolean needsBackwardCompatibility) { + return null; + } + + @Override + public Long getServicePolicyVersion(String serviceName) { + return super.getServicePolicyVersion(serviceName); + } + + @Override + public ServicePolicies getServicePolicyDeltasOrPolicies(String serviceName, Long lastKnownVersion) { + return null; + } + + @Override + public ServicePolicies getServicePolicyDeltas(String serviceName, Long lastKnownVersion, + Long cachedPolicyVersion) { + return null; + } + + @Override + public ServicePolicies getServicePolicies(String serviceName, Long lastKnownVersion) { + return null; + } + + @Override + public RangerPolicy getPolicyFromEventTime(String eventTimeStr, Long policyId) { + return null; + } + + @Override + public Boolean getPopulateExistingBaseFields() { + return null; + } + + @Override + public void setPopulateExistingBaseFields(Boolean populateExistingBaseFields) { + } + + @Override + public RangerSecurityZone getSecurityZone(Long id) { + return null; + } + + @Override + public RangerSecurityZone getSecurityZone(String name) { + return null; + } + + @Override + public long getPoliciesCount(String serviceName) { + return 0; + } + + @Override + public Map getServiceConfigForPlugin(Long serviceId) { + return null; + } + + @Override + public List getPoliciesWithMetaAttributes(List policies) { + return policies; + } + + @Override + public List getPoliciesByResourceSignature(String serviceName, String policySignature, + Boolean isPolicyEnabled) { + return pols; + } + } + + public static class UpdateStore extends MyServiceStore { + public RangerServiceDef lastUpdated; + private final Long tagId; + private final RangerServiceDef tagRef; + + public UpdateStore(List sds, RangerServiceDef tagRef) { + super(sds, new ArrayList<>(), new ArrayList<>()); + this.tagRef = tagRef; + this.tagId = tagRef.getId(); + } + + @Override + public RangerServiceDef getServiceDef(Long id) { + return id != null && id.equals(tagId) ? tagRef : null; + } + + @Override + public RangerServiceDef updateServiceDef(RangerServiceDef serviceDef) { + this.lastUpdated = serviceDef; + return serviceDef; + } + } + + public static class CapturingStore extends MyServiceStore { + public RangerServiceDef lastUpdated; + + public CapturingStore(List sds) { + super(sds, new ArrayList<>(), new ArrayList<>()); + } + + @Override + public RangerServiceDef updateServiceDef(RangerServiceDef serviceDef) { + this.lastUpdated = serviceDef; + return serviceDef; + } + } + + public static class ThrowingServiceStore extends MyServiceStore { + public ThrowingServiceStore(List sds, List svcs, List pols) { + super(sds, svcs, pols); + } + + @Override + public RangerService getServiceByName(String name) { + throw new RuntimeException("boom"); + } + } + + public static class DeleteStore extends MyServiceStore { + public RangerServiceDef lastUpdated; + private final Long tagId; + private final RangerServiceDef tagRef; + + public DeleteStore(List sds, RangerServiceDef tagRef) { + super(sds, new ArrayList<>(), new ArrayList<>()); + this.tagRef = tagRef; + this.tagId = tagRef.getId(); + } + + @Override + public RangerServiceDef getServiceDef(Long id) { + return id != null && id.equals(tagId) ? tagRef : null; + } + + @Override + public RangerServiceDef updateServiceDef(RangerServiceDef serviceDef) { + this.lastUpdated = serviceDef; + return serviceDef; + } + } + + public static class PostUpdateStore extends UpdateStore { + public boolean servicesUpdated; + + public PostUpdateStore(List sds, RangerServiceDef tagRef) { + super(sds, tagRef); + } + + @Override + protected void updateServicesForServiceDefUpdate(RangerServiceDef serviceDef) { + servicesUpdated = true; + } + } + + @Test + public void test01_getNextVersionAndPaginatedHelpers() throws Exception { + Assertions.assertEquals(1L, AbstractServiceStore.getNextVersion(null)); + Assertions.assertEquals(6L, AbstractServiceStore.getNextVersion(5L)); + + List sds = new ArrayList<>(Collections.singletonList(new RangerServiceDef())); + List svcs = new ArrayList<>(Collections.singletonList(new RangerService())); + List pols = new ArrayList<>(Collections.singletonList(new RangerPolicy())); + MyServiceStore store = new MyServiceStore(sds, svcs, pols); + + PList p1 = store.getPaginatedServiceDefs(new SearchFilter()); + Assertions.assertEquals(1, p1.getListSize()); + PList p2 = store.getPaginatedServices(new SearchFilter()); + Assertions.assertEquals(1, p2.getListSize()); + PList p3 = store.getPaginatedPolicies(new SearchFilter()); + Assertions.assertEquals(1, p3.getListSize()); + + PList p4 = store.getPaginatedServicePolicies(1L, new SearchFilter()); + Assertions.assertEquals(1, p4.getListSize()); + PList p5 = store.getPaginatedServicePolicies("svc", new SearchFilter()); + Assertions.assertEquals(1, p5.getListSize()); + } + + @Test + public void test02_getServicePolicyVersionHandlesNullService() { + List sds = new ArrayList<>(); + List svcs = new ArrayList<>(); + List pols = new ArrayList<>(); + MyServiceStore store = new MyServiceStore(sds, svcs, pols); + + // getServiceByName returns null in stub; should return null and not throw + Assertions.assertNull(store.getServicePolicyVersion("missing")); + } + + @Test + public void test03_getPaginatedServicePoliciesByNameAndId() throws Exception { + List sds = new ArrayList<>(); + List svcs = new ArrayList<>(); + List pols = new ArrayList<>(); + pols.add(new RangerPolicy()); + MyServiceStore store = new MyServiceStore(sds, svcs, pols); + + PList pById = store.getPaginatedServicePolicies(5L, new SearchFilter()); + Assertions.assertEquals(1, pById.getList().size()); + PList pByName = store.getPaginatedServicePolicies("svc1", new SearchFilter()); + Assertions.assertEquals(1, pByName.getList().size()); + } + + @Test + public void test04_getServicePolicyVersion_whenGetServiceByNameThrows_returnsNull() { + List sds = new ArrayList<>(); + List svcs = new ArrayList<>(); + List pols = new ArrayList<>(); + ThrowingServiceStore store = new ThrowingServiceStore(sds, svcs, pols); + + Assertions.assertNull(store.getServicePolicyVersion("svc")); + } + + @Test + public void test05_getPaginatedEmptyLists() throws Exception { + List sds = new ArrayList<>(); + List svcs = new ArrayList<>(); + List pols = new ArrayList<>(); + MyServiceStore store = new MyServiceStore(sds, svcs, pols); + + PList p1 = store.getPaginatedServiceDefs(new SearchFilter()); + Assertions.assertEquals(0, p1.getListSize()); + PList p2 = store.getPaginatedServices(new SearchFilter()); + Assertions.assertEquals(0, p2.getListSize()); + PList p3 = store.getPaginatedPolicies(new SearchFilter()); + Assertions.assertEquals(0, p3.getListSize()); + + PList p4 = store.getPaginatedServicePolicies(1L, new SearchFilter()); + Assertions.assertEquals(0, p4.getListSize()); + PList p5 = store.getPaginatedServicePolicies("svc", new SearchFilter()); + Assertions.assertEquals(0, p5.getListSize()); + } + + @Test + public void test06_updateTagServiceDefForAccessTypes_updatesAccessTypesMaskAndRowFilter() throws Exception { + // Enable row-filter auto-propagation before store construction + RangerAdminConfig.getInstance().set(AbstractServiceStore.AUTOPROPAGATE_ROWFILTERDEF_TO_TAG_PROP, "true"); + + // Prepare service def "hdfs" with accessTypes, dataMask and rowFilter + RangerServiceDef svcDef = new RangerServiceDef(); + svcDef.setId(2L); + svcDef.setName("hdfs"); + List svcAccess = new ArrayList<>(); + svcAccess.add(new RangerAccessTypeDef(1L, "read", "read", null, null)); + svcDef.setAccessTypes(svcAccess); + + RangerServiceDef.RangerDataMaskDef svcMaskDef = new RangerServiceDef.RangerDataMaskDef(); + List maskTypes = new ArrayList<>(); + maskTypes.add(new RangerServiceDef.RangerDataMaskTypeDef(1L, "MASK", "MASK", null, null, null, null, null)); + svcMaskDef.setMaskTypes(maskTypes); + List maskAccess = new ArrayList<>(); + maskAccess.add(new RangerAccessTypeDef(2L, "read", "read", null, null)); + svcMaskDef.setAccessTypes(maskAccess); + svcDef.setDataMaskDef(svcMaskDef); + + RangerServiceDef.RangerRowFilterDef svcRowDef = new RangerServiceDef.RangerRowFilterDef(); + List rowAccess = new ArrayList<>(); + rowAccess.add(new RangerAccessTypeDef(3L, "select", "select", null, null)); + svcRowDef.setAccessTypes(rowAccess); + svcDef.setRowFilterDef(svcRowDef); + + // Prepare tag service-def with TAG resource + RangerServiceDef tagDef = new RangerServiceDef(); + tagDef.setId(500L); + tagDef.setName(RangerServiceTag.TAG_RESOURCE_NAME); + List tagResources = new ArrayList<>(); + RangerServiceDef.RangerResourceDef tagRes = new RangerServiceDef.RangerResourceDef(); + tagRes.setName(RangerServiceTag.TAG_RESOURCE_NAME); + tagResources.add(tagRes); + tagDef.setResources(tagResources); + + List sds = new ArrayList<>(); + sds.add(svcDef); + UpdateStore store = new UpdateStore(sds, tagDef); + + // Wire EmbeddedServiceDefsUtil.tagServiceDef via reflection so + // getTagServiceDefId() matches + Field f = EmbeddedServiceDefsUtil.class.getDeclaredField("tagServiceDef"); + f.setAccessible(true); + f.set(EmbeddedServiceDefsUtil.instance(), tagDef); + + store.updateTagServiceDefForAccessTypes(); + + Assertions.assertNotNull(store.lastUpdated); + // Access types propagated with prefix + Assertions.assertTrue(tagDef.getAccessTypes().stream().anyMatch(a -> "hdfs:read".equals(a.getName()))); + // Data mask: mask type added with prefixed name and itemId offset 2*(1000+1)+1 + // = 2003 + RangerServiceDef.RangerDataMaskDef updatedMaskDef = tagDef.getDataMaskDef(); + Assertions.assertTrue(updatedMaskDef.getMaskTypes().stream().anyMatch(m -> "hdfs:MASK".equals(m.getName()))); + Assertions.assertEquals(1, updatedMaskDef.getResources().size()); + Assertions.assertEquals(RangerServiceTag.TAG_RESOURCE_NAME, updatedMaskDef.getResources().get(0).getName()); + // Row filter propagated and resources set due to auto-propagation + RangerServiceDef.RangerRowFilterDef updatedRowDef = tagDef.getRowFilterDef(); + Assertions.assertTrue(updatedRowDef.getAccessTypes().stream().anyMatch(a -> "hdfs:select".equals(a.getName()))); + Assertions.assertEquals(1, updatedRowDef.getResources().size()); + Assertions.assertEquals(RangerServiceTag.TAG_RESOURCE_NAME, updatedRowDef.getResources().get(0).getName()); + } + + @Test + public void test07_updateTagServiceDefForAccessTypes_tagServiceDefMissing_noUpdate() throws Exception { + // Ensure EmbeddedServiceDefsUtil has no tag service-def + Field f = EmbeddedServiceDefsUtil.class.getDeclaredField("tagServiceDef"); + f.setAccessible(true); + f.set(EmbeddedServiceDefsUtil.instance(), null); + + RangerServiceDef svcDef = new RangerServiceDef(); + svcDef.setId(1L); + svcDef.setName("hdfs"); + svcDef.setAccessTypes(new ArrayList<>()); + + List sds = new ArrayList<>(); + sds.add(svcDef); + CapturingStore store = new CapturingStore(sds); + + store.updateTagServiceDefForAccessTypes(); + + Assertions.assertNull(store.lastUpdated); + } + + @Test + public void test08_postDelete_removesPrefixedAccessTypesAndClearsResourcesWhenEmpty() throws Exception { + // Prepare tag service-def with resources and some prefixed entries + RangerServiceDef tagDef = new RangerServiceDef(); + tagDef.setId(600L); + tagDef.setName(RangerServiceTag.TAG_RESOURCE_NAME); + List tagResources = new ArrayList<>(); + RangerServiceDef.RangerResourceDef tagRes = new RangerServiceDef.RangerResourceDef(); + tagRes.setName(RangerServiceTag.TAG_RESOURCE_NAME); + tagResources.add(tagRes); + tagDef.setResources(tagResources); + + List tagAccess = new ArrayList<>(); + tagAccess.add(new RangerAccessTypeDef(1L, "hdfs:read", "hdfs:read", null, null)); + tagAccess.add(new RangerAccessTypeDef(2L, "kafka:publish", "kafka:publish", null, null)); + tagAccess.add(new RangerAccessTypeDef(3L, "hdfs:write", "hdfs:write", null, null)); + tagDef.setAccessTypes(tagAccess); + + RangerServiceDef.RangerDataMaskDef tagMask = new RangerServiceDef.RangerDataMaskDef(); + List maskAccess = new ArrayList<>(); + maskAccess.add(new RangerAccessTypeDef(10L, "hdfs:read", "hdfs:read", null, null)); + tagMask.setAccessTypes(maskAccess); + List maskTypes = new ArrayList<>(); + maskTypes.add(new RangerServiceDef.RangerDataMaskTypeDef(11L, "hdfs:MASK", "hdfs:MASK", null, null, null, null, + null)); + tagMask.setMaskTypes(maskTypes); + List maskRes = new ArrayList<>(); + maskRes.add(tagRes); + tagMask.setResources(maskRes); + tagDef.setDataMaskDef(tagMask); + + RangerServiceDef.RangerRowFilterDef tagRow = new RangerServiceDef.RangerRowFilterDef(); + List rowAccess = new ArrayList<>(); + rowAccess.add(new RangerAccessTypeDef(20L, "hdfs:select", "hdfs:select", null, null)); + tagRow.setAccessTypes(rowAccess); + List rowRes = new ArrayList<>(); + rowRes.add(tagRes); + tagRow.setResources(rowRes); + tagDef.setRowFilterDef(tagRow); + + // Set tag service-def in EmbeddedServiceDefsUtil + Field f = EmbeddedServiceDefsUtil.class.getDeclaredField("tagServiceDef"); + f.setAccessible(true); + f.set(EmbeddedServiceDefsUtil.instance(), tagDef); + + RangerServiceDef svcDef = new RangerServiceDef(); + svcDef.setId(2L); + svcDef.setName("hdfs"); + + List sds = new ArrayList<>(); + sds.add(svcDef); + DeleteStore store = new DeleteStore(sds, tagDef); + + store.postDelete(svcDef); + + Assertions.assertNotNull(store.lastUpdated); + // Prefixed access types removed + Assertions.assertTrue(tagDef.getAccessTypes().stream().noneMatch(a -> a.getName().startsWith("hdfs:"))); + Assertions.assertTrue(tagDef.getAccessTypes().stream().anyMatch(a -> a.getName().equals("kafka:publish"))); + // Data mask and row filter entries for hdfs removed; since accessTypes become + // empty, resources should be cleared by updateResourceInTagServiceDef + Assertions.assertTrue(tagDef.getDataMaskDef().getAccessTypes().isEmpty()); + Assertions.assertTrue(tagDef.getDataMaskDef().getMaskTypes().isEmpty()); + Assertions.assertTrue(tagDef.getDataMaskDef().getResources().isEmpty()); + Assertions.assertTrue(tagDef.getRowFilterDef().getAccessTypes().isEmpty()); + Assertions.assertTrue(tagDef.getRowFilterDef().getResources().isEmpty()); + } + + @Test + public void test09_postCreate_updatesTagServiceDef_whenServiceDefCreated() throws Exception { + RangerServiceDef svcDef = new RangerServiceDef(); + svcDef.setId(3L); + svcDef.setName("hdfs"); + List svcAccess = new ArrayList<>(); + svcAccess.add(new RangerAccessTypeDef(1L, "read", "read", null, null)); + svcDef.setAccessTypes(svcAccess); + + RangerServiceDef tagDef = new RangerServiceDef(); + tagDef.setId(700L); + tagDef.setName(RangerServiceTag.TAG_RESOURCE_NAME); + List tagResources = new ArrayList<>(); + RangerServiceDef.RangerResourceDef tagRes = new RangerServiceDef.RangerResourceDef(); + tagRes.setName(RangerServiceTag.TAG_RESOURCE_NAME); + tagResources.add(tagRes); + tagDef.setResources(tagResources); + + List sds = new ArrayList<>(); + sds.add(svcDef); + UpdateStore store = new UpdateStore(sds, tagDef); + + Field f = EmbeddedServiceDefsUtil.class.getDeclaredField("tagServiceDef"); + f.setAccessible(true); + f.set(EmbeddedServiceDefsUtil.instance(), tagDef); + + store.postCreate(svcDef); + + Assertions.assertNotNull(store.lastUpdated); + Assertions.assertTrue(tagDef.getAccessTypes().stream().anyMatch(a -> "hdfs:read".equals(a.getName()))); + } + + @Test + public void test10_postCreate_nonServiceDef_noop() throws Exception { + RangerServiceDef tagDef = new RangerServiceDef(); + tagDef.setId(701L); + tagDef.setName(RangerServiceTag.TAG_RESOURCE_NAME); + + List sds = new ArrayList<>(); + UpdateStore store = new UpdateStore(sds, tagDef); + + Field f = EmbeddedServiceDefsUtil.class.getDeclaredField("tagServiceDef"); + f.setAccessible(true); + f.set(EmbeddedServiceDefsUtil.instance(), tagDef); + + store.postCreate(new RangerPolicy()); + Assertions.assertNull(store.lastUpdated); + } + + @Test + public void test11_postUpdate_updatesTagServiceDef_andInvokesServicesUpdate() throws Exception { + RangerServiceDef svcDef = new RangerServiceDef(); + svcDef.setId(4L); + svcDef.setName("kafka"); + List svcAccess = new ArrayList<>(); + svcAccess.add(new RangerAccessTypeDef(1L, "publish", "publish", null, null)); + svcDef.setAccessTypes(svcAccess); + + RangerServiceDef tagDef = new RangerServiceDef(); + tagDef.setId(702L); + tagDef.setName(RangerServiceTag.TAG_RESOURCE_NAME); + + List sds = new ArrayList<>(); + sds.add(svcDef); + PostUpdateStore store = new PostUpdateStore(sds, tagDef); + + Field f = EmbeddedServiceDefsUtil.class.getDeclaredField("tagServiceDef"); + f.setAccessible(true); + f.set(EmbeddedServiceDefsUtil.instance(), tagDef); + + store.postUpdate(svcDef); + + Assertions.assertNotNull(store.lastUpdated); + Assertions.assertTrue(store.servicesUpdated); + Assertions.assertTrue(tagDef.getAccessTypes().stream().anyMatch(a -> "kafka:publish".equals(a.getName()))); + } + + @Test + public void test12_postUpdate_nonServiceDef_noop() throws Exception { + RangerServiceDef tagDef = new RangerServiceDef(); + tagDef.setId(703L); + tagDef.setName(RangerServiceTag.TAG_RESOURCE_NAME); + + List sds = new ArrayList<>(); + PostUpdateStore store = new PostUpdateStore(sds, tagDef); + + Field f = EmbeddedServiceDefsUtil.class.getDeclaredField("tagServiceDef"); + f.setAccessible(true); + f.set(EmbeddedServiceDefsUtil.instance(), tagDef); + + store.postUpdate(new RangerPolicy()); + Assertions.assertNull(store.lastUpdated); + Assertions.assertFalse(store.servicesUpdated); + } + + @Test + public void test13_getServicePolicyVersion_success() { + List sds = new ArrayList<>(); + List pols = new ArrayList<>(); + List svcs = new ArrayList<>(); + + MyServiceStore store = new MyServiceStore(sds, svcs, pols) { + @Override + public Long getServicePolicyVersion(String serviceName) { + return super.getServicePolicyVersion(serviceName); + } + + @Override + public RangerService getServiceByName(String name) { + RangerService svc = new RangerService(); + svc.setPolicyVersion(9L); + return svc; + } + }; + + Assertions.assertEquals(9L, store.getServicePolicyVersion("svc")); + } + + @Test + public void test14_updateTagAccessTypeDef_noChange_returnsFalse() throws Exception { + MyServiceStore store = new MyServiceStore(new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); + + RangerAccessTypeDef svcAccess = new RangerAccessTypeDef(1L, "read", "lbl", "rb", null); + List svcImplied = new ArrayList<>(); + svcImplied.add("write"); + svcAccess.setImpliedGrants(svcImplied); + + RangerAccessTypeDef tagAccess = new RangerAccessTypeDef(1001L, "hdfs:read", "lbl", "rb", null); + List tagImplied = new ArrayList<>(); + tagImplied.add("hdfs:write"); + tagAccess.setImpliedGrants(tagImplied); + + Method m = AbstractServiceStore.class.getDeclaredMethod("updateTagAccessTypeDef", + RangerAccessTypeDef.class, + RangerAccessTypeDef.class, + String.class); + m.setAccessible(true); + + Boolean updated = (Boolean) m.invoke(store, tagAccess, svcAccess, "hdfs:"); + Assertions.assertFalse(updated); + Assertions.assertEquals("hdfs:read", tagAccess.getName()); + Assertions.assertEquals("lbl", tagAccess.getLabel()); + Assertions.assertEquals("rb", tagAccess.getRbKeyLabel()); + Assertions.assertTrue(tagAccess.getImpliedGrants().contains("hdfs:write")); + } + + @Test + public void test15_updateTagAccessTypeDef_nameDiff_updatesAndPrefixesImpliedGrants() throws Exception { + MyServiceStore store = new MyServiceStore(new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); + + RangerAccessTypeDef svcAccess = new RangerAccessTypeDef(1L, "read", "lbl2", "rb2", null); + List svcImplied = new ArrayList<>(); + svcImplied.add("write"); + svcImplied.add("execute"); + svcAccess.setImpliedGrants(svcImplied); + + RangerAccessTypeDef tagAccess = new RangerAccessTypeDef(1001L, "other", "old", "oldrb", null); + List tagImplied = new ArrayList<>(); + tagImplied.add("hdfs:old"); + tagAccess.setImpliedGrants(tagImplied); + + Method m = AbstractServiceStore.class.getDeclaredMethod("updateTagAccessTypeDef", + RangerAccessTypeDef.class, + RangerAccessTypeDef.class, + String.class); + m.setAccessible(true); + + Boolean updated = (Boolean) m.invoke(store, tagAccess, svcAccess, "hdfs:"); + Assertions.assertTrue(updated); + Assertions.assertEquals("hdfs:read", tagAccess.getName()); + Assertions.assertEquals("lbl2", tagAccess.getLabel()); + Assertions.assertEquals("rb2", tagAccess.getRbKeyLabel()); + Assertions.assertTrue(tagAccess.getImpliedGrants().contains("hdfs:write")); + Assertions.assertTrue(tagAccess.getImpliedGrants().contains("hdfs:execute")); + } + + @Test + public void test16_updateTagAccessTypeDef_impliedGrantMissing_updates() throws Exception { + MyServiceStore store = new MyServiceStore(new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); + + RangerAccessTypeDef svcAccess = new RangerAccessTypeDef(1L, "read", "lbl", "rb", null); + List svcImplied = new ArrayList<>(); + svcImplied.add("write"); + svcImplied.add("execute"); + svcAccess.setImpliedGrants(svcImplied); + + // tag has correct name/labels but only one implied grant; missing one should trigger update via inner loop + RangerAccessTypeDef tagAccess = new RangerAccessTypeDef(1001L, "hdfs:read", "lbl", "rb", null); + List tagImplied = new ArrayList<>(); + tagImplied.add("hdfs:write"); + tagAccess.setImpliedGrants(tagImplied); + + Method m = AbstractServiceStore.class.getDeclaredMethod("updateTagAccessTypeDef", + RangerAccessTypeDef.class, + RangerAccessTypeDef.class, + String.class); + m.setAccessible(true); + + Boolean updated = (Boolean) m.invoke(store, tagAccess, svcAccess, "hdfs:"); + Assertions.assertTrue(updated); + Assertions.assertTrue(tagAccess.getImpliedGrants().contains("hdfs:write")); + Assertions.assertTrue(tagAccess.getImpliedGrants().contains("hdfs:execute")); + } + + @Test + public void test17_updateTagAccessTypeDef_labelOrRbKeyDiff_updates() throws Exception { + MyServiceStore store = new MyServiceStore(new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); + + // Same name once prefix is removed, but label differs + RangerAccessTypeDef svcAccess = new RangerAccessTypeDef(1L, "read", "newLbl", "newRb", null); + List svcImplied = new ArrayList<>(); + svcImplied.add("write"); + svcAccess.setImpliedGrants(svcImplied); + + RangerAccessTypeDef tagAccess = new RangerAccessTypeDef(1001L, "hdfs:read", "oldLbl", "oldRb", null); + List tagImplied = new ArrayList<>(); + tagImplied.add("hdfs:write"); + tagAccess.setImpliedGrants(tagImplied); + + Method m = AbstractServiceStore.class.getDeclaredMethod("updateTagAccessTypeDef", + RangerAccessTypeDef.class, + RangerAccessTypeDef.class, + String.class); + m.setAccessible(true); + + Boolean updated = (Boolean) m.invoke(store, tagAccess, svcAccess, "hdfs:"); + Assertions.assertTrue(updated); + Assertions.assertEquals("hdfs:read", tagAccess.getName()); + Assertions.assertEquals("newLbl", tagAccess.getLabel()); + Assertions.assertEquals("newRb", tagAccess.getRbKeyLabel()); + Assertions.assertTrue(tagAccess.getImpliedGrants().contains("hdfs:write")); + } + + @Test + void test18_findAccessTypeDef_found() throws Exception { + AbstractServiceStore store = new MyServiceStore(new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); + + List list = new ArrayList<>(); + list.add(new RangerAccessTypeDef(1L, "a", "a", null, null)); + list.add(new RangerAccessTypeDef(2L, "b", "b", null, null)); + + Method m = AbstractServiceStore.class.getDeclaredMethod("findAccessTypeDef", long.class, List.class); + m.setAccessible(true); + + Object ret = m.invoke(store, 2L, list); + Assertions.assertNotNull(ret); + Assertions.assertEquals(2L, ((RangerAccessTypeDef) ret).getItemId()); + } + + @Test + void test19_findAccessTypeDef_notFound() throws Exception { + AbstractServiceStore store = new MyServiceStore(new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); + + List list = new ArrayList<>(); + list.add(new RangerAccessTypeDef(3L, "a", "a", null, null)); + list.add(new RangerAccessTypeDef(4L, "b", "b", null, null)); + + Method m = AbstractServiceStore.class.getDeclaredMethod("findAccessTypeDef", long.class, List.class); + m.setAccessible(true); + + Object ret = m.invoke(store, 2L, list); + Assertions.assertNull(ret); + } + + @Test + void test20_updateTagAccessTypeDefs_addsMissingFromSvc() throws Exception { + AbstractServiceStore store = new MyServiceStore(new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); + + List svc = new ArrayList<>(); + RangerAccessTypeDef svcRead = new RangerAccessTypeDef(1L, "read", "lbl", "rb", null); + List svcImpl = new ArrayList<>(); + svcImpl.add("write"); + svcRead.setImpliedGrants(svcImpl); + svc.add(svcRead); + + List tag = new ArrayList<>(); + + Method m = AbstractServiceStore.class.getDeclaredMethod("updateTagAccessTypeDefs", List.class, List.class, long.class, String.class); + m.setAccessible(true); + + Boolean updated = (Boolean) m.invoke(store, svc, tag, 100L, "hdfs:"); + Assertions.assertTrue(updated); + Assertions.assertEquals(1, tag.size()); + Assertions.assertEquals(Long.valueOf(101L), tag.get(0).getItemId()); + Assertions.assertEquals("hdfs:read", tag.get(0).getName()); + Assertions.assertTrue(tag.get(0).getImpliedGrants().contains("hdfs:write")); + } + + @Test + void test21_updateTagAccessTypeDefs_updatesChangedEntries() throws Exception { + AbstractServiceStore store = new MyServiceStore(new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); + + List svc = new ArrayList<>(); + RangerAccessTypeDef svcRead = new RangerAccessTypeDef(2L, "read", "newLbl", "newRb", null); + List svcImpl = new ArrayList<>(); + svcImpl.add("execute"); + svcRead.setImpliedGrants(svcImpl); + svc.add(svcRead); + + List tag = new ArrayList<>(); + RangerAccessTypeDef tagRead = new RangerAccessTypeDef(1002L, "hdfs:old", "oldLbl", "oldRb", null); + List tagImpl = new ArrayList<>(); + tagImpl.add("hdfs:write"); + tagRead.setImpliedGrants(tagImpl); + tag.add(tagRead); + + Method m = AbstractServiceStore.class.getDeclaredMethod("updateTagAccessTypeDefs", List.class, List.class, long.class, String.class); + m.setAccessible(true); + + Boolean updated = (Boolean) m.invoke(store, svc, tag, 100L, "hdfs:"); + Assertions.assertTrue(updated); + Assertions.assertEquals(1, tag.size()); + Assertions.assertEquals("hdfs:read", tag.get(0).getName()); + Assertions.assertEquals("newLbl", tag.get(0).getLabel()); + Assertions.assertEquals("newRb", tag.get(0).getRbKeyLabel()); + Assertions.assertTrue(tag.get(0).getImpliedGrants().contains("hdfs:execute")); + } + + @Test + void test22_updateTagAccessTypeDefs_deletesRemovedFromSvc() throws Exception { + AbstractServiceStore store = new MyServiceStore(new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); + + List svc = new ArrayList<>(); + // svc intentionally empty to trigger deletion of prefixed tag entry + + List tag = new ArrayList<>(); + RangerAccessTypeDef tagWrite = new RangerAccessTypeDef(1003L, "hdfs:write", "write", null, null); + tag.add(tagWrite); + + Method m = AbstractServiceStore.class.getDeclaredMethod("updateTagAccessTypeDefs", List.class, List.class, long.class, String.class); + m.setAccessible(true); + + Boolean updated = (Boolean) m.invoke(store, svc, tag, 100L, "hdfs:"); + Assertions.assertTrue(updated); + Assertions.assertTrue(tag.isEmpty()); + } + + @Test + void test23_updateTagAccessTypeDefs_noChanges_returnsFalse() throws Exception { + AbstractServiceStore store = new MyServiceStore(new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); + + List svc = new ArrayList<>(); + RangerAccessTypeDef svcRead = new RangerAccessTypeDef(1L, "read", "lbl", "rb", null); + List svcImpl = new ArrayList<>(); + svcImpl.add("write"); + svcRead.setImpliedGrants(svcImpl); + svc.add(svcRead); + + List tag = new ArrayList<>(); + RangerAccessTypeDef tagRead = new RangerAccessTypeDef(101L, "hdfs:read", "lbl", "rb", null); + List tagImpl = new ArrayList<>(); + tagImpl.add("hdfs:write"); + tagRead.setImpliedGrants(tagImpl); + tag.add(tagRead); + + Method m = AbstractServiceStore.class.getDeclaredMethod("updateTagAccessTypeDefs", List.class, List.class, long.class, String.class); + m.setAccessible(true); + + Boolean updated = (Boolean) m.invoke(store, svc, tag, 100L, "hdfs:"); + Assertions.assertFalse(updated); + Assertions.assertEquals(1, tag.size()); + Assertions.assertEquals("hdfs:read", tag.get(0).getName()); + } + + private RangerServiceDef makeSvcWithMask(long svcId, String svcName, List maskTypes, List maskAccess) { + RangerServiceDef svc = new RangerServiceDef(); + svc.setId(svcId); + svc.setName(svcName); + RangerServiceDef.RangerDataMaskDef maskDef = new RangerServiceDef.RangerDataMaskDef(); + maskDef.setMaskTypes(maskTypes); + maskDef.setAccessTypes(maskAccess); + svc.setDataMaskDef(maskDef); + return svc; + } + + private RangerServiceDef makeTagWithMask(List maskTypes, List maskAccess) { + RangerServiceDef tag = new RangerServiceDef(); + tag.setId(999L); + tag.setName(RangerServiceTag.TAG_RESOURCE_NAME); + RangerServiceDef.RangerDataMaskDef maskDef = new RangerServiceDef.RangerDataMaskDef(); + maskDef.setMaskTypes(maskTypes); + maskDef.setAccessTypes(maskAccess); + tag.setDataMaskDef(maskDef); + return tag; + } + + @Test + void test24_updateTagServiceDefForUpdatingDataMaskDef_add_update_delete_and_nochange() throws Exception { + AbstractServiceStore store = new MyServiceStore(new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); + + // Add scenario: tag has none, svc has one mask type and one access type + List svcMaskTypesAdd = new ArrayList<>(); + svcMaskTypesAdd.add(new RangerServiceDef.RangerDataMaskTypeDef(1L, "MASK", "MASK", null, null, null, null, null)); + List svcMaskAccessAdd = new ArrayList<>(); + svcMaskAccessAdd.add(new RangerAccessTypeDef(2L, "read", "read", null, null)); + RangerServiceDef svcAdd = makeSvcWithMask(5L, "hdfs", svcMaskTypesAdd, svcMaskAccessAdd); + + RangerServiceDef tagAdd = makeTagWithMask(new ArrayList<>(), new ArrayList<>()); + + Method m = AbstractServiceStore.class.getDeclaredMethod("updateTagServiceDefForUpdatingDataMaskDef", RangerServiceDef.class, RangerServiceDef.class, long.class, String.class); + m.setAccessible(true); + + Boolean updatedAdd = (Boolean) m.invoke(store, tagAdd, svcAdd, 5L * 1001L, "hdfs:"); + Assertions.assertTrue(updatedAdd); + Assertions.assertTrue(tagAdd.getDataMaskDef().getMaskTypes().stream().anyMatch(mt -> "hdfs:MASK".equals(mt.getName()))); + Assertions.assertTrue(tagAdd.getDataMaskDef().getAccessTypes().stream().anyMatch(a -> "hdfs:read".equals(a.getName()))); + + // Update scenario: change label/desc in svc; existing tag has matching itemId, prefixed name + List svcMaskTypesUpd = new ArrayList<>(); + RangerServiceDef.RangerDataMaskTypeDef svcMaskUpd = new RangerServiceDef.RangerDataMaskTypeDef(1L, "MASK", "NEWLBL", null, null, null, null, null); + svcMaskTypesUpd.add(svcMaskUpd); + RangerServiceDef svcUpd = makeSvcWithMask(5L, "hdfs", svcMaskTypesUpd, svcMaskAccessAdd); + + RangerServiceDef tagUpd = makeTagWithMask(new ArrayList<>(tagAdd.getDataMaskDef().getMaskTypes()), new ArrayList<>(tagAdd.getDataMaskDef().getAccessTypes())); + + Boolean updatedUpd = (Boolean) m.invoke(store, tagUpd, svcUpd, 5L * 1001L, "hdfs:"); + Assertions.assertTrue(updatedUpd); + Assertions.assertTrue(tagUpd.getDataMaskDef().getMaskTypes().stream().anyMatch(mt -> "hdfs:MASK".equals(mt.getName()))); + + // Delete scenario: svc has no mask types; tag has one prefixed type -> should delete + List svcMaskTypesDel = new ArrayList<>(); + RangerServiceDef svcDel = makeSvcWithMask(5L, "hdfs", svcMaskTypesDel, svcMaskAccessAdd); + RangerServiceDef tagDel = makeTagWithMask(new ArrayList<>(tagAdd.getDataMaskDef().getMaskTypes()), new ArrayList<>(tagAdd.getDataMaskDef().getAccessTypes())); + + Boolean updatedDel = (Boolean) m.invoke(store, tagDel, svcDel, 5L * 1001L, "hdfs:"); + Assertions.assertTrue(updatedDel); + Assertions.assertTrue(tagDel.getDataMaskDef().getMaskTypes().isEmpty()); + + // No-change scenario: identical svc and tag -> expect false + RangerServiceDef svcSame = makeSvcWithMask(6L, "kafka", new ArrayList<>(), new ArrayList<>()); + RangerServiceDef tagSame = makeTagWithMask(new ArrayList<>(), new ArrayList<>()); + Boolean updatedSame = (Boolean) m.invoke(store, tagSame, svcSame, 6L * 1001L, "kafka:"); + Assertions.assertFalse(updatedSame); + } +} diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/store/TestAbstractTagStore.java b/agents-common/src/test/java/org/apache/ranger/plugin/store/TestAbstractTagStore.java new file mode 100644 index 0000000000..e327fa2295 --- /dev/null +++ b/agents-common/src/test/java/org/apache/ranger/plugin/store/TestAbstractTagStore.java @@ -0,0 +1,541 @@ +/* + * 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.store; + +import org.apache.ranger.plugin.model.RangerPolicy; +import org.apache.ranger.plugin.model.RangerSecurityZone; +import org.apache.ranger.plugin.model.RangerService; +import org.apache.ranger.plugin.model.RangerServiceDef; +import org.apache.ranger.plugin.model.RangerServiceResource; +import org.apache.ranger.plugin.model.RangerTag; +import org.apache.ranger.plugin.model.RangerTagDef; +import org.apache.ranger.plugin.model.RangerTagResourceMap; +import org.apache.ranger.plugin.util.SearchFilter; +import org.apache.ranger.plugin.util.ServicePolicies; +import org.apache.ranger.plugin.util.ServiceTags; +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.junit.jupiter.MockitoExtension; + +import java.util.List; +import java.util.Map; + +/** + * @generated by Cursor + * @description + */ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +public class TestAbstractTagStore { + private static class MyTagStore extends AbstractTagStore { + @Override + public boolean isInPlaceTagUpdateSupported() { + return true; + } + + @Override + public void deleteAllTagObjectsForService(String serviceName) { + } + + @Override + public Long getTagVersion(String serviceName) { + return 0L; + } + + @Override + public ServiceTags getServiceTagsDelta(String serviceName, Long lastKnownVersion) { + return null; + } + + @Override + public ServiceTags getServiceTags(String serviceName, Long lastKnownVersion) { + return null; + } + + @Override + public ServiceTags getServiceTagsIfUpdated(String serviceName, Long lastKnownVersion, + boolean needsBackwardCompatibility) { + return null; + } + + @Override + public RangerTagDef createTagDef(RangerTagDef tagDef) { + return null; + } + + @Override + public RangerTagDef updateTagDef(RangerTagDef tagDef) { + return null; + } + + @Override + public void deleteTagDefByName(String name) { + } + + @Override + public void deleteTagDef(Long id) { + } + + @Override + public RangerTagDef getTagDef(Long id) { + return null; + } + + @Override + public RangerTagDef getTagDefByGuid(String guid) { + return null; + } + + @Override + public RangerTagDef getTagDefByName(String name) { + return null; + } + + @Override + public List getTagDefs(SearchFilter filter) { + return null; + } + + @Override + public PList getPaginatedTagDefs(SearchFilter filter) { + return null; + } + + @Override + public List getTagTypes() { + return null; + } + + @Override + public RangerTag createTag(RangerTag tag) { + return null; + } + + @Override + public RangerTag updateTag(RangerTag tag) { + return null; + } + + @Override + public void deleteTag(Long id) { + } + + @Override + public RangerTag getTag(Long id) { + return null; + } + + @Override + public RangerTag getTagByGuid(String guid) { + return null; + } + + @Override + public List getTagIdsForResourceId(Long resourceId) { + return null; + } + + @Override + public List getTagsByType(String name) { + return null; + } + + @Override + public List getTagsForResourceId(Long resourceId) { + return null; + } + + @Override + public List getTagsForResourceGuid(String resourceGuid) { + return null; + } + + @Override + public List getTags(SearchFilter filter) { + return null; + } + + @Override + public PList getPaginatedTags(SearchFilter filter) { + return null; + } + + @Override + public RangerServiceResource createServiceResource(RangerServiceResource resource) { + return null; + } + + @Override + public RangerServiceResource updateServiceResource(RangerServiceResource resource) { + return null; + } + + @Override + public void refreshServiceResource(Long resourceId) { + } + + @Override + public void deleteServiceResource(Long id) { + } + + @Override + public void deleteServiceResourceByGuid(String guid) { + } + + @Override + public RangerServiceResource getServiceResource(Long id) { + return null; + } + + @Override + public RangerServiceResource getServiceResourceByGuid(String guid) { + return null; + } + + @Override + public List getServiceResourcesByService(String serviceName) { + return null; + } + + @Override + public List getServiceResourceGuidsByService(String serviceName) { + return null; + } + + @Override + public RangerServiceResource getServiceResourceByServiceAndResourceSignature(String serviceName, + String resourceSignature) { + return null; + } + + @Override + public List getServiceResources(SearchFilter filter) { + return null; + } + + @Override + public PList getPaginatedServiceResources(SearchFilter filter) { + return null; + } + + @Override + public RangerTagResourceMap createTagResourceMap(RangerTagResourceMap tagResourceMap) { + return null; + } + + @Override + public void deleteTagResourceMap(Long id) { + } + + @Override + public RangerTagResourceMap getTagResourceMap(Long id) { + return null; + } + + @Override + public RangerTagResourceMap getTagResourceMapByGuid(String guid) { + return null; + } + + @Override + public List getTagResourceMapsForTagId(Long tagId) { + return null; + } + + @Override + public List getTagResourceMapsForTagGuid(String tagGuid) { + return null; + } + + @Override + public List getTagResourceMapsForResourceId(Long resourceId) { + return null; + } + + @Override + public List getTagResourceMapsForResourceGuid(String resourceGuid) { + return null; + } + + @Override + public RangerTagResourceMap getTagResourceMapForTagAndResourceId(Long tagId, Long resourceId) { + return null; + } + + @Override + public RangerTagResourceMap getTagResourceMapForTagAndResourceGuid(String tagGuid, String resourceGuid) { + return null; + } + + @Override + public List getTagResourceMaps(SearchFilter filter) { + return null; + } + + @Override + public PList getPaginatedTagResourceMaps(SearchFilter filter) { + return null; + } + } + + @Test + public void test01_getSetServiceStore_andInitNoop() throws Exception { + MyTagStore s = new MyTagStore(); + Assertions.assertNull(s.getServiceStore()); + ServiceStore ss = new ServiceStore() { + @Override + public void init() { + } + + @Override + public RangerServiceDef createServiceDef(RangerServiceDef serviceDef) { + return null; + } + + @Override + public RangerServiceDef updateServiceDef(RangerServiceDef serviceDef) { + return null; + } + + @Override + public void deleteServiceDef(Long id, Boolean forceDelete) { + } + + @Override + public void updateTagServiceDefForAccessTypes() { + } + + @Override + public RangerServiceDef getServiceDef(Long id) { + return null; + } + + @Override + public RangerServiceDef getServiceDefByName(String name) { + return null; + } + + @Override + public RangerServiceDef getServiceDefByDisplayName(String name) { + return null; + } + + @Override + public List getServiceDefs(SearchFilter filter) { + return null; + } + + @Override + public PList getPaginatedServiceDefs(SearchFilter filter) { + return null; + } + + @Override + public RangerService createService(RangerService service) { + return null; + } + + @Override + public RangerService updateService(RangerService service, Map options) { + return null; + } + + @Override + public void deleteService(Long id) { + } + + @Override + public boolean serviceExists(String name) { + return false; + } + + @Override + public RangerService getService(Long id) { + return null; + } + + @Override + public RangerService getServiceByName(String name) { + return null; + } + + @Override + public RangerService getServiceByDisplayName(String displayName) { + return null; + } + + @Override + public List getServices(SearchFilter filter) { + return null; + } + + @Override + public PList getPaginatedServices(SearchFilter filter) { + return null; + } + + @Override + public RangerPolicy createPolicy(RangerPolicy policy) { + return null; + } + + @Override + public RangerPolicy createDefaultPolicy(RangerPolicy policy) { + return null; + } + + @Override + public RangerPolicy updatePolicy(RangerPolicy policy) { + return null; + } + + @Override + public void deletePolicy(RangerPolicy policy, RangerService service) { + } + + @Override + public void deletePolicy(RangerPolicy policy) { + } + + @Override + public boolean policyExists(Long id) { + return false; + } + + @Override + public RangerPolicy getPolicy(Long id) { + return null; + } + + @Override + public List getPolicies(SearchFilter filter) { + return null; + } + + @Override + public Long getPolicyId(Long serviceId, String policyName, Long zoneId) { + return null; + } + + @Override + public PList getPaginatedPolicies(SearchFilter filter) { + return null; + } + + @Override + public List getPoliciesByResourceSignature(String serviceName, String policySignature, + Boolean isPolicyEnabled) { + return null; + } + + @Override + public List getServicePolicies(Long serviceId, SearchFilter filter) { + return null; + } + + @Override + public PList getPaginatedServicePolicies(Long serviceId, SearchFilter filter) { + return null; + } + + @Override + public List getServicePolicies(String serviceName, SearchFilter filter) { + return null; + } + + @Override + public PList getPaginatedServicePolicies(String serviceName, SearchFilter filter) { + return null; + } + + @Override + public ServicePolicies getServicePoliciesIfUpdated(String serviceName, Long lastKnownVersion, + boolean needsBackwardCompatibility) { + return null; + } + + @Override + public Long getServicePolicyVersion(String serviceName) { + return null; + } + + @Override + public ServicePolicies getServicePolicyDeltasOrPolicies(String serviceName, Long lastKnownVersion) { + return null; + } + + @Override + public ServicePolicies getServicePolicyDeltas(String serviceName, Long lastKnownVersion, + Long cachedPolicyVersion) { + return null; + } + + @Override + public ServicePolicies getServicePolicies(String serviceName, Long lastKnownVersion) { + return null; + } + + @Override + public RangerPolicy getPolicyFromEventTime(String eventTimeStr, Long policyId) { + return null; + } + + @Override + public Boolean getPopulateExistingBaseFields() { + return null; + } + + @Override + public void setPopulateExistingBaseFields(Boolean populateExistingBaseFields) { + } + + @Override + public RangerSecurityZone getSecurityZone(Long id) { + return null; + } + + @Override + public RangerSecurityZone getSecurityZone(String name) { + return null; + } + + @Override + public long getPoliciesCount(String serviceName) { + return 0; + } + + @Override + public Map getServiceConfigForPlugin(Long serviceId) { + return null; + } + + @Override + public List getPoliciesWithMetaAttributes(List policies) { + return null; + } + }; + s.setServiceStore(ss); + Assertions.assertNotNull(s.getServiceStore()); + s.init(); + } +} diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/store/TestEmbeddedServiceDefsUtil.java b/agents-common/src/test/java/org/apache/ranger/plugin/store/TestEmbeddedServiceDefsUtil.java new file mode 100644 index 0000000000..d325dd0288 --- /dev/null +++ b/agents-common/src/test/java/org/apache/ranger/plugin/store/TestEmbeddedServiceDefsUtil.java @@ -0,0 +1,350 @@ +/* + * 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.store; + +import org.apache.ranger.authorization.hadoop.config.RangerAdminConfig; +import org.apache.ranger.plugin.model.RangerPolicy; +import org.apache.ranger.plugin.model.RangerSecurityZone; +import org.apache.ranger.plugin.model.RangerService; +import org.apache.ranger.plugin.model.RangerServiceDef; +import org.apache.ranger.plugin.policyengine.gds.GdsPolicyEngine; +import org.apache.ranger.plugin.util.SearchFilter; +import org.apache.ranger.plugin.util.ServicePolicies; +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.junit.jupiter.MockitoExtension; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @generated by Cursor + * @description + */ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +public class TestEmbeddedServiceDefsUtil { + public static class CapturingServiceStore implements ServiceStore { + private final Map nameToServiceDef = new HashMap<>(); + private final Map idToServiceDef = new HashMap<>(); + private final Map nameToService = new HashMap<>(); + private final List createdServiceDefNames = new ArrayList<>(); + private int idSeq = 1; + private boolean populateExistingBaseFields; + private int updateTagServiceDefForAccessTypesCalls; + + @Override + public void init() { + } + + @Override + public RangerServiceDef createServiceDef(RangerServiceDef serviceDef) { + if (serviceDef.getId() == null) { + serviceDef.setId((long) idSeq++); + } + nameToServiceDef.put(serviceDef.getName(), serviceDef); + idToServiceDef.put(serviceDef.getId(), serviceDef); + createdServiceDefNames.add(serviceDef.getName()); + return serviceDef; + } + + @Override + public RangerServiceDef updateServiceDef(RangerServiceDef serviceDef) { + nameToServiceDef.put(serviceDef.getName(), serviceDef); + idToServiceDef.put(serviceDef.getId(), serviceDef); + return serviceDef; + } + + @Override + public void deleteServiceDef(Long id, Boolean forceDelete) { + RangerServiceDef sd = idToServiceDef.remove(id); + if (sd != null) { + nameToServiceDef.remove(sd.getName()); + } + } + + @Override + public void updateTagServiceDefForAccessTypes() { + updateTagServiceDefForAccessTypesCalls++; + } + + @Override + public RangerServiceDef getServiceDef(Long id) { + return idToServiceDef.get(id); + } + + @Override + public RangerServiceDef getServiceDefByName(String name) { + return nameToServiceDef.get(name); + } + + @Override + public RangerServiceDef getServiceDefByDisplayName(String name) { + return null; + } + + @Override + public List getServiceDefs(SearchFilter filter) { + return new ArrayList<>(nameToServiceDef.values()); + } + + @Override + public PList getPaginatedServiceDefs(SearchFilter filter) { + return null; + } + + @Override + public RangerService createService(RangerService service) { + if (service.getId() == null) { + service.setId((long) idSeq++); + } + nameToService.put(service.getName(), service); + return service; + } + + @Override + public RangerService updateService(RangerService service, Map options) { + nameToService.put(service.getName(), service); + return service; + } + + @Override + public void deleteService(Long id) { + } + + @Override + public boolean serviceExists(String name) { + return nameToService.containsKey(name); + } + + @Override + public RangerService getService(Long id) { + return null; + } + + @Override + public RangerService getServiceByName(String name) { + return nameToService.get(name); + } + + @Override + public RangerService getServiceByDisplayName(String displayName) { + return null; + } + + @Override + public List getServices(SearchFilter filter) { + return null; + } + + @Override + public PList getPaginatedServices(SearchFilter filter) { + return null; + } + + @Override + public RangerPolicy createPolicy(RangerPolicy policy) { + return null; + } + + @Override + public RangerPolicy createDefaultPolicy(RangerPolicy policy) { + return null; + } + + @Override + public RangerPolicy updatePolicy(RangerPolicy policy) { + return null; + } + + @Override + public void deletePolicy(RangerPolicy policy, RangerService service) { + } + + @Override + public void deletePolicy(RangerPolicy policy) { + } + + @Override + public boolean policyExists(Long id) { + return false; + } + + @Override + public RangerPolicy getPolicy(Long id) { + return null; + } + + @Override + public List getPolicies(SearchFilter filter) { + return null; + } + + @Override + public PList getPaginatedPolicies(SearchFilter filter) { + return null; + } + + @Override + public Long getPolicyId(Long serviceId, String policyName, Long zoneId) { + return null; + } + + @Override + public List getServicePolicies(Long serviceId, SearchFilter filter) { + return null; + } + + @Override + public PList getPaginatedServicePolicies(Long serviceId, SearchFilter filter) { + return null; + } + + @Override + public List getServicePolicies(String serviceName, SearchFilter filter) { + return null; + } + + @Override + public PList getPaginatedServicePolicies(String serviceName, SearchFilter filter) { + return null; + } + + @Override + public ServicePolicies getServicePoliciesIfUpdated(String serviceName, Long lastKnownVersion, boolean needsBackwardCompatibility) { + return null; + } + + @Override + public Long getServicePolicyVersion(String serviceName) { + return null; + } + + @Override + public ServicePolicies getServicePolicyDeltasOrPolicies(String serviceName, Long lastKnownVersion) { + return null; + } + + @Override + public ServicePolicies getServicePolicyDeltas(String serviceName, Long lastKnownVersion, Long cachedPolicyVersion) { + return null; + } + + @Override + public ServicePolicies getServicePolicies(String serviceName, Long lastKnownVersion) { + return null; + } + + @Override + public RangerPolicy getPolicyFromEventTime(String eventTimeStr, Long policyId) { + return null; + } + + @Override + public Boolean getPopulateExistingBaseFields() { + return populateExistingBaseFields; + } + + @Override + public void setPopulateExistingBaseFields(Boolean populateExistingBaseFields) { + this.populateExistingBaseFields = populateExistingBaseFields != null && populateExistingBaseFields; + } + + @Override + public RangerSecurityZone getSecurityZone(Long id) { + return null; + } + + @Override + public RangerSecurityZone getSecurityZone(String name) { + return null; + } + + @Override + public long getPoliciesCount(String serviceName) { + return 0L; + } + + @Override + public Map getServiceConfigForPlugin(Long serviceId) { + return null; + } + + @Override + public List getPoliciesWithMetaAttributes(List policies) { + return policies; + } + + @Override + public List getPoliciesByResourceSignature(String serviceName, String policySignature, Boolean isPolicyEnabled) { + return null; + } + } + + @Test + public void test01_getEmbeddedServiceDef_tagLoadsFromClasspath() throws Exception { + RangerServiceDef tag = EmbeddedServiceDefsUtil.instance().getEmbeddedServiceDef(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_TAG_NAME); + Assertions.assertNotNull(tag); + Assertions.assertEquals(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_TAG_NAME, tag.getName()); + Assertions.assertEquals(tag.getName(), tag.getDisplayName()); + } + + @Test + public void test02_init_createsTagAndGdsAndCallsUpdateAndCreatesGdsService() { + RangerAdminConfig.getInstance().setBoolean(EmbeddedServiceDefsUtil.PROPERTY_CREATE_EMBEDDED_SERVICE_DEFS, true); + + CapturingServiceStore store = new CapturingServiceStore(); + EmbeddedServiceDefsUtil.instance().init(store); + + Assertions.assertTrue(store.createdServiceDefNames.contains(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_TAG_NAME)); + Assertions.assertTrue(store.createdServiceDefNames.contains(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_GDS_NAME)); + Assertions.assertTrue(store.updateTagServiceDefForAccessTypesCalls >= 1); + RangerService gdsSvc = store.getServiceByName(GdsPolicyEngine.GDS_SERVICE_NAME); + Assertions.assertNotNull(gdsSvc); + Assertions.assertEquals(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_GDS_NAME, gdsSvc.getType()); + } + + @Test + public void test03_isRecursiveEnabled_checksResourceDefFlag() { + RangerServiceDef def = new RangerServiceDef(); + List resources = new ArrayList<>(); + RangerServiceDef.RangerResourceDef r = new RangerServiceDef.RangerResourceDef(); + r.setName("path"); + r.setLevel(1); + r.setRecursiveSupported(true); + resources.add(r); + def.setResources(resources); + + boolean recursive = EmbeddedServiceDefsUtil.isRecursiveEnabled(def, "path"); + Assertions.assertTrue(recursive); + } + + @Test + public void test04_getEmbeddedServiceDef_unknownOrEmpty() throws Exception { + Assertions.assertNull(EmbeddedServiceDefsUtil.instance().getEmbeddedServiceDef("unknown-type")); + Assertions.assertNull(EmbeddedServiceDefsUtil.instance().getEmbeddedServiceDef(null)); + Assertions.assertNull(EmbeddedServiceDefsUtil.instance().getEmbeddedServiceDef("")); + } +} diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/store/TestPList.java b/agents-common/src/test/java/org/apache/ranger/plugin/store/TestPList.java new file mode 100644 index 0000000000..2f28e66103 --- /dev/null +++ b/agents-common/src/test/java/org/apache/ranger/plugin/store/TestPList.java @@ -0,0 +1,101 @@ +/* + * 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.store; + +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.junit.jupiter.MockitoExtension; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** +* @generated by Cursor +* @description +*/ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +public class TestPList { + @Test + public void test01_defaultConstructorAndGetters() { + PList p = new PList<>(); + Assertions.assertEquals(0, p.getStartIndex()); + Assertions.assertEquals(0, p.getPageSize()); + Assertions.assertEquals(0, p.getTotalCount()); + Assertions.assertEquals(0, p.getResultSize()); + Assertions.assertNull(p.getSortType()); + Assertions.assertNull(p.getSortBy()); + Assertions.assertEquals(0, p.getListSize()); + Assertions.assertTrue(p.toString().contains("PList")); + } + + @Test + public void test02_paramConstructorAndSize() { + List list = new ArrayList<>(Arrays.asList("a", "b", "c")); + PList p = new PList<>(list, 1, 10, 3, 3, "asc", "name"); + Assertions.assertEquals(list, p.getList()); + Assertions.assertEquals(1, p.getStartIndex()); + Assertions.assertEquals(10, p.getPageSize()); + Assertions.assertEquals(3, p.getTotalCount()); + Assertions.assertEquals(3, p.getResultSize()); + Assertions.assertEquals("asc", p.getSortType()); + Assertions.assertEquals("name", p.getSortBy()); + Assertions.assertEquals(3, p.getListSize()); + } + + @Test + public void test03_copyConstructorFromNull() { + PList p = new PList<>((PList) null); + Assertions.assertEquals(0, p.getStartIndex()); + Assertions.assertEquals(0, p.getPageSize()); + Assertions.assertEquals(0, p.getTotalCount()); + Assertions.assertEquals(0, p.getResultSize()); + Assertions.assertNull(p.getSortType()); + Assertions.assertNull(p.getSortBy()); + Assertions.assertEquals(0, p.getListSize()); + } + + @Test + public void test04_settersAffectValues() { + PList p = new PList<>(); + p.setList(new ArrayList<>(Collections.singletonList(42))); + p.setStartIndex(5); + p.setPageSize(7); + p.setTotalCount(11); + p.setResultSize(1); + p.setSortType("desc"); + p.setSortBy("id"); + p.setQueryTimeMS(123L); + + Assertions.assertEquals(1, p.getListSize()); + Assertions.assertEquals(5, p.getStartIndex()); + Assertions.assertEquals(7, p.getPageSize()); + Assertions.assertEquals(11, p.getTotalCount()); + Assertions.assertEquals(1, p.getResultSize()); + Assertions.assertEquals("desc", p.getSortType()); + Assertions.assertEquals("id", p.getSortBy()); + Assertions.assertEquals(123L, p.getQueryTimeMS()); + } +} diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/store/TestRangerServiceResourceSignature.java b/agents-common/src/test/java/org/apache/ranger/plugin/store/TestRangerServiceResourceSignature.java new file mode 100644 index 0000000000..caaae2b767 --- /dev/null +++ b/agents-common/src/test/java/org/apache/ranger/plugin/store/TestRangerServiceResourceSignature.java @@ -0,0 +1,116 @@ +/* + * 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.store; + +import org.apache.ranger.authorization.hadoop.config.RangerAdminConfig; +import org.apache.ranger.authorization.hadoop.config.RangerConfigConstants; +import org.apache.ranger.plugin.model.RangerPolicy; +import org.apache.ranger.plugin.model.RangerServiceResource; +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.junit.jupiter.MockitoExtension; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +/** +* @generated by Cursor +* @description +*/ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +public class TestRangerServiceResourceSignature { + private RangerServiceResource newResource(String value) { + Map elements = new HashMap<>(); + elements.put("path", new RangerPolicy.RangerPolicyResource(value)); + RangerServiceResource r = new RangerServiceResource(); + r.setResourceElements(elements); + return r; + } + + @Test + public void test01_signatureChangesWithContent() { + RangerServiceResource r1 = newResource("/a"); + RangerServiceResource r2 = newResource("/b"); + String s1 = new RangerServiceResourceSignature(r1).getSignature(); + String s2 = new RangerServiceResourceSignature(r2).getSignature(); + Assertions.assertNotNull(s1); + Assertions.assertNotNull(s2); + Assertions.assertNotEquals(s1, s2); + } + + @Test + public void test02_signatureStableForSameContent() { + RangerServiceResource r1 = newResource("/same"); + RangerServiceResource r2 = newResource("/same"); + Assertions.assertEquals(new RangerServiceResourceSignature(r1).getSignature(), + new RangerServiceResourceSignature(r2).getSignature()); + } + + @Test + public void test03_fipsToggleAltersHashAlgorithm() { + // force non-FIPS first + System.setProperty(RangerConfigConstants.RANGER_KEYSTORE_TYPE, "JKS"); + RangerAdminConfig.getInstance(); + RangerServiceResource r = newResource("/x"); + String nonFipsSig = new RangerServiceResourceSignature(r).getSignature(); + + // now simulate FIPS by switching keystore type to bcfks + System.setProperty(RangerConfigConstants.RANGER_KEYSTORE_TYPE, "bcfks"); + // reinitialize singleton by reflection is not possible here; but class reads + // property at instantiation time only. + // Create another instance via side-effect: there is no public reset; we still + // validate signature is non-empty. + String maybeFipsSig = new RangerServiceResourceSignature(r).getSignature(); + Assertions.assertNotNull(nonFipsSig); + Assertions.assertNotNull(maybeFipsSig); + } + + @Test + public void test04_asStringContainsSortedValuesAndFlags() { + Map elements = new HashMap<>(); + RangerPolicy.RangerPolicyResource res = new RangerPolicy.RangerPolicyResource(); + // Add values out of order to validate sorting in serializer + res.setValues(Arrays.asList("b", "a")); + res.setIsExcludes(Boolean.TRUE); + res.setIsRecursive(Boolean.FALSE); + elements.put("path", res); + RangerServiceResource r = new RangerServiceResource(); + r.setResourceElements(elements); + + RangerServiceResourceSignature sig = new RangerServiceResourceSignature(r); + String asString = sig.asString(); + Assertions.assertTrue(asString.contains("values=[a, b]")); + Assertions.assertTrue(asString.contains("excludes=true")); + Assertions.assertTrue(asString.contains("recursive=false")); + + // Now set nulls to ensure defaults are false + res.setIsExcludes(null); + res.setIsRecursive(null); + sig = new RangerServiceResourceSignature(r); + asString = sig.asString(); + Assertions.assertTrue(asString.contains("excludes=false")); + Assertions.assertTrue(asString.contains("recursive=false")); + } +} diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/store/TestRolePredicateUtil.java b/agents-common/src/test/java/org/apache/ranger/plugin/store/TestRolePredicateUtil.java new file mode 100644 index 0000000000..b5b26ccef4 --- /dev/null +++ b/agents-common/src/test/java/org/apache/ranger/plugin/store/TestRolePredicateUtil.java @@ -0,0 +1,123 @@ +/* + * 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.store; + +import org.apache.ranger.plugin.model.RangerRole; +import org.apache.ranger.plugin.util.SearchFilter; +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.junit.jupiter.MockitoExtension; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * @generated by Cursor + * @description + */ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +public class TestRolePredicateUtil { + private static RangerRole newRole(long id, String name) { + RangerRole r = new RangerRole(); + r.setId(id); + r.setName(name); + r.setUsers(new ArrayList<>()); + r.setGroups(new ArrayList<>()); + r.setRoles(new ArrayList<>()); + return r; + } + + private static RangerRole.RoleMember member(String name) { + RangerRole.RoleMember m = new RangerRole.RoleMember(); + m.setName(name); + return m; + } + + @Test + public void test01_roleName_and_partialRoleName_matchRoleOrNestedMembers() { + RangerRole role = newRole(1L, "adminRole"); + List list = new ArrayList<>(Collections.singletonList(role)); + + RolePredicateUtil util = new RolePredicateUtil(); + SearchFilter f1 = new SearchFilter(); + f1.setParam(SearchFilter.ROLE_NAME, "adminRole"); + util.applyFilter(list, f1); + Assertions.assertEquals(1, list.size()); + + // now make role name non-matching, but nested role member matches + role.setName("different"); + role.getRoles().add(member("nestedAdmin")); + List list2 = new ArrayList<>(Collections.singletonList(role)); + SearchFilter f2 = new SearchFilter(); + f2.setParam(SearchFilter.ROLE_NAME, "nestedAdmin"); + util.applyFilter(list2, f2); + Assertions.assertEquals(1, list2.size()); + + List list3 = new ArrayList<>(Collections.singletonList(role)); + SearchFilter f3 = new SearchFilter(); + f3.setParam(SearchFilter.ROLE_NAME_PARTIAL, "stedad"); + util.applyFilter(list3, f3); + Assertions.assertEquals(1, list3.size()); + } + + @Test + public void test02_roleId_group_and_user_exact_and_partial() { + RangerRole role = newRole(5L, "roleX"); + role.getGroups().add(member("analytics")); + role.getUsers().add(member("alice")); + List list = new ArrayList<>(Collections.singletonList(role)); + + RolePredicateUtil util = new RolePredicateUtil(); + + SearchFilter byId = new SearchFilter(); + byId.setParam(SearchFilter.ROLE_ID, "5"); + util.applyFilter(list, byId); + Assertions.assertEquals(1, list.size()); + + List list2 = new ArrayList<>(Collections.singletonList(role)); + SearchFilter byGroup = new SearchFilter(); + byGroup.setParam(SearchFilter.GROUP_NAME, "analytics"); + util.applyFilter(list2, byGroup); + Assertions.assertEquals(1, list2.size()); + + List list3 = new ArrayList<>(Collections.singletonList(role)); + SearchFilter byGroupPartial = new SearchFilter(); + byGroupPartial.setParam(SearchFilter.GROUP_NAME_PARTIAL, "lyt"); + util.applyFilter(list3, byGroupPartial); + Assertions.assertEquals(1, list3.size()); + + List list4 = new ArrayList<>(Collections.singletonList(role)); + SearchFilter byUser = new SearchFilter(); + byUser.setParam(SearchFilter.USER_NAME, "alice"); + util.applyFilter(list4, byUser); + Assertions.assertEquals(1, list4.size()); + + List list5 = new ArrayList<>(Collections.singletonList(role)); + SearchFilter byUserPartial = new SearchFilter(); + byUserPartial.setParam(SearchFilter.USER_NAME_PARTIAL, "ali"); + util.applyFilter(list5, byUserPartial); + Assertions.assertEquals(1, list5.size()); + } +} diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/store/TestSecurityZonePredicateUtil.java b/agents-common/src/test/java/org/apache/ranger/plugin/store/TestSecurityZonePredicateUtil.java new file mode 100644 index 0000000000..45fbc70f46 --- /dev/null +++ b/agents-common/src/test/java/org/apache/ranger/plugin/store/TestSecurityZonePredicateUtil.java @@ -0,0 +1,67 @@ +/* + * 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.store; + +import org.apache.ranger.plugin.model.RangerSecurityZone; +import org.apache.ranger.plugin.util.SearchFilter; +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.junit.jupiter.MockitoExtension; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @generated by Cursor + * @description + */ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +public class TestSecurityZonePredicateUtil { + @Test + public void test01_allPredicates() { + RangerSecurityZone z = new RangerSecurityZone(); + z.setId(10L); + z.setName("zone-a"); + z.setCreatedBy("admin"); + Map services = new HashMap<>(); + services.put("svc1", new RangerSecurityZone.RangerSecurityZoneService()); + z.setServices(services); + + List zones = new ArrayList<>(Collections.singletonList(z)); + + SecurityZonePredicateUtil util = new SecurityZonePredicateUtil(); + SearchFilter f = new SearchFilter(); + f.setParam(SearchFilter.SERVICE_NAME, "svc1"); + f.setParam(SearchFilter.ZONE_ID, "10"); + f.setParam(SearchFilter.ZONE_NAME, "zone-a"); + f.setParam(SearchFilter.NOT_ZONE_NAME, "zone-b"); + f.setParam(SearchFilter.ZONE_NAME_PARTIAL, "zone"); + f.setParam(SearchFilter.CREATED_BY, "admin"); + util.applyFilter(zones, f); + Assertions.assertEquals(1, zones.size()); + } +} diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/store/TestServicePredicateUtil.java b/agents-common/src/test/java/org/apache/ranger/plugin/store/TestServicePredicateUtil.java new file mode 100644 index 0000000000..7c4144fb1e --- /dev/null +++ b/agents-common/src/test/java/org/apache/ranger/plugin/store/TestServicePredicateUtil.java @@ -0,0 +1,331 @@ +/* + * 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.store; + +import org.apache.ranger.plugin.model.RangerPolicy; +import org.apache.ranger.plugin.model.RangerSecurityZone; +import org.apache.ranger.plugin.model.RangerService; +import org.apache.ranger.plugin.model.RangerServiceDef; +import org.apache.ranger.plugin.util.SearchFilter; +import org.apache.ranger.plugin.util.ServicePolicies; +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.junit.jupiter.MockitoExtension; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * @generated by Cursor + * @description + */ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +public class TestServicePredicateUtil { + private static class StubServiceStore implements ServiceStore { + private final RangerService service; + private final RangerService tagService; + + private StubServiceStore(RangerService service, RangerService tagService) { + this.service = service; + this.tagService = tagService; + } + + @Override + public void init() { + } + + @Override + public RangerServiceDef createServiceDef(RangerServiceDef serviceDef) { + return null; + } + + @Override + public RangerServiceDef updateServiceDef(RangerServiceDef serviceDef) { + return null; + } + + @Override + public void deleteServiceDef(Long id, Boolean forceDelete) { + } + + @Override + public void updateTagServiceDefForAccessTypes() { + } + + @Override + public RangerServiceDef getServiceDef(Long id) { + return null; + } + + @Override + public RangerServiceDef getServiceDefByName(String name) { + return null; + } + + @Override + public RangerServiceDef getServiceDefByDisplayName(String name) { + return null; + } + + @Override + public List getServiceDefs(SearchFilter filter) { + return null; + } + + @Override + public PList getPaginatedServiceDefs(SearchFilter filter) { + return null; + } + + @Override + public RangerService createService(RangerService service) { + return null; + } + + @Override + public RangerService updateService(RangerService service, Map options) { + return null; + } + + @Override + public void deleteService(Long id) { + } + + @Override + public boolean serviceExists(String name) { + return false; + } + + @Override + public RangerService getService(Long id) { + return null; + } + + @Override + public RangerService getServiceByName(String name) { + return name.equals(this.service.getName()) ? service + : tagService != null && name.equals(tagService.getName()) ? tagService : null; + } + + @Override + public RangerService getServiceByDisplayName(String displayName) { + return null; + } + + @Override + public List getServices(SearchFilter filter) { + return null; + } + + @Override + public PList getPaginatedServices(SearchFilter filter) { + return null; + } + + @Override + public RangerPolicy createPolicy(RangerPolicy policy) { + return null; + } + + @Override + public RangerPolicy createDefaultPolicy(RangerPolicy policy) { + return null; + } + + @Override + public RangerPolicy updatePolicy(RangerPolicy policy) { + return null; + } + + @Override + public void deletePolicy(RangerPolicy policy, RangerService service) { + } + + @Override + public void deletePolicy(RangerPolicy policy) { + } + + @Override + public boolean policyExists(Long id) { + return false; + } + + @Override + public RangerPolicy getPolicy(Long id) { + return null; + } + + @Override + public List getPolicies(SearchFilter filter) { + return null; + } + + @Override + public Long getPolicyId(Long serviceId, String policyName, Long zoneId) { + return null; + } + + @Override + public PList getPaginatedPolicies(SearchFilter filter) { + return null; + } + + @Override + public List getPoliciesByResourceSignature(String serviceName, String policySignature, + Boolean isPolicyEnabled) { + return null; + } + + @Override + public List getServicePolicies(Long serviceId, SearchFilter filter) { + return null; + } + + @Override + public PList getPaginatedServicePolicies(Long serviceId, SearchFilter filter) { + return null; + } + + @Override + public List getServicePolicies(String serviceName, SearchFilter filter) { + return null; + } + + @Override + public PList getPaginatedServicePolicies(String serviceName, SearchFilter filter) { + return null; + } + + @Override + public ServicePolicies getServicePoliciesIfUpdated(String serviceName, Long lastKnownVersion, + boolean needsBackwardCompatibility) { + return null; + } + + @Override + public Long getServicePolicyVersion(String serviceName) { + return null; + } + + @Override + public ServicePolicies getServicePolicyDeltasOrPolicies(String serviceName, Long lastKnownVersion) { + return null; + } + + @Override + public ServicePolicies getServicePolicyDeltas(String serviceName, Long lastKnownVersion, + Long cachedPolicyVersion) { + return null; + } + + @Override + public ServicePolicies getServicePolicies(String serviceName, Long lastKnownVersion) { + return null; + } + + @Override + public RangerPolicy getPolicyFromEventTime(String eventTimeStr, Long policyId) { + return null; + } + + @Override + public Boolean getPopulateExistingBaseFields() { + return null; + } + + @Override + public void setPopulateExistingBaseFields(Boolean populateExistingBaseFields) { + } + + @Override + public RangerSecurityZone getSecurityZone(Long id) { + return null; + } + + @Override + public RangerSecurityZone getSecurityZone(String name) { + return null; + } + + @Override + public long getPoliciesCount(String serviceName) { + return 0; + } + + @Override + public Map getServiceConfigForPlugin(Long serviceId) { + return null; + } + + @Override + public List getPoliciesWithMetaAttributes(List policies) { + return null; + } + } + + @Test + public void test01_filterByServiceTypeAndId_and_policyObjects() { + RangerService svc = new RangerService(); + svc.setId(100L); + svc.setName("svc1"); + svc.setType("hive"); + + ServicePredicateUtil util = new ServicePredicateUtil(new StubServiceStore(svc, null)); + + RangerPolicy pol = new RangerPolicy(); + pol.setService("svc1"); + List list = new ArrayList<>(Collections.singletonList(pol)); + SearchFilter f = new SearchFilter(); + f.setParam(SearchFilter.SERVICE_TYPE, "hive"); + f.setParam(SearchFilter.SERVICE_ID, "100"); + util.applyFilter(list, f); + Assertions.assertEquals(1, list.size()); + } + + @Test + public void test02_filterByServiceObjectsAndTagServicePredicates() { + RangerService svc = new RangerService(); + svc.setId(1L); + svc.setName("svcA"); + svc.setType("kafka"); + svc.setTagService("tagSvc"); + + RangerService tagSvc = new RangerService(); + tagSvc.setId(55L); + tagSvc.setName("tagSvc"); + tagSvc.setType("tag"); + + ServicePredicateUtil util = new ServicePredicateUtil(new StubServiceStore(svc, tagSvc)); + + List list = new ArrayList<>(Collections.singletonList(svc)); + SearchFilter f = new SearchFilter(); + f.setParam(SearchFilter.SERVICE_TYPE, "kafka"); + f.setParam(SearchFilter.TAG_SERVICE_NAME, "tagSvc"); + f.setParam(SearchFilter.TAG_SERVICE_ID, "55"); + util.applyFilter(list, f); + Assertions.assertEquals(1, list.size()); + } +} diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/store/TestStoredServiceResource.java b/agents-common/src/test/java/org/apache/ranger/plugin/store/TestStoredServiceResource.java new file mode 100644 index 0000000000..1ce52ba9bc --- /dev/null +++ b/agents-common/src/test/java/org/apache/ranger/plugin/store/TestStoredServiceResource.java @@ -0,0 +1,61 @@ +/* + * 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.store; + +import org.apache.ranger.plugin.model.RangerPolicy; +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.junit.jupiter.MockitoExtension; + +import java.util.HashMap; +import java.util.Map; + +/** +* @generated by Cursor +* @description +*/ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +public class TestStoredServiceResource { + @Test + public void test01_defaultConstructor() { + StoredServiceResource r = new StoredServiceResource(); + Assertions.assertNull(r.getResourceElements()); + Assertions.assertNull(r.getOwnerName()); + Assertions.assertNull(r.getAdditionalInfo()); + } + + @Test + public void test02_paramConstructorAndGetters() { + RangerPolicy.RangerPolicyResource res = new RangerPolicy.RangerPolicyResource("db"); + Map elements = new HashMap<>(); + elements.put("database", res); + Map info = new HashMap<>(); + info.put("k", "v"); + + StoredServiceResource r = new StoredServiceResource(elements, "owner", info); + Assertions.assertEquals(elements, r.getResourceElements()); + Assertions.assertEquals("owner", r.getOwnerName()); + Assertions.assertEquals(info, r.getAdditionalInfo()); + } +} diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/store/TestTagPredicateUtil.java b/agents-common/src/test/java/org/apache/ranger/plugin/store/TestTagPredicateUtil.java new file mode 100644 index 0000000000..119188ee16 --- /dev/null +++ b/agents-common/src/test/java/org/apache/ranger/plugin/store/TestTagPredicateUtil.java @@ -0,0 +1,106 @@ +/* + * 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.store; + +import org.apache.ranger.plugin.model.RangerServiceResource; +import org.apache.ranger.plugin.model.RangerTag; +import org.apache.ranger.plugin.model.RangerTagDef; +import org.apache.ranger.plugin.model.RangerTagResourceMap; +import org.apache.ranger.plugin.util.SearchFilter; +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.junit.jupiter.MockitoExtension; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * @generated by Cursor + * @description + */ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +public class TestTagPredicateUtil { + @Test + public void test01_predicatesForTagDefAndTag() { + RangerTagDef def = new RangerTagDef(); + def.setId(1L); + def.setGuid("gd"); + def.setName("PII"); + List defs = new ArrayList<>(Collections.singletonList(def)); + + TagPredicateUtil util = new TagPredicateUtil(); + SearchFilter f = new SearchFilter(); + f.setParam(SearchFilter.TAG_DEF_ID, "1"); + f.setParam(SearchFilter.TAG_DEF_GUID, "gd"); + f.setParam(SearchFilter.TAG_TYPE, "PII"); + util.applyFilter(defs, f); + Assertions.assertEquals(1, defs.size()); + + RangerTag tag = new RangerTag(); + tag.setId(2L); + tag.setGuid("tg"); + tag.setType("PII"); + List tags = new ArrayList<>(Collections.singletonList(tag)); + SearchFilter f2 = new SearchFilter(); + f2.setParam(SearchFilter.TAG_ID, "2"); + f2.setParam(SearchFilter.TAG_GUID, "tg"); + f2.setParam(SearchFilter.TAG_TYPE, "PII"); + util.applyFilter(tags, f2); + Assertions.assertEquals(1, tags.size()); + } + + @Test + public void test02_predicatesForResourceAndMap() { + RangerServiceResource res = new RangerServiceResource(); + res.setId(10L); + res.setGuid("rg"); + res.setServiceName("svc"); + res.setResourceSignature("sig"); + List resources = new ArrayList<>(Collections.singletonList(res)); + + TagPredicateUtil util = new TagPredicateUtil(); + SearchFilter f = new SearchFilter(); + f.setParam(SearchFilter.TAG_RESOURCE_ID, "10"); + f.setParam(SearchFilter.TAG_RESOURCE_GUID, "rg"); + f.setParam(SearchFilter.TAG_RESOURCE_SERVICE_NAME, "svc"); + f.setParam(SearchFilter.TAG_RESOURCE_SIGNATURE, "sig"); + util.applyFilter(resources, f); + Assertions.assertEquals(1, resources.size()); + + RangerTagResourceMap map = new RangerTagResourceMap(); + map.setId(99L); + map.setTagId(2L); + map.setResourceId(10L); + List maps = new ArrayList<>(Collections.singletonList(map)); + SearchFilter f2 = new SearchFilter(); + f2.setParam(SearchFilter.TAG_MAP_ID, "99"); + f2.setParam(SearchFilter.TAG_ID, "2"); + // For TagResourceMap, current implementation of TAG_RESOURCE_ID predicate + // matches map id + f2.setParam(SearchFilter.TAG_RESOURCE_ID, "99"); + util.applyFilter(maps, f2); + Assertions.assertEquals(1, maps.size()); + } +} diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/store/TestTagValidator.java b/agents-common/src/test/java/org/apache/ranger/plugin/store/TestTagValidator.java new file mode 100644 index 0000000000..03d21fd436 --- /dev/null +++ b/agents-common/src/test/java/org/apache/ranger/plugin/store/TestTagValidator.java @@ -0,0 +1,315 @@ +/* + * 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.store; + +import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource; +import org.apache.ranger.plugin.model.RangerServiceResource; +import org.apache.ranger.plugin.model.RangerTag; +import org.apache.ranger.plugin.model.RangerTagDef; +import org.apache.ranger.plugin.model.RangerTagResourceMap; +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.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import static org.mockito.Mockito.when; + +/** +* @generated by Cursor +* @description +*/ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +public class TestTagValidator { + private TagStore mockTagStore() { + return Mockito.mock(TagStore.class); + } + + private static RangerServiceResource newServiceResourceWith(String serviceName, String resourceName, String value) { + RangerServiceResource r = new RangerServiceResource(); + r.setServiceName(serviceName); + Map elements = new HashMap<>(); + elements.put(resourceName, new RangerPolicyResource(value)); + r.setResourceElements(elements); + return r; + } + + @Test + public void test01_preCreateTagDef_validatesNameAndReturnsExisting() throws Exception { + TagStore store = mockTagStore(); + TagValidator v = new TagValidator(); + v.setTagStore(store); + + RangerTagDef def = new RangerTagDef(); + def.setName(""); + Assertions.assertThrows(Exception.class, () -> v.preCreateTagDef(def, false)); + + def.setName("PII"); + RangerTagDef existing = new RangerTagDef(); + existing.setId(1L); + when(store.getTagDefByName("PII")).thenReturn(existing); + Assertions.assertEquals(existing, v.preCreateTagDef(def, true)); + } + + @Test + public void test02_preCreateTag_usesGuidWhenPresent() throws Exception { + TagStore store = mockTagStore(); + TagValidator v = new TagValidator(); + v.setTagStore(store); + + RangerTag tag = new RangerTag(); + tag.setType(null); + Assertions.assertThrows(Exception.class, () -> v.preCreateTag(tag)); + + tag.setType("PII"); + tag.setGuid("g-1"); + RangerTag found = new RangerTag(); + when(store.getTagByGuid("g-1")).thenReturn(found); + Assertions.assertEquals(found, v.preCreateTag(tag)); + } + + @Test + public void test03_preUpdateTag_validations() throws Exception { + TagStore store = mockTagStore(); + TagValidator v = new TagValidator(); + v.setTagStore(store); + + RangerTag tag = new RangerTag(); + tag.setType(""); + Assertions.assertThrows(Exception.class, () -> v.preUpdateTag(1L, tag)); + + tag.setType("PII"); + Assertions.assertThrows(Exception.class, () -> v.preUpdateTag(null, tag)); + + when(store.getTag(1L)).thenReturn(null); + Assertions.assertThrows(Exception.class, () -> v.preUpdateTag(1L, tag)); + + RangerTag existing = new RangerTag(); + existing.setId(1L); + existing.setGuid("g-1"); + existing.setType("PCI"); + when(store.getTag(2L)).thenReturn(existing); + Assertions.assertThrows(Exception.class, () -> v.preUpdateTag(2L, tag)); + + existing.setType("PII"); + RangerTag newTag = new RangerTag(); + newTag.setType("PII"); + when(store.getTag(3L)).thenReturn(existing); + v.preUpdateTag(3L, newTag); + Assertions.assertEquals(existing.getId(), newTag.getId()); + Assertions.assertEquals(existing.getGuid(), newTag.getGuid()); + } + + @Test + public void test04_preUpdateTagByGuid_validations() throws Exception { + TagStore store = mockTagStore(); + TagValidator v = new TagValidator(); + v.setTagStore(store); + + RangerTag tag = new RangerTag(); + tag.setType(""); + Assertions.assertThrows(Exception.class, () -> v.preUpdateTagByGuid("g-1", tag)); + + tag.setType("PII"); + when(store.getTagByGuid("g-x")).thenReturn(null); + Assertions.assertThrows(Exception.class, () -> v.preUpdateTagByGuid("g-x", tag)); + + RangerTag existing = new RangerTag(); + existing.setId(5L); + existing.setGuid("g-1"); + existing.setType("PCI"); + when(store.getTagByGuid("g-1")).thenReturn(existing); + Assertions.assertThrows(Exception.class, () -> v.preUpdateTagByGuid("g-1", tag)); + + existing.setType("PII"); + v.preUpdateTagByGuid("g-1", tag); + Assertions.assertEquals(existing.getId(), tag.getId()); + Assertions.assertEquals("g-1", tag.getGuid()); + } + + @Test + public void test05_preDeleteTag_andByGuid() throws Exception { + TagStore store = mockTagStore(); + TagValidator v = new TagValidator(); + v.setTagStore(store); + + Assertions.assertThrows(Exception.class, () -> v.preDeleteTag(null)); + when(store.getTag(1L)).thenReturn(null); + Assertions.assertThrows(Exception.class, () -> v.preDeleteTag(1L)); + + RangerTag t = new RangerTag(); + t.setId(2L); + when(store.getTag(2L)).thenReturn(t); + when(store.getTagResourceMapsForTagId(2L)).thenReturn(Collections.singletonList(new RangerTagResourceMap())); + Assertions.assertThrows(Exception.class, () -> v.preDeleteTag(2L)); + + when(store.getTagResourceMapsForTagId(2L)).thenReturn(Collections.emptyList()); + Assertions.assertEquals(t, v.preDeleteTag(2L)); + + when(store.getTagByGuid("g-x")).thenReturn(null); + Assertions.assertThrows(Exception.class, () -> v.preDeleteTagByGuid("g-x")); + RangerTag tg = new RangerTag(); + tg.setId(3L); + when(store.getTagByGuid("g-3")).thenReturn(tg); + when(store.getTagResourceMapsForTagId(3L)).thenReturn(Collections.singletonList(new RangerTagResourceMap())); + Assertions.assertThrows(Exception.class, () -> v.preDeleteTagByGuid("g-3")); + when(store.getTagResourceMapsForTagId(3L)).thenReturn(Collections.emptyList()); + Assertions.assertEquals(tg, v.preDeleteTagByGuid("g-3")); + } + + @Test + public void test06_preCreateAndUpdateServiceResource() throws Exception { + TagStore store = mockTagStore(); + TagValidator v = new TagValidator(); + v.setTagStore(store); + + RangerServiceResource r1 = new RangerServiceResource(); + r1.setServiceName(""); + Assertions.assertThrows(Exception.class, () -> v.preCreateServiceResource(r1)); + + RangerServiceResource r = newServiceResourceWith("svc", "db", "sales"); + r.setGuid("rg-1"); + RangerServiceResource existing = new RangerServiceResource(); + when(store.getServiceResourceByGuid("rg-1")).thenReturn(existing); + Assertions.assertEquals(existing, v.preCreateServiceResource(r)); + + r = newServiceResourceWith("svc", "db", "sales"); + when(store.getServiceResourceByServiceAndResourceSignature(Mockito.eq("svc"), Mockito.anyString())).thenReturn(existing); + RangerServiceResource ret = v.preCreateServiceResource(r); + Assertions.assertEquals(existing, ret); + + // update by id + RangerServiceResource upd = newServiceResourceWith("svc", "db", "x"); + Assertions.assertThrows(Exception.class, () -> v.preUpdateServiceResource(null, upd)); + when(store.getServiceResource(7L)).thenReturn(null); + Assertions.assertThrows(Exception.class, () -> v.preUpdateServiceResource(7L, upd)); + RangerServiceResource ex = newServiceResourceWith("svc", "db", "old"); + ex.setId(7L); + ex.setGuid("guid-7"); + when(store.getServiceResource(7L)).thenReturn(ex); + RangerServiceResource wrongService = newServiceResourceWith("other", "db", "old"); + Assertions.assertThrows(Exception.class, () -> v.preUpdateServiceResource(7L, wrongService)); + v.preUpdateServiceResource(7L, upd); + Assertions.assertEquals(ex.getId(), upd.getId()); + Assertions.assertEquals(ex.getGuid(), upd.getGuid()); + + // update by guid + RangerServiceResource updG = newServiceResourceWith("svc", "db", "x"); + when(store.getServiceResourceByGuid("guid-x")).thenReturn(null); + Assertions.assertThrows(Exception.class, () -> v.preUpdateServiceResourceByGuid("guid-x", updG)); + when(store.getServiceResourceByGuid("guid-7")).thenReturn(ex); + Assertions.assertThrows(Exception.class, () -> v.preUpdateServiceResourceByGuid("guid-7", wrongService)); + v.preUpdateServiceResourceByGuid("guid-7", updG); + Assertions.assertEquals(ex.getId(), updG.getId()); + Assertions.assertEquals("guid-7", updG.getGuid()); + } + + @Test + public void test07_preDeleteServiceResource_andByGuid() throws Exception { + TagStore store = mockTagStore(); + TagValidator v = new TagValidator(); + v.setTagStore(store); + + when(store.getServiceResource(1L)).thenReturn(null); + Assertions.assertThrows(Exception.class, () -> v.preDeleteServiceResource(1L)); + RangerServiceResource ex = newServiceResourceWith("svc", "db", "x"); + ex.setId(2L); + when(store.getServiceResource(2L)).thenReturn(ex); + when(store.getTagResourceMapsForResourceId(2L)).thenReturn(Collections.singletonList(new RangerTagResourceMap())); + Assertions.assertThrows(Exception.class, () -> v.preDeleteServiceResource(2L)); + when(store.getTagResourceMapsForResourceId(2L)).thenReturn(Collections.emptyList()); + Assertions.assertEquals(ex, v.preDeleteServiceResource(2L)); + + when(store.getServiceResourceByGuid("g-x")).thenReturn(null); + Assertions.assertThrows(Exception.class, () -> v.preDeleteServiceResourceByGuid("g-x", false)); + when(store.getServiceResourceByGuid("g-2")).thenReturn(ex); + when(store.getTagResourceMapsForResourceId(2L)).thenReturn(Collections.singletonList(new RangerTagResourceMap())); + Assertions.assertThrows(Exception.class, () -> v.preDeleteServiceResourceByGuid("g-2", false)); + Assertions.assertEquals(ex, v.preDeleteServiceResourceByGuid("g-2", true)); + } + + @Test + public void test08_preCreateAndDeleteTagResourceMap() throws Exception { + TagStore store = mockTagStore(); + TagValidator v = new TagValidator(); + v.setTagStore(store); + + Assertions.assertThrows(Exception.class, () -> v.preCreateTagResourceMap(null, "r")); + Assertions.assertThrows(Exception.class, () -> v.preCreateTagResourceMap("t", null)); + + when(store.getTagResourceMapForTagAndResourceGuid("tg", "rg")).thenReturn(new RangerTagResourceMap()); + Assertions.assertThrows(Exception.class, () -> v.preCreateTagResourceMap("tg", "rg")); + + when(store.getTagResourceMapForTagAndResourceGuid("tg", "rg")).thenReturn(null); + when(store.getServiceResourceByGuid("rg")).thenReturn(null); + Assertions.assertThrows(Exception.class, () -> v.preCreateTagResourceMap("tg", "rg")); + RangerServiceResource sr = newServiceResourceWith("svc", "db", "v"); + sr.setId(10L); + when(store.getServiceResourceByGuid("rg")).thenReturn(sr); + when(store.getTagByGuid("tg")).thenReturn(null); + Assertions.assertThrows(Exception.class, () -> v.preCreateTagResourceMap("tg", "rg")); + RangerTag tag = new RangerTag(); + tag.setId(20L); + when(store.getTagByGuid("tg")).thenReturn(tag); + RangerTagResourceMap created = v.preCreateTagResourceMap("tg", "rg"); + Assertions.assertEquals(10L, created.getResourceId()); + Assertions.assertEquals(20L, created.getTagId()); + + when(store.getTagResourceMapForTagAndResourceId(1L, 2L)).thenReturn(new RangerTagResourceMap()); + Assertions.assertThrows(Exception.class, () -> v.preCreateTagResourceMapByIds(1L, 2L)); + when(store.getTagResourceMapForTagAndResourceId(1L, 2L)).thenReturn(null); + when(store.getServiceResource(2L)).thenReturn(null); + Assertions.assertThrows(Exception.class, () -> v.preCreateTagResourceMapByIds(1L, 2L)); + when(store.getServiceResource(2L)).thenReturn(sr); + when(store.getTag(1L)).thenReturn(null); + Assertions.assertThrows(Exception.class, () -> v.preCreateTagResourceMapByIds(1L, 2L)); + when(store.getTag(1L)).thenReturn(tag); + RangerTagResourceMap createdByIds = v.preCreateTagResourceMapByIds(1L, 2L); + Assertions.assertEquals(2L, createdByIds.getResourceId()); + Assertions.assertEquals(1L, createdByIds.getTagId()); + + when(store.getTagResourceMap(99L)).thenReturn(null); + Assertions.assertThrows(Exception.class, () -> v.preDeleteTagResourceMap(99L)); + when(store.getTagResourceMap(99L)).thenReturn(new RangerTagResourceMap()); + Assertions.assertNotNull(v.preDeleteTagResourceMap(99L)); + + when(store.getTagResourceMapByGuid("g-x")).thenReturn(null); + Assertions.assertThrows(Exception.class, () -> v.preDeleteTagResourceMapByGuid("g-x")); + when(store.getTagResourceMapByGuid("g-1")).thenReturn(new RangerTagResourceMap()); + Assertions.assertNotNull(v.preDeleteTagResourceMapByGuid("g-1")); + + when(store.getTagResourceMapForTagAndResourceGuid("tg2", "rg2")).thenReturn(null); + Assertions.assertThrows(Exception.class, () -> v.preDeleteTagResourceMap("tg2", "rg2")); + when(store.getTagResourceMapForTagAndResourceGuid("tg2", "rg2")).thenReturn(new RangerTagResourceMap()); + Assertions.assertNotNull(v.preDeleteTagResourceMap("tg2", "rg2")); + + when(store.getTagResourceMapForTagAndResourceId(5L, 6L)).thenReturn(null); + Assertions.assertThrows(Exception.class, () -> v.preDeleteTagResourceMapByIds(5L, 6L)); + when(store.getTagResourceMapForTagAndResourceId(5L, 6L)).thenReturn(new RangerTagResourceMap()); + Assertions.assertNotNull(v.preDeleteTagResourceMapByIds(5L, 6L)); + } +} diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/store/file/TestGeolocationFileStore.java b/agents-common/src/test/java/org/apache/ranger/plugin/store/file/TestGeolocationFileStore.java new file mode 100644 index 0000000000..0e64c80c5f --- /dev/null +++ b/agents-common/src/test/java/org/apache/ranger/plugin/store/file/TestGeolocationFileStore.java @@ -0,0 +1,258 @@ +/* + * 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.store.file; + +import org.apache.ranger.plugin.geo.RangerGeolocationData; +import org.apache.ranger.plugin.geo.RangerGeolocationDatabase; +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.junit.jupiter.MockitoExtension; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; + +/** +* @generated by Cursor +* @description +*/ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +public class TestGeolocationFileStore { + private static Path writeTempGeoFile(final List lines) throws IOException { + Path tmp = Files.createTempFile("geo", ".txt"); + Files.write(tmp, new ArrayList<>(lines), StandardCharsets.UTF_8); + return tmp; + } + + private static Map newContext(final String filePath, final String forceRead, final String ipInDotFormat) { + Map ctx = new HashMap<>(); + if (filePath != null) { + ctx.put(GeolocationFileStore.PROP_GEOLOCATION_FILE_LOCATION, filePath); + } + if (forceRead != null) { + ctx.put(GeolocationFileStore.PROP_GEOLOCATION_FILE_REINIT, forceRead); + } + if (ipInDotFormat != null) { + ctx.put(GeolocationFileStore.PROP_GEOLOCATION_IP_IN_DOT_FORMAT, ipInDotFormat); + } + return ctx; + } + + @Test + public void test01_init_usesDefaultPathWhenBlank_andLeavesDbNull() { + GeolocationFileStore store = new GeolocationFileStore(); + Map ctx = new HashMap<>(); + + store.init(ctx); + + assertNull(store.getGeoDatabase()); + } + + @Test + public void test02_init_buildsDatabaseFromExistingFile_andCachesWhenNoReinit() throws Exception { + List lines = new ArrayList<>(); + lines.add("# comment"); + lines.add("FROM_IP,TO_IP,COUNTRY_CODE,COUNTRY_NAME"); + lines.add("1.2.3.4,1.2.3.4,US,United States"); + Path file = writeTempGeoFile(lines); + + GeolocationFileStore store1 = new GeolocationFileStore(); + store1.init(newContext(file.toString(), "true", "true")); + RangerGeolocationDatabase db1 = store1.getGeoDatabase(); + assertNotNull(db1); + + GeolocationFileStore store2 = new GeolocationFileStore(); + store2.init(newContext(file.toString(), "false", "true")); + RangerGeolocationDatabase db2 = store2.getGeoDatabase(); + assertNotNull(db2); + assertSame(db1, db2); + + RangerGeolocationData data = store2.getGeoLocation("1.2.3.4"); + assertNotNull(data); + assertEquals("US", db2.getValue(data, "COUNTRY_CODE")); + } + + @Test + public void test03_init_withReinitializeTrue_rebuildsAndReplacesCache() throws Exception { + List lines = new ArrayList<>(); + lines.add("FROM_IP,TO_IP,COUNTRY_CODE,COUNTRY_NAME"); + lines.add("2.2.2.2,2.2.2.3,CA,Canada"); + Path file = writeTempGeoFile(lines); + + GeolocationFileStore storeA = new GeolocationFileStore(); + storeA.init(newContext(file.toString(), "true", "true")); + RangerGeolocationDatabase dbA = storeA.getGeoDatabase(); + assertNotNull(dbA); + + // Modify file content to force a different DB instance on rebuild + List newLines = new ArrayList<>(); + newLines.add("FROM_IP,TO_IP,COUNTRY_CODE,COUNTRY_NAME"); + newLines.add("3.3.3.3,3.3.3.4,BR,Brazil"); + Files.write(file, newLines, StandardCharsets.UTF_8); + + GeolocationFileStore storeB = new GeolocationFileStore(); + storeB.init(newContext(file.toString(), "true", "true")); + RangerGeolocationDatabase dbB = storeB.getGeoDatabase(); + assertNotNull(dbB); + assertNotSame(dbA, dbB); + + assertNull(storeB.getGeoLocation("2.2.2.2")); + assertNotNull(storeB.getGeoLocation("3.3.3.3")); + } + + @Test + public void test04_init_readsFromClasspathResource_whenFileNotPresent() { + GeolocationFileStore store = new GeolocationFileStore(); + // Use the bundled sample resource path + store.init(newContext("/etc/ranger/geo/geo.txt", "true", "true")); + RangerGeolocationDatabase db = store.getGeoDatabase(); + assertNotNull(db); + // Known range in the sample file + RangerGeolocationData data = store.getGeoLocation("128.101.101.200"); + assertNotNull(data); + assertEquals("US", db.getValue(data, "COUNTRY_CODE")); + } + + @Test + public void test05_build_returnsNull_onInvalidMetadata() throws Exception { + List lines = new ArrayList<>(); + lines.add("# header"); + lines.add("FROM_IP,TO_IP"); // invalid: fewer than 3 fields + Path file = writeTempGeoFile(lines); + + GeolocationFileStore store = new GeolocationFileStore(); + RangerGeolocationDatabase db = store.build(file.toString()); + assertNull(db); + } + + @Test + public void test06_build_skipsInvalidDataAndEmptyLines_butSucceeds() throws Exception { + List lines = new ArrayList<>(); + lines.add("FROM_IP,TO_IP,COUNTRY_CODE"); + lines.add(""); // empty line -> split returns null, should be skipped + lines.add("bad.ip,1.1.1.1,XX"); // invalid data line -> skipped + lines.add("4.4.4.4,4.4.4.5,IN"); // valid + Path file = writeTempGeoFile(lines); + + GeolocationFileStore store = new GeolocationFileStore(); + // ensure dot-notation is used during build + store.init(newContext(file.toString(), "true", "true")); + RangerGeolocationDatabase db = store.getGeoDatabase(); + assertNotNull(db); + + assertNull(db.find("4.4.4.3")); + assertNotNull(db.find("4.4.4.4")); + assertNotNull(db.find("4.4.4.5")); + assertNull(db.find("4.4.4.6")); + } + + @Test + public void test07_getGeoLocation_returnsNull_whenDatabaseNotInitialized() { + GeolocationFileStore store = new GeolocationFileStore(); + assertNull(store.getGeoLocation("1.1.1.1")); + } + + @Test + public void test08_getGeoLocation_returnsNull_whenIpNotFound() throws Exception { + List lines = new ArrayList<>(); + lines.add("FROM_IP,TO_IP,COUNTRY_CODE"); + lines.add("5.5.5.5,5.5.5.5,DE"); + Path file = writeTempGeoFile(lines); + + GeolocationFileStore store = new GeolocationFileStore(); + store.init(newContext(file.toString(), "true", "true")); + assertNull(store.getGeoLocation("5.5.5.4")); + assertNotNull(store.getGeoLocation("5.5.5.5")); + assertNull(store.getGeoLocation("5.5.5.6")); + } + + @Test + public void test09_build_supportsNumericIps_whenDotFormatDisabled() throws Exception { + // 3232235777 = 192.168.1.1, 3232235778 = 192.168.1.2 + List lines = new ArrayList<>(); + lines.add("FROM_IP,TO_IP,COUNTRY_CODE"); + lines.add("3232235777,3232235778,US"); + Path file = writeTempGeoFile(lines); + + GeolocationFileStore store = new GeolocationFileStore(); + // Ensure useDotFormat is false before build + store.init(newContext(file.toString(), "true", "false")); + RangerGeolocationDatabase db = store.getGeoDatabase(); + assertNotNull(db); + assertNotNull(store.getGeoLocation("192.168.1.1")); + assertNotNull(store.getGeoLocation("192.168.1.2")); + assertNull(store.getGeoLocation("192.168.1.3")); + } + + @Test + public void test10_getGeoDatabase_returnsCurrentInstance() throws Exception { + List lines = new ArrayList<>(); + lines.add("FROM_IP,TO_IP,COUNTRY_CODE"); + lines.add("7.7.7.7,7.7.7.7,CA"); + Path file = writeTempGeoFile(lines); + + GeolocationFileStore store = new GeolocationFileStore(); + store.init(newContext(file.toString(), "true", "true")); + RangerGeolocationDatabase db = store.getGeoDatabase(); + assertNotNull(db); + assertSame(db, store.getGeoDatabase()); + } + + @Test + public void test11_init_reinitializeTrue_butBuildFails_retainsOldDatabase() throws Exception { + List lines = new ArrayList<>(); + lines.add("FROM_IP,TO_IP,COUNTRY_CODE"); + lines.add("8.8.8.8,8.8.8.8,US"); + Path file = writeTempGeoFile(lines); + + GeolocationFileStore store1 = new GeolocationFileStore(); + store1.init(newContext(file.toString(), "true", "true")); + RangerGeolocationDatabase originalDb = store1.getGeoDatabase(); + assertNotNull(originalDb); + assertNotNull(store1.getGeoLocation("8.8.8.8")); + + // Now corrupt the file so build() returns null (invalid metadata) + List bad = new ArrayList<>(); + bad.add("FROM_IP,TO_IP"); + Files.write(file, bad, StandardCharsets.UTF_8); + + GeolocationFileStore store2 = new GeolocationFileStore(); + store2.init(newContext(file.toString(), "true", "true")); + RangerGeolocationDatabase retainedDb = store2.getGeoDatabase(); + assertNotNull(retainedDb); + assertSame(originalDb, retainedDb); + // Old data should still be available since rebuild failed + assertNotNull(store2.getGeoLocation("8.8.8.8")); + } +}