You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ranger.apache.org by "rgupta94 (via GitHub)" <gi...@apache.org> on 2026/09/09 12:03:40 UTC
[PR] RANGER-5745 - Ranger: Support for wildcard in table name on SQL row f… [ranger]
rgupta94 opened a new pull request, #1220:
URL: https://github.com/apache/ranger/pull/1220
Experian has an application based on Hive in CDP Public Cloud. In a particular Hive database, each table is partitioned by ISO 8601 date string. Users of the database should have access to only the last five years of data.
We're currently able to achieve this requirement by applying a row-level filter policy. However, it's necessary to create one policy per table.
Experian has the same partition specification on every table in the database, so they'd like to be able to create a single policy, specifying criteria like "dt_part > '2019_01_10'", the name of the database, and "*" for the table name. Such wildcard table-name specification is not currently supported (as validated by documentation and testing).
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: dev-unsubscribe@ranger.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] RANGER-5745 - Ranger: Support for wildcard in table name on SQL row f… [ranger]
Posted by "rameeshm (via GitHub)" <gi...@apache.org>.
rameeshm commented on code in PR #1220:
URL: https://github.com/apache/ranger/pull/1220#discussion_r3972999212
##########
agents-common/src/main/resources/service-defs/ranger-servicedef-hive.json:
##########
@@ -198,7 +198,7 @@
],
"resources": [
{ "name": "database", "matcherOptions": { "wildCard": "false" }, "lookupSupported": true, "mandatory": true, "uiHint": "{ \"singleValue\":true }" },
- { "name": "table", "matcherOptions": { "wildCard": "false" }, "lookupSupported": true, "mandatory": true, "uiHint": "{ \"singleValue\":true }" }
+ { "name": "table", "matcherOptions": { "wildCard": "true" }, "lookupSupported": true, "mandatory": true, "uiHint": "" }
Review Comment:
@rgupta94 Ranger has a functionality of not to allow insert/update of table which has rowfilter / column masking in it and this will present the users from insert / update of the table in the database. Please check it out. There is a check in isBlockAccessIfRowfilterColumnMaskSpecified in RangerHiveAuthorizer which cause this issue. May be we should document this say that "applying a wildcard row filter will trigger RangerHivePlugin.blockUpdateIfRowfilterColumnMaskSpecified, effectively blocking all UPDATE/ALTER commands for that user across the entire database. Users should be advised to apply these wildcard policies strictly to Read-Only roles or disable the property in ranger-hive-security.xml." Also add some test cases for this in Hive Plugin. CC @mneethiraj
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: dev-unsubscribe@ranger.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] RANGER-5745 - Ranger: Support for wildcard in table name on SQL row f… [ranger]
Posted by "rgupta94 (via GitHub)" <gi...@apache.org>.
rgupta94 commented on code in PR #1220:
URL: https://github.com/apache/ranger/pull/1220#discussion_r3976309090
##########
agents-common/src/main/resources/service-defs/ranger-servicedef-hive.json:
##########
@@ -198,7 +198,7 @@
],
"resources": [
{ "name": "database", "matcherOptions": { "wildCard": "false" }, "lookupSupported": true, "mandatory": true, "uiHint": "{ \"singleValue\":true }" },
- { "name": "table", "matcherOptions": { "wildCard": "false" }, "lookupSupported": true, "mandatory": true, "uiHint": "{ \"singleValue\":true }" }
+ { "name": "table", "matcherOptions": { "wildCard": "true" }, "lookupSupported": true, "mandatory": true, "uiHint": "" }
Review Comment:
updated.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: dev-unsubscribe@ranger.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] RANGER-5745 - Ranger: Support for wildcard in table name on SQL row f… [ranger]
Posted by "rgupta94 (via GitHub)" <gi...@apache.org>.
rgupta94 closed pull request #1220: RANGER-5745 - Ranger: Support for wildcard in table name on SQL row f…
URL: https://github.com/apache/ranger/pull/1220
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: dev-unsubscribe@ranger.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] RANGER-5745 - Ranger: Support for wildcard in table name on SQL row f… [ranger]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #1220:
URL: https://github.com/apache/ranger/pull/1220#discussion_r3993577518
##########
agents-common/src/main/resources/service-defs/ranger-servicedef-hive.json:
##########
@@ -194,11 +194,30 @@
},
"rowFilterDef": {
"accessTypes": [
- { "name": "select" }
+ {
Review Comment:
I suggest retaining existing formatting - for conistency.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: dev-unsubscribe@ranger.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] RANGER-5745 - Ranger: Support for wildcard in table name on SQL row f… [ranger]
Posted by "Copilot (via GitHub)" <gi...@apache.org>.
Copilot commented on code in PR #1220:
URL: https://github.com/apache/ranger/pull/1220#discussion_r3973038654
##########
agents-common/src/main/resources/service-defs/ranger-servicedef-hive.json:
##########
@@ -198,7 +198,7 @@
],
"resources": [
{ "name": "database", "matcherOptions": { "wildCard": "false" }, "lookupSupported": true, "mandatory": true, "uiHint": "{ \"singleValue\":true }" },
- { "name": "table", "matcherOptions": { "wildCard": "false" }, "lookupSupported": true, "mandatory": true, "uiHint": "{ \"singleValue\":true }" }
+ { "name": "table", "matcherOptions": { "wildCard": "true" }, "lookupSupported": true, "mandatory": true, "uiHint": "" }
Review Comment:
This PR’s description focuses on enabling wildcard table names, but the embedded Hive service-def also changes `uiHint` from `{ "singleValue":true }` to an empty string. Clearing `uiHint` can affect UI behavior/validation independently of wildcard matching. If the goal is strictly wildcard support, consider keeping the prior `uiHint` (or documenting why it must be removed) and adjusting the Java patch accordingly (it currently copies `uiHint` from the embedded table resource into the DB service-def).
##########
security-admin/src/main/java/org/apache/ranger/patch/PatchForHiveServiceDefUpdate_J10068.java:
##########
@@ -0,0 +1,261 @@
+/*
+ * 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.patch;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.ranger.biz.ServiceDBStore;
+import org.apache.ranger.common.JSONUtil;
+import org.apache.ranger.common.RangerValidatorFactory;
+import org.apache.ranger.db.RangerDaoManager;
+import org.apache.ranger.entity.XXServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerRowFilterDef;
+import org.apache.ranger.plugin.model.validation.RangerServiceDefValidator;
+import org.apache.ranger.plugin.model.validation.RangerValidator.Action;
+import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
+import org.apache.ranger.util.CLIUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Component
+public class PatchForHiveServiceDefUpdate_J10068 extends BaseLoader {
+ private static final Logger logger = LoggerFactory.getLogger(PatchForHiveServiceDefUpdate_J10068.class);
+
+ private static final String HIVE_SERVICE_DEF_NAME = "hive";
+ private static final String ROW_FILTER_TABLE_RESOURCE_NAME = "table";
+
+ @Autowired
+ RangerDaoManager daoMgr;
+
+ @Autowired
+ ServiceDBStore svcStore;
+
+ @Autowired
+ JSONUtil jsonUtil;
+
+ @Autowired
+ RangerValidatorFactory validatorFactory;
+
+ public static void main(String[] args) {
+ logger.info("main()");
+
+ try {
+ PatchForHiveServiceDefUpdate_J10068 loader = (PatchForHiveServiceDefUpdate_J10068) CLIUtil.getBean(PatchForHiveServiceDefUpdate_J10068.class);
+
+ loader.init();
+
+ while (loader.isMoreToProcess()) {
+ loader.load();
+ }
+
+ logger.info("Load complete. Exiting!!!");
+
+ System.exit(0);
+ } catch (Exception e) {
+ logger.error("Error loading", e);
+
+ System.exit(1);
+ }
+ }
+
+ @Override
+ public void init() throws Exception {
+ // Do Nothing
+ }
+
+ @Override
+ public void printStats() {
+ logger.info("PatchForHiveServiceDefUpdate_J10068");
+ }
+
+ @Override
+ public void execLoad() {
+ logger.info("==> PatchForHiveServiceDefUpdate_J10068.execLoad()");
+
+ try {
+ updateHiveServiceDef();
+ } catch (Exception e) {
+ logger.error("Failed to apply PatchForHiveServiceDefUpdate_J10068.", e);
+
+ System.exit(1);
+ }
+
+ logger.info("<== PatchForHiveServiceDefUpdate_J10068.execLoad()");
+ }
+
+ private void updateHiveServiceDef() throws Exception {
+ RangerServiceDef embeddedHiveServiceDef = EmbeddedServiceDefsUtil.instance().getEmbeddedServiceDef(HIVE_SERVICE_DEF_NAME);
+
+ if (embeddedHiveServiceDef == null) {
+ throw new IllegalStateException("The embedded Hive service-definition does not exist.");
+ }
+
+ RangerRowFilterDef embeddedRowFilterDef = embeddedHiveServiceDef.getRowFilterDef();
+
+ if (embeddedRowFilterDef == null || CollectionUtils.isEmpty(embeddedRowFilterDef.getResources())) {
+ throw new IllegalStateException("Embedded " + HIVE_SERVICE_DEF_NAME + " service-def has no rowFilterDef.");
+ }
+
+ XXServiceDef xXServiceDefObj = daoMgr.getXXServiceDef().findByName(HIVE_SERVICE_DEF_NAME);
+
+ if (xXServiceDefObj == null) {
+ throw new IllegalStateException(HIVE_SERVICE_DEF_NAME + " service-def not found in DB.");
+ }
+
+ Map<String, String> serviceDefOptionsPreUpdate = jsonStringToMap(xXServiceDefObj.getDefOptions());
+ String valueBeforeUpdate = serviceDefOptionsPreUpdate == null ? null
+ : serviceDefOptionsPreUpdate.get(RangerServiceDef.OPTION_ENABLE_DENY_AND_EXCEPTIONS_IN_POLICIES);
+
+ RangerServiceDef dbHiveServiceDef = svcStore.getServiceDefByName(HIVE_SERVICE_DEF_NAME);
+
+ if (dbHiveServiceDef == null) {
+ throw new IllegalStateException(HIVE_SERVICE_DEF_NAME + " service-def not found in DB.");
+ }
+
+ updateRowFilterTableResource(embeddedRowFilterDef, dbHiveServiceDef.getRowFilterDef());
+
+ RangerServiceDefValidator validator = validatorFactory.getServiceDefValidator(svcStore);
+
+ validator.validate(dbHiveServiceDef, Action.UPDATE);
+
+ RangerServiceDef ret = svcStore.updateServiceDef(dbHiveServiceDef);
+
+ if (ret == null) {
+ throw new IllegalStateException("Error while updating " + HIVE_SERVICE_DEF_NAME + " service-def");
+ }
+
+ restoreDefOptionsIfNeeded(valueBeforeUpdate);
+
+ logger.info("Successfully updated rowFilterDef table resource for {} service-def", HIVE_SERVICE_DEF_NAME);
+ }
+
+ private void updateRowFilterTableResource(RangerRowFilterDef embeddedRowFilterDef, RangerRowFilterDef dbRowFilterDef) {
+ if (dbRowFilterDef == null || CollectionUtils.isEmpty(dbRowFilterDef.getResources())) {
+ throw new IllegalStateException("DB " + HIVE_SERVICE_DEF_NAME + " service-def has no rowFilterDef.");
+ }
+
+ RangerResourceDef embeddedTableResource = findRowFilterResource(embeddedRowFilterDef, ROW_FILTER_TABLE_RESOURCE_NAME);
+ RangerResourceDef dbTableResource = findRowFilterResource(dbRowFilterDef, ROW_FILTER_TABLE_RESOURCE_NAME);
+
+ if (embeddedTableResource == null) {
+ throw new IllegalStateException("Embedded " + HIVE_SERVICE_DEF_NAME + " rowFilterDef has no table resource.");
+ }
+
+ if (dbTableResource == null) {
+ throw new IllegalStateException("DB " + HIVE_SERVICE_DEF_NAME + " rowFilterDef has no table resource.");
+ }
+
+ Map<String, String> matcherOptions = embeddedTableResource.getMatcherOptions();
+
+ dbTableResource.setMatcherOptions(matcherOptions != null ? new HashMap<>(matcherOptions) : null);
+ dbTableResource.setUiHint(embeddedTableResource.getUiHint());
+ }
+
+ private RangerResourceDef findRowFilterResource(RangerRowFilterDef rowFilterDef, String resourceName) {
+ RangerResourceDef result = null;
+
+ if (rowFilterDef != null && CollectionUtils.isNotEmpty(rowFilterDef.getResources())) {
+ for (RangerResourceDef resourceDef : rowFilterDef.getResources()) {
+ if (resourceName.equals(resourceDef.getName())) {
+ result = resourceDef;
+ break;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ private void restoreDefOptionsIfNeeded(String valueBeforeUpdate) throws Exception {
+ XXServiceDef xXServiceDefObj = daoMgr.getXXServiceDef().findByName(HIVE_SERVICE_DEF_NAME);
+
+ if (xXServiceDefObj == null) {
+ return;
+ }
+
+ Map<String, String> serviceDefOptionsPostUpdate = jsonStringToMap(xXServiceDefObj.getDefOptions());
+
+ if (serviceDefOptionsPostUpdate == null) {
+ return;
+ }
+
+ String valueAfterUpdate = serviceDefOptionsPostUpdate.get(RangerServiceDef.OPTION_ENABLE_DENY_AND_EXCEPTIONS_IN_POLICIES);
+
+ if (!StringUtils.equals(valueBeforeUpdate, valueAfterUpdate)) {
+ if (StringUtils.isEmpty(valueBeforeUpdate)) {
+ serviceDefOptionsPostUpdate.remove(RangerServiceDef.OPTION_ENABLE_DENY_AND_EXCEPTIONS_IN_POLICIES);
+ } else {
+ serviceDefOptionsPostUpdate.put(RangerServiceDef.OPTION_ENABLE_DENY_AND_EXCEPTIONS_IN_POLICIES, valueBeforeUpdate);
+ }
+
+ xXServiceDefObj.setDefOptions(mapToJsonString(serviceDefOptionsPostUpdate));
+
+ daoMgr.getXXServiceDef().update(xXServiceDefObj);
+ }
+ }
+
+ protected Map<String, String> jsonStringToMap(String jsonStr) {
+ Map<String, String> ret = null;
+
+ if (!StringUtils.isEmpty(jsonStr)) {
+ try {
+ ret = jsonUtil.jsonToMap(jsonStr);
+ } catch (Exception excp) {
+ // fallback to earlier format: "name1=value1;name2=value2"
+ for (String optionString : jsonStr.split(";")) {
+ if (StringUtils.isEmpty(optionString)) {
+ continue;
+ }
+
+ String[] nvArr = optionString.split("=");
+ String name = (nvArr != null && nvArr.length > 0) ? nvArr[0].trim() : null;
+ String value = (nvArr != null && nvArr.length > 1) ? nvArr[1].trim() : null;
+
+ if (StringUtils.isEmpty(name)) {
+ continue;
+ }
+
+ if (ret == null) {
+ ret = new HashMap<>();
+ }
+
+ ret.put(name, value);
+ }
Review Comment:
`optionString.split("=")` will drop trailing empty values (e.g., `"c="` becomes `["c"]`) and will also truncate values containing `=` (e.g., `"a=b=c"` keeps only `"b"`). Prefer parsing by first `=` (e.g., `indexOf('=')`) or using `split("=", 2)` plus logic that preserves empty values, so legacy defOptions are round-tripped correctly.
##########
security-admin/src/test/java/org/apache/ranger/patch/TestPatchForHiveServiceDefUpdate_J10068.java:
##########
@@ -0,0 +1,433 @@
+/*
+ * 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.patch;
+
+import org.apache.ranger.biz.ServiceDBStore;
+import org.apache.ranger.common.JSONUtil;
+import org.apache.ranger.common.RangerValidatorFactory;
+import org.apache.ranger.db.RangerDaoManager;
+import org.apache.ranger.db.XXServiceDefDao;
+import org.apache.ranger.entity.XXServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerRowFilterDef;
+import org.apache.ranger.plugin.model.validation.RangerServiceDefValidator;
+import org.apache.ranger.plugin.model.validation.RangerValidator;
+import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
+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.ArgumentCaptor;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.Permission;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @description Unit Test for PatchForHiveServiceDefUpdate_J10068 class
+ */
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+class TestPatchForHiveServiceDefUpdate_J10068 {
+ private static final String HIVE_SERVICE_DEF_NAME = "hive";
+
+ @Test
+ void testExecLoadAndPrintStats() throws Exception {
+ try (MockedStatic<EmbeddedServiceDefsUtil> utilMock = mockEmbeddedServiceDef(createEmbeddedHiveServiceDef())) {
+ PatchForHiveServiceDefUpdate_J10068 patch = createPatchWithMocks();
+
+ mockSuccessfulDbUpdate(patch);
+
+ patch.execLoad();
+ patch.printStats();
+
+ Mockito.verify(patch.svcStore, Mockito.atLeastOnce()).updateServiceDef(Mockito.any(RangerServiceDef.class));
+ }
+ }
+
+ @Test
+ void testExecLoad_EmbeddedMissing_FailsAndExits() throws Exception {
+ try (MockedStatic<EmbeddedServiceDefsUtil> utilMock = mockEmbeddedServiceDef(null)) {
+ PatchForHiveServiceDefUpdate_J10068 patch = createPatchWithMocks();
+
+ assertExecLoadFailsAndExits(patch);
+
+ Mockito.verify(patch.svcStore, Mockito.never()).updateServiceDef(Mockito.any(RangerServiceDef.class));
+ }
+ }
+
+ @Test
+ void testExecLoad_UpdateReturnsNull_FailsAndExits() throws Exception {
+ try (MockedStatic<EmbeddedServiceDefsUtil> utilMock = mockEmbeddedServiceDef(createEmbeddedHiveServiceDef())) {
+ PatchForHiveServiceDefUpdate_J10068 patch = createPatchWithMocks();
+
+ RangerServiceDef dbServiceDef = createDbHiveServiceDef();
+
+ Mockito.doReturn(dbServiceDef).when(patch.svcStore).getServiceDefByName(HIVE_SERVICE_DEF_NAME);
+ Mockito.doReturn(null).when(patch.svcStore).updateServiceDef(Mockito.any(RangerServiceDef.class));
+
+ assertExecLoadFailsAndExits(patch);
+ }
+ }
+
+ @Test
+ void testUpdateHiveServiceDef_rowFilterDefMissing_throwsException() throws Exception {
+ RangerServiceDef embedded = new RangerServiceDef();
+ embedded.setName(HIVE_SERVICE_DEF_NAME);
+
+ try (MockedStatic<EmbeddedServiceDefsUtil> utilMock = mockEmbeddedServiceDef(embedded)) {
+ PatchForHiveServiceDefUpdate_J10068 patch = createPatchWithMocks();
+
+ IllegalStateException ex = Assertions.assertThrows(IllegalStateException.class,
+ () -> invokeUpdateHiveServiceDef(patch));
+ Assertions.assertTrue(ex.getMessage().contains("rowFilterDef"));
+ Mockito.verify(patch.svcStore, Mockito.never()).updateServiceDef(Mockito.any(RangerServiceDef.class));
+ }
+ }
+
+ @Test
+ void testUpdateHiveServiceDef_copiesOnlyTableResourceFields() throws Exception {
+ try (MockedStatic<EmbeddedServiceDefsUtil> utilMock = mockEmbeddedServiceDef(createEmbeddedHiveServiceDef())) {
+ PatchForHiveServiceDefUpdate_J10068 patch = createPatchWithMocks();
+ RangerServiceDefValidator validator = patch.validatorFactory.getServiceDefValidator(patch.svcStore);
+
+ RangerServiceDef dbServiceDef = createDbHiveServiceDef();
+ Mockito.doReturn(dbServiceDef).when(patch.svcStore).getServiceDefByName(HIVE_SERVICE_DEF_NAME);
+ Mockito.doReturn(dbServiceDef).when(patch.svcStore).updateServiceDef(Mockito.any(RangerServiceDef.class));
+
+ invokeUpdateHiveServiceDef(patch);
+
+ ArgumentCaptor<RangerServiceDef> captor = ArgumentCaptor.forClass(RangerServiceDef.class);
+
+ Mockito.verify(validator, Mockito.atLeastOnce()).validate(Mockito.any(RangerServiceDef.class),
+ Mockito.eq(RangerValidator.Action.UPDATE));
+ Mockito.verify(patch.svcStore).updateServiceDef(captor.capture());
+
+ RangerResourceDef tableResource = findRowFilterResource(captor.getValue(), "table");
+ RangerResourceDef databaseResource = findRowFilterResource(captor.getValue(), "database");
+
+ Assertions.assertNotNull(tableResource);
+ Assertions.assertNotNull(tableResource.getMatcherOptions());
+ Assertions.assertEquals("true", tableResource.getMatcherOptions().get("wildCard"));
+ Assertions.assertEquals("", tableResource.getUiHint());
+
+ Assertions.assertNotNull(databaseResource);
+ Assertions.assertNotNull(databaseResource.getMatcherOptions());
+ Assertions.assertEquals("false", databaseResource.getMatcherOptions().get("wildCard"));
+ Assertions.assertEquals("{ \"singleValue\":true }", databaseResource.getUiHint());
+ }
+ }
+
+ @Test
+ void testUpdateHiveServiceDef_copiesMatcherOptionsDefensively() throws Exception {
+ RangerServiceDef embedded = createEmbeddedHiveServiceDef();
+ Map<String, String> embeddedMatcherOptions = findRowFilterResource(embedded, "table").getMatcherOptions();
+
+ try (MockedStatic<EmbeddedServiceDefsUtil> utilMock = mockEmbeddedServiceDef(embedded)) {
+ PatchForHiveServiceDefUpdate_J10068 patch = createPatchWithMocks();
+
+ RangerServiceDef dbServiceDef = createDbHiveServiceDef();
+ Mockito.doReturn(dbServiceDef).when(patch.svcStore).getServiceDefByName(HIVE_SERVICE_DEF_NAME);
+ Mockito.doReturn(dbServiceDef).when(patch.svcStore).updateServiceDef(Mockito.any(RangerServiceDef.class));
+
+ invokeUpdateHiveServiceDef(patch);
+
+ ArgumentCaptor<RangerServiceDef> captor = ArgumentCaptor.forClass(RangerServiceDef.class);
+ Mockito.verify(patch.svcStore).updateServiceDef(captor.capture());
+
+ RangerResourceDef tableResource = findRowFilterResource(captor.getValue(), "table");
+
+ Assertions.assertNotNull(tableResource.getMatcherOptions());
+ Assertions.assertNotSame(embeddedMatcherOptions, tableResource.getMatcherOptions());
+ Assertions.assertEquals(embeddedMatcherOptions, tableResource.getMatcherOptions());
+ }
+ }
+
+ @Test
+ void testUpdateHiveServiceDef_idempotentWhenAlreadyPatched() throws Exception {
+ try (MockedStatic<EmbeddedServiceDefsUtil> utilMock = mockEmbeddedServiceDef(createEmbeddedHiveServiceDef())) {
+ PatchForHiveServiceDefUpdate_J10068 patch = createPatchWithMocks();
+
+ RangerServiceDef dbServiceDef = createEmbeddedHiveServiceDef();
+ Mockito.doReturn(dbServiceDef).when(patch.svcStore).getServiceDefByName(HIVE_SERVICE_DEF_NAME);
+ Mockito.doReturn(dbServiceDef).when(patch.svcStore).updateServiceDef(Mockito.any(RangerServiceDef.class));
+
+ invokeUpdateHiveServiceDef(patch);
+ invokeUpdateHiveServiceDef(patch);
+
+ Mockito.verify(patch.svcStore, Mockito.times(2)).updateServiceDef(Mockito.any(RangerServiceDef.class));
+
+ RangerResourceDef tableResource = findRowFilterResource(dbServiceDef, "table");
+ Assertions.assertEquals("true", tableResource.getMatcherOptions().get("wildCard"));
+ Assertions.assertEquals("", tableResource.getUiHint());
+ }
+ }
+
+ @Test
+ void testUpdateHiveServiceDef_restoresDefOptionsWhenInjected() throws Exception {
+ try (MockedStatic<EmbeddedServiceDefsUtil> utilMock = mockEmbeddedServiceDef(createEmbeddedHiveServiceDef())) {
+ PatchForHiveServiceDefUpdate_J10068 patch = createPatchWithMocks();
+
+ XXServiceDefDao xxServiceDefDao = patch.daoMgr.getXXServiceDef();
+ XXServiceDef xdefPre = Mockito.mock(XXServiceDef.class);
+ XXServiceDef xdefPost = Mockito.mock(XXServiceDef.class);
+
+ Mockito.when(xxServiceDefDao.findByName(HIVE_SERVICE_DEF_NAME)).thenReturn(xdefPre, xdefPost);
+ Mockito.when(xdefPre.getDefOptions()).thenReturn("{}");
+
+ Map<String, String> postMap = new HashMap<>();
+ postMap.put(RangerServiceDef.OPTION_ENABLE_DENY_AND_EXCEPTIONS_IN_POLICIES, "true");
+ Mockito.when(xdefPost.getDefOptions()).thenReturn(new JSONUtil().readMapToString(postMap));
+
+ RangerServiceDef dbServiceDef = createDbHiveServiceDef();
+ Mockito.doReturn(dbServiceDef).when(patch.svcStore).getServiceDefByName(HIVE_SERVICE_DEF_NAME);
+ Mockito.doReturn(dbServiceDef).when(patch.svcStore).updateServiceDef(Mockito.any(RangerServiceDef.class));
+
+ invokeUpdateHiveServiceDef(patch);
+
+ Mockito.verify(xxServiceDefDao, Mockito.times(1)).update(Mockito.eq(xdefPost));
+ }
+ }
+
+ @Test
+ void testJsonStringToMap_withJson() {
+ PatchForHiveServiceDefUpdate_J10068 patch = new PatchForHiveServiceDefUpdate_J10068();
+ patch.jsonUtil = new JSONUtil();
+
+ Map<String, String> result = patch.jsonStringToMap("{\"a\":\"1\",\"b\":\"2\"}");
+
+ Assertions.assertEquals("1", result.get("a"));
+ Assertions.assertEquals("2", result.get("b"));
+ }
+
+ @Test
+ void testJsonStringToMap_withLegacyFormat() {
+ PatchForHiveServiceDefUpdate_J10068 patch = new PatchForHiveServiceDefUpdate_J10068();
+ patch.jsonUtil = new JSONUtil();
+
+ Map<String, String> result = patch.jsonStringToMap("a=1;b=2;c=\n");
+
+ Assertions.assertEquals("1", result.get("a"));
+ Assertions.assertEquals("2", result.get("b"));
+ Assertions.assertTrue(result.containsKey("c"));
+ }
+
+ @Test
+ void testJsonStringToMap_nullOrEmpty() {
+ PatchForHiveServiceDefUpdate_J10068 patch = new PatchForHiveServiceDefUpdate_J10068();
+ patch.jsonUtil = new JSONUtil();
+
+ Assertions.assertNull(patch.jsonStringToMap(null));
+ Assertions.assertNull(patch.jsonStringToMap(""));
+ }
+
+ @Test
+ void testUpdateHiveServiceDef_preservesExistingDefOptions() throws Exception {
+ try (MockedStatic<EmbeddedServiceDefsUtil> utilMock = mockEmbeddedServiceDef(createEmbeddedHiveServiceDef())) {
+ PatchForHiveServiceDefUpdate_J10068 patch = createPatchWithMocks();
+
+ XXServiceDefDao xxServiceDefDao = patch.daoMgr.getXXServiceDef();
+ XXServiceDef xdefPre = Mockito.mock(XXServiceDef.class);
+ XXServiceDef xdefPost = Mockito.mock(XXServiceDef.class);
+
+ Mockito.when(xxServiceDefDao.findByName(HIVE_SERVICE_DEF_NAME)).thenReturn(xdefPre, xdefPost);
+
+ Map<String, String> preMap = new HashMap<>();
+ preMap.put(RangerServiceDef.OPTION_ENABLE_DENY_AND_EXCEPTIONS_IN_POLICIES, "abc");
+ Mockito.when(xdefPre.getDefOptions()).thenReturn(new JSONUtil().readMapToString(preMap));
+
+ Map<String, String> postMap = new HashMap<>();
+ postMap.put(RangerServiceDef.OPTION_ENABLE_DENY_AND_EXCEPTIONS_IN_POLICIES, "xyz");
+ Mockito.when(xdefPost.getDefOptions()).thenReturn(new JSONUtil().readMapToString(postMap));
+
+ RangerServiceDef dbServiceDef = createDbHiveServiceDef();
+ Mockito.doReturn(dbServiceDef).when(patch.svcStore).getServiceDefByName(HIVE_SERVICE_DEF_NAME);
+ Mockito.doReturn(dbServiceDef).when(patch.svcStore).updateServiceDef(Mockito.any(RangerServiceDef.class));
+
+ invokeUpdateHiveServiceDef(patch);
+
+ ArgumentCaptor<String> defOptionsCaptor = ArgumentCaptor.forClass(String.class);
+ Mockito.verify(xdefPost).setDefOptions(defOptionsCaptor.capture());
+ Mockito.verify(xxServiceDefDao, Mockito.times(1)).update(Mockito.eq(xdefPost));
+ Assertions.assertTrue(defOptionsCaptor.getValue()
+ .contains("\"" + RangerServiceDef.OPTION_ENABLE_DENY_AND_EXCEPTIONS_IN_POLICIES + "\":\"abc\""));
+ }
+ }
+
+ private void assertExecLoadFailsAndExits(PatchForHiveServiceDefUpdate_J10068 patch) {
+ SecurityManager original = System.getSecurityManager();
+
+ try {
+ System.setSecurityManager(new SecurityManager() {
+ @Override
+ public void checkPermission(Permission perm) {
+ }
+
+ @Override
+ public void checkExit(int status) {
+ throw new SecurityException("Intercepted System.exit");
+ }
+ });
+ patch.execLoad();
+ Assertions.fail("Expected SecurityException");
+ } catch (SecurityException ignored) {
+ } finally {
+ System.setSecurityManager(original);
+ }
+ }
Review Comment:
These tests rely on installing a custom `SecurityManager` to intercept `System.exit()`. `SecurityManager` is deprecated for removal and may be disabled in some build/runtime configurations, which can make the test suite fail or behave inconsistently. A more robust approach is to test the underlying behavior by invoking `updateHiveServiceDef()` (or a non-exiting helper) and asserting on thrown exceptions, rather than asserting on `System.exit()`.
##########
security-admin/src/test/java/org/apache/ranger/patch/TestPatchForHiveServiceDefUpdate_J10068.java:
##########
@@ -0,0 +1,433 @@
+/*
+ * 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.patch;
+
+import org.apache.ranger.biz.ServiceDBStore;
+import org.apache.ranger.common.JSONUtil;
+import org.apache.ranger.common.RangerValidatorFactory;
+import org.apache.ranger.db.RangerDaoManager;
+import org.apache.ranger.db.XXServiceDefDao;
+import org.apache.ranger.entity.XXServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerRowFilterDef;
+import org.apache.ranger.plugin.model.validation.RangerServiceDefValidator;
+import org.apache.ranger.plugin.model.validation.RangerValidator;
+import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
+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.ArgumentCaptor;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.Permission;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @description Unit Test for PatchForHiveServiceDefUpdate_J10068 class
+ */
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+class TestPatchForHiveServiceDefUpdate_J10068 {
+ private static final String HIVE_SERVICE_DEF_NAME = "hive";
+
+ @Test
+ void testExecLoadAndPrintStats() throws Exception {
+ try (MockedStatic<EmbeddedServiceDefsUtil> utilMock = mockEmbeddedServiceDef(createEmbeddedHiveServiceDef())) {
+ PatchForHiveServiceDefUpdate_J10068 patch = createPatchWithMocks();
+
+ mockSuccessfulDbUpdate(patch);
+
+ patch.execLoad();
+ patch.printStats();
+
+ Mockito.verify(patch.svcStore, Mockito.atLeastOnce()).updateServiceDef(Mockito.any(RangerServiceDef.class));
+ }
+ }
+
+ @Test
+ void testExecLoad_EmbeddedMissing_FailsAndExits() throws Exception {
+ try (MockedStatic<EmbeddedServiceDefsUtil> utilMock = mockEmbeddedServiceDef(null)) {
+ PatchForHiveServiceDefUpdate_J10068 patch = createPatchWithMocks();
+
+ assertExecLoadFailsAndExits(patch);
+
+ Mockito.verify(patch.svcStore, Mockito.never()).updateServiceDef(Mockito.any(RangerServiceDef.class));
+ }
+ }
+
+ @Test
+ void testExecLoad_UpdateReturnsNull_FailsAndExits() throws Exception {
+ try (MockedStatic<EmbeddedServiceDefsUtil> utilMock = mockEmbeddedServiceDef(createEmbeddedHiveServiceDef())) {
+ PatchForHiveServiceDefUpdate_J10068 patch = createPatchWithMocks();
+
+ RangerServiceDef dbServiceDef = createDbHiveServiceDef();
+
+ Mockito.doReturn(dbServiceDef).when(patch.svcStore).getServiceDefByName(HIVE_SERVICE_DEF_NAME);
+ Mockito.doReturn(null).when(patch.svcStore).updateServiceDef(Mockito.any(RangerServiceDef.class));
+
+ assertExecLoadFailsAndExits(patch);
+ }
+ }
+
+ @Test
+ void testUpdateHiveServiceDef_rowFilterDefMissing_throwsException() throws Exception {
+ RangerServiceDef embedded = new RangerServiceDef();
+ embedded.setName(HIVE_SERVICE_DEF_NAME);
+
+ try (MockedStatic<EmbeddedServiceDefsUtil> utilMock = mockEmbeddedServiceDef(embedded)) {
+ PatchForHiveServiceDefUpdate_J10068 patch = createPatchWithMocks();
+
+ IllegalStateException ex = Assertions.assertThrows(IllegalStateException.class,
+ () -> invokeUpdateHiveServiceDef(patch));
+ Assertions.assertTrue(ex.getMessage().contains("rowFilterDef"));
+ Mockito.verify(patch.svcStore, Mockito.never()).updateServiceDef(Mockito.any(RangerServiceDef.class));
+ }
+ }
+
+ @Test
+ void testUpdateHiveServiceDef_copiesOnlyTableResourceFields() throws Exception {
+ try (MockedStatic<EmbeddedServiceDefsUtil> utilMock = mockEmbeddedServiceDef(createEmbeddedHiveServiceDef())) {
+ PatchForHiveServiceDefUpdate_J10068 patch = createPatchWithMocks();
+ RangerServiceDefValidator validator = patch.validatorFactory.getServiceDefValidator(patch.svcStore);
+
+ RangerServiceDef dbServiceDef = createDbHiveServiceDef();
+ Mockito.doReturn(dbServiceDef).when(patch.svcStore).getServiceDefByName(HIVE_SERVICE_DEF_NAME);
+ Mockito.doReturn(dbServiceDef).when(patch.svcStore).updateServiceDef(Mockito.any(RangerServiceDef.class));
+
+ invokeUpdateHiveServiceDef(patch);
+
+ ArgumentCaptor<RangerServiceDef> captor = ArgumentCaptor.forClass(RangerServiceDef.class);
+
+ Mockito.verify(validator, Mockito.atLeastOnce()).validate(Mockito.any(RangerServiceDef.class),
+ Mockito.eq(RangerValidator.Action.UPDATE));
+ Mockito.verify(patch.svcStore).updateServiceDef(captor.capture());
+
+ RangerResourceDef tableResource = findRowFilterResource(captor.getValue(), "table");
+ RangerResourceDef databaseResource = findRowFilterResource(captor.getValue(), "database");
+
+ Assertions.assertNotNull(tableResource);
+ Assertions.assertNotNull(tableResource.getMatcherOptions());
+ Assertions.assertEquals("true", tableResource.getMatcherOptions().get("wildCard"));
+ Assertions.assertEquals("", tableResource.getUiHint());
+
+ Assertions.assertNotNull(databaseResource);
+ Assertions.assertNotNull(databaseResource.getMatcherOptions());
+ Assertions.assertEquals("false", databaseResource.getMatcherOptions().get("wildCard"));
+ Assertions.assertEquals("{ \"singleValue\":true }", databaseResource.getUiHint());
+ }
+ }
+
+ @Test
+ void testUpdateHiveServiceDef_copiesMatcherOptionsDefensively() throws Exception {
+ RangerServiceDef embedded = createEmbeddedHiveServiceDef();
+ Map<String, String> embeddedMatcherOptions = findRowFilterResource(embedded, "table").getMatcherOptions();
+
+ try (MockedStatic<EmbeddedServiceDefsUtil> utilMock = mockEmbeddedServiceDef(embedded)) {
+ PatchForHiveServiceDefUpdate_J10068 patch = createPatchWithMocks();
+
+ RangerServiceDef dbServiceDef = createDbHiveServiceDef();
+ Mockito.doReturn(dbServiceDef).when(patch.svcStore).getServiceDefByName(HIVE_SERVICE_DEF_NAME);
+ Mockito.doReturn(dbServiceDef).when(patch.svcStore).updateServiceDef(Mockito.any(RangerServiceDef.class));
+
+ invokeUpdateHiveServiceDef(patch);
+
+ ArgumentCaptor<RangerServiceDef> captor = ArgumentCaptor.forClass(RangerServiceDef.class);
+ Mockito.verify(patch.svcStore).updateServiceDef(captor.capture());
+
+ RangerResourceDef tableResource = findRowFilterResource(captor.getValue(), "table");
+
+ Assertions.assertNotNull(tableResource.getMatcherOptions());
+ Assertions.assertNotSame(embeddedMatcherOptions, tableResource.getMatcherOptions());
+ Assertions.assertEquals(embeddedMatcherOptions, tableResource.getMatcherOptions());
+ }
+ }
+
+ @Test
+ void testUpdateHiveServiceDef_idempotentWhenAlreadyPatched() throws Exception {
+ try (MockedStatic<EmbeddedServiceDefsUtil> utilMock = mockEmbeddedServiceDef(createEmbeddedHiveServiceDef())) {
+ PatchForHiveServiceDefUpdate_J10068 patch = createPatchWithMocks();
+
+ RangerServiceDef dbServiceDef = createEmbeddedHiveServiceDef();
+ Mockito.doReturn(dbServiceDef).when(patch.svcStore).getServiceDefByName(HIVE_SERVICE_DEF_NAME);
+ Mockito.doReturn(dbServiceDef).when(patch.svcStore).updateServiceDef(Mockito.any(RangerServiceDef.class));
+
+ invokeUpdateHiveServiceDef(patch);
+ invokeUpdateHiveServiceDef(patch);
+
+ Mockito.verify(patch.svcStore, Mockito.times(2)).updateServiceDef(Mockito.any(RangerServiceDef.class));
+
+ RangerResourceDef tableResource = findRowFilterResource(dbServiceDef, "table");
+ Assertions.assertEquals("true", tableResource.getMatcherOptions().get("wildCard"));
+ Assertions.assertEquals("", tableResource.getUiHint());
+ }
+ }
+
+ @Test
+ void testUpdateHiveServiceDef_restoresDefOptionsWhenInjected() throws Exception {
+ try (MockedStatic<EmbeddedServiceDefsUtil> utilMock = mockEmbeddedServiceDef(createEmbeddedHiveServiceDef())) {
+ PatchForHiveServiceDefUpdate_J10068 patch = createPatchWithMocks();
+
+ XXServiceDefDao xxServiceDefDao = patch.daoMgr.getXXServiceDef();
+ XXServiceDef xdefPre = Mockito.mock(XXServiceDef.class);
+ XXServiceDef xdefPost = Mockito.mock(XXServiceDef.class);
+
+ Mockito.when(xxServiceDefDao.findByName(HIVE_SERVICE_DEF_NAME)).thenReturn(xdefPre, xdefPost);
+ Mockito.when(xdefPre.getDefOptions()).thenReturn("{}");
+
+ Map<String, String> postMap = new HashMap<>();
+ postMap.put(RangerServiceDef.OPTION_ENABLE_DENY_AND_EXCEPTIONS_IN_POLICIES, "true");
+ Mockito.when(xdefPost.getDefOptions()).thenReturn(new JSONUtil().readMapToString(postMap));
+
+ RangerServiceDef dbServiceDef = createDbHiveServiceDef();
+ Mockito.doReturn(dbServiceDef).when(patch.svcStore).getServiceDefByName(HIVE_SERVICE_DEF_NAME);
+ Mockito.doReturn(dbServiceDef).when(patch.svcStore).updateServiceDef(Mockito.any(RangerServiceDef.class));
+
+ invokeUpdateHiveServiceDef(patch);
+
+ Mockito.verify(xxServiceDefDao, Mockito.times(1)).update(Mockito.eq(xdefPost));
+ }
+ }
+
+ @Test
+ void testJsonStringToMap_withJson() {
+ PatchForHiveServiceDefUpdate_J10068 patch = new PatchForHiveServiceDefUpdate_J10068();
+ patch.jsonUtil = new JSONUtil();
+
+ Map<String, String> result = patch.jsonStringToMap("{\"a\":\"1\",\"b\":\"2\"}");
+
+ Assertions.assertEquals("1", result.get("a"));
+ Assertions.assertEquals("2", result.get("b"));
+ }
+
+ @Test
+ void testJsonStringToMap_withLegacyFormat() {
+ PatchForHiveServiceDefUpdate_J10068 patch = new PatchForHiveServiceDefUpdate_J10068();
+ patch.jsonUtil = new JSONUtil();
+
+ Map<String, String> result = patch.jsonStringToMap("a=1;b=2;c=\n");
+
+ Assertions.assertEquals("1", result.get("a"));
+ Assertions.assertEquals("2", result.get("b"));
+ Assertions.assertTrue(result.containsKey("c"));
+ }
+
+ @Test
+ void testJsonStringToMap_nullOrEmpty() {
+ PatchForHiveServiceDefUpdate_J10068 patch = new PatchForHiveServiceDefUpdate_J10068();
+ patch.jsonUtil = new JSONUtil();
+
+ Assertions.assertNull(patch.jsonStringToMap(null));
+ Assertions.assertNull(patch.jsonStringToMap(""));
+ }
+
+ @Test
+ void testUpdateHiveServiceDef_preservesExistingDefOptions() throws Exception {
+ try (MockedStatic<EmbeddedServiceDefsUtil> utilMock = mockEmbeddedServiceDef(createEmbeddedHiveServiceDef())) {
+ PatchForHiveServiceDefUpdate_J10068 patch = createPatchWithMocks();
+
+ XXServiceDefDao xxServiceDefDao = patch.daoMgr.getXXServiceDef();
+ XXServiceDef xdefPre = Mockito.mock(XXServiceDef.class);
+ XXServiceDef xdefPost = Mockito.mock(XXServiceDef.class);
+
+ Mockito.when(xxServiceDefDao.findByName(HIVE_SERVICE_DEF_NAME)).thenReturn(xdefPre, xdefPost);
+
+ Map<String, String> preMap = new HashMap<>();
+ preMap.put(RangerServiceDef.OPTION_ENABLE_DENY_AND_EXCEPTIONS_IN_POLICIES, "abc");
+ Mockito.when(xdefPre.getDefOptions()).thenReturn(new JSONUtil().readMapToString(preMap));
+
+ Map<String, String> postMap = new HashMap<>();
+ postMap.put(RangerServiceDef.OPTION_ENABLE_DENY_AND_EXCEPTIONS_IN_POLICIES, "xyz");
+ Mockito.when(xdefPost.getDefOptions()).thenReturn(new JSONUtil().readMapToString(postMap));
+
+ RangerServiceDef dbServiceDef = createDbHiveServiceDef();
+ Mockito.doReturn(dbServiceDef).when(patch.svcStore).getServiceDefByName(HIVE_SERVICE_DEF_NAME);
+ Mockito.doReturn(dbServiceDef).when(patch.svcStore).updateServiceDef(Mockito.any(RangerServiceDef.class));
+
+ invokeUpdateHiveServiceDef(patch);
+
+ ArgumentCaptor<String> defOptionsCaptor = ArgumentCaptor.forClass(String.class);
+ Mockito.verify(xdefPost).setDefOptions(defOptionsCaptor.capture());
+ Mockito.verify(xxServiceDefDao, Mockito.times(1)).update(Mockito.eq(xdefPost));
+ Assertions.assertTrue(defOptionsCaptor.getValue()
+ .contains("\"" + RangerServiceDef.OPTION_ENABLE_DENY_AND_EXCEPTIONS_IN_POLICIES + "\":\"abc\""));
+ }
+ }
+
+ private void assertExecLoadFailsAndExits(PatchForHiveServiceDefUpdate_J10068 patch) {
+ SecurityManager original = System.getSecurityManager();
+
+ try {
+ System.setSecurityManager(new SecurityManager() {
+ @Override
+ public void checkPermission(Permission perm) {
+ }
+
+ @Override
+ public void checkExit(int status) {
+ throw new SecurityException("Intercepted System.exit");
+ }
+ });
+ patch.execLoad();
+ Assertions.fail("Expected SecurityException");
+ } catch (SecurityException ignored) {
+ } finally {
+ System.setSecurityManager(original);
+ }
+ }
+
+ private PatchForHiveServiceDefUpdate_J10068 createPatchWithMocks() {
+ PatchForHiveServiceDefUpdate_J10068 patch = new PatchForHiveServiceDefUpdate_J10068();
+
+ ServiceDBStore svcStore = Mockito.mock(ServiceDBStore.class);
+ RangerValidatorFactory validatorFactory = Mockito.mock(RangerValidatorFactory.class);
+ RangerServiceDefValidator validator = Mockito.mock(RangerServiceDefValidator.class);
+ RangerDaoManager daoMgr = Mockito.mock(RangerDaoManager.class);
+ XXServiceDefDao xxServiceDefDao = Mockito.mock(XXServiceDefDao.class);
+
+ Mockito.lenient().when(validatorFactory.getServiceDefValidator(svcStore)).thenReturn(validator);
+ Mockito.lenient().when(daoMgr.getXXServiceDef()).thenReturn(xxServiceDefDao);
+
+ XXServiceDef xXServiceDef = Mockito.mock(XXServiceDef.class);
+ Mockito.lenient().when(xxServiceDefDao.findByName(HIVE_SERVICE_DEF_NAME)).thenReturn(xXServiceDef);
+ Mockito.lenient().when(xXServiceDef.getDefOptions()).thenReturn("{}");
+
+ patch.svcStore = svcStore;
+ patch.validatorFactory = validatorFactory;
+ patch.daoMgr = daoMgr;
+ patch.jsonUtil = new JSONUtil();
+
+ return patch;
+ }
+
+ private void mockSuccessfulDbUpdate(PatchForHiveServiceDefUpdate_J10068 patch) throws Exception {
+ RangerServiceDef dbServiceDef = createDbHiveServiceDef();
+
+ Mockito.doReturn(dbServiceDef).when(patch.svcStore).getServiceDefByName(HIVE_SERVICE_DEF_NAME);
+ Mockito.doReturn(dbServiceDef).when(patch.svcStore).updateServiceDef(Mockito.any(RangerServiceDef.class));
+ }
+
+ private MockedStatic<EmbeddedServiceDefsUtil> mockEmbeddedServiceDef(RangerServiceDef embedded) throws Exception {
+ MockedStatic<EmbeddedServiceDefsUtil> utilMock = Mockito.mockStatic(EmbeddedServiceDefsUtil.class);
+ EmbeddedServiceDefsUtil util = Mockito.mock(EmbeddedServiceDefsUtil.class);
+
+ utilMock.when(EmbeddedServiceDefsUtil::instance).thenReturn(util);
+ Mockito.doReturn(embedded).when(util).getEmbeddedServiceDef(HIVE_SERVICE_DEF_NAME);
+
+ return utilMock;
+ }
+
+ private RangerServiceDef createEmbeddedHiveServiceDef() {
+ RangerServiceDef embedded = new RangerServiceDef();
+ embedded.setName(HIVE_SERVICE_DEF_NAME);
+ embedded.setRowFilterDef(createEmbeddedRowFilterDef());
+ return embedded;
+ }
+
+ private RangerServiceDef createDbHiveServiceDef() {
+ RangerServiceDef dbServiceDef = new RangerServiceDef();
+ dbServiceDef.setName(HIVE_SERVICE_DEF_NAME);
+ dbServiceDef.setRowFilterDef(createDbRowFilterDef());
+ return dbServiceDef;
+ }
+
+ private RangerRowFilterDef createEmbeddedRowFilterDef() {
+ Map<String, String> tableMatcherOptions = new HashMap<>();
+ tableMatcherOptions.put("wildCard", "true");
+
+ RangerResourceDef databaseResource = new RangerResourceDef();
+ databaseResource.setName("database");
+
+ RangerResourceDef tableResource = new RangerResourceDef();
+ tableResource.setName("table");
+ tableResource.setMatcherOptions(tableMatcherOptions);
+ tableResource.setUiHint("");
+
+ RangerRowFilterDef rowFilterDef = new RangerRowFilterDef();
+ rowFilterDef.setResources(Arrays.asList(databaseResource, tableResource));
+
+ return rowFilterDef;
+ }
+
+ private RangerRowFilterDef createDbRowFilterDef() {
+ Map<String, String> databaseMatcherOptions = new HashMap<>();
+ databaseMatcherOptions.put("wildCard", "false");
+
+ Map<String, String> tableMatcherOptions = new HashMap<>();
+ tableMatcherOptions.put("wildCard", "false");
+
+ RangerResourceDef databaseResource = new RangerResourceDef();
+ databaseResource.setName("database");
+ databaseResource.setMatcherOptions(databaseMatcherOptions);
+ databaseResource.setUiHint("{ \"singleValue\":true }");
+
+ RangerResourceDef tableResource = new RangerResourceDef();
+ tableResource.setName("table");
+ tableResource.setMatcherOptions(tableMatcherOptions);
+ tableResource.setUiHint("{ \"singleValue\":true }");
+
+ RangerRowFilterDef rowFilterDef = new RangerRowFilterDef();
+ rowFilterDef.setResources(Arrays.asList(databaseResource, tableResource));
+
+ return rowFilterDef;
+ }
+
+ private RangerResourceDef findRowFilterResource(RangerServiceDef serviceDef, String resourceName) {
+ RangerResourceDef result = null;
+
+ if (serviceDef != null && serviceDef.getRowFilterDef() != null && serviceDef.getRowFilterDef().getResources() != null) {
+ for (RangerResourceDef resourceDef : serviceDef.getRowFilterDef().getResources()) {
+ if (resourceName.equals(resourceDef.getName())) {
+ result = resourceDef;
+ break;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ private void invokeUpdateHiveServiceDef(PatchForHiveServiceDefUpdate_J10068 patch) throws Exception {
+ Method method = PatchForHiveServiceDefUpdate_J10068.class.getDeclaredMethod("updateHiveServiceDef");
+ method.setAccessible(true);
+
+ try {
+ method.invoke(patch);
+ } catch (InvocationTargetException e) {
+ Throwable cause = e.getCause();
+
+ if (cause instanceof Exception) {
+ throw (Exception) cause;
+ }
+
+ if (cause instanceof Error) {
+ throw (Error) cause;
+ }
+
+ throw e;
+ }
+ }
Review Comment:
The tests use reflection to call `updateHiveServiceDef()`, which adds verbosity and makes failures harder to debug (access checks, wrapped exceptions, etc.). Since the test is in the same package (`org.apache.ranger.patch`), consider making `updateHiveServiceDef()` package-private (or `protected` with a clear “visible for testing” intent) so tests can call it directly and avoid reflection.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: dev-unsubscribe@ranger.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] RANGER-5745 - Ranger: Support for wildcard in table name on SQL row f… [ranger]
Posted by "rgupta94 (via GitHub)" <gi...@apache.org>.
rgupta94 commented on PR #1220:
URL: https://github.com/apache/ranger/pull/1220#issuecomment-5728320675
This change is no longer needed,
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: dev-unsubscribe@ranger.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org