Repository: incubator-ranger Updated Branches: refs/heads/master 37351fbc8 -> 47c035603
RANGER-895: Ranger Hive plugin updates to support column-masking Project: http://git-wip-us.apache.org/repos/asf/incubator-ranger/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ranger/commit/47c03560 Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/47c03560 Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/47c03560 Branch: refs/heads/master Commit: 47c0356037ef47dfbe5590a5e72f1bb23277f914 Parents: 37351fb Author: Madhan Neethiraj <[email protected]> Authored: Fri Mar 25 10:13:53 2016 -0700 Committer: Madhan Neethiraj <[email protected]> Committed: Fri Apr 1 20:21:10 2016 -0700 ---------------------------------------------------------------------- .../policyengine/RangerDataMaskResult.java | 12 + .../ranger/plugin/util/ServiceDefUtil.java | 20 ++ .../service-defs/ranger-servicedef-hive.json | 86 ++++- .../hive/authorizer/RangerHiveAuthorizer.java | 99 +++++- pom.xml | 1 + ranger-hive-utils/pom.xml | 79 +++++ .../hive/udf/EncryptTransformer.java | 63 ++++ .../hive/udf/MaskFirstNTransformer.java | 46 +++ .../hive/udf/MaskLastNTransformer.java | 46 +++ .../hive/udf/MaskShowFirstNTransformer.java | 46 +++ .../hive/udf/MaskShowLastNTransformer.java | 46 +++ .../authorization/hive/udf/MaskTransformer.java | 209 ++++++++++++ .../authorization/hive/udf/RangerBaseUdf.java | 58 ++++ .../hive/udf/RangerTransformer.java | 61 ++++ .../hive/udf/RangerTransformerFactory.java | 80 +++++ .../authorization/hive/udf/RangerUdfMask.java | 324 +++++++++++++++++++ .../hive/udf/ShuffleTransformer.java | 102 ++++++ .../service/RangerServiceDefServiceBase.java | 2 + src/main/assembly/hive-agent.xml | 1 + 19 files changed, 1365 insertions(+), 16 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerDataMaskResult.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerDataMaskResult.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerDataMaskResult.java index 66d8eba..e0854df 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerDataMaskResult.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerDataMaskResult.java @@ -21,6 +21,8 @@ package org.apache.ranger.plugin.policyengine; import org.apache.commons.lang.StringUtils; import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemDataMaskInfo; import org.apache.ranger.plugin.model.RangerServiceDef; +import org.apache.ranger.plugin.model.RangerServiceDef.RangerDataMaskTypeDef; +import org.apache.ranger.plugin.util.ServiceDefUtil; public class RangerDataMaskResult extends RangerAccessResult { @@ -88,6 +90,16 @@ public class RangerDataMaskResult extends RangerAccessResult { return StringUtils.isNotEmpty(this.getMaskType()); } + public RangerDataMaskTypeDef getMaskTypeDef() { + RangerDataMaskTypeDef ret = null; + + if(StringUtils.isNotEmpty(maskType)) { + ret = ServiceDefUtil.getDataMaskType(getServiceDef(), maskType); + } + + return ret; + } + @Override public String toString( ) { StringBuilder sb = new StringBuilder(); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceDefUtil.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceDefUtil.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceDefUtil.java index c8e560a..34f4cc6 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceDefUtil.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceDefUtil.java @@ -24,6 +24,7 @@ import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.apache.ranger.plugin.model.RangerServiceDef; import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef; +import org.apache.ranger.plugin.model.RangerServiceDef.RangerDataMaskTypeDef; import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef; import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil; @@ -46,6 +47,25 @@ public class ServiceDefUtil { return ret; } + public static RangerDataMaskTypeDef getDataMaskType(RangerServiceDef serviceDef, String typeName) { + RangerDataMaskTypeDef ret = null; + + if(serviceDef != null && serviceDef.getDataMaskDef() != null) { + List<RangerDataMaskTypeDef> maskTypes = serviceDef.getDataMaskDef().getMaskTypes(); + + if(CollectionUtils.isNotEmpty(maskTypes)) { + for(RangerDataMaskTypeDef maskType : maskTypes) { + if(StringUtils.equals(maskType.getName(), typeName)) { + ret = maskType; + break; + } + } + } + } + + return ret; + } + public static RangerServiceDef normalize(RangerServiceDef serviceDef) { normalizeDataMaskDef(serviceDef); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/agents-common/src/main/resources/service-defs/ranger-servicedef-hive.json ---------------------------------------------------------------------- diff --git a/agents-common/src/main/resources/service-defs/ranger-servicedef-hive.json b/agents-common/src/main/resources/service-defs/ranger-servicedef-hive.json index 77167c4..f3c75d1 100644 --- a/agents-common/src/main/resources/service-defs/ranger-servicedef-hive.json +++ b/agents-common/src/main/resources/service-defs/ranger-servicedef-hive.json @@ -262,42 +262,110 @@ "name": "MASK", "label": "Mask", "description": "Replace lowercase with 'x', uppercase with 'X', digits with '0'", - "dataMaskOptions": { } + "transformer": "org.apache.ranger.authorization.hive.udf.MaskTransformer", + "dataMaskOptions": { + } }, { "itemId": 2, "name": "SHUFFLE", "label": "Shuffle", "description": "Shuffle the value of the column", - "dataMaskOptions": { } + "transformer": "org.apache.ranger.authorization.hive.udf.ShuffleTransformer", + "dataMaskOptions": { + } }, { "itemId": 3, "name": "MASK_x_SHOW_LAST_4", "label": "Partial mask: show last 4", "description": "Show last 4 characters; replace rest with 'x'", - "dataMaskOptions": { } + "transformer": "org.apache.ranger.authorization.hive.udf.MaskShowLastNTransformer", + "dataMaskOptions": { + "initParam": "charCount=4; upper=x; lower=x; digit=x; number=1" + } }, { "itemId": 4, "name": "MASK_x_SHOW_FIRST_4", "label": "Partial mask: show first 4", "description": "Show first 4 characters; replace rest with 'x'", - "dataMaskOptions": { } + "transformer": "org.apache.ranger.authorization.hive.udf.MaskShowFirstNTransformer", + "dataMaskOptions": { + "initParam": "charCount=4; upper=x; lower=x; digit=x; number=1" + } + }, + { + "itemId": 5, + "name": "MASK_DATE_DAY", + "label": "Date: show only month and year", + "description": "Date: show only month and year", + "transformer": "org.apache.ranger.authorization.hive.udf.MaskTransformer", + "dataMaskOptions": { + "initParam": "day=1; month=-1; year=-1" + } + }, + { + "itemId": 6, + "name": "MASK_DATE_MONTH", + "label": "Date: show only day and year", + "description": "Date: show only day and year", + "transformer": "org.apache.ranger.authorization.hive.udf.MaskTransformer", + "dataMaskOptions": { + "initParam": "day=-1; month=0; year=-1" + } + }, + { + "itemId": 7, + "name": "MASK_DATE_YEAR", + "label": "Date: show only day and month", + "description": "Date: show only day and month", + "transformer": "org.apache.ranger.authorization.hive.udf.MaskTransformer", + "dataMaskOptions": { + "initParam": "day=-1; month=-1; year=0" + } + }, + { + "itemId": 8, + "name": "MASK_DATE_SHOW_DAY", + "label": "Date: show only day", + "description": "Date: show only day", + "transformer": "org.apache.ranger.authorization.hive.udf.MaskTransformer", + "dataMaskOptions": { + "initParam": "day=-1; month=0; year=0" + } + }, + { + "itemId": 9, + "name": "MASK_DATE_SHOW_MONTH", + "label": "Date: show only month", + "description": "Date: show only month", + "transformer": "org.apache.ranger.authorization.hive.udf.MaskTransformer", + "dataMaskOptions": { + "initParam": "day=1; month=-1; year=0" + } }, { "itemId": 10, + "name": "MASK_DATE_YEAR", + "label": "Date: show only year", + "description": "Date: show only year", + "transformer": "org.apache.ranger.authorization.hive.udf.MaskTransformer", + "dataMaskOptions": { + "initParam": "day=1; month=0; year=-1" + } + }, + { + "itemId": 11, "name": "NULL", "label": "NULL", - "description": "Replace with NULL", - "dataMaskOptions": { } + "description": "Replace with NULL" }, { - "itemId": 11, + "itemId": 12, "name": "NONE", "label": "No masking", - "description": "No masking", - "dataMaskOptions": { } + "description": "No masking" } ] } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/hive-agent/src/main/java/org/apache/ranger/authorization/hive/authorizer/RangerHiveAuthorizer.java ---------------------------------------------------------------------- diff --git a/hive-agent/src/main/java/org/apache/ranger/authorization/hive/authorizer/RangerHiveAuthorizer.java b/hive-agent/src/main/java/org/apache/ranger/authorization/hive/authorizer/RangerHiveAuthorizer.java index f6f9324..9c57968 100644 --- a/hive-agent/src/main/java/org/apache/ranger/authorization/hive/authorizer/RangerHiveAuthorizer.java +++ b/hive-agent/src/main/java/org/apache/ranger/authorization/hive/authorizer/RangerHiveAuthorizer.java @@ -27,6 +27,7 @@ import java.util.Map; import java.util.Set; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -54,8 +55,10 @@ import org.apache.hadoop.security.UserGroupInformation; import org.apache.ranger.authorization.hadoop.config.RangerConfiguration; import org.apache.ranger.authorization.hadoop.constants.RangerHadoopConstants; import org.apache.ranger.authorization.utils.StringUtil; +import org.apache.ranger.plugin.model.RangerServiceDef.RangerDataMaskTypeDef; import org.apache.ranger.plugin.policyengine.RangerAccessRequest; import org.apache.ranger.plugin.policyengine.RangerAccessResult; +import org.apache.ranger.plugin.policyengine.RangerDataMaskResult; import org.apache.ranger.plugin.service.RangerBasePlugin; import org.apache.ranger.plugin.util.GrantRevokeRequest; import org.apache.ranger.plugin.util.RangerAccessRequestUtil; @@ -68,6 +71,10 @@ public class RangerHiveAuthorizer extends RangerHiveAuthorizerBase { private static final Log LOG = LogFactory.getLog(RangerHiveAuthorizer.class) ; private static final char COLUMN_SEP = ','; + private static final String MASK_TYPE_NULL = "NULL"; + private static final String MASK_TYPE_NONE = "NONE"; + private static final String MASK_TYPE_CONSTANT = "CONSTANT"; + private static final String MASK_UDF_NAME = "rangerUdfMask"; private static volatile RangerHivePlugin hivePlugin = null ; @@ -462,22 +469,100 @@ public class RangerHiveAuthorizer extends RangerHiveAuthorizerBase { @Override public String getRowFilterExpression(String databaseName, String tableOrViewName) throws SemanticException { - return null; + if(LOG.isDebugEnabled()) { + LOG.debug("==> getRowFilterExpression(" + databaseName + ", " + tableOrViewName + ")"); + } + + String ret = null; + + + if(LOG.isDebugEnabled()) { + LOG.debug("<== getRowFilterExpression(" + databaseName + ", " + tableOrViewName + "): " + ret); + } + + return ret; } @Override - public boolean needTransform() { - return false; + public String getCellValueTransformer(String databaseName, String tableOrViewName, String columnName) throws SemanticException { + UserGroupInformation ugi = getCurrentUserGroupInfo(); + + if(ugi == null) { + throw new SemanticException("user information not available"); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("==> getCellValueTransformer(" + databaseName + ", " + tableOrViewName + ", " + columnName + ")"); + } + + String ret = columnName; + + RangerHiveAuditHandler auditHandler = new RangerHiveAuditHandler(); + + try { + HiveAuthzContext context = null; // TODO: this should be provided as an argument to this method + HiveAuthzSessionContext sessionContext = getHiveAuthzSessionContext(); + String user = ugi.getShortUserName(); + Set<String> groups = Sets.newHashSet(ugi.getGroupNames()); + HiveObjectType objectType = HiveObjectType.COLUMN; + RangerHiveResource resource = new RangerHiveResource(objectType, databaseName, tableOrViewName, columnName); + RangerHiveAccessRequest request = new RangerHiveAccessRequest(resource, user, groups, objectType.name(), HiveAccessType.SELECT, context, sessionContext); + + RangerDataMaskResult result = hivePlugin.evalDataMaskPolicies(request, auditHandler); + + if(result != null && result.isMaskEnabled()) { + String maskType = result.getMaskType(); + RangerDataMaskTypeDef maskTypeDef = result.getMaskTypeDef(); + String transformer = maskTypeDef.getTransformer(); + String initParam = ""; + + if(MapUtils.isNotEmpty(maskTypeDef.getDataMaskOptions())) { + initParam = maskTypeDef.getDataMaskOptions().get("initParam"); + + if(initParam == null) { + initParam = ""; + } + } + + if(StringUtils.equalsIgnoreCase(maskType, MASK_TYPE_NONE)) { + ret = columnName; + } else if(StringUtils.equalsIgnoreCase(maskType, MASK_TYPE_NULL)) { + ret = "NULL"; + } else if(StringUtils.equalsIgnoreCase(maskType, MASK_TYPE_CONSTANT)) { + String maskedValue = result.getMaskedValue(); + + ret = maskedValue == null ? "NULL" : maskedValue; + } else { + ret = MASK_UDF_NAME + "(" + columnName + ", '" + maskType + "', '" + transformer + "', '" + initParam + "')"; + } + + /* + String maskCondition = result.getMaskCondition(); + + if(StringUtils.isNotEmpty(maskCondition)) { + ret = "if(" + maskCondition + ", " + ret + ", " + columnName + ")"; + } + */ + } + } finally { + auditHandler.flushAudit(); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== getCellValueTransformer(" + databaseName + ", " + tableOrViewName + ", " + columnName + "): " + ret); + } + + return ret; } @Override - public boolean needTransform(String databaseName, String tableOrViewName) { - return false; + public boolean needTransform() { + return true; // TODO: derive from the policies } @Override - public String getCellValueTransformer(String databaseName, String tableOrViewName, String columnName) throws SemanticException { - return columnName; + public boolean needTransform(String databaseName, String tableOrViewName) { + return true; // TODO: derive from the policies } RangerHiveResource createHiveResource(HivePrivilegeObject privilegeObject) { http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index 2e0366a..fcd4c52 100644 --- a/pom.xml +++ b/pom.xml @@ -103,6 +103,7 @@ <module>ranger-yarn-plugin-shim</module> <module>ranger-storm-plugin-shim</module> <module>ranger-kafka-plugin-shim</module> + <module>ranger-hive-utils</module> <module>ranger-examples</module> <module>ranger-tools</module> </modules> http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/ranger-hive-utils/pom.xml ---------------------------------------------------------------------- diff --git a/ranger-hive-utils/pom.xml b/ranger-hive-utils/pom.xml new file mode 100644 index 0000000..ed10ec5 --- /dev/null +++ b/ranger-hive-utils/pom.xml @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <artifactId>ranger-hive-utils</artifactId> + <name>Ranger Hive Utils</name> + <description>Ranger Hive Utils</description> + <packaging>jar</packaging> + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + <parent> + <groupId>org.apache.ranger</groupId> + <artifactId>ranger</artifactId> + <version>0.6.0</version> + <relativePath>..</relativePath> + </parent> + <dependencies> + <dependency> + <groupId>org.apache.calcite</groupId> + <artifactId>calcite-core</artifactId> + <version>${calcite.version}</version> + </dependency> + <dependency> + <groupId>org.apache.calcite</groupId> + <artifactId>calcite-avatica</artifactId> + <version>${calcite.version}</version> + </dependency> + <dependency> + <groupId>commons-lang</groupId> + <artifactId>commons-lang</artifactId> + <version>${commons.lang.version}</version> + </dependency> + <dependency> + <groupId>org.apache.hadoop</groupId> + <artifactId>hadoop-common</artifactId> + <version>${hadoop-common.version}</version> + </dependency> + <dependency> + <groupId>org.apache.hive</groupId> + <artifactId>hive-common</artifactId> + <version>${hive.version}</version> + </dependency> + <dependency> + <groupId>org.apache.hive</groupId> + <artifactId>hive-service</artifactId> + <version>${hive.version}</version> + </dependency> + <dependency> + <groupId>org.apache.hive</groupId> + <artifactId>hive-exec</artifactId> + <version>${hive.version}</version> + </dependency> + <dependency> + <groupId>org.apache.hive</groupId> + <artifactId>hive-metastore</artifactId> + <version>${hive.version}</version> + </dependency> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + </dependency> + </dependencies> +</project> http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/EncryptTransformer.java ---------------------------------------------------------------------- diff --git a/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/EncryptTransformer.java b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/EncryptTransformer.java new file mode 100644 index 0000000..f002f9a --- /dev/null +++ b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/EncryptTransformer.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.ranger.authorization.hive.udf; + +import org.apache.commons.codec.digest.DigestUtils; + +import java.sql.Date; + + +public class EncryptTransformer extends RangerTransformer { + public EncryptTransformer() { + } + + @Override + public void init(String initParam) { + } + + @Override + String transform(String value) { + return value == null ? STRING_0 : this.encryptToMd5Hex(value); + } + + @Override + Short transform(Short value) { + return SHORT_0; + } + + @Override + Integer transform(Integer value) { + return INTEGER_0; + } + + @Override + Long transform(Long value) { + return LONG_0; + } + + @Override + Date transform(Date value) { + return DATE_0; + } + + String encryptToMd5Hex(String value) { + return DigestUtils.md5Hex(value); + } +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskFirstNTransformer.java ---------------------------------------------------------------------- diff --git a/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskFirstNTransformer.java b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskFirstNTransformer.java new file mode 100644 index 0000000..e37b3ef --- /dev/null +++ b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskFirstNTransformer.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.ranger.authorization.hive.udf; + + +public class MaskFirstNTransformer extends MaskTransformer { + int charCount = 4; + + public MaskFirstNTransformer() { + super(); + } + + @Override + public void init(String initParam) { + super.init(initParam); + + charCount = getIntOption("charCount", 4); + } + + @Override + int getMaskStartIndex(String val) { + return 0; + } + + @Override + int getMaskEndIndex(String val) { + return charCount; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskLastNTransformer.java ---------------------------------------------------------------------- diff --git a/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskLastNTransformer.java b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskLastNTransformer.java new file mode 100644 index 0000000..18bc558 --- /dev/null +++ b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskLastNTransformer.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.ranger.authorization.hive.udf; + + +public class MaskLastNTransformer extends MaskTransformer { + int charCount = 4; + + public MaskLastNTransformer() { + super(); + } + + @Override + public void init(String initParam) { + super.init(initParam); + + this.charCount = getIntOption("charCount", 4); + } + + @Override + int getMaskStartIndex(String val) { + return val.length() - charCount; + } + + @Override + int getMaskEndIndex(String val) { + return val.length(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskShowFirstNTransformer.java ---------------------------------------------------------------------- diff --git a/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskShowFirstNTransformer.java b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskShowFirstNTransformer.java new file mode 100644 index 0000000..26a4c32 --- /dev/null +++ b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskShowFirstNTransformer.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.ranger.authorization.hive.udf; + + +public class MaskShowFirstNTransformer extends MaskTransformer { + int charCount = 4; + + public MaskShowFirstNTransformer() { + super(); + } + + @Override + public void init(String initParam) { + super.init(initParam); + + this.charCount = getIntOption("charCount", 4); + } + + @Override + int getMaskStartIndex(String val) { + return charCount; + } + + @Override + int getMaskEndIndex(String val) { + return val.length(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskShowLastNTransformer.java ---------------------------------------------------------------------- diff --git a/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskShowLastNTransformer.java b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskShowLastNTransformer.java new file mode 100644 index 0000000..cb30e50 --- /dev/null +++ b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskShowLastNTransformer.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.ranger.authorization.hive.udf; + + +public class MaskShowLastNTransformer extends MaskTransformer { + int charCount; + + public MaskShowLastNTransformer() { + super(); + } + + @Override + public void init(String initParam) { + super.init(initParam); + + this.charCount = getIntOption("charCount", 4); + } + + @Override + int getMaskStartIndex(String val) { + return 0; + } + + @Override + int getMaskEndIndex(String val) { + return val.length() - charCount; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskTransformer.java ---------------------------------------------------------------------- diff --git a/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskTransformer.java b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskTransformer.java new file mode 100644 index 0000000..64de392 --- /dev/null +++ b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/MaskTransformer.java @@ -0,0 +1,209 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.ranger.authorization.hive.udf; + +import org.apache.commons.lang3.StringUtils; + +import java.sql.Date; + + +public class MaskTransformer extends RangerTransformer { + final static int MASKED_UPPERCASE = 'X'; + final static int MASKED_LOWERCASE = 'x'; + final static int MASKED_NUMBER = '1'; + final static int MASKED_DAY_COMPONENT_VAL = 1; + final static int MASKED_MONTH_COMPONENT_VAL = 0; + final static int MASKED_YEAR_COMPONENT_VAL = 0; + final static int UNMASKED_DATE_COMPONENT_VAL = -1; + + int maskedUpperChar = MASKED_UPPERCASE; + int maskedLowerChar = MASKED_LOWERCASE; + int maskedDigitChar = MASKED_NUMBER; + int maskedNumber = MASKED_NUMBER; + int maskedDayValue = MASKED_DAY_COMPONENT_VAL; + int maskedMonthValue = MASKED_MONTH_COMPONENT_VAL; + int maskedYearValue = MASKED_YEAR_COMPONENT_VAL; + + public MaskTransformer() { + } + + @Override + public void init(String initParam) { + if(StringUtils.isNotEmpty(initParam)) { + for(String nvStr : initParam.split(";")) { + if(StringUtils.isNotEmpty(nvStr)) { + String[] nameValue = nvStr.split("=", 2); + String name = nameValue != null && nameValue.length > 0 ? nameValue[0] : null; + String value = nameValue != null && nameValue.length > 1 ? nameValue[1] : null; + + if(StringUtils.isNotEmpty(name)) { + options.put(name.trim(), value.trim()); + } + } + } + } + + maskedUpperChar = getCharOption("upper", MASKED_UPPERCASE); + maskedLowerChar = getCharOption("lower", MASKED_LOWERCASE); + maskedDigitChar = getCharOption("digit", MASKED_NUMBER); + maskedNumber = getCharOption("number", MASKED_NUMBER); + maskedDayValue = getIntOption("day", MASKED_DAY_COMPONENT_VAL); + maskedMonthValue = getIntOption("month", MASKED_MONTH_COMPONENT_VAL); + maskedYearValue = getIntOption("year", MASKED_YEAR_COMPONENT_VAL); + } + + @Override + String transform(String value) { + return value == null ? STRING_0 : transformAlphaNum(value); + } + + @Override + Short transform(Short value) { + return value == null ? SHORT_0 : Short.parseShort(transformNum(value.toString())); + } + + @Override + Integer transform(Integer value) { + return value == null ? INTEGER_0 : Integer.parseInt(transformNum(value.toString())); + } + + @Override + Long transform(Long value) { + return value == null ? LONG_0 : Long.parseLong(transformNum(value.toString())); + } + + @Override + Date transform(Date value) { + return mask(value, maskedDayValue, maskedMonthValue, maskedYearValue); + } + + String transformNum(String val) { + return transformNum(val, maskedNumber, getMaskStartIndex(val), getMaskEndIndex(val)); + } + + String transformAlphaNum(String val) { + return transformAlphaNum(val, maskedUpperChar, maskedLowerChar, maskedDigitChar, getMaskStartIndex(val), getMaskEndIndex(val)); + } + + Date mask(Date value, int maskedDay, int maskedMonth, int maskedYear) { + int year = maskedYear == UNMASKED_DATE_COMPONENT_VAL ? value.getYear() : MASKED_YEAR_COMPONENT_VAL; + int month = maskedMonth == UNMASKED_DATE_COMPONENT_VAL ? value.getMonth() : MASKED_MONTH_COMPONENT_VAL; + int day = maskedDay == UNMASKED_DATE_COMPONENT_VAL ? value.getDate() : MASKED_DAY_COMPONENT_VAL; + + return new Date(year, month, day); + } + + int getMaskStartIndex(String val) { + return 0; + } + + int getMaskEndIndex(String val) { + return val.length(); + } + + + String transformNum(String val, int replaceDigit, int startIdx, int endIdx) { + if(val == null) { + return null; + } + + StringBuffer strBuf = new StringBuffer(val.length()); + + if(startIdx < 0) { + startIdx = 0; + } + + if(endIdx > val.length()) { + endIdx = val.length(); + } + + for(int i = 0; i < startIdx; i++) { + strBuf.appendCodePoint(val.charAt(i)); + } + + for(int i = startIdx; i < endIdx; i++) { + int c = val.charAt(i); + + switch(Character.getType(c)) { + case Character.DECIMAL_DIGIT_NUMBER: + c = replaceDigit; + break; + } + + strBuf.appendCodePoint(c); + } + + for(int i = endIdx; i < val.length(); i++) { + strBuf.appendCodePoint(val.charAt(i)); + } + + String ret = strBuf.toString(); + + return ret; + } + + String transformAlphaNum(String val, int replaceUpperChar, int replaceLowerChar, int replaceDigit, int startIdx, int endIdx) { + if(val == null) { + return null; + } + + StringBuffer strBuf = new StringBuffer(val.length()); + + if(startIdx < 0) { + startIdx = 0; + } + + if(endIdx > val.length()) { + endIdx = val.length(); + } + + for(int i = 0; i < startIdx; i++) { + strBuf.appendCodePoint(val.charAt(i)); + } + + for(int i = startIdx; i < endIdx; i++) { + int c = val.charAt(i); + + switch(Character.getType(c)) { + case Character.UPPERCASE_LETTER: + c = replaceUpperChar; + break; + + case Character.LOWERCASE_LETTER: + c = replaceLowerChar; + break; + + case Character.DECIMAL_DIGIT_NUMBER: + c = replaceDigit; + break; + } + + strBuf.appendCodePoint(c); + } + + for(int i = endIdx; i < val.length(); i++) { + strBuf.appendCodePoint(val.charAt(i)); + } + + String ret = strBuf.toString(); + + return ret; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerBaseUdf.java ---------------------------------------------------------------------- diff --git a/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerBaseUdf.java b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerBaseUdf.java new file mode 100644 index 0000000..0f5a7b2 --- /dev/null +++ b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerBaseUdf.java @@ -0,0 +1,58 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ranger.authorization.hive.udf; + + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.hive.ql.exec.UDFArgumentException; +import org.apache.hadoop.hive.ql.udf.generic.GenericUDF; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; + + +public abstract class RangerBaseUdf extends GenericUDF { + private static final Log LOG = LogFactory.getLog(RangerBaseUdf.class); + + protected PrimitiveObjectInspector columnType = null; + + public RangerBaseUdf() { + LOG.debug("==> RangerBaseUdf()"); + + LOG.debug("<== RangerBaseUdf()"); + } + + @Override + public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException { + LOG.debug("==> RangerBaseUdf.initialize()"); + + ObjectInspector ret = null; + + checkArgPrimitive(arguments, 0); // column value + + columnType = ((PrimitiveObjectInspector)arguments[0]); + + ret = PrimitiveObjectInspectorFactory.getPrimitiveWritableObjectInspector(columnType.getPrimitiveCategory()); + + LOG.debug("<== RangerBaseUdf.initialize()"); + + return ret; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerTransformer.java ---------------------------------------------------------------------- diff --git a/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerTransformer.java b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerTransformer.java new file mode 100644 index 0000000..fff4ad5 --- /dev/null +++ b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerTransformer.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.ranger.authorization.hive.udf; + +import org.apache.commons.lang3.StringUtils; + +import java.sql.Date; +import java.util.HashMap; +import java.util.Map; + + +public abstract class RangerTransformer { + static final Short SHORT_0 = Short.valueOf((short)0); + static final Integer INTEGER_0 = Integer.valueOf((int)0); + static final Long LONG_0 = Long.valueOf((long)0); + static final Date DATE_0 = new Date(0); + static final String STRING_0 = new String("0"); + + final Map<String, String> options = new HashMap<String, String>(); + + + abstract void init(String initParam); + + abstract String transform(String value); + abstract Short transform(Short value); + abstract Integer transform(Integer value); + abstract Long transform(Long value); + abstract Date transform(Date value); + + + int getCharOption(String name, int defValue) { + String value = options.get(name); + + return StringUtils.isNotEmpty(value) ? value.charAt(0) : defValue; + } + + int getIntOption(String name, int defValue) { + String value = options.get(name); + + return StringUtils.isNotEmpty(value) ? Integer.parseInt(value) : defValue; + } +} + + http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerTransformerFactory.java ---------------------------------------------------------------------- diff --git a/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerTransformerFactory.java b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerTransformerFactory.java new file mode 100644 index 0000000..83f646a --- /dev/null +++ b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerTransformerFactory.java @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.ranger.authorization.hive.udf; + + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + + +public class RangerTransformerFactory { + private static final Log LOG = LogFactory.getLog(RangerTransformerFactory.class); + + + public static RangerTransformer getTransformer(String transformType, String transformerImpl, String initParam) { + RangerTransformer ret = null; + + if(StringUtils.isEmpty(transformerImpl)) { + LOG.warn("maskType: '" + transformType + "': no transformer specified. Will use '" + MaskTransformer.class.getName() + "' as transformer"); + + ret = new MaskTransformer(); + } else { + ret = createTransformer(transformerImpl); + + if(ret == null) { + LOG.warn("maskType: '" + transformType + "': failed to create transformer '" + transformerImpl + "'. Will use '" + MaskTransformer.class.getName() + "' as transformer"); + + ret = new MaskTransformer(); + } + } + + if(initParam == null) { + initParam = ""; + } + + ret.init(initParam); + + return ret; + } + + private static RangerTransformer createTransformer(String className) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerTransformerFactory.createTransformer(" + className + ")"); + } + + RangerTransformer ret = null; + + try { + @SuppressWarnings("unchecked") + Class<RangerTransformer> transformerClass = (Class<RangerTransformer>)Class.forName(className); + + ret = transformerClass.newInstance(); + } catch(Throwable t) { + LOG.error("RangerTransformerFactory.createTransformer(" + className + "): error instantiating transformer", t); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerTransformerFactory.createTransformer(" + className + "): " + ret); + } + + return ret; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerUdfMask.java ---------------------------------------------------------------------- diff --git a/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerUdfMask.java b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerUdfMask.java new file mode 100644 index 0000000..91caa8b --- /dev/null +++ b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/RangerUdfMask.java @@ -0,0 +1,324 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ranger.authorization.hive.udf; + + +import java.sql.Date; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.hive.common.type.HiveVarchar; +import org.apache.hadoop.hive.ql.exec.UDFArgumentException; +import org.apache.hadoop.hive.ql.metadata.HiveException; +import org.apache.hadoop.hive.serde2.io.DateWritable; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector.PrimitiveCategory; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.WritableConstantStringObjectInspector; +import org.apache.hadoop.hive.serde2.io.HiveVarcharWritable; +import org.apache.hadoop.hive.serde2.io.ShortWritable; +import org.apache.hadoop.io.IntWritable; +import org.apache.hadoop.io.LongWritable; +import org.apache.hadoop.io.Text; + + +public class RangerUdfMask extends RangerBaseUdf { + private static final Log LOG = LogFactory.getLog(RangerUdfMask.class); + + private TransformerAdapter transformerAdapter = null; + + public RangerUdfMask() { + LOG.debug("==> RangerUdfMask()"); + + LOG.debug("<== RangerUdfMask()"); + } + + @Override + public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerUdfMask.initialize(arguments.length=" + arguments.length + ")"); + } + + ObjectInspector ret = super.initialize(arguments); + + String transformType = null; + String transformerImpl = null; + String transformerArgs = null; + + if(arguments.length > 1) { // transformType + checkArgPrimitive(arguments, 1); + + if(arguments[1] instanceof WritableConstantStringObjectInspector) { + Text value = ((WritableConstantStringObjectInspector)arguments[1]).getWritableConstantValue(); + + if(value != null) { + transformType = value.toString(); + } + } + } + + if(arguments.length > 2) { // transformerImpl + checkArgPrimitive(arguments, 2); + + if(arguments[2] instanceof WritableConstantStringObjectInspector) { + Text value = ((WritableConstantStringObjectInspector)arguments[2]).getWritableConstantValue(); + + if(value != null) { + transformerImpl = value.toString(); + } + } + } + + if(arguments.length > 3) { // transformerArgs + checkArgPrimitive(arguments, 3); + + if(arguments[2] instanceof WritableConstantStringObjectInspector) { + Text value = ((WritableConstantStringObjectInspector)arguments[3]).getWritableConstantValue(); + + if(value != null) { + transformerArgs = value.toString(); + } + } + } + + RangerTransformer transformer = RangerTransformerFactory.getTransformer(transformType, transformerImpl, transformerArgs); + + transformerAdapter = TransformerAdapter.getTransformerAdapter(columnType.getPrimitiveCategory(), transformer); + + if(LOG.isDebugEnabled()) { + LOG.debug("getTransformerAdapter(category=" + columnType.getPrimitiveCategory() + ", transformer=" + transformer + "): " + transformerAdapter); + + LOG.debug("<== RangerUdfMask.initialize(arguments.length=" + arguments.length + "): ret=" + ret); + } + + return ret; + } + + @Override + public Object evaluate(DeferredObject[] arguments) throws HiveException { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerUdfMask.evaluate(arguments.length=" + arguments.length + ")"); + } + + final Object ret; + + if(transformerAdapter != null) { + Object columnValue = columnType.getPrimitiveJavaObject(arguments[0].get()); + + ret = transformerAdapter.getTransformedWritable(columnValue); + } else { + ret = columnType.getPrimitiveWritableObject(arguments[0].get()); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerUdfMask.evaluate(arguments.length=" + arguments.length + "): ret=" + ret); + } + + return ret; + } + + @Override + public String getDisplayString(String[] children) { + return getStandardDisplayString("RangerUdfMask", children, ","); + } +} + +abstract class TransformerAdapter { + final RangerTransformer transformer; + + TransformerAdapter(RangerTransformer transformer) { + this.transformer = transformer; + } + + abstract Object getTransformedWritable(Object value); + + static TransformerAdapter getTransformerAdapter(PrimitiveCategory category, RangerTransformer transformer) { + TransformerAdapter ret = null; + + if(transformer != null) { + switch(category) { + case STRING: + ret = new StringTransformerAdapter(transformer); + break; + + case VARCHAR: + ret = new VarCharTransformerAdapter(transformer); + break; + + case SHORT: + ret = new ShortTransformerAdapter(transformer); + break; + + case INT: + ret = new IntegerTransformerAdapter(transformer); + break; + + case LONG: + ret = new LongTransformerAdapter(transformer); + break; + + case DATE: + ret = new DateTransformerAdapter(transformer); + break; + + default: + break; + } + } + + return ret; + } +} + +class StringTransformerAdapter extends TransformerAdapter { + final Text writable; + + public StringTransformerAdapter(RangerTransformer transformer) { + this(transformer, new Text()); + } + + public StringTransformerAdapter(RangerTransformer transformer, Text writable) { + super(transformer); + + this.writable = writable; + } + + @Override + public Object getTransformedWritable(Object value) { + String transformedValue = transformer.transform((String)value); + + writable.set(transformedValue); + + return writable; + } +} + +class VarCharTransformerAdapter extends TransformerAdapter { + final HiveVarcharWritable writable; + + public VarCharTransformerAdapter(RangerTransformer transformer) { + this(transformer, new HiveVarcharWritable()); + } + + public VarCharTransformerAdapter(RangerTransformer transformer, HiveVarcharWritable writable) { + super(transformer); + + this.writable = writable; + } + + @Override + public Object getTransformedWritable(Object value) { + String transformedValue = transformer.transform(((HiveVarchar)value).getValue()); + + writable.set(transformedValue); + + return writable; + } +} + +class ShortTransformerAdapter extends TransformerAdapter { + final ShortWritable writable; + + public ShortTransformerAdapter(RangerTransformer transformer) { + this(transformer, new ShortWritable()); + } + + public ShortTransformerAdapter(RangerTransformer transformer, ShortWritable writable) { + super(transformer); + + this.writable = writable; + } + + @Override + public Object getTransformedWritable(Object value) { + Short transformedValue = transformer.transform((Short)value); + + writable.set(transformedValue); + + return writable; + } +} + +class IntegerTransformerAdapter extends TransformerAdapter { + final IntWritable writable; + + public IntegerTransformerAdapter(RangerTransformer transformer) { + this(transformer, new IntWritable()); + } + + public IntegerTransformerAdapter(RangerTransformer transformer, IntWritable writable) { + super(transformer); + + this.writable = writable; + } + + @Override + public Object getTransformedWritable(Object value) { + Integer transformedValue = transformer.transform((Integer)value); + + writable.set(transformedValue); + + return writable; + } +} + +class LongTransformerAdapter extends TransformerAdapter { + final LongWritable writable; + + public LongTransformerAdapter(RangerTransformer transformer) { + this(transformer, new LongWritable()); + } + + public LongTransformerAdapter(RangerTransformer transformer, LongWritable writable) { + super(transformer); + + this.writable = writable; + } + + @Override + public Object getTransformedWritable(Object value) { + Long transformedValue = transformer.transform((Long)value); + + writable.set(transformedValue); + + return writable; + } +} + +class DateTransformerAdapter extends TransformerAdapter { + final DateWritable writable; + + public DateTransformerAdapter(RangerTransformer transformer) { + this(transformer, new DateWritable()); + } + + public DateTransformerAdapter(RangerTransformer transformer, DateWritable writable) { + super(transformer); + + this.writable = writable; + } + + @Override + public Object getTransformedWritable(Object value) { + Date transformedValue = transformer.transform((Date)value); + + writable.set(transformedValue); + + return writable; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/ShuffleTransformer.java ---------------------------------------------------------------------- diff --git a/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/ShuffleTransformer.java b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/ShuffleTransformer.java new file mode 100644 index 0000000..ee5023a --- /dev/null +++ b/ranger-hive-utils/src/main/java/org/apache/ranger/authorization/hive/udf/ShuffleTransformer.java @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.ranger.authorization.hive.udf; + +import java.sql.Date; + + +public class ShuffleTransformer extends RangerTransformer { + public ShuffleTransformer() { + } + + @Override + public void init(String initParam) { + } + + @Override + String transform(String value) { + String ret = value; + + if(value != null) { + final char[] chars = value.toCharArray(); + + for(int i = 0; i < chars.length; i++) { + int rIdx = (int)(Math.random() * chars.length); + char swapTmp = chars[i]; + chars[i] = chars[rIdx]; + chars[rIdx] = swapTmp; + } + + ret = new String(chars); + } + + return ret; + } + + @Override + Short transform(Short value) { + Short ret = value; + + if(value != null) { + String strValue = Short.toString(value); + + ret = Short.parseShort(transform(strValue)); + } + + return ret; + } + + @Override + Integer transform(Integer value) { + Integer ret = value; + + if(value != null) { + String strValue = Integer.toString(value); + + ret = Integer.parseInt(transform(strValue)); + } + + return ret; + } + + @Override + Long transform(Long value) { + Long ret = value; + + if(value != null) { + String strValue = Long.toString(value); + + ret = Long.parseLong(transform(strValue)); + } + + return ret; + } + + @Override + Date transform(Date value) { + Date ret = value; + + if(value != null) { + // TODO: date shuffle + } + + return ret; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/security-admin/src/main/java/org/apache/ranger/service/RangerServiceDefServiceBase.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerServiceDefServiceBase.java b/security-admin/src/main/java/org/apache/ranger/service/RangerServiceDefServiceBase.java index 9e2e9f5..a0047a5 100644 --- a/security-admin/src/main/java/org/apache/ranger/service/RangerServiceDefServiceBase.java +++ b/security-admin/src/main/java/org/apache/ranger/service/RangerServiceDefServiceBase.java @@ -490,6 +490,7 @@ public abstract class RangerServiceDefServiceBase<T extends XXServiceDefBase, V xObj.setName(vObj.getName()); xObj.setLabel(vObj.getLabel()); xObj.setDescription(vObj.getDescription()); + xObj.setTransformer(vObj.getTransformer()); xObj.setDataMaskOptions(mapToJsonString(vObj.getDataMaskOptions())); xObj.setRbkeylabel(vObj.getRbKeyLabel()); xObj.setRbKeyDescription(vObj.getRbKeyDescription()); @@ -503,6 +504,7 @@ public abstract class RangerServiceDefServiceBase<T extends XXServiceDefBase, V vObj.setName(xObj.getName()); vObj.setLabel(xObj.getLabel()); vObj.setDescription(xObj.getDescription()); + vObj.setTransformer(xObj.getTransformer()); vObj.setDataMaskOptions(jsonStringToMap(xObj.getDataMaskOptions())); vObj.setRbKeyLabel(xObj.getRbkeylabel()); vObj.setRbKeyDescription(xObj.getRbKeyDescription()); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/47c03560/src/main/assembly/hive-agent.xml ---------------------------------------------------------------------- diff --git a/src/main/assembly/hive-agent.xml b/src/main/assembly/hive-agent.xml index 8d91bac..e1b9d7e 100644 --- a/src/main/assembly/hive-agent.xml +++ b/src/main/assembly/hive-agent.xml @@ -35,6 +35,7 @@ <includes> <include>org.apache.ranger:ranger-hive-plugin-shim</include> <include>org.apache.ranger:ranger-plugin-classloader</include> + <include>org.apache.ranger:ranger-hive-utils</include> </includes> </moduleSet> <moduleSet>
