This is an automated email from the ASF dual-hosted git repository.
rmani pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/master by this push:
new fd9c285 RANGER-2480:Hive URL Policy doesn't match if recursive flag
is on for the url resource
fd9c285 is described below
commit fd9c2852aebb785309825721e3deefdcf5e0d99d
Author: rmani <[email protected]>
AuthorDate: Tue Jul 2 11:56:28 2019 -0700
RANGER-2480:Hive URL Policy doesn't match if recursive flag is on for the
url resource
Signed-off-by: rmani <[email protected]>
---
.../resourcematcher/RangerURLResourceMatcher.java | 317 +++++++++++++++++++++
.../service-defs/ranger-servicedef-hive.json | 2 +-
.../RangerURLResourceMatcherTest.java | 88 ++++++
.../optimized/current/ranger_core_db_mysql.sql | 1 +
.../optimized/current/ranger_core_db_oracle.sql | 1 +
.../optimized/current/ranger_core_db_postgres.sql | 1 +
.../current/ranger_core_db_sqlanywhere.sql | 2 +
.../optimized/current/ranger_core_db_sqlserver.sql | 1 +
.../patch/PatchForHiveServiceDefUpdate_J10030.java | 207 ++++++++++++++
9 files changed, 619 insertions(+), 1 deletion(-)
diff --git
a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerURLResourceMatcher.java
b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerURLResourceMatcher.java
new file mode 100644
index 0000000..40f3df9
--- /dev/null
+++
b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerURLResourceMatcher.java
@@ -0,0 +1,317 @@
+/*
+ * 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.resourcematcher;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.io.IOCase;
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.util.ServiceDefUtil;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+public class RangerURLResourceMatcher extends RangerDefaultResourceMatcher {
+ private static final Log LOG =
LogFactory.getLog(RangerURLResourceMatcher.class);
+
+ public static final String OPTION_PATH_SEPARATOR =
"pathSeparatorChar";
+ public static final char DEFAULT_PATH_SEPARATOR_CHAR =
org.apache.hadoop.fs.Path.SEPARATOR_CHAR;
+
+ boolean policyIsRecursive;
+ char pathSeparatorChar = DEFAULT_PATH_SEPARATOR_CHAR;
+
+ @Override
+ public void init() {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerURLResourceMatcher.init()");
+ }
+
+ Map<String, String> options = resourceDef == null ? null :
resourceDef.getMatcherOptions();
+
+ policyIsRecursive = policyResource != null &&
policyResource.getIsRecursive();
+ pathSeparatorChar = ServiceDefUtil.getCharOption(options,
OPTION_PATH_SEPARATOR, DEFAULT_PATH_SEPARATOR_CHAR);
+
+ super.init();
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerURLResourceMatcher.init()");
+ }
+ }
+
+ @Override
+
+ protected ResourceMatcherWrapper buildResourceMatchers() {
+ List<ResourceMatcher> resourceMatchers = new ArrayList<>();
+ boolean needsDynamicEval = false;
+
+ for (String policyValue : policyValues) {
+ if (optWildCard && policyIsRecursive) {
+ if (policyValue.charAt(policyValue.length() - 1) ==
pathSeparatorChar) {
+ policyValue += WILDCARD_ASTERISK;
+ }
+ }
+
+ ResourceMatcher matcher = getMatcher(policyValue);
+
+ if (matcher != null) {
+ if (matcher.isMatchAny()) {
+ resourceMatchers.clear();
+ break;
+ }
+ if (!needsDynamicEval && matcher.getNeedsDynamicEval()) {
+ needsDynamicEval = true;
+ }
+ resourceMatchers.add(matcher);
+ }
+ }
+
+ Collections.sort(resourceMatchers, new
ResourceMatcher.PriorityComparator());
+
+ return CollectionUtils.isNotEmpty(resourceMatchers) ?
+ new ResourceMatcherWrapper(needsDynamicEval, resourceMatchers)
: null;
+ }
+
+ @Override
+ ResourceMatcher getMatcher(String policyValue) {
+ if(! policyIsRecursive) {
+ return super.getMatcher(policyValue);
+ }
+
+ final int len = policyValue != null ? policyValue.length() : 0;
+
+ if (len == 0) {
+ return null;
+ }
+
+ // To ensure that when policyValue is single '*', ResourceMatcher
created here returns true for isMatchAny()
+ if (optWildCard && WILDCARD_ASTERISK.equals(policyValue)) {
+ return new CaseInsensitiveStringMatcher("");
+ }
+
+ boolean isWildcardPresent = false;
+
+ if (optWildCard) {
+ for (int i = 0; i < len; i++) {
+ final char c = policyValue.charAt(i);
+
+ if (c == '?' || c == '*') {
+ isWildcardPresent = true;
+ break;
+ }
+ }
+ }
+
+ final ResourceMatcher ret;
+
+ if (isWildcardPresent) {
+ ret = optIgnoreCase ? new
CaseInsensitiveURLRecursiveWildcardMatcher(policyValue, pathSeparatorChar)
+ : new
CaseSensitiveURLRecursiveWildcardMatcher(policyValue, pathSeparatorChar);
+ } else {
+ ret = optIgnoreCase ? new
CaseInsensitiveURLRecursiveMatcher(policyValue, pathSeparatorChar) : new
CaseSensitiveURLRecursiveMatcher(policyValue, pathSeparatorChar);
+ }
+
+ if (optReplaceTokens) {
+ ret.setDelimiters(startDelimiterChar, endDelimiterChar,
escapeChar, tokenPrefix);
+ }
+
+ return ret;
+ }
+
+ static boolean isRecursiveWildCardMatch(String pathToCheck, String
wildcardPath, char pathSeparatorChar, IOCase caseSensitivity) {
+
+ boolean ret = false;
+
+ String url = StringUtils.trim(pathToCheck);
+
+ if (!StringUtils.isEmpty(url) && isPathURLType(url)) {
+ String scheme = getScheme(url);
+ if (StringUtils.isEmpty(scheme)) {
+ return ret;
+ }
+
+ String path = getPathWithOutScheme(url);
+
+ String[] pathElements = StringUtils.split(path,
pathSeparatorChar);
+
+ if (!ArrayUtils.isEmpty(pathElements)) {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append(scheme);
+
+ if (pathToCheck.charAt(0) == pathSeparatorChar) {
+ sb.append(pathSeparatorChar); // preserve the initial
pathSeparatorChar
+ }
+
+ for (String p : pathElements) {
+ sb.append(p);
+
+ ret = FilenameUtils.wildcardMatch(sb.toString(),
wildcardPath, caseSensitivity);
+
+ if (ret) {
+ break;
+ }
+
+ sb.append(pathSeparatorChar);
+ }
+
+ sb = null;
+ } else { // pathToCheck consists of only pathSeparatorChar
+ ret = FilenameUtils.wildcardMatch(pathToCheck,
wildcardPath, caseSensitivity);
+ }
+ }
+
+ return ret;
+ }
+
+ public StringBuilder toString(StringBuilder sb) {
+ sb.append("RangerURLResourceMatcher={");
+
+ super.toString(sb);
+
+ sb.append("policyIsRecursive={").append(policyIsRecursive).append("}
");
+
+ sb.append("}");
+
+ return sb;
+ }
+
+ static boolean isPathURLType(String url) {
+
+ Pattern p1 = Pattern.compile(":/{2}");
+ Matcher m1 = p1.matcher(url);
+
+ Pattern p2 = Pattern.compile(":/{3,}");
+ Matcher m2 = p2.matcher(url);
+
+ return (m1.find() && !(m2.find()));
+ }
+
+
+ static String getScheme(String url){
+ return StringUtils.substring(url,0,(StringUtils.indexOf(url,":") + 3));
+ }
+
+ static String getPathWithOutScheme(String url) {
+ return StringUtils.substring(url,(StringUtils.indexOf(url,":") + 2));
+ }
+}
+
+final class CaseSensitiveURLRecursiveWildcardMatcher extends ResourceMatcher {
+ private final char levelSeparatorChar;
+ CaseSensitiveURLRecursiveWildcardMatcher(String value, char
levelSeparatorChar) {
+ super(value);
+ this.levelSeparatorChar = levelSeparatorChar;
+ }
+
+ @Override
+ boolean isMatch(String resourceValue, Map<String, Object> evalContext) {
+ return
RangerURLResourceMatcher.isRecursiveWildCardMatch(resourceValue,
getExpandedValue(evalContext), levelSeparatorChar, IOCase.SENSITIVE);
+ }
+ int getPriority() { return 7 + (getNeedsDynamicEval() ?
DYNAMIC_EVALUATION_PENALTY : 0);}
+}
+
+final class CaseInsensitiveURLRecursiveWildcardMatcher extends ResourceMatcher
{
+ private final char levelSeparatorChar;
+ CaseInsensitiveURLRecursiveWildcardMatcher(String value, char
levelSeparatorChar) {
+ super(value);
+ this.levelSeparatorChar = levelSeparatorChar;
+ }
+
+ @Override
+ boolean isMatch(String resourceValue, Map<String, Object> evalContext) {
+ return
RangerURLResourceMatcher.isRecursiveWildCardMatch(resourceValue,
getExpandedValue(evalContext), levelSeparatorChar, IOCase.INSENSITIVE);
+ }
+ int getPriority() { return 8 + (getNeedsDynamicEval() ?
DYNAMIC_EVALUATION_PENALTY : 0);}
+
+}
+
+
+final class CaseSensitiveURLRecursiveMatcher extends RecursiveMatcher {
+ CaseSensitiveURLRecursiveMatcher(String value, char levelSeparatorChar) {
+ super(value, levelSeparatorChar);
+ }
+
+ @Override
+ boolean isMatch(String resourceValue, Map<String, Object> evalContext) {
+
+ final String noSeparator;
+ if (getNeedsDynamicEval()) {
+ String expandedPolicyValue = getExpandedValue(evalContext);
+ noSeparator = expandedPolicyValue != null ?
getStringToCompare(expandedPolicyValue) : null;
+ } else {
+ if (valueWithoutSeparator == null && value != null) {
+ valueWithoutSeparator = getStringToCompare(value);
+ valueWithSeparator = valueWithoutSeparator +
Character.toString(levelSeparatorChar);
+ }
+ noSeparator = valueWithoutSeparator;
+ }
+
+ boolean ret = StringUtils.equals(resourceValue, noSeparator);
+
+ if (!ret && noSeparator != null) {
+ final String withSeparator = getNeedsDynamicEval() ? noSeparator +
Character.toString(levelSeparatorChar) : valueWithSeparator;
+ ret = StringUtils.startsWith(resourceValue, withSeparator);
+ }
+
+ return ret;
+ }
+ int getPriority() { return 7 + (getNeedsDynamicEval() ?
DYNAMIC_EVALUATION_PENALTY : 0);}
+}
+
+final class CaseInsensitiveURLRecursiveMatcher extends RecursiveMatcher {
+ CaseInsensitiveURLRecursiveMatcher(String value, char levelSeparatorChar) {
+ super(value, levelSeparatorChar);
+ }
+
+ @Override
+ boolean isMatch(String resourceValue, Map<String, Object> evalContext) {
+
+ final String noSeparator;
+ if (getNeedsDynamicEval()) {
+ String expandedPolicyValue = getExpandedValue(evalContext);
+ noSeparator = expandedPolicyValue != null ?
getStringToCompare(expandedPolicyValue) : null;
+ } else {
+ if (valueWithoutSeparator == null && value != null) {
+ valueWithoutSeparator = getStringToCompare(value);
+ valueWithSeparator = valueWithoutSeparator +
Character.toString(levelSeparatorChar);
+ }
+ noSeparator = valueWithoutSeparator;
+ }
+
+ boolean ret = StringUtils.equalsIgnoreCase(resourceValue, noSeparator);
+
+ if (!ret && noSeparator != null) {
+ final String withSeparator = getNeedsDynamicEval() ? noSeparator +
Character.toString(levelSeparatorChar) : valueWithSeparator;
+ ret = StringUtils.startsWithIgnoreCase(resourceValue,
withSeparator);
+ }
+
+ return ret;
+ }
+
+ int getPriority() { return 8 + (getNeedsDynamicEval() ?
DYNAMIC_EVALUATION_PENALTY : 0);}
+}
\ No newline at end of file
diff --git
a/agents-common/src/main/resources/service-defs/ranger-servicedef-hive.json
b/agents-common/src/main/resources/service-defs/ranger-servicedef-hive.json
index 370ff56..7408cbc 100644
--- a/agents-common/src/main/resources/service-defs/ranger-servicedef-hive.json
+++ b/agents-common/src/main/resources/service-defs/ranger-servicedef-hive.json
@@ -93,7 +93,7 @@
"lookupSupported": false,
"recursiveSupported": true,
"excludesSupported": false,
- "matcher":
"org.apache.ranger.plugin.resourcematcher.RangerPathResourceMatcher",
+ "matcher":
"org.apache.ranger.plugin.resourcematcher.RangerURLResourceMatcher",
"matcherOptions": { "wildCard":true, "ignoreCase":false
},
"validationRegEx":"",
"validationMessage": "",
diff --git
a/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/RangerURLResourceMatcherTest.java
b/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/RangerURLResourceMatcherTest.java
new file mode 100644
index 0000000..2762932
--- /dev/null
+++
b/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/RangerURLResourceMatcherTest.java
@@ -0,0 +1,88 @@
+/*
+ * 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.resourcematcher;
+
+import com.google.common.collect.Lists;
+import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+
+public class RangerURLResourceMatcherTest {
+
+ Object[][] data = {
+ // { resource, policy, optWildcard, recursive, result
+ { "hdfs://hostname:8020/app/warehouse/data/emp.db",
"hdfs://hostname:8020/app/warehouse/*", true, true, true, "user" },
+ { "hdfs://hostname:8020/app/warehouse/data/emp.db",
"hdfs://hostname:8020/*", true, true, true, "user" },
+ { "hdfs://hostname:8020/app/warehouse/data/emp.db",
"hdfs://hostname:8020/app/*", true, false, true, "user" },
+ { "hdfs://hostname:8020/app/warehouse/data/emp.db",
"hdfs://hostname:8020/app/*", false, false, true, "user" },
+ { "hdfs://hostname:8020/app/warehouse/data/emp.db",
"hdfs://hostname:8020/app/", true, true, true, "user" },
+ { "s3a://app/warehouse/data/emp.db",
"s3a://app/*", true, true, true, "user" },
+ { "adls:/app/warehouse/data/emp.db",
"adls://app/*", true, true, false, "user" },
+ { "hdfs://app/warehouse/data/emp.db", "/app/*",
true, true, false, "user" },
+ { "/app/warehouse/data/emp.db",
"hdfs://app/*", true, true, false, "user" },
+ { "hdfs:/app/warehouse/data/emp.db",
"hdfs://app/*", true, true, false, "user" },
+ { "///app/warehouse/file://data/emp.db",
"hdfs://app/*", true, true, false, "user" },
+ { "hdfs:///app/warehouse/data/emp.db",
"hdfs://app/*", true, true, false, "user" },
+ { "hdfs://///app/warehouse/data/emp.db",
"hdfs://app/*", true, true, false, "user" },
+ { "://apps/warehouse/data/emp.db",
"hdfs://app/*", true, true, false, "user" }
+ };
+
+ @Test
+ public void testIsMatch() throws Exception {
+ for (Object[] row : data) {
+ String resource = (String)row[0];
+ String policyValue = (String)row[1];
+ boolean optWildcard = (boolean)row[2];
+ boolean isRecursive = (boolean)row[3];
+ boolean result = (boolean)row[4];
+ String user = (String) row[5];
+
+ Map<String, Object> evalContext = new HashMap<>();
+ RangerAccessRequestUtil.setCurrentUserInContext(evalContext, user);
+
+ MatcherWrapper matcher = new MatcherWrapper(policyValue,
optWildcard, isRecursive);
+ assertEquals(getMessage(row), result, matcher.isMatch(resource,
evalContext));
+ }
+ }
+
+ String getMessage(Object[] row) {
+ return String.format("Resource=%s, Policy=%s, optWildcard=%s,
recursive=%s, result=%s",
+ (String)row[0], (String)row[1], (boolean)row[2],
(boolean)row[3], (boolean)row[4]);
+ }
+
+ static class MatcherWrapper extends RangerURLResourceMatcher {
+ MatcherWrapper(String policyValue, boolean optWildcard, boolean
isRecursive) {
+ super.optWildCard = optWildcard;
+
+ RangerPolicy.RangerPolicyResource policyResource = new
RangerPolicy.RangerPolicyResource();
+ policyResource.setIsRecursive(isRecursive);
+ policyResource.setValues(Lists.newArrayList(policyValue));
+ setPolicyResource(policyResource);
+
+ init();
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/security-admin/db/mysql/optimized/current/ranger_core_db_mysql.sql
b/security-admin/db/mysql/optimized/current/ranger_core_db_mysql.sql
index 7aa9b3f..a6b033a 100644
--- a/security-admin/db/mysql/optimized/current/ranger_core_db_mysql.sql
+++ b/security-admin/db/mysql/optimized/current/ranger_core_db_mysql.sql
@@ -1717,4 +1717,5 @@ INSERT INTO x_db_version_h
(version,inst_at,inst_by,updated_at,updated_by,active
INSERT INTO x_db_version_h
(version,inst_at,inst_by,updated_at,updated_by,active) VALUES
('J10025',UTC_TIMESTAMP(),'Ranger 1.0.0',UTC_TIMESTAMP(),'localhost','Y');
INSERT INTO x_db_version_h
(version,inst_at,inst_by,updated_at,updated_by,active) VALUES
('J10026',UTC_TIMESTAMP(),'Ranger 1.0.0',UTC_TIMESTAMP(),'localhost','Y');
INSERT INTO x_db_version_h
(version,inst_at,inst_by,updated_at,updated_by,active) VALUES
('J10027',UTC_TIMESTAMP(),'Ranger 1.0.0',UTC_TIMESTAMP(),'localhost','Y');
+INSERT INTO x_db_version_h
(version,inst_at,inst_by,updated_at,updated_by,active) VALUES
('J10030',UTC_TIMESTAMP(),'Ranger 1.0.0',UTC_TIMESTAMP(),'localhost','Y');
INSERT INTO x_db_version_h
(version,inst_at,inst_by,updated_at,updated_by,active) VALUES
('JAVA_PATCHES',UTC_TIMESTAMP(),'Ranger 1.0.0',UTC_TIMESTAMP(),'localhost','Y');
diff --git
a/security-admin/db/oracle/optimized/current/ranger_core_db_oracle.sql
b/security-admin/db/oracle/optimized/current/ranger_core_db_oracle.sql
index 100ee9e..a4439d2 100644
--- a/security-admin/db/oracle/optimized/current/ranger_core_db_oracle.sql
+++ b/security-admin/db/oracle/optimized/current/ranger_core_db_oracle.sql
@@ -1888,5 +1888,6 @@ INSERT INTO x_db_version_h
(id,version,inst_at,inst_by,updated_at,updated_by,act
INSERT INTO x_db_version_h
(id,version,inst_at,inst_by,updated_at,updated_by,active) VALUES
(X_DB_VERSION_H_SEQ.nextval,'J10025',sys_extract_utc(systimestamp),'Ranger
1.0.0',sys_extract_utc(systimestamp),'localhost','Y');
INSERT INTO x_db_version_h
(id,version,inst_at,inst_by,updated_at,updated_by,active) VALUES
(X_DB_VERSION_H_SEQ.nextval,'J10026',sys_extract_utc(systimestamp),'Ranger
1.0.0',sys_extract_utc(systimestamp),'localhost','Y');
INSERT INTO x_db_version_h
(id,version,inst_at,inst_by,updated_at,updated_by,active) VALUES
(X_DB_VERSION_H_SEQ.nextval,'J10027',sys_extract_utc(systimestamp),'Ranger
1.0.0',sys_extract_utc(systimestamp),'localhost','Y');
+INSERT INTO x_db_version_h
(id,version,inst_at,inst_by,updated_at,updated_by,active) VALUES
(X_DB_VERSION_H_SEQ.nextval,'J10030',sys_extract_utc(systimestamp),'Ranger
1.0.0',sys_extract_utc(systimestamp),'localhost','Y');
INSERT INTO x_db_version_h
(id,version,inst_at,inst_by,updated_at,updated_by,active) VALUES
(X_DB_VERSION_H_SEQ.nextval,'JAVA_PATCHES',sys_extract_utc(systimestamp),'Ranger
1.0.0',sys_extract_utc(systimestamp),'localhost','Y');
commit;
diff --git
a/security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql
b/security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql
index eac6a75..2d5a891 100644
--- a/security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql
+++ b/security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql
@@ -1833,6 +1833,7 @@ INSERT INTO x_db_version_h
(version,inst_at,inst_by,updated_at,updated_by,active
INSERT INTO x_db_version_h
(version,inst_at,inst_by,updated_at,updated_by,active) VALUES
('J10025',current_timestamp,'Ranger 1.0.0',current_timestamp,'localhost','Y');
INSERT INTO x_db_version_h
(version,inst_at,inst_by,updated_at,updated_by,active) VALUES
('J10026',current_timestamp,'Ranger 1.0.0',current_timestamp,'localhost','Y');
INSERT INTO x_db_version_h
(version,inst_at,inst_by,updated_at,updated_by,active) VALUES
('J10027',current_timestamp,'Ranger 1.0.0',current_timestamp,'localhost','Y');
+INSERT INTO x_db_version_h
(version,inst_at,inst_by,updated_at,updated_by,active) VALUES
('J10030',current_timestamp,'Ranger 1.0.0',current_timestamp,'localhost','Y');
INSERT INTO x_db_version_h
(version,inst_at,inst_by,updated_at,updated_by,active) VALUES
('JAVA_PATCHES',current_timestamp,'Ranger
1.0.0',current_timestamp,'localhost','Y');
DROP VIEW IF EXISTS vx_trx_log;
diff --git
a/security-admin/db/sqlanywhere/optimized/current/ranger_core_db_sqlanywhere.sql
b/security-admin/db/sqlanywhere/optimized/current/ranger_core_db_sqlanywhere.sql
index b836ff1..f2e2840 100644
---
a/security-admin/db/sqlanywhere/optimized/current/ranger_core_db_sqlanywhere.sql
+++
b/security-admin/db/sqlanywhere/optimized/current/ranger_core_db_sqlanywhere.sql
@@ -2216,6 +2216,8 @@ INSERT INTO x_db_version_h
(version,inst_at,inst_by,updated_at,updated_by,active
GO
INSERT INTO x_db_version_h
(version,inst_at,inst_by,updated_at,updated_by,active) VALUES
('J10027',CURRENT_TIMESTAMP,'Ranger 1.0.0',CURRENT_TIMESTAMP,'localhost','Y');
GO
+INSERT INTO x_db_version_h
(version,inst_at,inst_by,updated_at,updated_by,active) VALUES
('J10030',CURRENT_TIMESTAMP,'Ranger 1.0.0',CURRENT_TIMESTAMP,'localhost','Y');
+GO
INSERT INTO x_db_version_h
(version,inst_at,inst_by,updated_at,updated_by,active) VALUES
('JAVA_PATCHES',CURRENT_TIMESTAMP,'Ranger
1.0.0',CURRENT_TIMESTAMP,'localhost','Y');
GO
exit
diff --git
a/security-admin/db/sqlserver/optimized/current/ranger_core_db_sqlserver.sql
b/security-admin/db/sqlserver/optimized/current/ranger_core_db_sqlserver.sql
index cca959a..be1e8a3 100644
--- a/security-admin/db/sqlserver/optimized/current/ranger_core_db_sqlserver.sql
+++ b/security-admin/db/sqlserver/optimized/current/ranger_core_db_sqlserver.sql
@@ -3903,6 +3903,7 @@ INSERT INTO x_db_version_h
(version,inst_at,inst_by,updated_at,updated_by,active
INSERT INTO x_db_version_h
(version,inst_at,inst_by,updated_at,updated_by,active) VALUES
('J10025',CURRENT_TIMESTAMP,'Ranger 1.0.0',CURRENT_TIMESTAMP,'localhost','Y');
INSERT INTO x_db_version_h
(version,inst_at,inst_by,updated_at,updated_by,active) VALUES
('J10026',CURRENT_TIMESTAMP,'Ranger 1.0.0',CURRENT_TIMESTAMP,'localhost','Y');
INSERT INTO x_db_version_h
(version,inst_at,inst_by,updated_at,updated_by,active) VALUES
('J10027',CURRENT_TIMESTAMP,'Ranger 1.0.0',CURRENT_TIMESTAMP,'localhost','Y');
+INSERT INTO x_db_version_h
(version,inst_at,inst_by,updated_at,updated_by,active) VALUES
('J10030',CURRENT_TIMESTAMP,'Ranger 1.0.0',CURRENT_TIMESTAMP,'localhost','Y');
INSERT INTO x_db_version_h
(version,inst_at,inst_by,updated_at,updated_by,active) VALUES
('JAVA_PATCHES',CURRENT_TIMESTAMP,'Ranger
1.0.0',CURRENT_TIMESTAMP,'localhost','Y');
GO
CREATE VIEW [dbo].[vx_trx_log] AS
diff --git
a/security-admin/src/main/java/org/apache/ranger/patch/PatchForHiveServiceDefUpdate_J10030.java
b/security-admin/src/main/java/org/apache/ranger/patch/PatchForHiveServiceDefUpdate_J10030.java
new file mode 100644
index 0000000..6dc5bfe
--- /dev/null
+++
b/security-admin/src/main/java/org/apache/ranger/patch/PatchForHiveServiceDefUpdate_J10030.java
@@ -0,0 +1,207 @@
+/*
+ * 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.lang.StringUtils;
+import org.apache.log4j.Logger;
+import org.apache.ranger.biz.RangerBizUtil;
+import org.apache.ranger.biz.ServiceDBStore;
+import org.apache.ranger.common.JSONUtil;
+import org.apache.ranger.common.RangerValidatorFactory;
+import org.apache.ranger.common.StringUtil;
+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.validation.RangerServiceDefValidator;
+import org.apache.ranger.plugin.model.validation.RangerValidator.Action;
+import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
+import org.apache.ranger.service.RangerPolicyService;
+import org.apache.ranger.service.XPermMapService;
+import org.apache.ranger.service.XPolicyService;
+import org.apache.ranger.util.CLIUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+
+@Component
+public class PatchForHiveServiceDefUpdate_J10030 extends BaseLoader {
+ private static final Logger logger =
Logger.getLogger(PatchForHiveServiceDefUpdate_J10030.class);
+ public static final String SERVICEDBSTORE_SERVICEDEFBYNAME_HIVE_NAME =
"hive";
+ public static final String HIVE_URL_MATCHER ="RangerURLResourceMatcher";
+
+ @Autowired
+ RangerDaoManager daoMgr;
+
+ @Autowired
+ ServiceDBStore svcDBStore;
+
+ @Autowired
+ JSONUtil jsonUtil;
+
+ @Autowired
+ RangerPolicyService policyService;
+
+ @Autowired
+ StringUtil stringUtil;
+
+ @Autowired
+ XPolicyService xPolService;
+
+ @Autowired
+ XPermMapService xPermMapService;
+
+ @Autowired
+ RangerBizUtil bizUtil;
+
+ @Autowired
+ RangerValidatorFactory validatorFactory;
+
+ @Autowired
+ ServiceDBStore svcStore;
+
+ public static void main(String[] args) {
+ logger.info("main()");
+ try {
+ PatchForHiveServiceDefUpdate_J10030 loader =
(PatchForHiveServiceDefUpdate_J10030)
CLIUtil.getBean(PatchForHiveServiceDefUpdate_J10030.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 execLoad() {
+ logger.info("==>
PatchForHiveServiceDefUpdateForURLTypeResourceUpdate.execLoad()");
+ try {
+ updateHiveServiceDef();
+ } catch (Exception e) {
+ logger.error("Error whille
updateHiveServiceDef()data.", e);
+ }
+ logger.info("<==
PatchForHiveServiceDefUpdateForURLTypeResourceUpdate.execLoad()");
+ }
+
+ @Override
+ public void printStats() {
+
logger.info("PatchForHiveServiceDefUpdateForURLTypeResourceUpdate data ");
+ }
+
+ private void updateHiveServiceDef(){
+ RangerServiceDef embeddedHiveServiceDef = null;
+ RangerServiceDef dbHiveServiceDef = null;
+ XXServiceDef xXServiceDefObj = null;
+ try{
+ embeddedHiveServiceDef =
EmbeddedServiceDefsUtil.instance().getEmbeddedServiceDef(SERVICEDBSTORE_SERVICEDEFBYNAME_HIVE_NAME);
+
+ if (embeddedHiveServiceDef != null) {
+ xXServiceDefObj =
daoMgr.getXXServiceDef().findByName(SERVICEDBSTORE_SERVICEDEFBYNAME_HIVE_NAME);
+ if (xXServiceDefObj == null) {
+ logger.error("Service def for " +
SERVICEDBSTORE_SERVICEDEFBYNAME_HIVE_NAME + " is not found!!");
+ return;
+ }
+
+ String jsonStrPreUpdate =
xXServiceDefObj.getDefOptions();
+ Map<String, String> serviceDefOptionsPreUpdate
= jsonUtil.jsonToMap(jsonStrPreUpdate);
+ String valueBeforeUpdate =
serviceDefOptionsPreUpdate.get(RangerServiceDef.OPTION_ENABLE_DENY_AND_EXCEPTIONS_IN_POLICIES);
+
+ dbHiveServiceDef =
svcDBStore.getServiceDefByName(SERVICEDBSTORE_SERVICEDEFBYNAME_HIVE_NAME);
+
+ if(dbHiveServiceDef != null) {
+ boolean isServiceDefUpdated =
updateServiceDef(dbHiveServiceDef, embeddedHiveServiceDef);
+
+ if (isServiceDefUpdated) {
+ xXServiceDefObj =
daoMgr.getXXServiceDef().findByName(SERVICEDBSTORE_SERVICEDEFBYNAME_HIVE_NAME);
+
+ if (xXServiceDefObj != null) {
+ String
jsonStrPostUpdate = xXServiceDefObj.getDefOptions();
+ Map<String, String>
serviceDefOptionsPostUpdate = jsonUtil.jsonToMap(jsonStrPostUpdate);
+ 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);
+ }
+ }
+ }
+ }
+ }
+ } catch(Exception e) {
+ logger.error("Error while updating
"+SERVICEDBSTORE_SERVICEDEFBYNAME_HIVE_NAME+"service-def", e);
+ }
+ }
+
+ private boolean updateServiceDef(RangerServiceDef serviceDef,
RangerServiceDef embeddedHiveServiceDef ) throws Exception {
+ boolean ret = false;
+
+ List<RangerServiceDef.RangerResourceDef>
embeddedHiveResourceDefs = null;
+
+ embeddedHiveResourceDefs =
embeddedHiveServiceDef.getResources();
+
+ if
(checkHiveURLResourceMatcherPresent(embeddedHiveResourceDefs)) {
+ // This is to check if URL resource matcher is added to
the resource definition, if so update the resource def
+ if (embeddedHiveResourceDefs != null) {
+
serviceDef.setResources(embeddedHiveResourceDefs);
+ }
+ ret = true;
+ }
+
+ RangerServiceDefValidator validator =
validatorFactory.getServiceDefValidator(svcStore);
+ validator.validate(serviceDef, Action.UPDATE);
+ svcStore.updateServiceDef(serviceDef);
+
+ return ret;
+ }
+
+ private boolean
checkHiveURLResourceMatcherPresent(List<RangerServiceDef.RangerResourceDef>
resourceDefs) {
+ boolean ret = false;
+ for(RangerServiceDef.RangerResourceDef resourceDef :
resourceDefs) {
+ String urlResourceMatcher = resourceDef.getMatcher();
+ if (StringUtils.isNotEmpty(urlResourceMatcher) &&
urlResourceMatcher.endsWith(HIVE_URL_MATCHER) ) {
+ ret = true ;
+ break;
+ }
+ }
+ return ret;
+ }
+
+ private String mapToJsonString(Map<String, String> map) throws
Exception {
+ String ret = null;
+ if(map != null) {
+ ret = jsonUtil.readMapToString(map);
+ }
+ return ret;
+ }
+}
+