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 <amis...@cloudera.com> Authored: Wed Sep 26 15:10:18 2018 -0500 Committer: amishra <amis...@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); + } }