You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by ma...@apache.org on 2016/04/02 05:22:23 UTC

incubator-ranger git commit: RANGER-895: Ranger Hive plugin updates to support column-masking

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 <ma...@apache.org>
Authored: Fri Mar 25 10:13:53 2016 -0700
Committer: Madhan Neethiraj <ma...@apache.org>
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>