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>