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;
+       }
+}
+

Reply via email to