You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sentry.apache.org by am...@apache.org on 2018/09/26 20:14:28 UTC

sentry git commit: SENTRY-2406: Make sure inputHierarchy and outputHierarchy have unique values (Arjun Mishra reviewed by Na Li)

Repository: sentry
Updated Branches:
  refs/heads/master 831594907 -> a7b68f62c


SENTRY-2406: Make sure inputHierarchy and outputHierarchy have unique values (Arjun Mishra reviewed by Na Li)

Change-Id: I3c9f4da47f7da2317a2e8debb72bde5d9849a679


Project: http://git-wip-us.apache.org/repos/asf/sentry/repo
Commit: http://git-wip-us.apache.org/repos/asf/sentry/commit/a7b68f62
Tree: http://git-wip-us.apache.org/repos/asf/sentry/tree/a7b68f62
Diff: http://git-wip-us.apache.org/repos/asf/sentry/diff/a7b68f62

Branch: refs/heads/master
Commit: a7b68f62c5dfa7f8a2a3b81772d1d279962ecbc7
Parents: 8315949
Author: amishra <am...@cloudera.com>
Authored: Wed Sep 26 15:10:18 2018 -0500
Committer: amishra <am...@cloudera.com>
Committed: Wed Sep 26 15:10:21 2018 -0500

----------------------------------------------------------------------
 .../binding/hive/authz/HiveAuthzBinding.java    |  12 +-
 .../hive/authz/DefaultSentryValidator.java      |  17 +-
 .../hive/authz/HiveAuthzBindingHookBase.java    |  21 +-
 .../metastore/MetastoreAuthzBinding.java        |   5 +-
 .../metastore/MetastoreAuthzBindingBase.java    |  11 +-
 .../binding/util/SentryAuthorizerUtil.java      |   5 +-
 .../hive/TestHiveAuthzBindingHookBase.java      | 246 +++++++++++++++++++
 .../binding/hive/TestHiveAuthzBindings.java     |   6 +-
 .../apache/sentry/core/model/db/AccessURI.java  |  23 ++
 .../org/apache/sentry/core/model/db/Column.java |  23 ++
 .../apache/sentry/core/model/db/Database.java   |  23 ++
 .../org/apache/sentry/core/model/db/Server.java |  23 ++
 .../org/apache/sentry/core/model/db/Table.java  |  23 ++
 .../org/apache/sentry/core/model/db/View.java   |  23 ++
 14 files changed, 427 insertions(+), 34 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/sentry/blob/a7b68f62/sentry-binding/sentry-binding-hive-common/src/main/java/org/apache/sentry/binding/hive/authz/HiveAuthzBinding.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-hive-common/src/main/java/org/apache/sentry/binding/hive/authz/HiveAuthzBinding.java b/sentry-binding/sentry-binding-hive-common/src/main/java/org/apache/sentry/binding/hive/authz/HiveAuthzBinding.java
index 6a1556f..520de52 100644
--- a/sentry-binding/sentry-binding-hive-common/src/main/java/org/apache/sentry/binding/hive/authz/HiveAuthzBinding.java
+++ b/sentry-binding/sentry-binding-hive-common/src/main/java/org/apache/sentry/binding/hive/authz/HiveAuthzBinding.java
@@ -289,17 +289,19 @@ public class HiveAuthzBinding {
 
   /**
    * Validate the privilege for the given operation for the given subject
-   * @param hiveOp
-   * @param stmtAuthPrivileges
-   * @param subject
    * @param currDB
    * @param inputEntities
    * @param outputEntities
+   * @param hiveOp
+   * @param stmtAuthPrivileges
+   * @param subject
+   * @param inputHierarchyList
+   * @param outputHierarchyList
    * @throws AuthorizationException
    */
   public void authorize(HiveOperation hiveOp, HiveAuthzPrivileges stmtAuthPrivileges,
-      Subject subject, List<List<DBModelAuthorizable>> inputHierarchyList,
-      List<List<DBModelAuthorizable>> outputHierarchyList)
+      Subject subject, Set<List<DBModelAuthorizable>> inputHierarchyList,
+      Set<List<DBModelAuthorizable>> outputHierarchyList)
           throws AuthorizationException {
     if (!open) {
       throw new IllegalStateException("Binding has been closed");

http://git-wip-us.apache.org/repos/asf/sentry/blob/a7b68f62/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/DefaultSentryValidator.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/DefaultSentryValidator.java b/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/DefaultSentryValidator.java
index f076476..38ce2db 100644
--- a/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/DefaultSentryValidator.java
+++ b/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/DefaultSentryValidator.java
@@ -23,6 +23,7 @@ import java.security.CodeSource;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.EnumSet;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import org.apache.hadoop.hive.conf.HiveConf;
@@ -167,10 +168,10 @@ public class DefaultSentryValidator extends SentryHiveAuthorizationValidator {
         return;
       }
 
-      List<List<DBModelAuthorizable>> inputHierarchyList =
+      Set<List<DBModelAuthorizable>> inputHierarchyList =
           SentryAuthorizerUtil.convert2SentryPrivilegeList(hiveAuthzBinding.getAuthServer(),
               inputHObjs);
-      List<List<DBModelAuthorizable>> outputHierarchyList =
+      Set<List<DBModelAuthorizable>> outputHierarchyList =
           SentryAuthorizerUtil.convert2SentryPrivilegeList(hiveAuthzBinding.getAuthServer(),
               outputHObjs);
 
@@ -238,8 +239,8 @@ public class DefaultSentryValidator extends SentryHiveAuthorizationValidator {
   }
 
   private void addExtendHierarchy(HiveOperation hiveOp, HiveAuthzPrivileges stmtAuthPrivileges,
-      List<List<DBModelAuthorizable>> inputHierarchyList,
-      List<List<DBModelAuthorizable>> outputHierarchyList, String command,
+      Set<List<DBModelAuthorizable>> inputHierarchyList,
+      Set<List<DBModelAuthorizable>> outputHierarchyList, String command,
       HiveAuthzBinding hiveAuthzBinding) throws HiveAuthzPluginException,
       HiveAccessControlException {
     String currDatabase = null;
@@ -413,8 +414,8 @@ public class DefaultSentryValidator extends SentryHiveAuthorizationValidator {
       Database database;
       database = new Database(obj.getDbname());
 
-      List<List<DBModelAuthorizable>> inputHierarchy = new ArrayList<List<DBModelAuthorizable>>();
-      List<List<DBModelAuthorizable>> outputHierarchy = new ArrayList<List<DBModelAuthorizable>>();
+      Set<List<DBModelAuthorizable>> inputHierarchy = new HashSet<List<DBModelAuthorizable>>();
+      Set<List<DBModelAuthorizable>> outputHierarchy = new HashSet<List<DBModelAuthorizable>>();
       List<DBModelAuthorizable> externalAuthorizableHierarchy =
           new ArrayList<DBModelAuthorizable>();
       externalAuthorizableHierarchy.add(hiveAuthzBinding.getAuthServer());
@@ -466,8 +467,8 @@ public class DefaultSentryValidator extends SentryHiveAuthorizationValidator {
 
       database = new Database(obj.getObjectName());
 
-      List<List<DBModelAuthorizable>> inputHierarchy = new ArrayList<List<DBModelAuthorizable>>();
-      List<List<DBModelAuthorizable>> outputHierarchy = new ArrayList<List<DBModelAuthorizable>>();
+      Set<List<DBModelAuthorizable>> inputHierarchy = new HashSet<List<DBModelAuthorizable>>();
+      Set<List<DBModelAuthorizable>> outputHierarchy = new HashSet<List<DBModelAuthorizable>>();
       List<DBModelAuthorizable> externalAuthorizableHierarchy =
           new ArrayList<DBModelAuthorizable>();
       externalAuthorizableHierarchy.add(hiveAuthzBinding.getAuthServer());

http://git-wip-us.apache.org/repos/asf/sentry/blob/a7b68f62/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/HiveAuthzBindingHookBase.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/HiveAuthzBindingHookBase.java b/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/HiveAuthzBindingHookBase.java
index da1956b..63d8d1c 100644
--- a/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/HiveAuthzBindingHookBase.java
+++ b/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/HiveAuthzBindingHookBase.java
@@ -22,6 +22,7 @@ import com.google.common.base.Splitter;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
+import java.util.HashSet;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.hive.common.JavaUtils;
@@ -340,8 +341,8 @@ public abstract class HiveAuthzBindingHookBase extends AbstractSemanticAnalyzerH
       HiveAuthzPrivileges stmtAuthObject, HiveOperation stmtOperation) throws  AuthorizationException {
     Set<ReadEntity> inputs = context.getInputs();
     Set<WriteEntity> outputs = context.getOutputs();
-    List<List<DBModelAuthorizable>> inputHierarchy = new ArrayList<List<DBModelAuthorizable>>();
-    List<List<DBModelAuthorizable>> outputHierarchy = new ArrayList<List<DBModelAuthorizable>>();
+    Set<List<DBModelAuthorizable>> inputHierarchy = new HashSet<List<DBModelAuthorizable>>();
+    Set<List<DBModelAuthorizable>> outputHierarchy = new HashSet<List<DBModelAuthorizable>>();
 
     if(LOG.isDebugEnabled()) {
       LOG.debug("stmtAuthObject.getOperationScope() = " + stmtAuthObject.getOperationScope());
@@ -555,7 +556,7 @@ public abstract class HiveAuthzBindingHookBase extends AbstractSemanticAnalyzerH
    * @param entity
    * @param sentryContext
    */
-  protected void addColumnHierarchy(List<List<DBModelAuthorizable>> inputHierarchy,
+  protected void addColumnHierarchy(Set<List<DBModelAuthorizable>> inputHierarchy,
       ReadEntity entity) {
     List<DBModelAuthorizable> entityHierarchy = new ArrayList<DBModelAuthorizable>();
     entityHierarchy.add(hiveAuthzBinding.getAuthServer());
@@ -583,7 +584,7 @@ public abstract class HiveAuthzBindingHookBase extends AbstractSemanticAnalyzerH
    * @param entity
    * @param sentryContext
    */
-  protected void getInputHierarchyFromInputs(List<List<DBModelAuthorizable>> inputHierarchy,
+  public void getInputHierarchyFromInputs(Set<List<DBModelAuthorizable>> inputHierarchy,
       Set<ReadEntity> inputs) {
     for (ReadEntity readEntity: inputs) {
       // skip the tables/view that are part of expanded view definition
@@ -655,8 +656,8 @@ public abstract class HiveAuthzBindingHookBase extends AbstractSemanticAnalyzerH
       Database database;
       database = new Database(dbName);
 
-      List<List<DBModelAuthorizable>> inputHierarchy = new ArrayList<List<DBModelAuthorizable>>();
-      List<List<DBModelAuthorizable>> outputHierarchy = new ArrayList<List<DBModelAuthorizable>>();
+      Set<List<DBModelAuthorizable>> inputHierarchy = new HashSet<List<DBModelAuthorizable>>();
+      Set<List<DBModelAuthorizable>> outputHierarchy = new HashSet<List<DBModelAuthorizable>>();
       List<DBModelAuthorizable> externalAuthorizableHierarchy = new ArrayList<DBModelAuthorizable>();
       externalAuthorizableHierarchy.add(hiveAuthzBinding.getAuthServer());
       externalAuthorizableHierarchy.add(database);
@@ -690,8 +691,8 @@ public abstract class HiveAuthzBindingHookBase extends AbstractSemanticAnalyzerH
     Table table = new Table(tableName);
     for (FieldSchema col : cols) {
       // if user has privileges on column, add to filtered list, else discard
-      List<List<DBModelAuthorizable>> inputHierarchy = new ArrayList<List<DBModelAuthorizable>>();
-      List<List<DBModelAuthorizable>> outputHierarchy = new ArrayList<List<DBModelAuthorizable>>();
+      Set<List<DBModelAuthorizable>> inputHierarchy = new HashSet<List<DBModelAuthorizable>>();
+      Set<List<DBModelAuthorizable>> outputHierarchy = new HashSet<List<DBModelAuthorizable>>();
       List<DBModelAuthorizable> externalAuthorizableHierarchy = new ArrayList<DBModelAuthorizable>();
       externalAuthorizableHierarchy.add(hiveAuthzBinding.getAuthServer());
       externalAuthorizableHierarchy.add(database);
@@ -742,8 +743,8 @@ public abstract class HiveAuthzBindingHookBase extends AbstractSemanticAnalyzerH
 
       database = new Database(dbName);
 
-      List<List<DBModelAuthorizable>> inputHierarchy = new ArrayList<List<DBModelAuthorizable>>();
-      List<List<DBModelAuthorizable>> outputHierarchy = new ArrayList<List<DBModelAuthorizable>>();
+      Set<List<DBModelAuthorizable>> inputHierarchy = new HashSet<List<DBModelAuthorizable>>();
+      Set<List<DBModelAuthorizable>> outputHierarchy = new HashSet<List<DBModelAuthorizable>>();
       List<DBModelAuthorizable> externalAuthorizableHierarchy = new ArrayList<DBModelAuthorizable>();
       externalAuthorizableHierarchy.add(hiveAuthzBinding.getAuthServer());
       externalAuthorizableHierarchy.add(database);

http://git-wip-us.apache.org/repos/asf/sentry/blob/a7b68f62/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/metastore/MetastoreAuthzBinding.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/metastore/MetastoreAuthzBinding.java b/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/metastore/MetastoreAuthzBinding.java
index 5beda9f..a1aebca 100644
--- a/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/metastore/MetastoreAuthzBinding.java
+++ b/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/metastore/MetastoreAuthzBinding.java
@@ -20,6 +20,7 @@ package org.apache.sentry.binding.metastore;
 import java.io.IOException;
 import java.util.List;
 
+import java.util.Set;
 import javax.security.auth.login.LoginException;
 
 import org.apache.hadoop.conf.Configuration;
@@ -48,8 +49,8 @@ public class MetastoreAuthzBinding extends MetastoreAuthzBindingBase {
 
   @Override
   protected void authorizeMetastoreAccess(HiveOperation hiveOp,
-      List<List<DBModelAuthorizable>> inputHierarchy,
-      List<List<DBModelAuthorizable>> outputHierarchy) throws InvalidOperationException {
+      Set<List<DBModelAuthorizable>> inputHierarchy,
+      Set<List<DBModelAuthorizable>> outputHierarchy) throws InvalidOperationException {
     if (isSentryCacheOutOfSync()) {
       throw invalidOperationException(new SentryUserException(
           "Metastore/Sentry cache is out of sync"));

http://git-wip-us.apache.org/repos/asf/sentry/blob/a7b68f62/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/metastore/MetastoreAuthzBindingBase.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/metastore/MetastoreAuthzBindingBase.java b/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/metastore/MetastoreAuthzBindingBase.java
index 0909656..8ad9e50 100644
--- a/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/metastore/MetastoreAuthzBindingBase.java
+++ b/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/metastore/MetastoreAuthzBindingBase.java
@@ -19,6 +19,7 @@ package org.apache.sentry.binding.metastore;
 
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
+import java.util.HashSet;
 import java.util.Iterator;
 import org.apache.commons.lang.StringUtils;
 import org.apache.hadoop.conf.Configuration;
@@ -74,10 +75,10 @@ public abstract class MetastoreAuthzBindingBase extends MetaStorePreEventListene
    * Build the set of object hierarchies ie fully qualified db model objects
    */
   protected static class HierarcyBuilder {
-    private List<List<DBModelAuthorizable>> authHierarchy;
+    private Set<List<DBModelAuthorizable>> authHierarchy;
 
     public HierarcyBuilder() {
-      authHierarchy = new ArrayList<List<DBModelAuthorizable>>();
+      authHierarchy = new HashSet<List<DBModelAuthorizable>>();
     }
 
     public HierarcyBuilder addServerToOutput(Server server) {
@@ -122,7 +123,7 @@ public abstract class MetastoreAuthzBindingBase extends MetaStorePreEventListene
       return this;
     }
 
-    public List<List<DBModelAuthorizable>> build() {
+    public Set<List<DBModelAuthorizable>> build() {
       return authHierarchy;
     }
   }
@@ -403,8 +404,8 @@ public abstract class MetastoreAuthzBindingBase extends MetaStorePreEventListene
    * @throws InvalidOperationException
    */
   protected abstract void authorizeMetastoreAccess(HiveOperation hiveOp,
-      List<List<DBModelAuthorizable>> inputHierarchy,
-      List<List<DBModelAuthorizable>> outputHierarchy)
+      Set<List<DBModelAuthorizable>> inputHierarchy,
+      Set<List<DBModelAuthorizable>> outputHierarchy)
       throws InvalidOperationException;
 
   public Server getAuthServer() {

http://git-wip-us.apache.org/repos/asf/sentry/blob/a7b68f62/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/util/SentryAuthorizerUtil.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/util/SentryAuthorizerUtil.java b/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/util/SentryAuthorizerUtil.java
index dd6936c..5996b6c 100644
--- a/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/util/SentryAuthorizerUtil.java
+++ b/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/util/SentryAuthorizerUtil.java
@@ -18,6 +18,7 @@ import com.google.common.base.Splitter;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
@@ -146,9 +147,9 @@ public class SentryAuthorizerUtil {
    * @param server
    * @param privilges
    */
-  public static List<List<DBModelAuthorizable>> convert2SentryPrivilegeList(Server server,
+  public static Set<List<DBModelAuthorizable>> convert2SentryPrivilegeList(Server server,
       List<HivePrivilegeObject> privilges) {
-    List<List<DBModelAuthorizable>> hierarchyList = new ArrayList<List<DBModelAuthorizable>>();
+    Set<List<DBModelAuthorizable>> hierarchyList = new HashSet<List<DBModelAuthorizable>>();
     if (privilges != null && !privilges.isEmpty()) {
       for (HivePrivilegeObject p : privilges) {
         hierarchyList.addAll(getAuthzHierarchy(server, p));

http://git-wip-us.apache.org/repos/asf/sentry/blob/a7b68f62/sentry-binding/sentry-binding-hive/src/test/java/org/apache/sentry/binding/hive/TestHiveAuthzBindingHookBase.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-hive/src/test/java/org/apache/sentry/binding/hive/TestHiveAuthzBindingHookBase.java b/sentry-binding/sentry-binding-hive/src/test/java/org/apache/sentry/binding/hive/TestHiveAuthzBindingHookBase.java
new file mode 100644
index 0000000..0df74c5
--- /dev/null
+++ b/sentry-binding/sentry-binding-hive/src/test/java/org/apache/sentry/binding/hive/TestHiveAuthzBindingHookBase.java
@@ -0,0 +1,246 @@
+/*
+ * 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.sentry.binding.hive;
+
+import com.google.common.io.Files;
+import com.google.common.io.Resources;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.ServerSocket;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.commons.io.FileUtils;
+import org.apache.hadoop.hive.conf.HiveConf;
+import org.apache.hadoop.hive.conf.HiveConf.ConfVars;
+import org.apache.hadoop.hive.ql.hooks.Entity.Type;
+import org.apache.hadoop.hive.ql.hooks.ReadEntity;
+import org.apache.hadoop.hive.ql.session.SessionState;
+import org.apache.sentry.binding.hive.authz.SentryHiveAuthorizerFactory;
+import org.apache.sentry.binding.hive.conf.HiveAuthzConf;
+import org.apache.sentry.binding.hive.conf.HiveAuthzConf.AuthzConfVars;
+import org.apache.sentry.core.common.utils.PolicyFiles;
+import org.apache.sentry.core.model.db.DBModelAuthorizable;
+import org.apache.sentry.provider.file.LocalGroupResourceAuthorizationProvider;
+import org.apache.sentry.service.common.ServiceConstants.ServerConfig;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+/**
+ * Test for hive authz bindingshook
+ * It uses the access.provider.file.ResourceAuthorizationProvider with the
+ * resource test-authz-provider.ini
+ */
+public class TestHiveAuthzBindingHookBase {
+  private static final String RESOURCE_PATH = "test-authz-provider.ini";
+  // Servers, Database, Table
+  private static final String SERVER1 = "server1";
+
+  //Columns
+  private static final String COLUMN1 = "col1";
+  private static final String COLUMN2 = "col2";
+  private static final String COLUMN3 = "col3";
+  private static final List<String>COLUMN_LIST = Arrays.asList(COLUMN1, COLUMN2, COLUMN3);
+
+  // Entities
+  private Set<List<DBModelAuthorizable>> inputTabHierarcyList = new HashSet<List<DBModelAuthorizable>>();
+  private Set<List<DBModelAuthorizable>> outputTabHierarcyList = new HashSet<List<DBModelAuthorizable>>();
+  private Set<ReadEntity>inputs = new HashSet<ReadEntity>();
+  Map<String, List<String>> tableToColumnAccessMap = new HashMap<String, List<String>>();
+  private HiveAuthzConf authzConf = new HiveAuthzConf(Resources.getResource("sentry-deprecated-site.xml"));
+
+  // auth bindings handler
+  private HiveAuthzBindingHook testAuth = null;
+  private File baseDir;
+  protected File policyFileLocation;
+
+
+  @Before
+  public void setUp() throws Exception {
+    inputTabHierarcyList.clear();
+    outputTabHierarcyList.clear();
+    inputs.clear();
+    tableToColumnAccessMap.clear();
+    baseDir = Files.createTempDir();
+    PolicyFiles.copyToDir(baseDir, RESOURCE_PATH);
+
+    // create auth configuration
+    authzConf.set(AuthzConfVars.AUTHZ_PROVIDER.getVar(),
+        "org.apache.sentry.provider.file.LocalGroupResourceAuthorizationProvider");
+    authzConf.set(AuthzConfVars.AUTHZ_PROVIDER_RESOURCE.getVar(),
+        new File(baseDir, RESOURCE_PATH).getPath());
+    authzConf.set(AuthzConfVars.AUTHZ_SERVER_NAME.getVar(), SERVER1);
+    authzConf.set(AuthzConfVars.SENTRY_TESTING_MODE.getVar(), "true");
+
+    policyFileLocation = new File(baseDir, RESOURCE_PATH);
+    HiveConf hiveConf = configureHiveAndMetastore();
+
+    SessionState.start(hiveConf);
+    testAuth = new HiveAuthzBindingHook();
+  }
+
+  @After
+  public void teardown() {
+    if(baseDir != null) {
+      FileUtils.deleteQuietly(baseDir);
+    }
+  }
+
+  /**
+   * Test getInputHierarchyFromInputs with duplicate ReadEntity inputs
+   */
+  @Test
+  public void testGetInputHierarchyFromInputsWithRepeatedInputs() throws Exception {
+
+    inputTabHierarcyList = new HashSet<List<DBModelAuthorizable>>();
+    ReadEntity entityObj = buildInputListWithColumnInputs(COLUMN_LIST);
+    inputs.add(entityObj);
+    testAuth.getInputHierarchyFromInputs(inputTabHierarcyList, inputs);
+
+    Assert.assertEquals(1, inputTabHierarcyList.size());
+    //Add the same inputs again
+    testAuth.getInputHierarchyFromInputs(inputTabHierarcyList, inputs);
+    Assert.assertEquals(1, inputTabHierarcyList.size());
+  }
+
+  private ReadEntity buildInputListWithColumnInputs(List<String> columns) {
+
+    ReadEntity entity = Mockito.mock(ReadEntity.class);
+    Mockito.when(entity.getAccessedColumns()).thenReturn(columns);
+    Mockito.when(entity.getType()).thenReturn(Type.DATABASE);
+
+    return entity;
+  }
+
+  private HiveConf configureHiveAndMetastore() throws IOException, InterruptedException {
+    HiveConf hiveConf = new HiveConf();
+    hiveConf.set("sentry.metastore.plugins", "org.apache.sentry.hdfs.MetastorePlugin");
+    hiveConf.set("sentry.service.client.server.rpc-addresses", "localhost");
+    hiveConf.set("sentry.hdfs.service.client.server.rpc-addresses", "localhost");
+    hiveConf.set("sentry.hdfs.service.client.server.rpc-port", String.valueOf(findPort()));
+    hiveConf.set("sentry.service.client.server.rpc-port", String.valueOf(findPort()));
+    hiveConf.set("sentry.service.security.mode", "none");
+    hiveConf.set("sentry.hdfs.service.security.mode", "none");
+    hiveConf.set("sentry.hdfs.init.update.retry.delay.ms", "500");
+    hiveConf.set("sentry.hive.provider.backend",
+        "org.apache.sentry.provider.db.SimpleDBProviderBackend");
+    hiveConf.set("sentry.provider", LocalGroupResourceAuthorizationProvider.class.getName());
+    hiveConf
+        .set("sentry.hive.provider", LocalGroupResourceAuthorizationProvider.class.getName());
+    hiveConf.set("sentry.hive.provider.resource", policyFileLocation.getPath());
+    hiveConf.set("sentry.hive.testing.mode", "true");
+    hiveConf.set("sentry.hive.server", SERVER1);
+
+    hiveConf.set(ServerConfig.SENTRY_STORE_GROUP_MAPPING,
+        ServerConfig.SENTRY_STORE_LOCAL_GROUP_MAPPING);
+    hiveConf
+        .set(ServerConfig.SENTRY_STORE_GROUP_MAPPING_RESOURCE, policyFileLocation.getPath());
+    hiveConf.set("hive.metastore.execute.setugi", "true");
+    hiveConf.set("hive.metastore.warehouse.dir", "hdfs:///user/hive/warehouse");
+    hiveConf.set("javax.jdo.option.ConnectionURL",
+        "jdbc:derby:;databaseName=" + baseDir.getAbsolutePath() + "/metastore_db;create=true");
+    hiveConf
+        .set("javax.jdo.option.ConnectionDriverName", "org.apache.derby.jdbc.EmbeddedDriver");
+    hiveConf.set("javax.jdo.option.ConnectionUserName", "hive");
+    hiveConf.set("javax.jdo.option.ConnectionPassword", "hive");
+    hiveConf.set("datanucleus.schema.autoCreateAll", "true");
+    hiveConf.set("datanucleus.autoStartMechanism", "SchemaTable");
+    hiveConf.set("datanucleus.schema.autoCreateTables", "true");
+
+    hiveConf.set(ConfVars.HIVE_AUTHORIZATION_ENABLED.varname, "true");
+    hiveConf.set(ConfVars.HIVE_AUTHORIZATION_MANAGER.varname,
+        SentryHiveAuthorizerFactory.class.getName());
+    hiveConf.set(ConfVars.HIVE_CBO_ENABLED.varname, "false");
+    hiveConf.set(ConfVars.METASTORE_DISALLOW_INCOMPATIBLE_COL_TYPE_CHANGES.varname, "false");
+    hiveConf.set(ConfVars.HIVE_IN_TEST.varname, "true");
+
+    // Sets the hadoop temporary directory specified by the java.io.tmpdir (already set to the
+    // maven build directory to avoid writing to the /tmp directly
+    String hadoopTempDir = System.getProperty("java.io.tmpdir") + File.separator + "hadoop-tmp";
+    hiveConf.set("hadoop.tmp.dir", hadoopTempDir);
+
+    // This configuration will avoid that the HMS fails if the metastore schema has not version
+    // information. For some reason, HMS does not set a version initially on our tests.
+    hiveConf.set(ConfVars.METASTORE_SCHEMA_VERIFICATION.varname, "false");
+
+    // Sets hive.metastore.authorization.storage.checks to true, so that
+    // disallow the operations such as drop-partition if the user in question
+    // doesn't have permissions to delete the corresponding directory
+    // on the storage.
+    hiveConf.set("hive.metastore.authorization.storage.checks", "true");
+    hiveConf.set("hive.metastore.uris", "thrift://localhost:" + findPort());
+    hiveConf.set("hive.metastore.pre.event.listeners",
+        "org.apache.sentry.binding.metastore.MetastoreAuthzBinding");
+    hiveConf.set("hive.metastore.transactional.event.listeners",
+        "org.apache.hive.hcatalog.listener.DbNotificationListener");
+    hiveConf.set("hive.metastore.event.listeners",
+        "org.apache.sentry.binding.metastore.SentrySyncHMSNotificationsPostEventListener");
+    hiveConf.set("hive.metastore.event.message.factory",
+        "org.apache.sentry.binding.metastore.messaging.json.SentryJSONMessageFactory");
+    hiveConf.set("hive.security.authorization.task.factory",
+        "org.apache.sentry.binding.hive.SentryHiveAuthorizationTaskFactoryImpl");
+    hiveConf.set("hive.server2.session.hook",
+        "org.apache.sentry.binding.hive.HiveAuthzBindingSessionHook");
+    hiveConf.set("sentry.metastore.service.users",
+        "hive");// queries made by hive user (beeline) skip meta store check
+    // make sure metastore calls sentry post event listener
+    hiveConf.set("hive.metastore.event.listeners",
+        "org.apache.sentry.binding.metastore.SentrySyncHMSNotificationsPostEventListener");
+
+    HiveAuthzConf authzConf = new HiveAuthzConf(Resources.getResource("sentry-site.xml"));
+    authzConf.addResource(hiveConf);
+    File confDir = assertCreateDir(new File(baseDir, "etc"));
+    File accessSite = new File(confDir, HiveAuthzConf.AUTHZ_SITE_FILE);
+    OutputStream out = new FileOutputStream(accessSite);
+    authzConf.writeXml(out);
+    out.close();
+
+    hiveConf.set("hive.sentry.conf.url", accessSite.getPath());
+
+    File hiveSite = new File(confDir, "hive-site.xml");
+    hiveConf.set("hive.server2.enable.doAs", "false");
+    hiveConf.set(HiveAuthzConf.HIVE_SENTRY_CONF_URL, accessSite.toURI().toURL()
+        .toExternalForm());
+    out = new FileOutputStream(hiveSite);
+    hiveConf.writeXml(out);
+    out.close();
+
+    return hiveConf;
+  }
+
+  protected static File assertCreateDir(File dir) {
+    if(!dir.isDirectory()) {
+      Assert.assertTrue("Failed creating " + dir, dir.mkdirs());
+    }
+    return dir;
+  }
+
+  private static int findPort() throws IOException {
+    ServerSocket socket = new ServerSocket(0);
+    int port = socket.getLocalPort();
+    socket.close();
+    return port;
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/a7b68f62/sentry-binding/sentry-binding-hive/src/test/java/org/apache/sentry/binding/hive/TestHiveAuthzBindings.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-hive/src/test/java/org/apache/sentry/binding/hive/TestHiveAuthzBindings.java b/sentry-binding/sentry-binding-hive/src/test/java/org/apache/sentry/binding/hive/TestHiveAuthzBindings.java
index 3bbf6fb..c17229f 100644
--- a/sentry-binding/sentry-binding-hive/src/test/java/org/apache/sentry/binding/hive/TestHiveAuthzBindings.java
+++ b/sentry-binding/sentry-binding-hive/src/test/java/org/apache/sentry/binding/hive/TestHiveAuthzBindings.java
@@ -19,8 +19,10 @@ package org.apache.sentry.binding.hive;
 import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashSet;
 import java.util.List;
 
+import java.util.Set;
 import org.junit.Assert;
 
 import org.apache.commons.io.FileUtils;
@@ -79,8 +81,8 @@ public class TestHiveAuthzBindings {
   private static final String AGE_COL = "age";
 
   // Entities
-  private List<List<DBModelAuthorizable>> inputTabHierarcyList = new ArrayList<List<DBModelAuthorizable>>();
-  private List<List<DBModelAuthorizable>> outputTabHierarcyList = new ArrayList<List<DBModelAuthorizable>>();
+  private Set<List<DBModelAuthorizable>> inputTabHierarcyList = new HashSet<List<DBModelAuthorizable>>();
+  private Set<List<DBModelAuthorizable>> outputTabHierarcyList = new HashSet<List<DBModelAuthorizable>>();
   private HiveConf hiveConf = new HiveConf();
   private HiveAuthzConf authzConf = new HiveAuthzConf(Resources.getResource("sentry-deprecated-site.xml"));
 

http://git-wip-us.apache.org/repos/asf/sentry/blob/a7b68f62/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/AccessURI.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/AccessURI.java b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/AccessURI.java
index dd8104d..070fc31 100644
--- a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/AccessURI.java
+++ b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/AccessURI.java
@@ -71,4 +71,27 @@ public class AccessURI implements DBModelAuthorizable {
   public String getTypeName() {
     return getAuthzType().name();
   }
+
+  @Override
+  public int hashCode() {
+    return uriName.hashCode();
+  }
+
+  @Override
+  public boolean equals(Object o) {
+
+    if(o == null) {
+      return false;
+    }
+
+    if(!(o instanceof AccessURI)) {
+      return false;
+    }
+
+    if(((AccessURI) o).getName() ==  null) {
+      return false;
+    }
+
+    return ((AccessURI) o).getName().equals(uriName);
+  }
 }

http://git-wip-us.apache.org/repos/asf/sentry/blob/a7b68f62/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/Column.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/Column.java b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/Column.java
index 305fd1f..e36b09a 100644
--- a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/Column.java
+++ b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/Column.java
@@ -50,4 +50,27 @@ public class Column implements DBModelAuthorizable {
   public String getTypeName() {
     return getAuthzType().name();
   }
+
+  @Override
+  public int hashCode() {
+    return name.hashCode();
+  }
+
+  @Override
+  public boolean equals(Object o) {
+
+    if(o == null) {
+      return false;
+    }
+
+    if(!(o instanceof Column)) {
+      return false;
+    }
+
+    if(((Column) o).getName() ==  null) {
+      return false;
+    }
+
+    return ((Column) o).getName().equals(name);
+  }
 }

http://git-wip-us.apache.org/repos/asf/sentry/blob/a7b68f62/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/Database.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/Database.java b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/Database.java
index 0d94805..e8dc140 100644
--- a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/Database.java
+++ b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/Database.java
@@ -48,4 +48,27 @@ public class Database implements DBModelAuthorizable {
   public String getTypeName() {
     return getAuthzType().name();
   }
+
+  @Override
+  public int hashCode() {
+    return name.hashCode();
+  }
+
+  @Override
+  public boolean equals(Object o) {
+
+    if(o == null) {
+      return false;
+    }
+
+    if(!(o instanceof Database)) {
+      return false;
+    }
+
+    if(((Database) o).getName() ==  null) {
+      return false;
+    }
+
+    return ((Database) o).getName().equals(name);
+  }
 }

http://git-wip-us.apache.org/repos/asf/sentry/blob/a7b68f62/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/Server.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/Server.java b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/Server.java
index 33e735e..41693c2 100644
--- a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/Server.java
+++ b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/Server.java
@@ -48,4 +48,27 @@ public class Server implements DBModelAuthorizable {
   public String getTypeName() {
     return getAuthzType().name();
   }
+
+  @Override
+  public int hashCode() {
+    return name.hashCode();
+  }
+
+  @Override
+  public boolean equals(Object o) {
+
+    if(o == null) {
+      return false;
+    }
+
+    if(!(o instanceof Server)) {
+      return false;
+    }
+
+    if(((Server) o).getName() ==  null) {
+      return false;
+    }
+
+    return ((Server) o).getName().equals(name);
+  }
 }

http://git-wip-us.apache.org/repos/asf/sentry/blob/a7b68f62/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/Table.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/Table.java b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/Table.java
index b161d02..5a98158 100644
--- a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/Table.java
+++ b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/Table.java
@@ -49,4 +49,27 @@ public class Table implements TableOrView {
   public String getTypeName() {
     return getAuthzType().name();
   }
+
+  @Override
+  public int hashCode() {
+    return name.hashCode();
+  }
+
+  @Override
+  public boolean equals(Object o) {
+
+    if(o == null) {
+      return false;
+    }
+
+    if(!(o instanceof Table)) {
+      return false;
+    }
+
+    if(((Table) o).getName() ==  null) {
+      return false;
+    }
+
+    return ((Table) o).getName().equals(name);
+  }
 }

http://git-wip-us.apache.org/repos/asf/sentry/blob/a7b68f62/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/View.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/View.java b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/View.java
index f6d8499..243cc7a 100644
--- a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/View.java
+++ b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/View.java
@@ -48,4 +48,27 @@ public class View implements TableOrView {
   public String getTypeName() {
     return getAuthzType().name();
   }
+
+  @Override
+  public int hashCode() {
+    return name.hashCode();
+  }
+
+  @Override
+  public boolean equals(Object o) {
+
+    if(o == null) {
+      return false;
+    }
+
+    if(!(o instanceof View)) {
+      return false;
+    }
+
+    if(((View) o).getName() ==  null) {
+      return false;
+    }
+
+    return ((View) o).getName().equals(name);
+  }
 }