Repository: incubator-ranger
Updated Branches:
  refs/heads/master 37351fbc8 -> 47c035603


RANGER-895: Ranger Hive plugin updates to support column-masking


Project: http://git-wip-us.apache.org/repos/asf/incubator-ranger/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ranger/commit/47c03560
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/47c03560
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/47c03560

Branch: refs/heads/master
Commit: 47c0356037ef47dfbe5590a5e72f1bb23277f914
Parents: 37351fb
Author: Madhan Neethiraj <[email protected]>
Authored: Fri Mar 25 10:13:53 2016 -0700
Committer: Madhan Neethiraj <[email protected]>
Committed: Fri Apr 1 20:21:10 2016 -0700

----------------------------------------------------------------------
 .../policyengine/RangerDataMaskResult.java      |  12 +
 .../ranger/plugin/util/ServiceDefUtil.java      |  20 ++
 .../service-defs/ranger-servicedef-hive.json    |  86 ++++-
 .../hive/authorizer/RangerHiveAuthorizer.java   |  99 +++++-
 pom.xml                                         |   1 +
 ranger-hive-utils/pom.xml                       |  79 +++++
 .../hive/udf/EncryptTransformer.java            |  63 ++++
 .../hive/udf/MaskFirstNTransformer.java         |  46 +++
 .../hive/udf/MaskLastNTransformer.java          |  46 +++
 .../hive/udf/MaskShowFirstNTransformer.java     |  46 +++
 .../hive/udf/MaskShowLastNTransformer.java      |  46 +++
 .../authorization/hive/udf/MaskTransformer.java | 209 ++++++++++++
 .../authorization/hive/udf/RangerBaseUdf.java   |  58 ++++
 .../hive/udf/RangerTransformer.java             |  61 ++++
 .../hive/udf/RangerTransformerFactory.java      |  80 +++++
 .../authorization/hive/udf/RangerUdfMask.java   | 324 +++++++++++++++++++
 .../hive/udf/ShuffleTransformer.java            | 102 ++++++
 .../service/RangerServiceDefServiceBase.java    |   2 +
 src/main/assembly/hive-agent.xml                |   1 +
 19 files changed, 1365 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerDataMaskResult.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerDataMaskResult.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerDataMaskResult.java
index 66d8eba..e0854df 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerDataMaskResult.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerDataMaskResult.java
@@ -21,6 +21,8 @@ package org.apache.ranger.plugin.policyengine;
 import org.apache.commons.lang.StringUtils;
 import 
org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemDataMaskInfo;
 import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerDataMaskTypeDef;
+import org.apache.ranger.plugin.util.ServiceDefUtil;
 
 
 public class RangerDataMaskResult extends RangerAccessResult {
@@ -88,6 +90,16 @@ public class RangerDataMaskResult extends RangerAccessResult 
{
                return StringUtils.isNotEmpty(this.getMaskType());
        }
 
+       public RangerDataMaskTypeDef getMaskTypeDef() {
+               RangerDataMaskTypeDef ret = null;
+
+               if(StringUtils.isNotEmpty(maskType)) {
+                       ret = ServiceDefUtil.getDataMaskType(getServiceDef(), 
maskType);
+               }
+
+               return ret;
+       }
+
        @Override
        public String toString( ) {
                StringBuilder sb = new StringBuilder();

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceDefUtil.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceDefUtil.java 
b/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceDefUtil.java
index c8e560a..34f4cc6 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceDefUtil.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceDefUtil.java
@@ -24,6 +24,7 @@ import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.ranger.plugin.model.RangerServiceDef;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerDataMaskTypeDef;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
 import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
 
@@ -46,6 +47,25 @@ public class ServiceDefUtil {
         return ret;
     }
 
+    public static RangerDataMaskTypeDef getDataMaskType(RangerServiceDef 
serviceDef, String typeName) {
+        RangerDataMaskTypeDef ret = null;
+
+        if(serviceDef != null && serviceDef.getDataMaskDef() != null) {
+            List<RangerDataMaskTypeDef> maskTypes = 
serviceDef.getDataMaskDef().getMaskTypes();
+
+            if(CollectionUtils.isNotEmpty(maskTypes)) {
+                for(RangerDataMaskTypeDef maskType : maskTypes) {
+                    if(StringUtils.equals(maskType.getName(), typeName)) {
+                        ret = maskType;
+                        break;
+                    }
+                }
+            }
+        }
+
+        return ret;
+    }
+
     public static RangerServiceDef normalize(RangerServiceDef serviceDef) {
         normalizeDataMaskDef(serviceDef);
 

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/agents-common/src/main/resources/service-defs/ranger-servicedef-hive.json
----------------------------------------------------------------------
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 77167c4..f3c75d1 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
@@ -262,42 +262,110 @@
                                "name": "MASK",
                                "label": "Mask",
                                "description": "Replace lowercase with 'x', 
uppercase with 'X', digits with '0'",
-                               "dataMaskOptions": { }
+                               "transformer": 
"org.apache.ranger.authorization.hive.udf.MaskTransformer",
+                               "dataMaskOptions": {
+                               }
                        },
                        {
                                "itemId": 2,
                                "name": "SHUFFLE",
                                "label": "Shuffle",
                                "description": "Shuffle the value of the 
column",
-                               "dataMaskOptions": { }
+                               "transformer": 
"org.apache.ranger.authorization.hive.udf.ShuffleTransformer",
+                               "dataMaskOptions": {
+                               }
                        },
                        {
                                "itemId": 3,
                                "name": "MASK_x_SHOW_LAST_4",
                                "label": "Partial mask: show last 4",
                                "description": "Show last 4 characters; replace 
rest with 'x'",
-                               "dataMaskOptions": { }
+                               "transformer": 
"org.apache.ranger.authorization.hive.udf.MaskShowLastNTransformer",
+                               "dataMaskOptions": {
+                                       "initParam": "charCount=4; upper=x; 
lower=x; digit=x; number=1"
+                               }
                        },
                        {
                                "itemId": 4,
                                "name": "MASK_x_SHOW_FIRST_4",
                                "label": "Partial mask: show first 4",
                                "description": "Show first 4 characters; 
replace rest with 'x'",
-                               "dataMaskOptions": { }
+                               "transformer": 
"org.apache.ranger.authorization.hive.udf.MaskShowFirstNTransformer",
+                               "dataMaskOptions": {
+                                       "initParam": "charCount=4; upper=x; 
lower=x; digit=x; number=1"
+                               }
+                       },
+                       {
+                               "itemId": 5,
+                               "name": "MASK_DATE_DAY",
+                               "label": "Date: show only month and year",
+                               "description": "Date: show only month and year",
+                               "transformer": 
"org.apache.ranger.authorization.hive.udf.MaskTransformer",
+                               "dataMaskOptions": {
+                                       "initParam": "day=1; month=-1; year=-1"
+                               }
+                       },
+                       {
+                               "itemId": 6,
+                               "name": "MASK_DATE_MONTH",
+                               "label": "Date: show only day and year",
+                               "description": "Date: show only day and year",
+                               "transformer": 
"org.apache.ranger.authorization.hive.udf.MaskTransformer",
+                               "dataMaskOptions": {
+                                       "initParam": "day=-1; month=0; year=-1"
+                               }
+                       },
+                       {
+                               "itemId": 7,
+                               "name": "MASK_DATE_YEAR",
+                               "label": "Date: show only day and month",
+                               "description": "Date: show only day and month",
+                               "transformer": 
"org.apache.ranger.authorization.hive.udf.MaskTransformer",
+                               "dataMaskOptions": {
+                                       "initParam": "day=-1; month=-1; year=0"
+                               }
+                       },
+                       {
+                               "itemId": 8,
+                               "name": "MASK_DATE_SHOW_DAY",
+                               "label": "Date: show only day",
+                               "description": "Date: show only day",
+                               "transformer": 
"org.apache.ranger.authorization.hive.udf.MaskTransformer",
+                               "dataMaskOptions": {
+                                       "initParam": "day=-1; month=0; year=0"
+                               }
+                       },
+                       {
+                               "itemId": 9,
+                               "name": "MASK_DATE_SHOW_MONTH",
+                               "label": "Date: show only month",
+                               "description": "Date: show only month",
+                               "transformer": 
"org.apache.ranger.authorization.hive.udf.MaskTransformer",
+                               "dataMaskOptions": {
+                                       "initParam": "day=1; month=-1; year=0"
+                               }
                        },
                        {
                                "itemId": 10,
+                               "name": "MASK_DATE_YEAR",
+                               "label": "Date: show only year",
+                               "description": "Date: show only year",
+                               "transformer": 
"org.apache.ranger.authorization.hive.udf.MaskTransformer",
+                               "dataMaskOptions": {
+                                       "initParam": "day=1; month=0; year=-1"
+                               }
+                       },
+                       {
+                               "itemId": 11,
                                "name": "NULL",
                                "label": "NULL",
-                               "description": "Replace with NULL",
-                               "dataMaskOptions": { }
+                               "description": "Replace with NULL"
                        },
                        {
-                               "itemId": 11,
+                               "itemId": 12,
                                "name": "NONE",
                                "label": "No masking",
-                               "description": "No masking",
-                               "dataMaskOptions": { }
+                               "description": "No masking"
                        }
                ]
        }

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/hive-agent/src/main/java/org/apache/ranger/authorization/hive/authorizer/RangerHiveAuthorizer.java
----------------------------------------------------------------------
diff --git 
a/hive-agent/src/main/java/org/apache/ranger/authorization/hive/authorizer/RangerHiveAuthorizer.java
 
b/hive-agent/src/main/java/org/apache/ranger/authorization/hive/authorizer/RangerHiveAuthorizer.java
index f6f9324..9c57968 100644
--- 
a/hive-agent/src/main/java/org/apache/ranger/authorization/hive/authorizer/RangerHiveAuthorizer.java
+++ 
b/hive-agent/src/main/java/org/apache/ranger/authorization/hive/authorizer/RangerHiveAuthorizer.java
@@ -27,6 +27,7 @@ import java.util.Map;
 import java.util.Set;
 
 import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -54,8 +55,10 @@ import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.ranger.authorization.hadoop.config.RangerConfiguration;
 import org.apache.ranger.authorization.hadoop.constants.RangerHadoopConstants;
 import org.apache.ranger.authorization.utils.StringUtil;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerDataMaskTypeDef;
 import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
 import org.apache.ranger.plugin.policyengine.RangerAccessResult;
+import org.apache.ranger.plugin.policyengine.RangerDataMaskResult;
 import org.apache.ranger.plugin.service.RangerBasePlugin;
 import org.apache.ranger.plugin.util.GrantRevokeRequest;
 import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
@@ -68,6 +71,10 @@ public class RangerHiveAuthorizer extends 
RangerHiveAuthorizerBase {
        private static final Log LOG = 
LogFactory.getLog(RangerHiveAuthorizer.class) ; 
 
        private static final char COLUMN_SEP = ',';
+       private static final String MASK_TYPE_NULL     = "NULL";
+       private static final String MASK_TYPE_NONE     = "NONE";
+       private static final String MASK_TYPE_CONSTANT = "CONSTANT";
+       private static final String MASK_UDF_NAME      = "rangerUdfMask";
 
        private static volatile RangerHivePlugin hivePlugin = null ;
 
@@ -462,22 +469,100 @@ public class RangerHiveAuthorizer extends 
RangerHiveAuthorizerBase {
 
        @Override
        public String getRowFilterExpression(String databaseName, String 
tableOrViewName) throws SemanticException {
-               return null;
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("==> getRowFilterExpression(" + databaseName 
+ ", " + tableOrViewName + ")");
+               }
+
+               String ret = null;
+
+
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("<== getRowFilterExpression(" + databaseName 
+ ", " + tableOrViewName + "): " + ret);
+               }
+
+               return ret;
        }
 
        @Override
-       public boolean needTransform() {
-               return false;
+       public String getCellValueTransformer(String databaseName, String 
tableOrViewName, String columnName) throws SemanticException {
+               UserGroupInformation ugi = getCurrentUserGroupInfo();
+
+               if(ugi == null) {
+                       throw new SemanticException("user information not 
available");
+               }
+
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("==> getCellValueTransformer(" + databaseName 
+ ", " + tableOrViewName + ", " + columnName + ")");
+               }
+
+               String ret = columnName;
+
+               RangerHiveAuditHandler auditHandler = new 
RangerHiveAuditHandler();
+
+               try {
+                       HiveAuthzContext        context        = null; // TODO: 
this should be provided as an argument to this method
+                       HiveAuthzSessionContext sessionContext = 
getHiveAuthzSessionContext();
+                       String                  user           = 
ugi.getShortUserName();
+                       Set<String>             groups         = 
Sets.newHashSet(ugi.getGroupNames());
+                       HiveObjectType          objectType     = 
HiveObjectType.COLUMN;
+                       RangerHiveResource      resource       = new 
RangerHiveResource(objectType, databaseName, tableOrViewName, columnName);
+                       RangerHiveAccessRequest request        = new 
RangerHiveAccessRequest(resource, user, groups, objectType.name(), 
HiveAccessType.SELECT, context, sessionContext);
+
+                       RangerDataMaskResult result = 
hivePlugin.evalDataMaskPolicies(request, auditHandler);
+
+                       if(result != null && result.isMaskEnabled()) {
+                               String                maskType    = 
result.getMaskType();
+                               RangerDataMaskTypeDef maskTypeDef = 
result.getMaskTypeDef();
+                               String                transformer = 
maskTypeDef.getTransformer();
+                               String                initParam   = "";
+
+                               
if(MapUtils.isNotEmpty(maskTypeDef.getDataMaskOptions())) {
+                                       initParam = 
maskTypeDef.getDataMaskOptions().get("initParam");
+
+                                       if(initParam == null) {
+                                               initParam = "";
+                                       }
+                               }
+
+                               if(StringUtils.equalsIgnoreCase(maskType, 
MASK_TYPE_NONE)) {
+                                       ret = columnName;
+                               } else 
if(StringUtils.equalsIgnoreCase(maskType, MASK_TYPE_NULL)) {
+                                       ret = "NULL";
+                               } else 
if(StringUtils.equalsIgnoreCase(maskType, MASK_TYPE_CONSTANT)) {
+                                       String maskedValue = 
result.getMaskedValue();
+
+                                       ret = maskedValue == null ? "NULL" : 
maskedValue;
+                               } else {
+                                       ret = MASK_UDF_NAME + "(" + columnName 
+ ", '" + maskType + "', '" + transformer + "', '" + initParam + "')";
+                               }
+
+                               /*
+                               String maskCondition = 
result.getMaskCondition();
+
+                               if(StringUtils.isNotEmpty(maskCondition)) {
+                                       ret = "if(" + maskCondition + ", " + 
ret + ", " + columnName + ")";
+                               }
+                               */
+                       }
+               } finally {
+                       auditHandler.flushAudit();
+               }
+
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("<== getCellValueTransformer(" + databaseName 
+ ", " + tableOrViewName + ", " + columnName + "): " + ret);
+               }
+
+               return ret;
        }
 
        @Override
-       public boolean needTransform(String databaseName, String 
tableOrViewName) {
-               return false;
+       public boolean needTransform() {
+               return true; // TODO: derive from the policies
        }
 
        @Override
-       public String getCellValueTransformer(String databaseName, String 
tableOrViewName, String columnName) throws SemanticException {
-               return columnName;
+       public boolean needTransform(String databaseName, String 
tableOrViewName) {
+               return true; // TODO: derive from the policies
        }
 
        RangerHiveResource createHiveResource(HivePrivilegeObject 
privilegeObject) {

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 2e0366a..fcd4c52 100644
--- a/pom.xml
+++ b/pom.xml
@@ -103,6 +103,7 @@
         <module>ranger-yarn-plugin-shim</module>
         <module>ranger-storm-plugin-shim</module>
         <module>ranger-kafka-plugin-shim</module>
+        <module>ranger-hive-utils</module>
         <module>ranger-examples</module>
         <module>ranger-tools</module>
     </modules>

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/ranger-hive-utils/pom.xml
----------------------------------------------------------------------
diff --git a/ranger-hive-utils/pom.xml b/ranger-hive-utils/pom.xml
new file mode 100644
index 0000000..ed10ec5
--- /dev/null
+++ b/ranger-hive-utils/pom.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>ranger-hive-utils</artifactId>
+  <name>Ranger Hive Utils</name>
+  <description>Ranger Hive Utils</description>
+  <packaging>jar</packaging>
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+  <parent>
+     <groupId>org.apache.ranger</groupId>
+     <artifactId>ranger</artifactId>
+     <version>0.6.0</version>
+     <relativePath>..</relativePath>
+  </parent>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.calcite</groupId>
+      <artifactId>calcite-core</artifactId>
+      <version>${calcite.version}</version>
+    </dependency>   
+    <dependency>
+      <groupId>org.apache.calcite</groupId>
+      <artifactId>calcite-avatica</artifactId>
+      <version>${calcite.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+      <version>${commons.lang.version}</version>
+    </dependency>
+    <dependency>
+         <groupId>org.apache.hadoop</groupId>
+         <artifactId>hadoop-common</artifactId>
+         <version>${hadoop-common.version}</version>
+    </dependency>
+    <dependency>
+         <groupId>org.apache.hive</groupId>
+         <artifactId>hive-common</artifactId>
+         <version>${hive.version}</version>
+    </dependency>
+    <dependency>
+         <groupId>org.apache.hive</groupId>
+         <artifactId>hive-service</artifactId>
+         <version>${hive.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.hive</groupId>
+      <artifactId>hive-exec</artifactId>
+      <version>${hive.version}</version>
+    </dependency>
+    <dependency>
+         <groupId>org.apache.hive</groupId>
+         <artifactId>hive-metastore</artifactId>
+         <version>${hive.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.google.code.gson</groupId>
+      <artifactId>gson</artifactId>
+    </dependency>
+  </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/EncryptTransformer.java
----------------------------------------------------------------------
diff --git 
a/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/EncryptTransformer.java
 
b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/EncryptTransformer.java
new file mode 100644
index 0000000..f002f9a
--- /dev/null
+++ 
b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/EncryptTransformer.java
@@ -0,0 +1,63 @@
+/*
+ * 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.authorization.hive.udf;
+
+import org.apache.commons.codec.digest.DigestUtils;
+
+import java.sql.Date;
+
+
+public class EncryptTransformer extends RangerTransformer {
+       public EncryptTransformer() {
+       }
+
+       @Override
+       public void init(String initParam) {
+       }
+
+       @Override
+       String transform(String value) {
+               return value == null ? STRING_0 : this.encryptToMd5Hex(value);
+       }
+
+       @Override
+       Short transform(Short value) {
+               return SHORT_0;
+       }
+
+       @Override
+       Integer transform(Integer value) {
+               return INTEGER_0;
+       }
+
+       @Override
+       Long transform(Long value) {
+               return LONG_0;
+       }
+
+       @Override
+       Date transform(Date value) {
+               return DATE_0;
+       }
+
+       String encryptToMd5Hex(String value) {
+               return DigestUtils.md5Hex(value);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskFirstNTransformer.java
----------------------------------------------------------------------
diff --git 
a/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskFirstNTransformer.java
 
b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskFirstNTransformer.java
new file mode 100644
index 0000000..e37b3ef
--- /dev/null
+++ 
b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskFirstNTransformer.java
@@ -0,0 +1,46 @@
+/*
+ * 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.authorization.hive.udf;
+
+
+public class MaskFirstNTransformer extends MaskTransformer {
+       int charCount = 4;
+
+       public MaskFirstNTransformer() {
+               super();
+       }
+
+       @Override
+       public void init(String initParam) {
+               super.init(initParam);
+
+               charCount = getIntOption("charCount", 4);
+       }
+
+       @Override
+       int getMaskStartIndex(String val) {
+               return 0;
+       }
+
+       @Override
+       int getMaskEndIndex(String val) {
+               return charCount;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskLastNTransformer.java
----------------------------------------------------------------------
diff --git 
a/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskLastNTransformer.java
 
b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskLastNTransformer.java
new file mode 100644
index 0000000..18bc558
--- /dev/null
+++ 
b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskLastNTransformer.java
@@ -0,0 +1,46 @@
+/*
+ * 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.authorization.hive.udf;
+
+
+public class MaskLastNTransformer extends MaskTransformer {
+       int charCount = 4;
+
+       public MaskLastNTransformer() {
+               super();
+       }
+
+       @Override
+       public void init(String initParam) {
+               super.init(initParam);
+
+               this.charCount = getIntOption("charCount", 4);
+       }
+
+       @Override
+       int getMaskStartIndex(String val) {
+               return val.length() - charCount;
+       }
+
+       @Override
+       int getMaskEndIndex(String val) {
+               return val.length();
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskShowFirstNTransformer.java
----------------------------------------------------------------------
diff --git 
a/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskShowFirstNTransformer.java
 
b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskShowFirstNTransformer.java
new file mode 100644
index 0000000..26a4c32
--- /dev/null
+++ 
b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskShowFirstNTransformer.java
@@ -0,0 +1,46 @@
+/*
+ * 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.authorization.hive.udf;
+
+
+public class MaskShowFirstNTransformer extends MaskTransformer {
+       int charCount = 4;
+
+       public MaskShowFirstNTransformer() {
+               super();
+       }
+
+       @Override
+       public void init(String initParam) {
+               super.init(initParam);
+
+               this.charCount = getIntOption("charCount", 4);
+       }
+
+       @Override
+       int getMaskStartIndex(String val) {
+               return charCount;
+       }
+
+       @Override
+       int getMaskEndIndex(String val) {
+               return val.length();
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskShowLastNTransformer.java
----------------------------------------------------------------------
diff --git 
a/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskShowLastNTransformer.java
 
b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskShowLastNTransformer.java
new file mode 100644
index 0000000..cb30e50
--- /dev/null
+++ 
b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskShowLastNTransformer.java
@@ -0,0 +1,46 @@
+/*
+ * 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.authorization.hive.udf;
+
+
+public class MaskShowLastNTransformer extends MaskTransformer {
+       int charCount;
+
+       public MaskShowLastNTransformer() {
+               super();
+       }
+
+       @Override
+       public void init(String initParam) {
+               super.init(initParam);
+
+               this.charCount = getIntOption("charCount", 4);
+       }
+
+       @Override
+       int getMaskStartIndex(String val) {
+               return 0;
+       }
+
+       @Override
+       int getMaskEndIndex(String val) {
+               return val.length() - charCount;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskTransformer.java
----------------------------------------------------------------------
diff --git 
a/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskTransformer.java
 
b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskTransformer.java
new file mode 100644
index 0000000..64de392
--- /dev/null
+++ 
b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskTransformer.java
@@ -0,0 +1,209 @@
+/*
+ * 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.authorization.hive.udf;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.sql.Date;
+
+
+public class MaskTransformer extends RangerTransformer {
+       final static int MASKED_UPPERCASE            = 'X';
+       final static int MASKED_LOWERCASE            = 'x';
+       final static int MASKED_NUMBER               = '1';
+       final static int MASKED_DAY_COMPONENT_VAL    = 1;
+       final static int MASKED_MONTH_COMPONENT_VAL  = 0;
+       final static int MASKED_YEAR_COMPONENT_VAL   = 0;
+       final static int UNMASKED_DATE_COMPONENT_VAL = -1;
+
+       int maskedUpperChar   = MASKED_UPPERCASE;
+       int maskedLowerChar   = MASKED_LOWERCASE;
+       int maskedDigitChar   = MASKED_NUMBER;
+       int maskedNumber      = MASKED_NUMBER;
+       int maskedDayValue    = MASKED_DAY_COMPONENT_VAL;
+       int maskedMonthValue  = MASKED_MONTH_COMPONENT_VAL;
+       int maskedYearValue   = MASKED_YEAR_COMPONENT_VAL;
+
+       public MaskTransformer() {
+       }
+
+       @Override
+       public void init(String initParam) {
+               if(StringUtils.isNotEmpty(initParam)) {
+                       for(String nvStr : initParam.split(";")) {
+                               if(StringUtils.isNotEmpty(nvStr)) {
+                                       String[] nameValue = nvStr.split("=", 
2);
+                                       String  name  = nameValue != null && 
nameValue.length > 0 ? nameValue[0] : null;
+                                       String  value = nameValue != null && 
nameValue.length > 1 ? nameValue[1] : null;
+
+                                       if(StringUtils.isNotEmpty(name)) {
+                                               options.put(name.trim(), 
value.trim());
+                                       }
+                               }
+                       }
+               }
+
+               maskedUpperChar  = getCharOption("upper", MASKED_UPPERCASE);
+               maskedLowerChar  = getCharOption("lower", MASKED_LOWERCASE);
+               maskedDigitChar  = getCharOption("digit", MASKED_NUMBER);
+               maskedNumber     = getCharOption("number", MASKED_NUMBER);
+               maskedDayValue   = getIntOption("day", 
MASKED_DAY_COMPONENT_VAL);
+               maskedMonthValue = getIntOption("month", 
MASKED_MONTH_COMPONENT_VAL);
+               maskedYearValue  = getIntOption("year", 
MASKED_YEAR_COMPONENT_VAL);
+       }
+
+       @Override
+       String transform(String value) {
+               return value == null ? STRING_0 : transformAlphaNum(value);
+       }
+
+       @Override
+       Short transform(Short value) {
+               return value == null ? SHORT_0 : 
Short.parseShort(transformNum(value.toString()));
+       }
+
+       @Override
+       Integer transform(Integer value) {
+               return value == null ? INTEGER_0 : 
Integer.parseInt(transformNum(value.toString()));
+       }
+
+       @Override
+       Long transform(Long value) {
+               return value == null ? LONG_0 : 
Long.parseLong(transformNum(value.toString()));
+       }
+
+       @Override
+       Date transform(Date value) {
+               return mask(value, maskedDayValue, maskedMonthValue, 
maskedYearValue);
+       }
+
+       String transformNum(String val) {
+               return transformNum(val, maskedNumber, getMaskStartIndex(val), 
getMaskEndIndex(val));
+       }
+
+       String transformAlphaNum(String val) {
+               return transformAlphaNum(val, maskedUpperChar, maskedLowerChar, 
maskedDigitChar, getMaskStartIndex(val), getMaskEndIndex(val));
+       }
+
+       Date mask(Date value, int maskedDay, int maskedMonth, int maskedYear) {
+               int year  = maskedYear  == UNMASKED_DATE_COMPONENT_VAL ? 
value.getYear()  : MASKED_YEAR_COMPONENT_VAL;
+               int month = maskedMonth == UNMASKED_DATE_COMPONENT_VAL ? 
value.getMonth() : MASKED_MONTH_COMPONENT_VAL;
+               int day   = maskedDay   == UNMASKED_DATE_COMPONENT_VAL ? 
value.getDate()  : MASKED_DAY_COMPONENT_VAL;
+
+               return new Date(year, month, day);
+       }
+
+       int getMaskStartIndex(String val) {
+               return 0;
+       }
+
+       int getMaskEndIndex(String val) {
+               return val.length();
+       }
+
+
+       String transformNum(String val, int replaceDigit, int startIdx, int 
endIdx) {
+               if(val == null) {
+                       return null;
+               }
+
+               StringBuffer strBuf = new StringBuffer(val.length());
+
+               if(startIdx < 0) {
+                       startIdx = 0;
+               }
+
+               if(endIdx > val.length()) {
+                       endIdx = val.length();
+               }
+
+               for(int i = 0; i < startIdx; i++) {
+                       strBuf.appendCodePoint(val.charAt(i));
+               }
+
+               for(int i = startIdx; i < endIdx; i++) {
+                       int c = val.charAt(i);
+
+                       switch(Character.getType(c)) {
+                               case Character.DECIMAL_DIGIT_NUMBER:
+                                       c = replaceDigit;
+                                       break;
+                       }
+
+                       strBuf.appendCodePoint(c);
+               }
+
+               for(int i = endIdx; i < val.length(); i++) {
+                       strBuf.appendCodePoint(val.charAt(i));
+               }
+
+               String ret = strBuf.toString();
+
+               return ret;
+       }
+
+       String transformAlphaNum(String val, int replaceUpperChar, int 
replaceLowerChar, int replaceDigit, int startIdx, int endIdx) {
+               if(val == null) {
+                       return null;
+               }
+
+               StringBuffer strBuf = new StringBuffer(val.length());
+
+               if(startIdx < 0) {
+                       startIdx = 0;
+               }
+
+               if(endIdx > val.length()) {
+                       endIdx = val.length();
+               }
+
+               for(int i = 0; i < startIdx; i++) {
+                       strBuf.appendCodePoint(val.charAt(i));
+               }
+
+               for(int i = startIdx; i < endIdx; i++) {
+                       int c = val.charAt(i);
+
+                       switch(Character.getType(c)) {
+                               case Character.UPPERCASE_LETTER:
+                                       c = replaceUpperChar;
+                                       break;
+
+                               case Character.LOWERCASE_LETTER:
+                                       c = replaceLowerChar;
+                                       break;
+
+                               case Character.DECIMAL_DIGIT_NUMBER:
+                                       c = replaceDigit;
+                                       break;
+                       }
+
+                       strBuf.appendCodePoint(c);
+               }
+
+               for(int i = endIdx; i < val.length(); i++) {
+                       strBuf.appendCodePoint(val.charAt(i));
+               }
+
+               String ret = strBuf.toString();
+
+               return ret;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerBaseUdf.java
----------------------------------------------------------------------
diff --git 
a/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerBaseUdf.java
 
b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerBaseUdf.java
new file mode 100644
index 0000000..0f5a7b2
--- /dev/null
+++ 
b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerBaseUdf.java
@@ -0,0 +1,58 @@
+/**
+ * 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.authorization.hive.udf;
+
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
+import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
+import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
+import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
+import 
org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
+
+
+public abstract class RangerBaseUdf extends GenericUDF {
+       private static final Log LOG = LogFactory.getLog(RangerBaseUdf.class);
+
+       protected PrimitiveObjectInspector columnType = null;
+
+       public RangerBaseUdf() {
+               LOG.debug("==> RangerBaseUdf()");
+
+               LOG.debug("<== RangerBaseUdf()");
+       }
+
+       @Override
+       public ObjectInspector initialize(ObjectInspector[] arguments) throws 
UDFArgumentException {
+               LOG.debug("==> RangerBaseUdf.initialize()");
+
+               ObjectInspector ret = null;
+
+               checkArgPrimitive(arguments, 0); // column value
+
+               columnType = ((PrimitiveObjectInspector)arguments[0]);
+
+               ret = 
PrimitiveObjectInspectorFactory.getPrimitiveWritableObjectInspector(columnType.getPrimitiveCategory());
+
+               LOG.debug("<== RangerBaseUdf.initialize()");
+
+               return ret;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerTransformer.java
----------------------------------------------------------------------
diff --git 
a/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerTransformer.java
 
b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerTransformer.java
new file mode 100644
index 0000000..fff4ad5
--- /dev/null
+++ 
b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerTransformer.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.authorization.hive.udf;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.sql.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+
+public abstract class RangerTransformer {
+       static final Short   SHORT_0   = Short.valueOf((short)0);
+       static final Integer INTEGER_0 = Integer.valueOf((int)0);
+       static final Long    LONG_0    = Long.valueOf((long)0);
+       static final Date    DATE_0    = new Date(0);
+       static final String  STRING_0  = new String("0");
+
+       final Map<String, String> options = new HashMap<String, String>();
+
+
+       abstract void    init(String initParam);
+
+       abstract String  transform(String value);
+       abstract Short   transform(Short value);
+       abstract Integer transform(Integer value);
+       abstract Long    transform(Long value);
+       abstract Date    transform(Date value);
+
+
+       int getCharOption(String name, int defValue) {
+               String value = options.get(name);
+
+               return StringUtils.isNotEmpty(value) ? value.charAt(0) : 
defValue;
+       }
+
+       int getIntOption(String name, int defValue) {
+               String value = options.get(name);
+
+               return StringUtils.isNotEmpty(value) ? Integer.parseInt(value) 
: defValue;
+       }
+}
+
+

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerTransformerFactory.java
----------------------------------------------------------------------
diff --git 
a/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerTransformerFactory.java
 
b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerTransformerFactory.java
new file mode 100644
index 0000000..83f646a
--- /dev/null
+++ 
b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerTransformerFactory.java
@@ -0,0 +1,80 @@
+/*
+ * 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.authorization.hive.udf;
+
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
+public class RangerTransformerFactory {
+    private static final Log LOG = 
LogFactory.getLog(RangerTransformerFactory.class);
+
+
+    public static RangerTransformer getTransformer(String transformType, 
String transformerImpl, String initParam) {
+        RangerTransformer ret = null;
+
+        if(StringUtils.isEmpty(transformerImpl)) {
+            LOG.warn("maskType: '" + transformType + "': no transformer 
specified. Will use '" + MaskTransformer.class.getName() + "' as transformer");
+
+            ret = new MaskTransformer();
+        } else {
+            ret = createTransformer(transformerImpl);
+
+            if(ret == null) {
+                LOG.warn("maskType: '" + transformType + "': failed to create 
transformer '" + transformerImpl + "'. Will use '" + 
MaskTransformer.class.getName() + "' as transformer");
+
+                ret = new MaskTransformer();
+            }
+        }
+
+        if(initParam == null) {
+            initParam = "";
+        }
+
+        ret.init(initParam);
+
+        return ret;
+    }
+
+       private static RangerTransformer createTransformer(String className) {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("==> 
RangerTransformerFactory.createTransformer(" + className + ")");
+               }
+
+               RangerTransformer ret = null;
+
+               try {
+                       @SuppressWarnings("unchecked")
+                       Class<RangerTransformer> transformerClass = 
(Class<RangerTransformer>)Class.forName(className);
+
+            ret = transformerClass.newInstance();
+               } catch(Throwable t) {
+                       LOG.error("RangerTransformerFactory.createTransformer(" 
+ className + "): error instantiating transformer", t);
+               }
+
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("<== 
RangerTransformerFactory.createTransformer(" + className + "): " + ret);
+               }
+
+               return ret;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerUdfMask.java
----------------------------------------------------------------------
diff --git 
a/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerUdfMask.java
 
b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerUdfMask.java
new file mode 100644
index 0000000..91caa8b
--- /dev/null
+++ 
b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerUdfMask.java
@@ -0,0 +1,324 @@
+/**
+ * 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.authorization.hive.udf;
+
+
+import java.sql.Date;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hive.common.type.HiveVarchar;
+import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
+import org.apache.hadoop.hive.ql.metadata.HiveException;
+import org.apache.hadoop.hive.serde2.io.DateWritable;
+import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
+import 
org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector.PrimitiveCategory;
+import 
org.apache.hadoop.hive.serde2.objectinspector.primitive.WritableConstantStringObjectInspector;
+import org.apache.hadoop.hive.serde2.io.HiveVarcharWritable;
+import org.apache.hadoop.hive.serde2.io.ShortWritable;
+import org.apache.hadoop.io.IntWritable;
+import org.apache.hadoop.io.LongWritable;
+import org.apache.hadoop.io.Text;
+
+
+public class RangerUdfMask extends RangerBaseUdf {
+       private static final Log LOG = LogFactory.getLog(RangerUdfMask.class);
+
+       private TransformerAdapter transformerAdapter = null;
+
+       public RangerUdfMask() {
+               LOG.debug("==> RangerUdfMask()");
+
+               LOG.debug("<== RangerUdfMask()");
+       }
+
+       @Override
+       public ObjectInspector initialize(ObjectInspector[] arguments) throws 
UDFArgumentException {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("==> 
RangerUdfMask.initialize(arguments.length=" + arguments.length + ")");
+               }
+
+               ObjectInspector ret = super.initialize(arguments);
+
+               String transformType   = null;
+               String transformerImpl = null;
+               String transformerArgs = null;
+
+               if(arguments.length > 1) { // transformType
+                       checkArgPrimitive(arguments, 1);
+
+                       if(arguments[1] instanceof 
WritableConstantStringObjectInspector) {
+                               Text value = 
((WritableConstantStringObjectInspector)arguments[1]).getWritableConstantValue();
+
+                               if(value != null) {
+                                       transformType = value.toString();
+                               }
+                       }
+               }
+
+               if(arguments.length > 2) { // transformerImpl
+                       checkArgPrimitive(arguments, 2);
+
+                       if(arguments[2] instanceof 
WritableConstantStringObjectInspector) {
+                               Text value = 
((WritableConstantStringObjectInspector)arguments[2]).getWritableConstantValue();
+
+                               if(value != null) {
+                                       transformerImpl = value.toString();
+                               }
+                       }
+               }
+
+               if(arguments.length > 3) { // transformerArgs
+                       checkArgPrimitive(arguments, 3);
+
+                       if(arguments[2] instanceof 
WritableConstantStringObjectInspector) {
+                               Text value = 
((WritableConstantStringObjectInspector)arguments[3]).getWritableConstantValue();
+
+                               if(value != null) {
+                                       transformerArgs = value.toString();
+                               }
+                       }
+               }
+
+               RangerTransformer transformer = 
RangerTransformerFactory.getTransformer(transformType, transformerImpl, 
transformerArgs);
+
+               transformerAdapter = 
TransformerAdapter.getTransformerAdapter(columnType.getPrimitiveCategory(), 
transformer);
+
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("getTransformerAdapter(category=" + 
columnType.getPrimitiveCategory() + ", transformer=" + transformer + "): " + 
transformerAdapter);
+
+                       LOG.debug("<== 
RangerUdfMask.initialize(arguments.length=" + arguments.length + "): ret=" + 
ret);
+               }
+
+               return ret;
+       }
+
+       @Override
+       public Object evaluate(DeferredObject[] arguments) throws HiveException 
{
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("==> 
RangerUdfMask.evaluate(arguments.length=" + arguments.length + ")");
+               }
+
+               final Object ret;
+
+               if(transformerAdapter != null) {
+                       Object columnValue = 
columnType.getPrimitiveJavaObject(arguments[0].get());
+                       
+                       ret = 
transformerAdapter.getTransformedWritable(columnValue);
+               } else {
+                       ret = 
columnType.getPrimitiveWritableObject(arguments[0].get());
+               }
+
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("<== 
RangerUdfMask.evaluate(arguments.length=" + arguments.length + "): ret=" + ret);
+               }
+
+               return ret;
+       }
+
+       @Override
+       public String getDisplayString(String[] children) {
+               return getStandardDisplayString("RangerUdfMask", children, ",");
+       }
+}
+
+abstract class TransformerAdapter {
+       final RangerTransformer transformer;
+
+       TransformerAdapter(RangerTransformer transformer) {
+               this.transformer = transformer;
+       }
+
+       abstract Object getTransformedWritable(Object value);
+
+       static TransformerAdapter getTransformerAdapter(PrimitiveCategory 
category, RangerTransformer transformer) {
+               TransformerAdapter ret = null;
+
+               if(transformer != null) {
+                       switch(category) {
+                               case STRING:
+                                       ret = new 
StringTransformerAdapter(transformer);
+                               break;
+
+                               case VARCHAR:
+                                       ret = new 
VarCharTransformerAdapter(transformer);
+                               break;
+
+                               case SHORT:
+                                       ret = new 
ShortTransformerAdapter(transformer);
+                               break;
+
+                               case INT:
+                                       ret = new 
IntegerTransformerAdapter(transformer);
+                               break;
+
+                               case LONG:
+                                       ret = new 
LongTransformerAdapter(transformer);
+                               break;
+
+                               case DATE:
+                                       ret = new 
DateTransformerAdapter(transformer);
+                               break;
+
+                               default:
+                               break;
+                       }
+               }
+
+               return ret;
+       }
+}
+
+class StringTransformerAdapter extends TransformerAdapter {
+       final Text writable;
+
+       public StringTransformerAdapter(RangerTransformer transformer) {
+               this(transformer, new Text());
+       }
+
+       public StringTransformerAdapter(RangerTransformer transformer, Text 
writable) {
+               super(transformer);
+
+               this.writable = writable;
+       }
+
+       @Override
+       public Object getTransformedWritable(Object value) {
+               String transformedValue = transformer.transform((String)value);
+
+               writable.set(transformedValue);
+
+               return writable;
+       }
+}
+
+class VarCharTransformerAdapter extends TransformerAdapter {
+       final HiveVarcharWritable writable;
+
+       public VarCharTransformerAdapter(RangerTransformer transformer) {
+               this(transformer, new HiveVarcharWritable());
+       }
+
+       public VarCharTransformerAdapter(RangerTransformer transformer, 
HiveVarcharWritable writable) {
+               super(transformer);
+
+               this.writable = writable;
+       }
+
+       @Override
+       public Object getTransformedWritable(Object value) {
+               String transformedValue = 
transformer.transform(((HiveVarchar)value).getValue());
+
+               writable.set(transformedValue);
+
+               return writable;
+       }
+}
+
+class ShortTransformerAdapter extends TransformerAdapter {
+       final ShortWritable writable;
+
+       public ShortTransformerAdapter(RangerTransformer transformer) {
+               this(transformer, new ShortWritable());
+       }
+
+       public ShortTransformerAdapter(RangerTransformer transformer, 
ShortWritable writable) {
+               super(transformer);
+
+               this.writable = writable;
+       }
+
+       @Override
+       public Object getTransformedWritable(Object value) {
+               Short transformedValue = transformer.transform((Short)value);
+
+               writable.set(transformedValue);
+
+               return writable;
+       }
+}
+
+class IntegerTransformerAdapter extends TransformerAdapter {
+       final IntWritable writable;
+
+       public IntegerTransformerAdapter(RangerTransformer transformer) {
+               this(transformer, new IntWritable());
+       }
+
+       public IntegerTransformerAdapter(RangerTransformer transformer, 
IntWritable writable) {
+               super(transformer);
+
+               this.writable = writable;
+       }
+
+       @Override
+       public Object getTransformedWritable(Object value) {
+               Integer transformedValue = 
transformer.transform((Integer)value);
+
+               writable.set(transformedValue);
+
+               return writable;
+       }
+}
+
+class LongTransformerAdapter extends TransformerAdapter {
+       final LongWritable writable;
+
+       public LongTransformerAdapter(RangerTransformer transformer) {
+               this(transformer, new LongWritable());
+       }
+
+       public LongTransformerAdapter(RangerTransformer transformer, 
LongWritable writable) {
+               super(transformer);
+
+               this.writable = writable;
+       }
+
+       @Override
+       public Object getTransformedWritable(Object value) {
+               Long transformedValue = transformer.transform((Long)value);
+
+               writable.set(transformedValue);
+
+               return writable;
+       }
+}
+
+class DateTransformerAdapter extends TransformerAdapter {
+       final DateWritable writable;
+
+       public DateTransformerAdapter(RangerTransformer transformer) {
+               this(transformer, new DateWritable());
+       }
+
+       public DateTransformerAdapter(RangerTransformer transformer, 
DateWritable writable) {
+               super(transformer);
+
+               this.writable = writable;
+       }
+
+       @Override
+       public Object getTransformedWritable(Object value) {
+               Date transformedValue = transformer.transform((Date)value);
+
+               writable.set(transformedValue);
+
+               return writable;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/ShuffleTransformer.java
----------------------------------------------------------------------
diff --git 
a/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/ShuffleTransformer.java
 
b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/ShuffleTransformer.java
new file mode 100644
index 0000000..ee5023a
--- /dev/null
+++ 
b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/ShuffleTransformer.java
@@ -0,0 +1,102 @@
+/*
+ * 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.authorization.hive.udf;
+
+import java.sql.Date;
+
+
+public class ShuffleTransformer extends RangerTransformer {
+       public ShuffleTransformer() {
+       }
+
+       @Override
+       public void init(String initParam) {
+       }
+
+       @Override
+       String transform(String value) {
+               String ret = value;
+
+               if(value != null) {
+                       final char[] chars = value.toCharArray();
+
+                       for(int i = 0; i < chars.length; i++) {
+                               int rIdx = (int)(Math.random() * chars.length);
+                               char swapTmp = chars[i];
+                               chars[i] = chars[rIdx];
+                               chars[rIdx] = swapTmp;
+                       }
+
+                       ret = new String(chars);
+               }
+
+               return ret;
+       }
+
+       @Override
+       Short transform(Short value) {
+               Short ret = value;
+
+               if(value != null) {
+                       String strValue = Short.toString(value);
+
+                       ret = Short.parseShort(transform(strValue));
+               }
+
+               return ret;
+       }
+
+       @Override
+       Integer transform(Integer value) {
+               Integer ret = value;
+
+               if(value != null) {
+                       String strValue = Integer.toString(value);
+
+                       ret = Integer.parseInt(transform(strValue));
+               }
+
+               return ret;
+       }
+
+       @Override
+       Long transform(Long value) {
+               Long ret = value;
+
+               if(value != null) {
+                       String strValue = Long.toString(value);
+
+                       ret = Long.parseLong(transform(strValue));
+               }
+
+               return ret;
+       }
+
+       @Override
+       Date transform(Date value) {
+               Date ret = value;
+
+               if(value != null) {
+                       // TODO: date shuffle
+               }
+
+               return ret;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/security-admin/src/main/java/org/apache/ranger/service/RangerServiceDefServiceBase.java
----------------------------------------------------------------------
diff --git 
a/security-admin/src/main/java/org/apache/ranger/service/RangerServiceDefServiceBase.java
 
b/security-admin/src/main/java/org/apache/ranger/service/RangerServiceDefServiceBase.java
index 9e2e9f5..a0047a5 100644
--- 
a/security-admin/src/main/java/org/apache/ranger/service/RangerServiceDefServiceBase.java
+++ 
b/security-admin/src/main/java/org/apache/ranger/service/RangerServiceDefServiceBase.java
@@ -490,6 +490,7 @@ public abstract class RangerServiceDefServiceBase<T extends 
XXServiceDefBase, V
                xObj.setName(vObj.getName());
                xObj.setLabel(vObj.getLabel());
                xObj.setDescription(vObj.getDescription());
+               xObj.setTransformer(vObj.getTransformer());
                
xObj.setDataMaskOptions(mapToJsonString(vObj.getDataMaskOptions()));
                xObj.setRbkeylabel(vObj.getRbKeyLabel());
                xObj.setRbKeyDescription(vObj.getRbKeyDescription());
@@ -503,6 +504,7 @@ public abstract class RangerServiceDefServiceBase<T extends 
XXServiceDefBase, V
                vObj.setName(xObj.getName());
                vObj.setLabel(xObj.getLabel());
                vObj.setDescription(xObj.getDescription());
+               vObj.setTransformer(xObj.getTransformer());
                
vObj.setDataMaskOptions(jsonStringToMap(xObj.getDataMaskOptions()));
                vObj.setRbKeyLabel(xObj.getRbkeylabel());
                vObj.setRbKeyDescription(xObj.getRbKeyDescription());

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/src/main/assembly/hive-agent.xml
----------------------------------------------------------------------
diff --git a/src/main/assembly/hive-agent.xml b/src/main/assembly/hive-agent.xml
index 8d91bac..e1b9d7e 100644
--- a/src/main/assembly/hive-agent.xml
+++ b/src/main/assembly/hive-agent.xml
@@ -35,6 +35,7 @@
      <includes>
          <include>org.apache.ranger:ranger-hive-plugin-shim</include>
          <include>org.apache.ranger:ranger-plugin-classloader</include>
+         <include>org.apache.ranger:ranger-hive-utils</include>
      </includes>
     </moduleSet>
     <moduleSet>

Reply via email to