blob: c3f254b48e1af1156c7cc964a0bffc91f22a0a7e [file] [log] [blame]
/*
* 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.access.binding.hive;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.access.binding.hive.authz.HiveAuthzBinding;
import org.apache.access.binding.hive.authz.HiveAuthzPrivileges;
import org.apache.access.binding.hive.authz.HiveAuthzPrivilegesMap;
import org.apache.access.binding.hive.conf.HiveAuthzConf;
import org.apache.access.binding.hive.conf.HiveAuthzConf.AuthzConfVars;
import org.apache.access.core.AccessConstants;
import org.apache.access.core.AccessURI;
import org.apache.access.core.Authorizable;
import org.apache.access.core.Database;
import org.apache.access.core.Server;
import org.apache.access.core.Subject;
import org.apache.access.core.Table;
import org.apache.access.provider.file.PolicyFiles;
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.metadata.AuthorizationException;
import org.apache.hadoop.hive.ql.plan.HiveOperation;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.google.common.io.Files;
import com.google.common.io.Resources;
/**
* Test for hive authz bindings
* It uses the access.provider.file.ResourceAuthorizationProvider with the
* resource test-authz-provider.ini
*/
public class TestHiveAuthzBindings {
private static final String RESOURCE_PATH = "test-authz-provider.ini";
// Servers
private static final String SERVER1 = "server1";
// Users
private static final Subject ADMIN_SUBJECT = new Subject("admin1");
private static final Subject MANAGER_SUBJECT = new Subject("manager1");
private static final Subject ANALYST_SUBJECT = new Subject("analyst1");
private static final Subject JUNIOR_ANALYST_SUBJECT = new Subject("junior_analyst1");
private static final Subject NO_SUCH_SUBJECT = new Subject("no such subject");
// Databases
private static final String CUSTOMER_DB = "customers";
private static final String ANALYST_DB = "analyst";
private static final String JUNIOR_ANALYST_DB = "junior_analyst";
// Tables
private static final String PURCHASES_TAB = "purchases";
private static final String PAYMENT_TAB = "payments";
// Entities
private List<List<Authorizable>> inputTabHierarcyList = new ArrayList<List<Authorizable>>();
private List<List<Authorizable>> outputTabHierarcyList = new ArrayList<List<Authorizable>>();
private HiveConf hiveConf = new HiveConf();
private HiveAuthzConf authzConf = new HiveAuthzConf(Resources.getResource("access-site.xml"));
// Privileges
private static final HiveAuthzPrivileges queryPrivileges =
HiveAuthzPrivilegesMap.getHiveAuthzPrivileges(HiveOperation.QUERY);
private static final HiveAuthzPrivileges createTabPrivileges =
HiveAuthzPrivilegesMap.getHiveAuthzPrivileges(HiveOperation.CREATETABLE);
private static final HiveAuthzPrivileges loadTabPrivileges =
HiveAuthzPrivilegesMap.getHiveAuthzPrivileges(HiveOperation.LOAD);
private static final HiveAuthzPrivileges createDbPrivileges =
HiveAuthzPrivilegesMap.getHiveAuthzPrivileges(HiveOperation.CREATEDATABASE);
private static final HiveAuthzPrivileges createFuncPrivileges =
HiveAuthzPrivilegesMap.getHiveAuthzPrivileges(HiveOperation.CREATEFUNCTION);
// auth bindings handler
private HiveAuthzBinding testAuth = null;
private File baseDir;
@Before
public void setUp() throws Exception {
inputTabHierarcyList.clear();
outputTabHierarcyList.clear();
baseDir = Files.createTempDir();
PolicyFiles.copyToDir(baseDir, RESOURCE_PATH);
// create auth configuration
authzConf.set(AuthzConfVars.AUTHZ_PROVIDER.getVar(),
"org.apache.access.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.ACCESS_TESTING_MODE.getVar(), "true");
testAuth = new HiveAuthzBinding(hiveConf, authzConf);
}
@After
public void teardown() {
if(baseDir != null) {
FileUtils.deleteQuietly(baseDir);
}
}
/**
* validate read permission for admin on customer:purchase
*/
@Test
public void testValidateSelectPrivilegesForAdmin() throws Exception {
inputTabHierarcyList.add(buildObjectHierarchy(SERVER1, CUSTOMER_DB, PURCHASES_TAB));
testAuth.authorize(HiveOperation.QUERY, queryPrivileges, ADMIN_SUBJECT,
inputTabHierarcyList, outputTabHierarcyList);
}
/**
* validate read permission for admin on customer:purchase
*/
@Test
public void testValidateSelectPrivilegesForUsers() throws Exception {
inputTabHierarcyList.add(buildObjectHierarchy(SERVER1, CUSTOMER_DB, PURCHASES_TAB));
testAuth.authorize(HiveOperation.QUERY, queryPrivileges, ANALYST_SUBJECT,
inputTabHierarcyList, outputTabHierarcyList);
}
/**
* validate read permission for denied for junior analyst on customer:purchase
*/
@Test(expected=AuthorizationException.class)
public void testValidateSelectPrivilegesRejectionForUsers() throws Exception {
inputTabHierarcyList.add(buildObjectHierarchy(SERVER1, CUSTOMER_DB, PURCHASES_TAB));
testAuth.authorize(HiveOperation.QUERY, queryPrivileges, JUNIOR_ANALYST_SUBJECT,
inputTabHierarcyList, outputTabHierarcyList);
}
/**
* validate create table permissions for admin in customer db
*/
@Test
public void testValidateCreateTabPrivilegesForAdmin() throws Exception {
outputTabHierarcyList.add(buildObjectHierarchy(SERVER1, CUSTOMER_DB, PAYMENT_TAB));
testAuth.authorize(HiveOperation.CREATETABLE, createTabPrivileges, ADMIN_SUBJECT,
inputTabHierarcyList, outputTabHierarcyList);
}
/**
* validate create table permissions for manager in junior_analyst sandbox db
*/
@Test
public void testValidateCreateTabPrivilegesForUser() throws Exception {
outputTabHierarcyList.add(buildObjectHierarchy(SERVER1, JUNIOR_ANALYST_DB, PAYMENT_TAB));
testAuth.authorize(HiveOperation.CREATETABLE, createTabPrivileges, MANAGER_SUBJECT,
inputTabHierarcyList, outputTabHierarcyList);
}
/**
* validate create table permissions denided to junior_analyst in customer db
*/
@Test(expected=AuthorizationException.class)
public void testValidateCreateTabPrivilegesRejectionForUser() throws Exception {
outputTabHierarcyList.add(buildObjectHierarchy(SERVER1, CUSTOMER_DB, null));
testAuth.authorize(HiveOperation.CREATETABLE, createTabPrivileges, JUNIOR_ANALYST_SUBJECT,
inputTabHierarcyList, outputTabHierarcyList);
}
/**
* validate create table permissions denided to junior_analyst in analyst sandbox db
*/
@Test(expected=AuthorizationException.class)
public void testValidateCreateTabPrivilegesRejectionForUser2() throws Exception {
outputTabHierarcyList.add(buildObjectHierarchy(SERVER1, ANALYST_DB, null));
testAuth.authorize(HiveOperation.CREATETABLE, createTabPrivileges, JUNIOR_ANALYST_SUBJECT,
inputTabHierarcyList, outputTabHierarcyList);
}
/**
* validate load permissions for admin on customer:purchases
*/
@Test
public void testValidateLoadTabPrivilegesForAdmin() throws Exception {
outputTabHierarcyList.add(buildObjectHierarchy(SERVER1, CUSTOMER_DB, PURCHASES_TAB));
testAuth.authorize(HiveOperation.LOAD, loadTabPrivileges, ADMIN_SUBJECT,
inputTabHierarcyList, outputTabHierarcyList);
}
/**
* validate load table permissions on manager for customer:purchases
*/
@Test
public void testValidateLoadTabPrivilegesForUser() throws Exception {
outputTabHierarcyList.add(buildObjectHierarchy(SERVER1, CUSTOMER_DB, PURCHASES_TAB));
testAuth.authorize(HiveOperation.LOAD, loadTabPrivileges, MANAGER_SUBJECT,
inputTabHierarcyList, outputTabHierarcyList); }
/**
* validate load table permissions rejected for analyst on customer:purchases
*/
@Test(expected=AuthorizationException.class)
public void testValidateLoadTabPrivilegesRejectionForUser() throws Exception {
outputTabHierarcyList.add(buildObjectHierarchy(SERVER1, CUSTOMER_DB, PURCHASES_TAB));
testAuth.authorize(HiveOperation.LOAD, loadTabPrivileges, ANALYST_SUBJECT,
inputTabHierarcyList, outputTabHierarcyList);
}
/**
* validate create database permission for admin
*/
@Test
public void testValidateCreateDbForAdmin() throws Exception {
outputTabHierarcyList.add(buildObjectHierarchy(SERVER1, null, null));
testAuth.authorize(HiveOperation.CREATEDATABASE, createDbPrivileges, ADMIN_SUBJECT,
inputTabHierarcyList, outputTabHierarcyList);
}
/**
* validate create database permission for admin
*/
@Test(expected=AuthorizationException.class)
public void testValidateCreateDbRejectionForUser() throws Exception {
// Hive compiler doesn't capture Entities for DB operations
outputTabHierarcyList.add(buildObjectHierarchy(SERVER1, null, null));
testAuth.authorize(HiveOperation.CREATEDATABASE, createDbPrivileges, ANALYST_SUBJECT,
inputTabHierarcyList, outputTabHierarcyList);
}
/**
* Validate create function permission for admin (server level priviledge
*/
@Test
public void testValidateCreateFunctionForAdmin() throws Exception {
inputTabHierarcyList.add(buildObjectHierarchy(SERVER1, null, null));
inputTabHierarcyList.add(Arrays.asList(new Authorizable[] {
new Server(SERVER1), new AccessURI("file:///some/path/to/a/jar")
}));
testAuth.authorize(HiveOperation.CREATEFUNCTION, createFuncPrivileges, ADMIN_SUBJECT,
inputTabHierarcyList, outputTabHierarcyList);
}
@Test
public void testValidateCreateFunctionAppropiateURI() throws Exception {
inputTabHierarcyList.add(Arrays.asList(new Authorizable[] {
new Server(SERVER1), new Database(CUSTOMER_DB), new Table(AccessConstants.ALL)
}));
inputTabHierarcyList.add(Arrays.asList(new Authorizable[] {
new Server(SERVER1), new AccessURI("file:///path/to/some/lib/dir/my.jar")
}));
testAuth.authorize(HiveOperation.CREATEFUNCTION, createFuncPrivileges, ANALYST_SUBJECT,
inputTabHierarcyList, outputTabHierarcyList);
}
@Test(expected=AuthorizationException.class)
public void testValidateCreateFunctionRejectionForUnknownUser() throws Exception {
inputTabHierarcyList.add(buildObjectHierarchy(SERVER1, CUSTOMER_DB, AccessConstants.ALL));
testAuth.authorize(HiveOperation.CREATEFUNCTION, createFuncPrivileges, NO_SUCH_SUBJECT,
inputTabHierarcyList, outputTabHierarcyList);
}
@Test(expected=AuthorizationException.class)
public void testValidateCreateFunctionRejectionForUserWithoutURI() throws Exception {
inputTabHierarcyList.add(Arrays.asList(new Authorizable[] {
new Server(SERVER1), new Database(CUSTOMER_DB), new Table(AccessConstants.ALL)
}));
inputTabHierarcyList.add(Arrays.asList(new Authorizable[] {
new Server(SERVER1), new AccessURI("file:///some/path/to/a.jar")
}));
testAuth.authorize(HiveOperation.CREATEFUNCTION, createFuncPrivileges, ANALYST_SUBJECT,
inputTabHierarcyList, outputTabHierarcyList);
}
/**
* Turn on impersonation and make sure that the authorization fails.
* @throws Exception
*/
@Test(expected=AuthorizationException.class)
public void testImpersonationRestriction() throws Exception {
// perpare the hive and auth configs
hiveConf.setBoolVar(ConfVars.HIVE_SERVER2_KERBEROS_IMPERSONATION, true);
hiveConf.setVar(ConfVars.HIVE_SERVER2_AUTHENTICATION, "Kerberos");
authzConf.set(AuthzConfVars.ACCESS_TESTING_MODE.getVar(), "false");
testAuth = new HiveAuthzBinding(hiveConf, authzConf);
// following check should pass, but with impersonation it will fail with due to NoAuthorizationProvider
inputTabHierarcyList.add(buildObjectHierarchy(SERVER1, CUSTOMER_DB, PURCHASES_TAB));
testAuth.authorize(HiveOperation.QUERY, queryPrivileges, ADMIN_SUBJECT,
inputTabHierarcyList, outputTabHierarcyList);
}
/**
* Turn on impersonation and make sure that the authorization fails.
* @throws Exception
*/
@Test
public void testImpersonationAllowed() throws Exception {
// perpare the hive and auth configs
hiveConf.setBoolVar(ConfVars.HIVE_SERVER2_KERBEROS_IMPERSONATION, true);
hiveConf.setVar(ConfVars.HIVE_SERVER2_AUTHENTICATION, "Kerberos");
authzConf.set(AuthzConfVars.ACCESS_TESTING_MODE.getVar(), "false");
authzConf.set(AuthzConfVars.AUTHZ_ALLOW_HIVE_IMPERSONATION.getVar(), "true");
testAuth = new HiveAuthzBinding(hiveConf, authzConf);
// following check should pass, even with impersonation
inputTabHierarcyList.add(buildObjectHierarchy(SERVER1, CUSTOMER_DB, PURCHASES_TAB));
testAuth.authorize(HiveOperation.QUERY, queryPrivileges, ADMIN_SUBJECT,
inputTabHierarcyList, outputTabHierarcyList);
}
private List <Authorizable> buildObjectHierarchy(String server, String db, String table) {
List <Authorizable> authList = new ArrayList<Authorizable> ();
authList.add(new Server(server));
if (db != null) {
authList.add(new Database(db));
if (table != null) {
authList.add(new Table(table));
}
}
return authList;
}
}